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>2023-06-20 21:08:32 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-20 21:08:32 +0300
commit995bcca3fc5544e5d2d8ee274dc9275d5b4ce375 (patch)
tree370881ef6e9de8f93ce5546b725b2f91b4072a5f /spec
parenta5d7e614fe1d038a7f9e2af76106773b98e2b5e8 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js94
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb40
-rw-r--r--spec/lib/gitlab/ci/config/external/file/component_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/yaml/interpolator_spec.rb144
-rw-r--r--spec/lib/gitlab/ci/config/yaml/loader_spec.rb165
-rw-r--r--spec/lib/gitlab/ci/config/yaml_spec.rb172
-rw-r--r--spec/models/plan_limits_spec.rb28
-rw-r--r--spec/models/project_spec.rb7
-rw-r--r--spec/rubocop/cop_todo_spec.rb15
-rw-r--r--spec/rubocop/formatter/todo_formatter_spec.rb37
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb4
12 files changed, 195 insertions, 515 deletions
diff --git a/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js b/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js
index cda3876f9b2..ad20d7682ed 100644
--- a/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js
+++ b/spec/frontend/ci/runner/components/cells/runner_summary_cell_spec.js
@@ -1,5 +1,6 @@
+import { GlSprintf } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import RunnerSummaryCell from '~/ci/runner/components/cells/runner_summary_cell.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -31,8 +32,8 @@ describe('RunnerTypeCell', () => {
wrapper.findAllComponents(RunnerSummaryField).filter((w) => w.props('icon') === icon)
.wrappers[0];
- const createComponent = (runner, options) => {
- wrapper = mountExtended(RunnerSummaryCell, {
+ const createComponent = ({ runner, mountFn = shallowMountExtended, ...options } = {}) => {
+ wrapper = mountFn(RunnerSummaryCell, {
propsData: {
runner: {
...mockRunner,
@@ -40,7 +41,7 @@ describe('RunnerTypeCell', () => {
},
},
stubs: {
- RunnerSummaryField,
+ GlSprintf,
},
...options,
});
@@ -51,6 +52,8 @@ describe('RunnerTypeCell', () => {
});
it('Displays the runner name as id and short token', () => {
+ createComponent({ mountFn: mountExtended });
+
expect(wrapper.text()).toContain(
`#${getIdFromGraphQLId(mockRunner.id)} (${mockRunner.shortSha})`,
);
@@ -58,13 +61,16 @@ describe('RunnerTypeCell', () => {
it('Displays no runner manager count', () => {
createComponent({
- managers: { count: 0 },
+ runner: { managers: { nodes: { count: 0 } } },
+ mountFn: mountExtended,
});
expect(findRunnerManagersBadge().html()).toBe('');
});
it('Displays runner manager count', () => {
+ createComponent({ mountFn: mountExtended });
+
expect(findRunnerManagersBadge().text()).toBe('2');
});
@@ -74,8 +80,8 @@ describe('RunnerTypeCell', () => {
it('Displays the locked icon for locked runners', () => {
createComponent({
- runnerType: PROJECT_TYPE,
- locked: true,
+ runner: { runnerType: PROJECT_TYPE, locked: true },
+ mountFn: mountExtended,
});
expect(findLockIcon().exists()).toBe(true);
@@ -83,8 +89,8 @@ describe('RunnerTypeCell', () => {
it('Displays the runner type', () => {
createComponent({
- runnerType: INSTANCE_TYPE,
- locked: true,
+ runner: { runnerType: INSTANCE_TYPE, locked: true },
+ mountFn: mountExtended,
});
expect(wrapper.text()).toContain(I18N_INSTANCE_TYPE);
@@ -101,7 +107,7 @@ describe('RunnerTypeCell', () => {
it('Displays "No description" for missing runner description', () => {
createComponent({
- description: null,
+ runner: { description: null },
});
expect(wrapper.findByText(I18N_NO_DESCRIPTION).classes()).toContain('gl-text-secondary');
@@ -109,7 +115,7 @@ describe('RunnerTypeCell', () => {
it('Displays last contact', () => {
createComponent({
- contactedAt: '2022-01-02',
+ runner: { contactedAt: '2022-01-02' },
});
expect(findRunnerSummaryField('clock').findComponent(TimeAgo).props('time')).toBe('2022-01-02');
@@ -124,20 +130,46 @@ describe('RunnerTypeCell', () => {
expect(findRunnerSummaryField('clock').text()).toContain(__('Never'));
});
- it('Displays ip address', () => {
- createComponent({
- ipAddress: '127.0.0.1',
+ describe('IP address', () => {
+ it('with no managers', () => {
+ createComponent({
+ runner: {
+ managers: { count: 0, nodes: [] },
+ },
+ });
+
+ expect(findRunnerSummaryField('disk')).toBeUndefined();
});
- expect(findRunnerSummaryField('disk').text()).toContain('127.0.0.1');
- });
+ it('with no ip', () => {
+ createComponent({
+ runner: {
+ managers: { count: 1, nodes: [{ ipAddress: null }] },
+ },
+ });
- it('Displays no ip address', () => {
- createComponent({
- ipAddress: null,
+ expect(findRunnerSummaryField('disk')).toBeUndefined();
});
- expect(findRunnerSummaryField('disk')).toBeUndefined();
+ it.each`
+ count | ipAddress | expected
+ ${1} | ${'127.0.0.1'} | ${'127.0.0.1'}
+ ${2} | ${'127.0.0.2'} | ${'127.0.0.2 (+1)'}
+ ${11} | ${'127.0.0.3'} | ${'127.0.0.3 (+10)'}
+ ${1001} | ${'127.0.0.4'} | ${'127.0.0.4 (+1,000)'}
+ `(
+ 'with $count managers, ip $ipAddress displays $expected',
+ ({ count, ipAddress, expected }) => {
+ createComponent({
+ runner: {
+ // `first: 1` is requested, `count` varies when there are more managers
+ managers: { count, nodes: [{ ipAddress }] },
+ },
+ });
+
+ expect(findRunnerSummaryField('disk').text()).toMatchInterpolatedText(expected);
+ },
+ );
});
it('Displays job count', () => {
@@ -146,7 +178,7 @@ describe('RunnerTypeCell', () => {
it('Formats large job counts', () => {
createComponent({
- jobCount: 1000,
+ runner: { jobCount: 1000 },
});
expect(findRunnerSummaryField('pipeline').text()).toContain('1,000');
@@ -154,7 +186,7 @@ describe('RunnerTypeCell', () => {
it('Formats large job counts with a plus symbol', () => {
createComponent({
- jobCount: 1001,
+ runner: { jobCount: 1001 },
});
expect(findRunnerSummaryField('pipeline').text()).toContain('1,000+');
@@ -165,7 +197,7 @@ describe('RunnerTypeCell', () => {
it('Displays created at ...', () => {
createComponent({
- createdBy: null,
+ runner: { createdBy: null },
});
expect(findRunnerSummaryField('calendar').text()).toMatchInterpolatedText(
@@ -177,12 +209,15 @@ describe('RunnerTypeCell', () => {
});
it('Displays created at ... by ...', () => {
+ createComponent({ mountFn: mountExtended });
+
expect(findRunnerSummaryField('calendar').text()).toMatchInterpolatedText(
sprintf(I18N_CREATED_AT_BY_LABEL, {
timeAgo: findCreatedTime().text(),
avatar: mockRunner.createdBy.username,
}),
);
+
expect(findCreatedTime().props('time')).toBe(mockRunner.createdAt);
});
@@ -200,7 +235,7 @@ describe('RunnerTypeCell', () => {
it('Displays tag list', () => {
createComponent({
- tagList: ['shell', 'linux'],
+ runner: { tagList: ['shell', 'linux'] },
});
expect(findRunnerTags().props('tagList')).toEqual(['shell', 'linux']);
@@ -209,14 +244,11 @@ describe('RunnerTypeCell', () => {
it('Displays a custom runner-name slot', () => {
const slotContent = 'My custom runner name';
- createComponent(
- {},
- {
- slots: {
- 'runner-name': slotContent,
- },
+ createComponent({
+ slots: {
+ 'runner-name': slotContent,
},
- );
+ });
expect(wrapper.text()).toContain(slotContent);
});
diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
index 1c5918f77ca..d6dd75f4b10 100644
--- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -106,7 +106,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base, feature_category: :pipe
it 'is not a valid file' do
expect(valid?).to be_falsy
expect(file.error_message)
- .to eq('`some/file/xxxxxxxxxxxxxxxx.yml`: content does not have a valid YAML syntax')
+ .to eq('`some/file/xxxxxxxxxxxxxxxx.yml`: Invalid configuration format')
end
end
@@ -128,31 +128,6 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base, feature_category: :pipe
end
end
- context 'when interpolation is disabled but there is a spec header' do
- before do
- stub_feature_flags(ci_includable_files_interpolation: false)
- end
-
- let(:location) { 'some-location.yml' }
-
- let(:content) do
- <<~YAML
- spec:
- include:
- website:
- ---
- run:
- script: deploy $[[ inputs.website ]]
- YAML
- end
-
- it 'returns an error saying that interpolation is disabled' do
- expect(valid?).to be_falsy
- expect(file.errors)
- .to include('`some-location.yml`: can not evaluate included file because interpolation is disabled')
- end
- end
-
context 'when interpolation was unsuccessful' do
let(:location) { 'some-location.yml' }
@@ -275,4 +250,17 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base, feature_category: :pipe
it { is_expected.to eq([{ location: location, content: content }, nil, 'HEAD'].hash) }
end
end
+
+ describe '#load_and_validate_expanded_hash!' do
+ let(:location) { 'some/file/config.yml' }
+ let(:logger) { instance_double(::Gitlab::Ci::Pipeline::Logger, :instrument) }
+ let(:context_params) { { sha: 'HEAD', variables: variables, project: project, logger: logger } }
+
+ it 'includes instrumentation for loading and expanding the content' do
+ expect(logger).to receive(:instrument).once.ordered.with(:config_file_fetch_content_hash).and_yield
+ expect(logger).to receive(:instrument).once.ordered.with(:config_file_expand_content_includes).and_yield
+
+ file.load_and_validate_expanded_hash!
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/config/external/file/component_spec.rb b/spec/lib/gitlab/ci/config/external/file/component_spec.rb
index fe811bce9fe..7e3406413d0 100644
--- a/spec/lib/gitlab/ci/config/external/file/component_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/component_spec.rb
@@ -121,7 +121,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Component, feature_category:
it 'is invalid' do
expect(subject).to be_falsy
- expect(external_resource.error_message).to match(/does not have a valid YAML syntax/)
+ expect(external_resource.error_message).to match(/Invalid configuration format/)
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 74afb3b1e97..935b6989dd7 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -221,7 +221,7 @@ RSpec.describe Gitlab::Ci::Config::External::Processor, feature_category: :pipel
it 'raises an error' do
expect { processor.perform }.to raise_error(
described_class::IncludeError,
- '`lib/gitlab/ci/templates/template.yml`: content does not have a valid YAML syntax'
+ '`lib/gitlab/ci/templates/template.yml`: Invalid configuration format'
)
end
end
diff --git a/spec/lib/gitlab/ci/config/yaml/interpolator_spec.rb b/spec/lib/gitlab/ci/config/yaml/interpolator_spec.rb
index 726ed6d95a0..888756a3eb1 100644
--- a/spec/lib/gitlab/ci/config/yaml/interpolator_spec.rb
+++ b/spec/lib/gitlab/ci/config/yaml/interpolator_spec.rb
@@ -5,10 +5,10 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Yaml::Interpolator, feature_category: :pipeline_composition do
let_it_be(:project) { create(:project) }
- let(:ctx) { instance_double(Gitlab::Ci::Config::External::Context, project: project, user: build(:user, id: 1234)) }
+ let(:current_user) { build(:user, id: 1234) }
let(:result) { ::Gitlab::Ci::Config::Yaml::Result.new(config: [header, content]) }
- subject { described_class.new(result, arguments, ctx) }
+ subject { described_class.new(result, arguments, current_user: current_user) }
context 'when input data is valid' do
let(:header) do
@@ -39,7 +39,7 @@ RSpec.describe Gitlab::Ci::Config::Yaml::Interpolator, feature_category: :pipeli
end
context 'when config has a syntax error' do
- let(:result) { ::Gitlab::Ci::Config::Yaml::Result.new(error: ArgumentError.new) }
+ let(:result) { ::Gitlab::Ci::Config::Yaml::Result.new(error: 'Invalid configuration format') }
let(:arguments) do
{ website: 'gitlab.com' }
@@ -50,7 +50,7 @@ RSpec.describe Gitlab::Ci::Config::Yaml::Interpolator, feature_category: :pipeli
expect(subject).not_to be_valid
expect(subject.error_message).to eq subject.errors.first
- expect(subject.errors).to include 'content does not have a valid YAML syntax'
+ expect(subject.errors).to include 'Invalid configuration format'
end
end
@@ -142,28 +142,6 @@ RSpec.describe Gitlab::Ci::Config::Yaml::Interpolator, feature_category: :pipeli
end
describe '#to_hash' do
- context 'when interpolation is disabled' do
- before do
- stub_feature_flags(ci_includable_files_interpolation: false)
- end
-
- let(:header) do
- { spec: { inputs: { website: nil } } }
- end
-
- let(:content) do
- { test: 'deploy $[[ inputs.website ]]' }
- end
-
- let(:arguments) { {} }
-
- it 'returns an empty hash' do
- subject.interpolate!
-
- expect(subject.to_hash).to be_empty
- end
- end
-
context 'when interpolation is not used' do
let(:result) do
::Gitlab::Ci::Config::Yaml::Result.new(config: content)
@@ -202,118 +180,4 @@ RSpec.describe Gitlab::Ci::Config::Yaml::Interpolator, feature_category: :pipeli
end
end
end
-
- describe '#ready?' do
- let(:header) do
- { spec: { inputs: { website: nil } } }
- end
-
- let(:content) do
- { test: 'deploy $[[ inputs.website ]]' }
- end
-
- let(:arguments) do
- { website: 'gitlab.com' }
- end
-
- it 'returns false if interpolation has not been done yet' do
- expect(subject).not_to be_ready
- end
-
- it 'returns true if interpolation has been performed' do
- subject.interpolate!
-
- expect(subject).to be_ready
- end
-
- context 'when interpolation can not be performed' do
- let(:result) do
- ::Gitlab::Ci::Config::Yaml::Result.new(error: ArgumentError.new)
- end
-
- it 'returns true if interpolator has preliminary errors' do
- expect(subject).to be_ready
- end
-
- it 'returns true if interpolation has been attempted' do
- subject.interpolate!
-
- expect(subject).to be_ready
- end
- end
- end
-
- describe '#interpolate?' do
- let(:header) do
- { spec: { inputs: { website: nil } } }
- end
-
- let(:content) do
- { test: 'deploy $[[ inputs.something.abc ]] $[[ inputs.cde ]] $[[ efg ]]' }
- end
-
- let(:arguments) do
- { website: 'gitlab.com' }
- end
-
- context 'when interpolation can be performed' do
- it 'will perform interpolation' do
- expect(subject.interpolate?).to eq true
- end
- end
-
- context 'when interpolation is disabled' do
- before do
- stub_feature_flags(ci_includable_files_interpolation: false)
- end
-
- it 'will not perform interpolation' do
- expect(subject.interpolate?).to eq false
- end
- end
-
- context 'when an interpolation header is missing' do
- let(:header) { nil }
-
- it 'will not perform interpolation' do
- expect(subject.interpolate?).to eq false
- end
- end
-
- context 'when interpolator has preliminary errors' do
- let(:result) do
- ::Gitlab::Ci::Config::Yaml::Result.new(error: ArgumentError.new)
- end
-
- it 'will not perform interpolation' do
- expect(subject.interpolate?).to eq false
- end
- end
- end
-
- describe '#has_header?' do
- let(:content) do
- { test: 'deploy $[[ inputs.something.abc ]] $[[ inputs.cde ]] $[[ efg ]]' }
- end
-
- let(:arguments) do
- { website: 'gitlab.com' }
- end
-
- context 'when header is an empty hash' do
- let(:header) { {} }
-
- it 'does not have a header available' do
- expect(subject).not_to have_header
- end
- end
-
- context 'when header is not specified' do
- let(:header) { nil }
-
- it 'does not have a header available' do
- expect(subject).not_to have_header
- end
- end
- end
end
diff --git a/spec/lib/gitlab/ci/config/yaml/loader_spec.rb b/spec/lib/gitlab/ci/config/yaml/loader_spec.rb
index 1e417bcd8af..4e6151677e6 100644
--- a/spec/lib/gitlab/ci/config/yaml/loader_spec.rb
+++ b/spec/lib/gitlab/ci/config/yaml/loader_spec.rb
@@ -2,151 +2,58 @@
require 'spec_helper'
-RSpec.describe Gitlab::Ci::Config::Yaml::Loader, feature_category: :pipeline_composition do
- describe '#to_result' do
+RSpec.describe ::Gitlab::Ci::Config::Yaml::Loader, feature_category: :pipeline_composition do
+ describe '#load' do
let_it_be(:project) { create(:project) }
- subject(:result) { described_class.new(yaml, project: project).to_result }
-
- context 'when syntax is invalid' do
- let(:yaml) { 'some: invalid: syntax' }
-
- it 'returns an invalid result object' do
- expect(result).not_to be_valid
- expect(result.error).to be_a ::Gitlab::Config::Loader::FormatError
- end
+ let(:inputs) { { test_input: 'hello test' } }
+
+ let(:yaml) do
+ <<~YAML
+ ---
+ spec:
+ inputs:
+ test_input:
+ ---
+ test_job:
+ script:
+ - echo "$[[ inputs.test_input ]]"
+ YAML
end
- context 'when the first document is a header' do
- context 'with explicit document start marker' do
- let(:yaml) do
- <<~YAML
- ---
- spec:
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as header and the second as content' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result.header).to eq({ spec: nil })
- expect(result.content).to eq({ b: 2 })
- end
- end
- end
+ subject(:result) { described_class.new(yaml, inputs: inputs, current_user: project.creator).load }
- context 'when first document is empty' do
- let(:yaml) do
- <<~YAML
- ---
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as header and the second as content' do
- expect(result).not_to have_header
- end
- end
-
- context 'when first document is an empty hash' do
- let(:yaml) do
- <<~YAML
- {}
- ---
- b: 2
- YAML
- end
+ it 'loads and interpolates CI config YAML' do
+ expected_config = { test_job: { script: ['echo "hello test"'] } }
- it 'returns second document as a content' do
- expect(result).not_to have_header
- expect(result.content).to eq({ b: 2 })
- end
+ expect(result).to be_valid
+ expect(result.content).to eq(expected_config)
end
- context 'when first an array' do
- let(:yaml) do
- <<~YAML
- ---
- - a
- - b
- ---
- b: 2
- YAML
- end
+ it 'allows the use of YAML reference tags' do
+ expect(Psych).to receive(:add_tag).once.with(
+ ::Gitlab::Ci::Config::Yaml::Tags::Reference.tag,
+ ::Gitlab::Ci::Config::Yaml::Tags::Reference
+ )
- it 'considers the first document as header and the second as content' do
- expect(result).not_to have_header
- end
+ result
end
- context 'when the first document is not a header' do
- let(:yaml) do
- <<~YAML
- a: 1
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as content for backwards compatibility' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
-
- context 'with explicit document start marker' do
- let(:yaml) do
- <<~YAML
- ---
- a: 1
- ---
- b: 2
- YAML
- end
+ context 'when there is an error loading the YAML' do
+ let(:yaml) { 'invalid...yaml' }
- it 'considers the first document as content for backwards compatibility' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
+ it 'returns an error result' do
+ expect(result).not_to be_valid
+ expect(result.error).to eq('Invalid configuration format')
end
end
- context 'when the first document is not a header and second document is empty' do
- let(:yaml) do
- <<~YAML
- a: 1
- ---
- YAML
- end
-
- it 'considers the first document as content' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
-
- context 'with explicit document start marker' do
- let(:yaml) do
- <<~YAML
- ---
- a: 1
- ---
- YAML
- end
+ context 'when there is an error interpolating the YAML' do
+ let(:inputs) { {} }
- it 'considers the first document as content' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
+ it 'returns an error result' do
+ expect(result).not_to be_valid
+ expect(result.error).to eq('`test_input` input: required value has not been provided')
end
end
end
diff --git a/spec/lib/gitlab/ci/config/yaml_spec.rb b/spec/lib/gitlab/ci/config/yaml_spec.rb
index 3576dd481c6..27d93d555f1 100644
--- a/spec/lib/gitlab/ci/config/yaml_spec.rb
+++ b/spec/lib/gitlab/ci/config/yaml_spec.rb
@@ -3,18 +3,20 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Yaml, feature_category: :pipeline_composition do
- describe '.load!' do
- it 'loads a YAML file' do
- yaml = <<~YAML
- image: 'image:1.0'
- texts:
- nested_key: 'value1'
- more_text:
- more_nested_key: 'value2'
- YAML
+ let(:yaml) do
+ <<~YAML
+ image: 'image:1.0'
+ texts:
+ nested_key: 'value1'
+ more_text:
+ more_nested_key: 'value2'
+ YAML
+ end
- config = described_class.load!(yaml)
+ describe '.load!' do
+ subject(:config) { described_class.load!(yaml) }
+ it 'loads a YAML file' do
expect(config).to eq({
image: 'image:1.0',
texts: {
@@ -30,156 +32,20 @@ RSpec.describe Gitlab::Ci::Config::Yaml, feature_category: :pipeline_composition
let(:yaml) { 'some: invalid: syntax' }
it 'raises an error' do
- expect { described_class.load!(yaml) }
+ expect { config }
.to raise_error ::Gitlab::Config::Loader::FormatError, /mapping values are not allowed in this context/
end
end
- end
-
- describe '.load_result!' do
- let_it_be(:project) { create(:project) }
-
- subject(:result) { described_class.load_result!(yaml, project: project) }
-
- context 'when syntax is invalid' do
- let(:yaml) { 'some: invalid: syntax' }
-
- it 'returns an invalid result object' do
- expect(result).not_to be_valid
- expect(result.error).to be_a ::Gitlab::Config::Loader::FormatError
- end
- end
-
- context 'when the first document is a header' do
- context 'with explicit document start marker' do
- let(:yaml) do
- <<~YAML
- ---
- spec:
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as header and the second as content' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result.header).to eq({ spec: nil })
- expect(result.content).to eq({ b: 2 })
- end
- end
- end
-
- context 'when first document is empty' do
- let(:yaml) do
- <<~YAML
- ---
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as header and the second as content' do
- expect(result).not_to have_header
- end
- end
-
- context 'when first document is an empty hash' do
- let(:yaml) do
- <<~YAML
- {}
- ---
- b: 2
- YAML
- end
- it 'returns second document as a content' do
- expect(result).not_to have_header
- expect(result.content).to eq({ b: 2 })
- end
- end
+ context 'when given a user' do
+ let(:user) { instance_double(User) }
- context 'when first an array' do
- let(:yaml) do
- <<~YAML
- ---
- - a
- - b
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as header and the second as content' do
- expect(result).not_to have_header
- end
- end
-
- context 'when the first document is not a header' do
- let(:yaml) do
- <<~YAML
- a: 1
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as content for backwards compatibility' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
-
- context 'with explicit document start marker' do
- let(:yaml) do
- <<~YAML
- ---
- a: 1
- ---
- b: 2
- YAML
- end
-
- it 'considers the first document as content for backwards compatibility' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
- end
- end
-
- context 'when the first document is not a header and second document is empty' do
- let(:yaml) do
- <<~YAML
- a: 1
- ---
- YAML
- end
-
- it 'considers the first document as content' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
+ subject(:config) { described_class.load!(yaml, current_user: user) }
- context 'with explicit document start marker' do
- let(:yaml) do
- <<~YAML
- ---
- a: 1
- ---
- YAML
- end
+ it 'passes it to Loader' do
+ expect(::Gitlab::Ci::Config::Yaml::Loader).to receive(:new).with(yaml, current_user: user).and_call_original
- it 'considers the first document as content' do
- expect(result).to be_valid
- expect(result.error).to be_nil
- expect(result).not_to have_header
- expect(result.content).to eq({ a: 1 })
- end
+ config
end
end
end
diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb
index d211499e9e9..265f781d61d 100644
--- a/spec/models/plan_limits_spec.rb
+++ b/spec/models/plan_limits_spec.rb
@@ -364,32 +364,4 @@ RSpec.describe PlanLimits do
end
end
end
-
- describe '#limit_attribute_changes', :freeze_time do
- let(:user) { create(:user) }
- let(:current_timestamp) { Time.current.utc.to_i }
- let(:plan_limits) do
- create(:plan_limits,
- limits_history: { 'enforcement_limit' => [
- { user_id: user.id, username: user.username, timestamp: current_timestamp,
- value: 20_000 }, { user_id: user.id, username: user.username, timestamp: current_timestamp,
- value: 50_000 }
- ] })
- end
-
- it 'returns an empty array for attribute with no changes' do
- changes = plan_limits.limit_attribute_changes(:notification_limit)
-
- expect(changes).to eq([])
- end
-
- it 'returns the changes for a specific attribute' do
- changes = plan_limits.limit_attribute_changes(:enforcement_limit)
-
- expect(changes).to eq(
- [{ timestamp: current_timestamp, value: 20_000, username: user.username, user_id: user.id },
- { timestamp: current_timestamp, value: 50_000, username: user.username, user_id: user.id }]
- )
- end
- end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index f44331521e9..b5c47d9fc40 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -6576,7 +6576,8 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
it 'does not allow access to branches for which the merge request was closed' do
create(
- :merge_request, :closed,
+ :merge_request,
+ :closed,
target_project: target_project,
target_branch: 'target-branch',
source_project: project,
@@ -9081,7 +9082,9 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
def create_build(new_pipeline = pipeline, name = 'test')
create(
- :ci_build, :success, :artifacts,
+ :ci_build,
+ :success,
+ :artifacts,
pipeline: new_pipeline,
status: new_pipeline.status,
name: name
diff --git a/spec/rubocop/cop_todo_spec.rb b/spec/rubocop/cop_todo_spec.rb
index c641001789f..49206d76d5a 100644
--- a/spec/rubocop/cop_todo_spec.rb
+++ b/spec/rubocop/cop_todo_spec.rb
@@ -3,7 +3,7 @@
require 'rubocop_spec_helper'
require_relative '../../rubocop/cop_todo'
-RSpec.describe RuboCop::CopTodo do
+RSpec.describe RuboCop::CopTodo, feature_category: :tooling do
let(:cop_name) { 'Cop/Rule' }
subject(:cop_todo) { described_class.new(cop_name) }
@@ -32,6 +32,19 @@ RSpec.describe RuboCop::CopTodo do
end
end
+ describe '#add_files' do
+ it 'adds files' do
+ cop_todo.add_files(%w[a.rb b.rb])
+ cop_todo.add_files(%w[a.rb])
+ cop_todo.add_files(%w[])
+
+ expect(cop_todo).to have_attributes(
+ files: contain_exactly('a.rb', 'b.rb'),
+ offense_count: 0
+ )
+ end
+ end
+
describe '#autocorrectable?' do
subject { cop_todo.autocorrectable? }
diff --git a/spec/rubocop/formatter/todo_formatter_spec.rb b/spec/rubocop/formatter/todo_formatter_spec.rb
index 5494d518605..fdd6117d0e6 100644
--- a/spec/rubocop/formatter/todo_formatter_spec.rb
+++ b/spec/rubocop/formatter/todo_formatter_spec.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
# rubocop:disable RSpec/VerifiedDoubles
require 'fast_spec_helper'
@@ -10,7 +11,7 @@ require 'tmpdir'
require_relative '../../../rubocop/formatter/todo_formatter'
require_relative '../../../rubocop/todo_dir'
-RSpec.describe RuboCop::Formatter::TodoFormatter do
+RSpec.describe RuboCop::Formatter::TodoFormatter, feature_category: :tooling do
let(:stdout) { StringIO.new }
let(:tmp_dir) { Dir.mktmpdir }
let(:real_tmp_dir) { File.join(tmp_dir, 'real') }
@@ -97,6 +98,36 @@ RSpec.describe RuboCop::Formatter::TodoFormatter do
YAML
end
+ context 'with existing HAML exclusions' do
+ before do
+ todo_dir.write('B/TooManyOffenses', <<~YAML)
+ ---
+ B/TooManyOffenses:
+ Exclude:
+ - 'd.rb'
+ - 'app/views/project.html.haml.rb'
+ - 'app/views/unrelated.html.haml.rb.ext'
+ - 'app/views/unrelated.html.haml.ext'
+ - 'app/views/unrelated.html.haml'
+ YAML
+
+ todo_dir.inspect_all
+ end
+
+ it 'does not remove them' do
+ run_formatter
+
+ expect(todo_yml('B/TooManyOffenses')).to eq(<<~YAML)
+ ---
+ B/TooManyOffenses:
+ Exclude:
+ - 'a.rb'
+ - 'app/views/project.html.haml.rb'
+ - 'c.rb'
+ YAML
+ end
+ end
+
context 'when cop previously not explicitly disabled' do
before do
todo_dir.write('B/TooManyOffenses', <<~YAML)
@@ -105,6 +136,8 @@ RSpec.describe RuboCop::Formatter::TodoFormatter do
Exclude:
- 'x.rb'
YAML
+
+ todo_dir.inspect_all
end
it 'does not disable cop' do
@@ -158,6 +191,8 @@ RSpec.describe RuboCop::Formatter::TodoFormatter do
Exclude:
- 'x.rb'
YAML
+
+ todo_dir.inspect_all
end
it 'keeps cop disabled' do
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index f75c95c66f9..a28ede89cee 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -2035,7 +2035,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
expect(pipeline).to be_persisted
expect(pipeline.yaml_errors)
- .to include 'content does not have a valid YAML syntax'
+ .to include 'mapping values are not allowed'
end
end
end
@@ -2172,7 +2172,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
expect(pipeline).to be_persisted
expect(pipeline.yaml_errors)
- .to include 'content does not have a valid YAML syntax'
+ .to include 'mapping values are not allowed'
end
end
end