summaryrefslogtreecommitdiff
path: root/spec/lib
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/banzai/filter/inline_observability_filter_spec.rb52
-rw-r--r--spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb84
-rw-r--r--spec/lib/gitlab/regex_spec.rb10
-rw-r--r--spec/lib/gitlab/untrusted_regexp_spec.rb32
-rw-r--r--spec/lib/gitlab/url_sanitizer_spec.rb31
-rw-r--r--spec/lib/rouge/formatters/html_gitlab_spec.rb21
6 files changed, 212 insertions, 18 deletions
diff --git a/spec/lib/banzai/filter/inline_observability_filter_spec.rb b/spec/lib/banzai/filter/inline_observability_filter_spec.rb
index fb1ba46e76c..69a9dc96c2c 100644
--- a/spec/lib/banzai/filter/inline_observability_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_observability_filter_spec.rb
@@ -34,6 +34,58 @@ RSpec.describe Banzai::Filter::InlineObservabilityFilter do
end
end
+ context 'when the document contains an embeddable observability link with redirect' do
+ let(:url) { 'https://observe.gitlab.com@example.com/12345' }
+
+ it 'leaves the original link unchanged' do
+ expect(doc.at_css('a').to_s).to eq(input)
+ end
+
+ it 'does not append an observability charts placeholder' do
+ node = doc.at_css('.js-render-observability')
+
+ expect(node).not_to be_present
+ end
+ end
+
+ context 'when the document contains an embeddable observability link with different port' do
+ let(:url) { 'https://observe.gitlab.com:3000/12345' }
+ let(:observe_url) { 'https://observe.gitlab.com:3001' }
+
+ before do
+ stub_env('OVERRIDE_OBSERVABILITY_URL', observe_url)
+ end
+
+ it 'leaves the original link unchanged' do
+ expect(doc.at_css('a').to_s).to eq(input)
+ end
+
+ it 'does not append an observability charts placeholder' do
+ node = doc.at_css('.js-render-observability')
+
+ expect(node).not_to be_present
+ end
+ end
+
+ context 'when the document contains an embeddable observability link with auth/start' do
+ let(:url) { 'https://observe.gitlab.com/auth/start' }
+ let(:observe_url) { 'https://observe.gitlab.com' }
+
+ before do
+ stub_env('OVERRIDE_OBSERVABILITY_URL', observe_url)
+ end
+
+ it 'leaves the original link unchanged' do
+ expect(doc.at_css('a').to_s).to eq(input)
+ end
+
+ it 'does not append an observability charts placeholder' do
+ node = doc.at_css('.js-render-observability')
+
+ expect(node).not_to be_present
+ end
+ end
+
context 'when feature flag is disabled' do
let(:url) { 'https://observe.gitlab.com/12345' }
diff --git a/spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb b/spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb
new file mode 100644
index 00000000000..62f908ed79b
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::NullifyLastErrorFromProjectMirrorData, feature_category: :source_code_management do # rubocop:disable Layout/LineLength
+ it 'nullifies last_error column on all rows' do
+ namespaces = table(:namespaces)
+ projects = table(:projects)
+ project_import_states = table(:project_mirror_data)
+
+ group = namespaces.create!(name: 'gitlab', path: 'gitlab-org')
+
+ project_namespace_1 = namespaces.create!(name: 'gitlab', path: 'gitlab-org')
+ project_namespace_2 = namespaces.create!(name: 'gitlab', path: 'gitlab-org')
+ project_namespace_3 = namespaces.create!(name: 'gitlab', path: 'gitlab-org')
+
+ project_1 = projects.create!(
+ namespace_id: group.id,
+ project_namespace_id: project_namespace_1.id,
+ name: 'test1'
+ )
+ project_2 = projects.create!(
+ namespace_id: group.id,
+ project_namespace_id: project_namespace_2.id,
+ name: 'test2'
+ )
+ project_3 = projects.create!(
+ namespace_id: group.id,
+ project_namespace_id: project_namespace_3.id,
+ name: 'test3'
+ )
+
+ project_import_state_1 = project_import_states.create!(
+ project_id: project_1.id,
+ status: 0,
+ last_update_started_at: 1.hour.ago,
+ last_update_scheduled_at: 1.hour.ago,
+ last_update_at: 1.hour.ago,
+ last_successful_update_at: 2.days.ago,
+ last_error: '13:fetch remote: "fatal: unable to look up user:pass@gitlab.com (port 9418) (nodename nor servname provided, or not known)\n": exit status 128.', # rubocop:disable Layout/LineLength
+ correlation_id_value: SecureRandom.uuid,
+ jid: SecureRandom.uuid
+ )
+
+ project_import_states.create!(
+ project_id: project_2.id,
+ status: 1,
+ last_update_started_at: 1.hour.ago,
+ last_update_scheduled_at: 1.hour.ago,
+ last_update_at: 1.hour.ago,
+ last_successful_update_at: nil,
+ next_execution_timestamp: 1.day.from_now,
+ last_error: '',
+ correlation_id_value: SecureRandom.uuid,
+ jid: SecureRandom.uuid
+ )
+
+ project_import_state_3 = project_import_states.create!(
+ project_id: project_3.id,
+ status: 2,
+ last_update_started_at: 1.hour.ago,
+ last_update_scheduled_at: 1.hour.ago,
+ last_update_at: 1.hour.ago,
+ last_successful_update_at: 1.hour.ago,
+ next_execution_timestamp: 1.day.from_now,
+ last_error: nil,
+ correlation_id_value: SecureRandom.uuid,
+ jid: SecureRandom.uuid
+ )
+
+ migration = described_class.new(
+ start_id: project_import_state_1.id,
+ end_id: project_import_state_3.id,
+ batch_table: :project_mirror_data,
+ batch_column: :id,
+ sub_batch_size: 1,
+ pause_ms: 0,
+ connection: ApplicationRecord.connection
+ )
+
+ w_last_error_count = -> { project_import_states.where.not(last_error: nil).count } # rubocop:disable CodeReuse/ActiveRecord
+ expect { migration.perform }.to change(&w_last_error_count).from(2).to(0)
+ end
+end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 31de4068bc5..bc0f9e22d50 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -1140,7 +1140,7 @@ RSpec.describe Gitlab::Regex, feature_category: :tooling do
end
context 'HTML comment lines' do
- subject { described_class::MARKDOWN_HTML_COMMENT_LINE_REGEX }
+ subject { Gitlab::UntrustedRegexp.new(described_class::MARKDOWN_HTML_COMMENT_LINE_REGEX_UNTRUSTED, multiline: true) }
let(:expected) { [['<!-- an HTML comment -->'], ['<!-- another HTML comment -->']] }
let(:markdown) do
@@ -1158,20 +1158,20 @@ RSpec.describe Gitlab::Regex, feature_category: :tooling do
it { is_expected.to match(%(<!-- single line comment -->)) }
it { is_expected.not_to match(%(<!--\nblock comment\n-->)) }
it { is_expected.not_to match(%(must start in first column <!-- comment -->)) }
- it { expect(markdown.scan(subject)).to eq expected }
+ it { expect(subject.scan(markdown)).to eq expected }
end
context 'HTML comment blocks' do
- subject { described_class::MARKDOWN_HTML_COMMENT_BLOCK_REGEX }
+ subject { Gitlab::UntrustedRegexp.new(described_class::MARKDOWN_HTML_COMMENT_BLOCK_REGEX_UNTRUSTED, multiline: true) }
- let(:expected) { %(<!-- the start of an HTML comment\n- [ ] list item commented out\n-->) }
+ let(:expected) { %(<!-- the start of an HTML comment\n- [ ] list item commented out\nmore text -->) }
let(:markdown) do
<<~MARKDOWN
Regular text
<!-- the start of an HTML comment
- [ ] list item commented out
- -->
+ more text -->
MARKDOWN
end
diff --git a/spec/lib/gitlab/untrusted_regexp_spec.rb b/spec/lib/gitlab/untrusted_regexp_spec.rb
index 270c4beec97..66675b20107 100644
--- a/spec/lib/gitlab/untrusted_regexp_spec.rb
+++ b/spec/lib/gitlab/untrusted_regexp_spec.rb
@@ -137,6 +137,38 @@ RSpec.describe Gitlab::UntrustedRegexp do
end
end
+ describe '#extract_named_group' do
+ let(:re) { described_class.new('(?P<name>\w+) (?P<age>\d+)|(?P<name_only>\w+)') }
+ let(:text) { 'Bob 40' }
+
+ it 'returns values for both named groups' do
+ matched = re.scan(text).first
+
+ expect(re.extract_named_group(:name, matched)).to eq 'Bob'
+ expect(re.extract_named_group(:age, matched)).to eq '40'
+ end
+
+ it 'returns nil if there was no match for group' do
+ matched = re.scan('Bob').first
+
+ expect(re.extract_named_group(:name, matched)).to be_nil
+ expect(re.extract_named_group(:age, matched)).to be_nil
+ expect(re.extract_named_group(:name_only, matched)).to eq 'Bob'
+ end
+
+ it 'returns nil if match is nil' do
+ matched = '(?P<age>\d+)'.scan(text).first
+
+ expect(re.extract_named_group(:age, matched)).to be_nil
+ end
+
+ it 'raises if name is not a capture group' do
+ matched = re.scan(text).first
+
+ expect { re.extract_named_group(:foo, matched) }.to raise_error('Invalid named capture group: foo')
+ end
+ end
+
describe '#match' do
context 'when there are matches' do
it 'returns a match object' do
diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb
index 0ffbf5f81e7..c02cbef8328 100644
--- a/spec/lib/gitlab/url_sanitizer_spec.rb
+++ b/spec/lib/gitlab/url_sanitizer_spec.rb
@@ -10,29 +10,36 @@ RSpec.describe Gitlab::UrlSanitizer do
# We want to try with multi-line content because is how error messages are formatted
described_class.sanitize(%Q{
remote: Not Found
- fatal: repository '#{url}' not found
+ fatal: repository `#{url}` not found
})
end
where(:input, :output) do
- 'http://user:pass@test.com/root/repoC.git/' | 'http://*****:*****@test.com/root/repoC.git/'
- 'https://user:pass@test.com/root/repoA.git/' | 'https://*****:*****@test.com/root/repoA.git/'
- 'ssh://user@host.test/path/to/repo.git' | 'ssh://*****@host.test/path/to/repo.git'
-
- # git protocol does not support authentication but clean any details anyway
- 'git://user:pass@host.test/path/to/repo.git' | 'git://*****:*****@host.test/path/to/repo.git'
- 'git://host.test/path/to/repo.git' | 'git://host.test/path/to/repo.git'
+ # http(s), ssh, git, relative, and schemeless URLs should all be masked correctly
+ urls = ['http://', 'https://', 'ssh://', 'git://', '//', ''].flat_map do |protocol|
+ [
+ ["#{protocol}test.com", "#{protocol}test.com"],
+ ["#{protocol}test.com/", "#{protocol}test.com/"],
+ ["#{protocol}test.com/path/to/repo.git", "#{protocol}test.com/path/to/repo.git"],
+ ["#{protocol}user@test.com", "#{protocol}*****@test.com"],
+ ["#{protocol}user:pass@test.com", "#{protocol}*****:*****@test.com"],
+ ["#{protocol}user:@test.com", "#{protocol}*****@test.com"],
+ ["#{protocol}:pass@test.com", "#{protocol}:*****@test.com"]
+ ]
+ end
# SCP-style URLs are left unmodified
- 'user@server:project.git' | 'user@server:project.git'
- 'user:pass@server:project.git' | 'user:pass@server:project.git'
+ urls << ['user@server:project.git', 'user@server:project.git']
+ urls << ['user:@server:project.git', 'user:@server:project.git']
+ urls << [':pass@server:project.git', ':pass@server:project.git']
+ urls << ['user:pass@server:project.git', 'user:pass@server:project.git']
# return an empty string for invalid URLs
- 'ssh://' | ''
+ urls << ['ssh://', '']
end
with_them do
- it { expect(sanitize_url(input)).to include("repository '#{output}' not found") }
+ it { expect(sanitize_url(input)).to include("repository `#{output}` not found") }
end
end
diff --git a/spec/lib/rouge/formatters/html_gitlab_spec.rb b/spec/lib/rouge/formatters/html_gitlab_spec.rb
index 79bfdb262c0..6fc1b395fc8 100644
--- a/spec/lib/rouge/formatters/html_gitlab_spec.rb
+++ b/spec/lib/rouge/formatters/html_gitlab_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Rouge::Formatters::HTMLGitlab do
+RSpec.describe Rouge::Formatters::HTMLGitlab, feature_category: :source_code_management do
describe '#format' do
subject { described_class.format(tokens, **options) }
@@ -67,5 +67,24 @@ RSpec.describe Rouge::Formatters::HTMLGitlab do
is_expected.to include(%{<span class="unicode-bidi has-tooltip" data-toggle="tooltip" title="#{message}">}).exactly(4).times
end
end
+
+ context 'when space characters and zero-width spaces are used' do
+ let(:lang) { 'ruby' }
+ let(:tokens) { lexer.lex(code, continue: false) }
+
+ let(:code) do
+ <<~JS
+ def\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000hello
+ JS
+ end
+
+ it 'replaces the space characters with spaces' do
+ is_expected.to eq(
+ "<span id=\"LC1\" class=\"line\" lang=\"ruby\">" \
+ "<span class=\"k\">def</span><span class=\"err\"> </span><span class=\"n\">hello</span>" \
+ "</span>"
+ )
+ end
+ end
end
end