Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-01-26 18:08:58 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-01-26 18:08:58 +0300
commitff89c3c372cd3b317915fb21940f9c8c065d94c0 (patch)
treece6674c2d661f25ffc156679846b0d6b48247e8e /spec
parent0121231095b3a50a18aaf4eb4a7058b55fe62fc1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/groups_controller_spec.rb60
-rw-r--r--spec/lib/gitlab/changelog/committer_spec.rb90
-rw-r--r--spec/lib/gitlab/changelog/config_spec.rb96
-rw-r--r--spec/lib/gitlab/changelog/generator_spec.rb164
-rw-r--r--spec/lib/gitlab/changelog/release_spec.rb107
-rw-r--r--spec/lib/gitlab/changelog/template/compiler_spec.rb129
-rw-r--r--spec/lib/gitlab/suggestions/commit_message_spec.rb11
-rw-r--r--spec/models/release_spec.rb57
-rw-r--r--spec/requests/api/graphql/mutations/releases/create_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/release_spec.rb4
-rw-r--r--spec/requests/api/suggestions_spec.rb27
-rw-r--r--spec/services/suggestions/apply_service_spec.rb14
-rw-r--r--spec/support/helpers/snowplow_helpers.rb10
-rw-r--r--spec/support/snowplow.rb1
-rw-r--r--spec/validators/nested_attributes_duplicates_validator_spec.rb (renamed from spec/validators/variable_duplicates_validator_spec.rb)50
15 files changed, 752 insertions, 76 deletions
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 939c36a98b2..9e5f68820d9 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -306,66 +306,6 @@ RSpec.describe GroupsController, factory_default: :keep do
end
end
end
-
- describe 'tracking group creation for onboarding issues experiment' do
- before do
- sign_in(user)
- end
-
- subject(:create_namespace) { post :create, params: { group: { name: 'new_group', path: 'new_group' } } }
-
- context 'experiment disabled' do
- before do
- stub_experiment(onboarding_issues: false)
- end
-
- it 'does not track anything', :snowplow do
- create_namespace
-
- expect_no_snowplow_event
- end
- end
-
- context 'experiment enabled' do
- before do
- stub_experiment(onboarding_issues: true)
- end
-
- context 'and the user is part of the control group' do
- before do
- stub_experiment_for_subject(onboarding_issues: false)
- end
-
- it 'tracks the event with the "created_namespace" action with the "control_group" property', :snowplow do
- create_namespace
-
- expect_snowplow_event(
- category: 'Growth::Conversion::Experiment::OnboardingIssues',
- action: 'created_namespace',
- label: anything,
- property: 'control_group'
- )
- end
- end
-
- context 'and the user is part of the experimental group' do
- before do
- stub_experiment_for_subject(onboarding_issues: true)
- end
-
- it 'tracks the event with the "created_namespace" action with the "experimental_group" property', :snowplow do
- create_namespace
-
- expect_snowplow_event(
- category: 'Growth::Conversion::Experiment::OnboardingIssues',
- action: 'created_namespace',
- label: anything,
- property: 'experimental_group'
- )
- end
- end
- end
- end
end
describe 'GET #index' do
diff --git a/spec/lib/gitlab/changelog/committer_spec.rb b/spec/lib/gitlab/changelog/committer_spec.rb
new file mode 100644
index 00000000000..71a80264f29
--- /dev/null
+++ b/spec/lib/gitlab/changelog/committer_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Committer do
+ let(:project) { create(:project, :repository) }
+ let(:user) { project.creator }
+ let(:committer) { described_class.new(project, user) }
+ let(:config) { Gitlab::Changelog::Config.new(project) }
+
+ describe '#commit' do
+ context "when the release isn't in the changelog" do
+ it 'commits the changes' do
+ release = Gitlab::Changelog::Release
+ .new(version: '1.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ committer.commit(
+ release: release,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Test commit'
+ )
+
+ content = project.repository.blob_at('master', 'CHANGELOG.md').data
+
+ expect(content).to eq(<<~MARKDOWN)
+ ## 1.0.0 (2020-01-01)
+
+ No changes.
+ MARKDOWN
+ end
+ end
+
+ context 'when the release is already in the changelog' do
+ it "doesn't commit the changes" do
+ release = Gitlab::Changelog::Release
+ .new(version: '1.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ 2.times do
+ committer.commit(
+ release: release,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Test commit'
+ )
+ end
+
+ content = project.repository.blob_at('master', 'CHANGELOG.md').data
+
+ expect(content).to eq(<<~MARKDOWN)
+ ## 1.0.0 (2020-01-01)
+
+ No changes.
+ MARKDOWN
+ end
+ end
+
+ context 'when committing the changes fails' do
+ it 'retries the operation' do
+ release = Gitlab::Changelog::Release
+ .new(version: '1.0.0', date: Time.utc(2020, 1, 1), config: config)
+
+ service = instance_spy(Files::MultiService)
+ errored = false
+
+ allow(Files::MultiService)
+ .to receive(:new)
+ .and_return(service)
+
+ allow(service).to receive(:execute) do
+ if errored
+ { status: :success }
+ else
+ errored = true
+ { status: :error }
+ end
+ end
+
+ expect do
+ committer.commit(
+ release: release,
+ file: 'CHANGELOG.md',
+ branch: 'master',
+ message: 'Test commit'
+ )
+ end.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/config_spec.rb b/spec/lib/gitlab/changelog/config_spec.rb
new file mode 100644
index 00000000000..adf82fa3ac2
--- /dev/null
+++ b/spec/lib/gitlab/changelog/config_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Config do
+ let(:project) { build_stubbed(:project) }
+
+ describe '.from_git' do
+ it 'retrieves the configuration from Git' do
+ allow(project.repository)
+ .to receive(:changelog_config)
+ .and_return("---\ndate_format: '%Y'")
+
+ expect(described_class)
+ .to receive(:from_hash)
+ .with(project, 'date_format' => '%Y')
+
+ described_class.from_git(project)
+ end
+
+ it 'returns the default configuration when no YAML file exists in Git' do
+ allow(project.repository)
+ .to receive(:changelog_config)
+ .and_return(nil)
+
+ expect(described_class)
+ .to receive(:new)
+ .with(project)
+
+ described_class.from_git(project)
+ end
+ end
+
+ describe '.from_hash' do
+ it 'sets the configuration according to a Hash' do
+ config = described_class.from_hash(
+ project,
+ 'date_format' => 'foo',
+ 'template' => 'bar',
+ 'categories' => { 'foo' => 'bar' }
+ )
+
+ expect(config.date_format).to eq('foo')
+ expect(config.template).to be_instance_of(Gitlab::Changelog::Template::Template)
+ expect(config.categories).to eq({ 'foo' => 'bar' })
+ end
+
+ it 'raises ConfigError when the categories are not a Hash' do
+ expect { described_class.from_hash(project, 'categories' => 10) }
+ .to raise_error(described_class::ConfigError)
+ end
+ end
+
+ describe '#contributor?' do
+ it 'returns true if a user is a contributor' do
+ user = build_stubbed(:author)
+
+ allow(project.team).to receive(:contributor?).with(user).and_return(true)
+
+ expect(described_class.new(project).contributor?(user)).to eq(true)
+ end
+
+ it "returns true if a user isn't a contributor" do
+ user = build_stubbed(:author)
+
+ allow(project.team).to receive(:contributor?).with(user).and_return(false)
+
+ expect(described_class.new(project).contributor?(user)).to eq(false)
+ end
+ end
+
+ describe '#category' do
+ it 'returns the name of a category' do
+ config = described_class.new(project)
+
+ config.categories['foo'] = 'Foo'
+
+ expect(config.category('foo')).to eq('Foo')
+ end
+
+ it 'returns the raw category name when no alternative name is configured' do
+ config = described_class.new(project)
+
+ expect(config.category('bla')).to eq('bla')
+ end
+ end
+
+ describe '#format_date' do
+ it 'formats a date according to the configured date format' do
+ config = described_class.new(project)
+ time = Time.utc(2021, 1, 5)
+
+ expect(config.format_date(time)).to eq('2021-01-05')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/generator_spec.rb b/spec/lib/gitlab/changelog/generator_spec.rb
new file mode 100644
index 00000000000..bc4a7c5dd6b
--- /dev/null
+++ b/spec/lib/gitlab/changelog/generator_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Generator do
+ describe '#add' do
+ let(:project) { build_stubbed(:project) }
+ let(:author) { build_stubbed(:user) }
+ let(:commit) { build_stubbed(:commit) }
+ let(:config) { Gitlab::Changelog::Config.new(project) }
+
+ it 'generates the Markdown for the first release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '1.0.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new('')
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ ## 1.0.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+ MARKDOWN
+ end
+
+ it 'generates the Markdown for a newer release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '2.0.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+ end
+
+ it 'generates the Markdown for a patch release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '1.1.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.1.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+ end
+
+ it 'generates the Markdown for an old release' do
+ release = Gitlab::Changelog::Release.new(
+ version: '0.5.0',
+ date: Time.utc(2021, 1, 5),
+ config: config
+ )
+
+ release.add_entry(
+ title: 'This is a new change',
+ commit: commit,
+ category: 'added',
+ author: author
+ )
+
+ gen = described_class.new(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+ MARKDOWN
+
+ expect(gen.add(release)).to eq(<<~MARKDOWN)
+ This is a changelog file.
+
+ ## 2.0.0
+
+ This is another release.
+
+ ## 1.0.0
+
+ This is the changelog for version 1.0.0.
+
+ ## 0.5.0 (2021-01-05)
+
+ ### added (1 change)
+
+ - [This is a new change](#{commit.to_reference(full: true)})
+ MARKDOWN
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/release_spec.rb b/spec/lib/gitlab/changelog/release_spec.rb
new file mode 100644
index 00000000000..50a23d23299
--- /dev/null
+++ b/spec/lib/gitlab/changelog/release_spec.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Release do
+ describe '#to_markdown' do
+ let(:config) { Gitlab::Changelog::Config.new(build_stubbed(:project)) }
+ let(:commit) { build_stubbed(:commit) }
+ let(:author) { build_stubbed(:user) }
+ let(:mr) { build_stubbed(:merge_request) }
+ let(:release) do
+ described_class
+ .new(version: '1.0.0', date: Time.utc(2021, 1, 5), config: config)
+ end
+
+ context 'when there are no entries' do
+ it 'includes a notice about the lack of entries' do
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ No changes.
+
+ OUT
+ end
+ end
+
+ context 'when all data is present' do
+ it 'includes all data' do
+ allow(config).to receive(:contributor?).with(author).and_return(true)
+
+ release.add_entry(
+ title: 'Entry title',
+ commit: commit,
+ category: 'fixed',
+ author: author,
+ merge_request: mr
+ )
+
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ ### fixed (1 change)
+
+ - [Entry title](#{commit.to_reference(full: true)}) \
+ by #{author.to_reference(full: true)} \
+ ([merge request](#{mr.to_reference(full: true)}))
+
+ OUT
+ end
+ end
+
+ context 'when no merge request is present' do
+ it "doesn't include a merge request link" do
+ allow(config).to receive(:contributor?).with(author).and_return(true)
+
+ release.add_entry(
+ title: 'Entry title',
+ commit: commit,
+ category: 'fixed',
+ author: author
+ )
+
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ ### fixed (1 change)
+
+ - [Entry title](#{commit.to_reference(full: true)}) \
+ by #{author.to_reference(full: true)}
+
+ OUT
+ end
+ end
+
+ context 'when the author is not a contributor' do
+ it "doesn't include the author" do
+ allow(config).to receive(:contributor?).with(author).and_return(false)
+
+ release.add_entry(
+ title: 'Entry title',
+ commit: commit,
+ category: 'fixed',
+ author: author
+ )
+
+ expect(release.to_markdown).to eq(<<~OUT)
+ ## 1.0.0 (2021-01-05)
+
+ ### fixed (1 change)
+
+ - [Entry title](#{commit.to_reference(full: true)})
+
+ OUT
+ end
+ end
+ end
+
+ describe '#header_start_position' do
+ it 'returns a regular expression for finding the start of a release section' do
+ config = Gitlab::Changelog::Config.new(build_stubbed(:project))
+ release = described_class
+ .new(version: '1.0.0', date: Time.utc(2021, 1, 5), config: config)
+
+ expect(release.header_start_pattern).to eq(/^##\s*1\.0\.0/)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/changelog/template/compiler_spec.rb b/spec/lib/gitlab/changelog/template/compiler_spec.rb
new file mode 100644
index 00000000000..d940fbaec89
--- /dev/null
+++ b/spec/lib/gitlab/changelog/template/compiler_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Changelog::Template::Compiler do
+ def compile(template, data = {})
+ Gitlab::Changelog::Template::Compiler.new.compile(template).render(data)
+ end
+
+ describe '#compile' do
+ it 'compiles an empty template' do
+ expect(compile('')).to eq('')
+ end
+
+ it 'compiles a template with an undefined variable' do
+ expect(compile('{{number}}')).to eq('')
+ end
+
+ it 'compiles a template with a defined variable' do
+ expect(compile('{{number}}', 'number' => 42)).to eq('42')
+ end
+
+ it 'compiles a template with the special "it" variable' do
+ expect(compile('{{it}}', 'values' => 10)).to eq({ 'values' => 10 }.to_s)
+ end
+
+ it 'compiles a template containing an if statement' do
+ expect(compile('{% if foo %}yes{% end %}', 'foo' => true)).to eq('yes')
+ end
+
+ it 'compiles a template containing an if/else statement' do
+ expect(compile('{% if foo %}yes{% else %}no{% end %}', 'foo' => false))
+ .to eq('no')
+ end
+
+ it 'compiles a template that iterates over an Array' do
+ expect(compile('{% each numbers %}{{it}}{% end %}', 'numbers' => [1, 2, 3]))
+ .to eq('123')
+ end
+
+ it 'compiles a template that iterates over a Hash' do
+ output = compile(
+ '{% each pairs %}{{0}}={{1}}{% end %}',
+ 'pairs' => { 'key' => 'value' }
+ )
+
+ expect(output).to eq('key=value')
+ end
+
+ it 'compiles a template that iterates over a Hash of Arrays' do
+ output = compile(
+ '{% each values %}{{key}}{% end %}',
+ 'values' => [{ 'key' => 'value' }]
+ )
+
+ expect(output).to eq('value')
+ end
+
+ it 'compiles a template with a variable path' do
+ output = compile('{{foo.bar}}', 'foo' => { 'bar' => 10 })
+
+ expect(output).to eq('10')
+ end
+
+ it 'compiles a template with a variable path that uses an Array index' do
+ output = compile('{{foo.values.1}}', 'foo' => { 'values' => [10, 20] })
+
+ expect(output).to eq('20')
+ end
+
+ it 'compiles a template with a variable path that uses a Hash and a numeric index' do
+ output = compile('{{foo.1}}', 'foo' => { 'key' => 'value' })
+
+ expect(output).to eq('')
+ end
+
+ it 'compiles a template with a variable path that uses an Array and a String based index' do
+ output = compile('{{foo.numbers.bla}}', 'foo' => { 'numbers' => [10, 20] })
+
+ expect(output).to eq('')
+ end
+
+ it 'ignores ERB tags provided by the user' do
+ input = '<% exit %> <%= exit %> <%= foo -%>'
+
+ expect(compile(input)).to eq(input)
+ end
+
+ it 'removes newlines introduced by end statements on their own lines' do
+ output = compile(<<~TPL, 'foo' => true)
+ {% if foo %}
+ foo
+ {% end %}
+ TPL
+
+ expect(output).to eq("foo\n")
+ end
+
+ it 'supports escaping of trailing newlines' do
+ output = compile(<<~TPL)
+ foo \
+ bar\
+ baz
+ TPL
+
+ expect(output).to eq("foo barbaz\n")
+ end
+
+ # rubocop: disable Lint/InterpolationCheck
+ it 'ignores embedded Ruby expressions' do
+ input = '#{exit}'
+
+ expect(compile(input)).to eq(input)
+ end
+ # rubocop: enable Lint/InterpolationCheck
+
+ it 'ignores ERB tags inside variable tags' do
+ input = '{{<%= exit %>}}'
+
+ expect(compile(input)).to eq(input)
+ end
+
+ it 'ignores malicious code that tries to escape a variable' do
+ input = "{{') ::Kernel.exit # '}}"
+
+ expect(compile(input)).to eq(input)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/suggestions/commit_message_spec.rb b/spec/lib/gitlab/suggestions/commit_message_spec.rb
index 1411f64f8b7..965960f0c3e 100644
--- a/spec/lib/gitlab/suggestions/commit_message_spec.rb
+++ b/spec/lib/gitlab/suggestions/commit_message_spec.rb
@@ -72,6 +72,17 @@ RSpec.describe Gitlab::Suggestions::CommitMessage do
end
end
+ context 'when a custom commit message is specified' do
+ let(:message) { "i'm a project message. a user's custom message takes precedence over me :(" }
+ let(:custom_message) { "hello there! i'm a cool custom commit message." }
+
+ it 'shows the custom commit message' do
+ expect(Gitlab::Suggestions::CommitMessage
+ .new(user, suggestion_set, custom_message)
+ .message).to eq(custom_message)
+ end
+ end
+
context 'is specified and includes all placeholders' do
let(:message) do
'*** %{branch_name} %{files_count} %{file_paths} %{project_name} %{project_path} %{user_full_name} %{username} %{suggestions_count} ***'
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index b436c2e1088..209ac471210 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Release do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository) }
- let_it_be(:release) { create(:release, project: project, author: user) }
+ let(:release) { create(:release, project: project, author: user) }
it { expect(release).to be_valid }
@@ -89,6 +89,61 @@ RSpec.describe Release do
end
end
+ describe '#update' do
+ subject { release.update(params) }
+
+ context 'when links do not exist' do
+ context 'when params are specified for creation' do
+ let(:params) do
+ { links_attributes: [{ name: 'test', url: 'https://www.google.com/' }] }
+ end
+
+ it 'creates a link successfuly' do
+ is_expected.to eq(true)
+
+ expect(release.links.count).to eq(1)
+ expect(release.links.first.name).to eq('test')
+ expect(release.links.first.url).to eq('https://www.google.com/')
+ end
+ end
+ end
+
+ context 'when a link exists' do
+ let!(:link1) { create(:release_link, release: release, name: 'test1', url: 'https://www.google1.com/') }
+ let!(:link2) { create(:release_link, release: release, name: 'test2', url: 'https://www.google2.com/') }
+
+ before do
+ release.reload
+ end
+
+ context 'when params are specified for update' do
+ let(:params) do
+ { links_attributes: [{ id: link1.id, name: 'new' }] }
+ end
+
+ it 'updates the link successfully' do
+ is_expected.to eq(true)
+
+ expect(release.links.count).to eq(2)
+ expect(release.links.first.name).to eq('new')
+ end
+ end
+
+ context 'when params are specified for deletion' do
+ let(:params) do
+ { links_attributes: [{ id: link1.id, _destroy: true }] }
+ end
+
+ it 'removes the link successfuly' do
+ is_expected.to eq(true)
+
+ expect(release.links.count).to eq(1)
+ expect(release.links.first.name).to eq(link2.name)
+ end
+ end
+ end
+ end
+
describe '#sources' do
subject { release.sources }
diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb
index 79bdcec7944..a4918cd560c 100644
--- a/spec/requests/api/graphql/mutations/releases/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb
@@ -309,10 +309,7 @@ RSpec.describe 'Creation of a new release' do
let(:asset_link_2) { { name: 'My link', url: 'https://example.com/2' } }
let(:assets) { { links: [asset_link_1, asset_link_2] } }
- # Right now the raw Postgres error message is sent to the user as the validation message.
- # We should catch this validation error and return a nicer message:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/277087
- it_behaves_like 'errors-as-data with message', 'PG::UniqueViolation'
+ it_behaves_like 'errors-as-data with message', %r{Validation failed: Links have duplicate values \(My link\)}
end
context 'when two release assets share the same URL' do
@@ -320,8 +317,7 @@ RSpec.describe 'Creation of a new release' do
let(:asset_link_2) { { name: 'My second link', url: 'https://example.com' } }
let(:assets) { { links: [asset_link_1, asset_link_2] } }
- # Same note as above about the ugly error message
- it_behaves_like 'errors-as-data with message', 'PG::UniqueViolation'
+ it_behaves_like 'errors-as-data with message', %r{Validation failed: Links have duplicate values \(https://example.com\)}
end
context 'when the provided tag name is HEAD' do
diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb
index ccc2825da25..963b594a202 100644
--- a/spec/requests/api/graphql/project/release_spec.rb
+++ b/spec/requests/api/graphql/project/release_spec.rb
@@ -283,7 +283,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be(:project) { create(:project, :repository, :private) }
let_it_be(:milestone_1) { create(:milestone, project: project) }
let_it_be(:milestone_2) { create(:milestone, project: project) }
- let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
+ let_it_be(:release, reload: true) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
let_it_be(:release_link_1) { create(:release_link, release: release) }
let_it_be(:release_link_2) { create(:release_link, release: release, filepath: link_filepath) }
@@ -324,7 +324,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:milestone_1) { create(:milestone, project: project) }
let_it_be(:milestone_2) { create(:milestone, project: project) }
- let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
+ let_it_be(:release, reload: true) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
let_it_be(:release_link_1) { create(:release_link, release: release) }
let_it_be(:release_link_2) { create(:release_link, release: release, filepath: link_filepath) }
diff --git a/spec/requests/api/suggestions_spec.rb b/spec/requests/api/suggestions_spec.rb
index 78a2688ac5e..7f53d379af5 100644
--- a/spec/requests/api/suggestions_spec.rb
+++ b/spec/requests/api/suggestions_spec.rb
@@ -65,6 +65,19 @@ RSpec.describe API::Suggestions do
end
end
+ context 'when a custom commit message is included' do
+ it 'renders an ok response and returns json content' do
+ project.add_maintainer(user)
+
+ message = "cool custom commit message!"
+
+ put api(url, user), params: { commit_message: message }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(project.repository.commit.message).to eq(message)
+ end
+ end
+
context 'when not able to apply patch' do
let(:url) { "/suggestions/#{unappliable_suggestion.id}/apply" }
@@ -113,9 +126,11 @@ RSpec.describe API::Suggestions do
let(:url) { "/suggestions/batch_apply" }
context 'when successfully applies multiple patches as a batch' do
- it 'renders an ok response and returns json content' do
+ before do
project.add_maintainer(user)
+ end
+ it 'renders an ok response and returns json content' do
put api(url, user), params: { ids: [suggestion.id, suggestion2.id] }
expect(response).to have_gitlab_http_status(:ok)
@@ -123,6 +138,16 @@ RSpec.describe API::Suggestions do
'appliable', 'applied',
'from_content', 'to_content'))
end
+
+ it 'provides a custom commit message' do
+ message = "cool custom commit message!"
+
+ put api(url, user), params: { ids: [suggestion.id, suggestion2.id],
+ commit_message: message }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(project.repository.commit.message).to eq(message)
+ end
end
context 'when not able to apply one or more of the patches' do
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index e31dd7031eb..77d0e892725 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -32,8 +32,8 @@ RSpec.describe Suggestions::ApplyService do
create(:suggestion, :content_from_repo, suggestion_args)
end
- def apply(suggestions)
- result = apply_service.new(user, *suggestions).execute
+ def apply(suggestions, custom_message = nil)
+ result = apply_service.new(user, *suggestions, message: custom_message).execute
suggestions.map { |suggestion| suggestion.reload }
@@ -111,6 +111,16 @@ RSpec.describe Suggestions::ApplyService do
end
end
end
+
+ context 'with a user suggested commit message' do
+ let(:message) { "i'm a custom commit message!" }
+
+ it "uses the user's commit message" do
+ apply(suggestions, message)
+
+ expect(project.repository.commit.message).to(eq(message))
+ end
+ end
end
subject(:apply_service) { described_class }
diff --git a/spec/support/helpers/snowplow_helpers.rb b/spec/support/helpers/snowplow_helpers.rb
index 70a4eadd8de..a6de8dabdac 100644
--- a/spec/support/helpers/snowplow_helpers.rb
+++ b/spec/support/helpers/snowplow_helpers.rb
@@ -46,7 +46,7 @@ module SnowplowHelpers
# }
# ]
# )
- def expect_snowplow_event(category:, action:, context: nil, **kwargs)
+ def expect_snowplow_event(category:, action:, context: nil, standard_context: nil, **kwargs)
if context
kwargs[:context] = []
context.each do |c|
@@ -56,6 +56,14 @@ module SnowplowHelpers
end
end
+ if standard_context
+ expect(Gitlab::Tracking::StandardContext)
+ .to have_received(:new)
+ .with(**standard_context)
+
+ kwargs[:standard_context] = an_instance_of(Gitlab::Tracking::StandardContext)
+ end
+
expect(Gitlab::Tracking).to have_received(:event) # rubocop:disable RSpec/ExpectGitlabTracking
.with(category, action, **kwargs).at_least(:once)
end
diff --git a/spec/support/snowplow.rb b/spec/support/snowplow.rb
index 0d6102f1705..91325d867d4 100644
--- a/spec/support/snowplow.rb
+++ b/spec/support/snowplow.rb
@@ -18,6 +18,7 @@ RSpec.configure do |config|
stub_application_setting(snowplow_enabled: true)
allow(SnowplowTracker::SelfDescribingJson).to receive(:new).and_call_original
+ allow(Gitlab::Tracking::StandardContext).to receive(:new).and_call_original
allow(Gitlab::Tracking).to receive(:event).and_call_original # rubocop:disable RSpec/ExpectGitlabTracking
end
diff --git a/spec/validators/variable_duplicates_validator_spec.rb b/spec/validators/nested_attributes_duplicates_validator_spec.rb
index acc47ff225f..f59e422e5d4 100644
--- a/spec/validators/variable_duplicates_validator_spec.rb
+++ b/spec/validators/nested_attributes_duplicates_validator_spec.rb
@@ -2,13 +2,16 @@
require 'spec_helper'
-RSpec.describe VariableDuplicatesValidator do
- let(:validator) { described_class.new(attributes: [:variables], **options) }
+RSpec.describe NestedAttributesDuplicatesValidator do
+ let(:validator) { described_class.new(attributes: [attribute], **options) }
describe '#validate_each' do
let(:project) { build(:project) }
+ let(:record) { project }
+ let(:attribute) { :variables }
+ let(:value) { project.variables }
- subject { validator.validate_each(project, :variables, project.variables) }
+ subject { validator.validate_each(record, attribute, value) }
context 'with no scope' do
let(:options) { {} }
@@ -65,5 +68,46 @@ RSpec.describe VariableDuplicatesValidator do
end
end
end
+
+ context 'with a child attribute' do
+ let(:release) { build(:release) }
+ let(:first_link) { build(:release_link, name: 'test1', url: 'https://www.google1.com', release: release) }
+ let(:second_link) { build(:release_link, name: 'test2', url: 'https://www.google2.com', release: release) }
+ let(:record) { release }
+ let(:attribute) { :links }
+ let(:value) { release.links }
+ let(:options) { { scope: :release, child_attributes: %i[name url] } }
+
+ before do
+ release.links << first_link
+ release.links << second_link
+ end
+
+ it 'does not have any errors' do
+ subject
+
+ expect(release.errors.empty?).to be true
+ end
+
+ context 'when name is duplicated' do
+ let(:second_link) { build(:release_link, name: 'test1', release: release) }
+
+ it 'has a duplicate error' do
+ subject
+
+ expect(release.errors).to have_key(attribute)
+ end
+ end
+
+ context 'when url is duplicated' do
+ let(:second_link) { build(:release_link, url: 'https://www.google1.com', release: release) }
+
+ it 'has a duplicate error' do
+ subject
+
+ expect(release.errors).to have_key(attribute)
+ end
+ end
+ end
end
end