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-07-07 09:08:10 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-07-07 09:08:10 +0300
commitf23de8014c9104ab62c68e88b4c8e924469cd996 (patch)
treea513f5c77fe54ff68309f1b0508422c5d2d3b39f /spec
parent896eadaa13c8852efa907d2555de883d07c38e48 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/ci/pipeline_schedules/components/pipeline_schedules_form_spec.js184
-rw-r--r--spec/frontend/ci/pipeline_schedules/mock_data.js15
-rw-r--r--spec/frontend/fixtures/pipeline_schedules.rb6
-rw-r--r--spec/graphql/mutations/ci/pipeline_schedule/variable_input_type_spec.rb2
-rw-r--r--spec/helpers/ci/pipeline_schedules_helper_spec.rb31
-rw-r--r--spec/lib/gitlab/background_migration/backfill_missing_ci_cd_settings_spec.rb98
-rw-r--r--spec/migrations/20230628023103_queue_backfill_missing_ci_cd_settings_spec.rb26
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_schedule_update_spec.rb42
-rw-r--r--spec/services/ci/pipeline_schedules/update_service_spec.rb48
9 files changed, 441 insertions, 11 deletions
diff --git a/spec/frontend/ci/pipeline_schedules/components/pipeline_schedules_form_spec.js b/spec/frontend/ci/pipeline_schedules/components/pipeline_schedules_form_spec.js
index 1697533803a..bb48d4dc38d 100644
--- a/spec/frontend/ci/pipeline_schedules/components/pipeline_schedules_form_spec.js
+++ b/spec/frontend/ci/pipeline_schedules/components/pipeline_schedules_form_spec.js
@@ -1,5 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
-import { GlForm } from '@gitlab/ui';
+import { GlForm, GlLoadingIcon } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -14,8 +14,14 @@ import { REF_TYPE_BRANCHES, REF_TYPE_TAGS } from '~/ref/constants';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown/timezone_dropdown.vue';
import IntervalPatternInput from '~/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue';
import createPipelineScheduleMutation from '~/ci/pipeline_schedules/graphql/mutations/create_pipeline_schedule.mutation.graphql';
+import updatePipelineScheduleMutation from '~/ci/pipeline_schedules/graphql/mutations/update_pipeline_schedule.mutation.graphql';
+import getPipelineSchedulesQuery from '~/ci/pipeline_schedules/graphql/queries/get_pipeline_schedules.query.graphql';
import { timezoneDataFixture } from '../../../vue_shared/components/timezone_dropdown/helpers';
-import { createScheduleMutationResponse } from '../mock_data';
+import {
+ createScheduleMutationResponse,
+ updateScheduleMutationResponse,
+ mockSinglePipelineScheduleNode,
+} from '../mock_data';
Vue.use(VueApollo);
@@ -23,8 +29,20 @@ jest.mock('~/alert');
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
joinPaths: jest.fn().mockReturnValue(''),
+ queryToObject: jest.fn().mockReturnValue({ id: '1' }),
}));
+const {
+ data: {
+ project: {
+ pipelineSchedules: { nodes },
+ },
+ },
+} = mockSinglePipelineScheduleNode;
+
+const schedule = nodes[0];
+const variables = schedule.variables.nodes;
+
describe('Pipeline schedules form', () => {
let wrapper;
const defaultBranch = 'main';
@@ -32,8 +50,13 @@ describe('Pipeline schedules form', () => {
const cron = '';
const dailyLimit = '';
+ const querySuccessHandler = jest.fn().mockResolvedValue(mockSinglePipelineScheduleNode);
+ const queryFailedHandler = jest.fn().mockRejectedValue(new Error('GraphQL error'));
+
const createMutationHandlerSuccess = jest.fn().mockResolvedValue(createScheduleMutationResponse);
const createMutationHandlerFailed = jest.fn().mockRejectedValue(new Error('GraphQL error'));
+ const updateMutationHandlerSuccess = jest.fn().mockResolvedValue(updateScheduleMutationResponse);
+ const updateMutationHandlerFailed = jest.fn().mockRejectedValue(new Error('GraphQL error'));
const createMockApolloProvider = (
requestHandlers = [[createPipelineScheduleMutation, createMutationHandlerSuccess]],
@@ -52,8 +75,6 @@ describe('Pipeline schedules form', () => {
fullPath: 'gitlab-org/gitlab',
projectId,
defaultBranch,
- cron,
- cronTimezone: '',
dailyLimit,
settingsLink: '',
schedulesPath: '/root/ci-project/-/pipeline_schedules',
@@ -69,6 +90,7 @@ describe('Pipeline schedules form', () => {
const findRefSelector = () => wrapper.findComponent(RefSelector);
const findSubmitButton = () => wrapper.findByTestId('schedule-submit-button');
const findCancelButton = () => wrapper.findByTestId('schedule-cancel-button');
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
// Variables
const findVariableRows = () => wrapper.findAllByTestId('ci-variable-row');
const findKeyInputs = () => wrapper.findAllByTestId('pipeline-form-ci-variable-key');
@@ -187,7 +209,38 @@ describe('Pipeline schedules form', () => {
});
});
- describe('schedule creation', () => {
+ describe('Button text', () => {
+ it.each`
+ editing | expectedText
+ ${true} | ${'Edit pipeline schedule'}
+ ${false} | ${'Create pipeline schedule'}
+ `(
+ 'button text is $expectedText when editing is $editing',
+ async ({ editing, expectedText }) => {
+ createComponent(shallowMountExtended, editing, [
+ [getPipelineSchedulesQuery, querySuccessHandler],
+ ]);
+
+ await waitForPromises();
+
+ expect(findSubmitButton().text()).toBe(expectedText);
+ },
+ );
+ });
+
+ describe('Schedule creation', () => {
+ it('when creating a schedule the query is not called', () => {
+ createComponent();
+
+ expect(querySuccessHandler).not.toHaveBeenCalled();
+ });
+
+ it('does not show loading state when creating new schedule', () => {
+ createComponent();
+
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
describe('schedule creation success', () => {
let mock;
@@ -259,4 +312,125 @@ describe('Pipeline schedules form', () => {
});
});
});
+
+ describe('Schedule editing', () => {
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ it('shows loading state when editing', async () => {
+ createComponent(shallowMountExtended, true, [
+ [getPipelineSchedulesQuery, querySuccessHandler],
+ ]);
+
+ expect(findLoadingIcon().exists()).toBe(true);
+
+ await waitForPromises();
+
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ describe('schedule fetch success', () => {
+ it('fetches schedule and sets form data correctly', async () => {
+ createComponent(mountExtended, true, [[getPipelineSchedulesQuery, querySuccessHandler]]);
+
+ expect(querySuccessHandler).toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(findDescription().element.value).toBe(schedule.description);
+ expect(findIntervalComponent().props('initialCronInterval')).toBe(schedule.cron);
+ expect(findTimezoneDropdown().props('value')).toBe(schedule.cronTimezone);
+ expect(findRefSelector().props('value')).toBe(schedule.ref);
+ expect(findVariableRows()).toHaveLength(3);
+ expect(findKeyInputs().at(0).element.value).toBe(variables[0].key);
+ expect(findKeyInputs().at(1).element.value).toBe(variables[1].key);
+ expect(findValueInputs().at(0).element.value).toBe(variables[0].value);
+ expect(findValueInputs().at(1).element.value).toBe(variables[1].value);
+ });
+ });
+
+ it('schedule fetch failure', async () => {
+ createComponent(shallowMountExtended, true, [
+ [getPipelineSchedulesQuery, queryFailedHandler],
+ ]);
+
+ await waitForPromises();
+
+ expect(createAlert).toHaveBeenCalledWith({
+ message: 'An error occurred while trying to fetch the pipeline schedule.',
+ });
+ });
+
+ it('edit schedule success', async () => {
+ createComponent(mountExtended, true, [
+ [getPipelineSchedulesQuery, querySuccessHandler],
+ [updatePipelineScheduleMutation, updateMutationHandlerSuccess],
+ ]);
+
+ await waitForPromises();
+
+ findDescription().element.value = 'Updated schedule';
+ findDescription().trigger('change');
+
+ findIntervalComponent().vm.$emit('cronValue', '0 22 16 * *');
+
+ // Ensures variable is sent with destroy property set true
+ findRemoveIcons().at(0).vm.$emit('click');
+
+ findSubmitButton().vm.$emit('click');
+
+ await waitForPromises();
+
+ expect(updateMutationHandlerSuccess).toHaveBeenCalledWith({
+ input: {
+ active: schedule.active,
+ cron: '0 22 16 * *',
+ cronTimezone: schedule.cronTimezone,
+ id: schedule.id,
+ ref: schedule.ref,
+ description: 'Updated schedule',
+ variables: [
+ {
+ destroy: true,
+ id: variables[0].id,
+ key: variables[0].key,
+ value: variables[0].value,
+ variableType: variables[0].variableType,
+ },
+ {
+ destroy: false,
+ id: variables[1].id,
+ key: variables[1].key,
+ value: variables[1].value,
+ variableType: variables[1].variableType,
+ },
+ ],
+ },
+ });
+ });
+
+ it('edit schedule failure', async () => {
+ createComponent(shallowMountExtended, true, [
+ [getPipelineSchedulesQuery, querySuccessHandler],
+ [updatePipelineScheduleMutation, updateMutationHandlerFailed],
+ ]);
+
+ await waitForPromises();
+
+ findSubmitButton().vm.$emit('click');
+
+ await waitForPromises();
+
+ expect(createAlert).toHaveBeenCalledWith({
+ message: 'An error occurred while updating the pipeline schedule.',
+ });
+ });
+ });
});
diff --git a/spec/frontend/ci/pipeline_schedules/mock_data.js b/spec/frontend/ci/pipeline_schedules/mock_data.js
index 58fc4a616e4..81283a7170b 100644
--- a/spec/frontend/ci/pipeline_schedules/mock_data.js
+++ b/spec/frontend/ci/pipeline_schedules/mock_data.js
@@ -2,6 +2,7 @@
import mockGetPipelineSchedulesGraphQLResponse from 'test_fixtures/graphql/pipeline_schedules/get_pipeline_schedules.query.graphql.json';
import mockGetPipelineSchedulesAsGuestGraphQLResponse from 'test_fixtures/graphql/pipeline_schedules/get_pipeline_schedules.query.graphql.as_guest.json';
import mockGetPipelineSchedulesTakeOwnershipGraphQLResponse from 'test_fixtures/graphql/pipeline_schedules/get_pipeline_schedules.query.graphql.take_ownership.json';
+import mockGetSinglePipelineScheduleGraphQLResponse from 'test_fixtures/graphql/pipeline_schedules/get_pipeline_schedules.query.graphql.single.json';
const {
data: {
@@ -30,10 +31,10 @@ const {
export const mockPipelineScheduleNodes = nodes;
export const mockPipelineScheduleCurrentUser = currentUser;
-
export const mockPipelineScheduleAsGuestNodes = guestNodes;
-
export const mockTakeOwnershipNodes = takeOwnershipNodes;
+export const mockSinglePipelineScheduleNode = mockGetSinglePipelineScheduleGraphQLResponse;
+
export const emptyPipelineSchedulesResponse = {
data: {
project: {
@@ -89,4 +90,14 @@ export const createScheduleMutationResponse = {
},
};
+export const updateScheduleMutationResponse = {
+ data: {
+ pipelineScheduleUpdate: {
+ clientMutationId: null,
+ errors: [],
+ __typename: 'PipelineScheduleUpdatePayload',
+ },
+ },
+};
+
export { mockGetPipelineSchedulesGraphQLResponse };
diff --git a/spec/frontend/fixtures/pipeline_schedules.rb b/spec/frontend/fixtures/pipeline_schedules.rb
index 3bfe9113e83..7bba7910b87 100644
--- a/spec/frontend/fixtures/pipeline_schedules.rb
+++ b/spec/frontend/fixtures/pipeline_schedules.rb
@@ -63,6 +63,12 @@ RSpec.describe 'Pipeline schedules (JavaScript fixtures)' do
expect_graphql_errors_to_be_empty
end
+ it "#{fixtures_path}#{get_pipeline_schedules_query}.single.json" do
+ post_graphql(query, current_user: user, variables: { projectPath: project.full_path, ids: pipeline_schedule_populated.id })
+
+ expect_graphql_errors_to_be_empty
+ end
+
it "#{fixtures_path}#{get_pipeline_schedules_query}.as_guest.json" do
guest = create(:user)
project.add_guest(user)
diff --git a/spec/graphql/mutations/ci/pipeline_schedule/variable_input_type_spec.rb b/spec/graphql/mutations/ci/pipeline_schedule/variable_input_type_spec.rb
index 564bc95b352..a932002d614 100644
--- a/spec/graphql/mutations/ci/pipeline_schedule/variable_input_type_spec.rb
+++ b/spec/graphql/mutations/ci/pipeline_schedule/variable_input_type_spec.rb
@@ -5,5 +5,5 @@ require 'spec_helper'
RSpec.describe Mutations::Ci::PipelineSchedule::VariableInputType, feature_category: :continuous_integration do
specify { expect(described_class.graphql_name).to eq('PipelineScheduleVariableInput') }
- it { expect(described_class.arguments.keys).to match_array(%w[key value variableType]) }
+ it { expect(described_class.arguments.keys).to match_array(%w[id key value variableType destroy]) }
end
diff --git a/spec/helpers/ci/pipeline_schedules_helper_spec.rb b/spec/helpers/ci/pipeline_schedules_helper_spec.rb
new file mode 100644
index 00000000000..1ba24a08b58
--- /dev/null
+++ b/spec/helpers/ci/pipeline_schedules_helper_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineSchedulesHelper, feature_category: :continuous_integration do
+ let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:user) { build_stubbed(:user) }
+ let_it_be(:pipeline_schedule) { build_stubbed(:ci_pipeline_schedule, project: project, owner: user) }
+ let_it_be(:timezones) { [{ identifier: "Pacific/Honolulu", name: "Hawaii" }] }
+
+ let_it_be(:pipeline_schedule_variable) do
+ build_stubbed(:ci_pipeline_schedule_variable, key: 'foo', value: 'foovalue', pipeline_schedule: pipeline_schedule)
+ end
+
+ describe '#js_pipeline_schedules_form_data' do
+ before do
+ allow(helper).to receive(:timezone_data).and_return(timezones)
+ end
+
+ it 'returns pipeline schedule form data' do
+ expect(helper.js_pipeline_schedules_form_data(project, pipeline_schedule)).to include({
+ full_path: project.full_path,
+ daily_limit: nil,
+ project_id: project.id,
+ schedules_path: pipeline_schedules_path(project),
+ settings_link: project_settings_ci_cd_path(project),
+ timezone_data: timezones.to_json
+ })
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_missing_ci_cd_settings_spec.rb b/spec/lib/gitlab/background_migration/backfill_missing_ci_cd_settings_spec.rb
new file mode 100644
index 00000000000..8f7d5f25a80
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_missing_ci_cd_settings_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillMissingCiCdSettings, schema: 20230628023103, feature_category: :source_code_management do # rubocop:disable Layout/LineLength
+ let(:projects_table) { table(:projects) }
+ let(:namespaces_table) { table(:namespaces) }
+ let(:ci_cd_settings_table) { table(:project_ci_cd_settings) }
+
+ let(:namespace_1) { namespaces_table.create!(name: 'namespace', path: 'namespace-path-1') }
+
+ let(:project_namespace_2) { namespaces_table.create!(name: 'namespace', path: 'namespace-path-2', type: 'Project') }
+ let(:project_namespace_3) { namespaces_table.create!(name: 'namespace', path: 'namespace-path-3', type: 'Project') }
+ let(:project_namespace_4) { namespaces_table.create!(name: 'namespace', path: 'namespace-path-4', type: 'Project') }
+ let(:project_namespace_5) { namespaces_table.create!(name: 'namespace', path: 'namespace-path-4', type: 'Project') }
+ let!(:project_1) do
+ projects_table
+ .create!(
+ name: 'project1',
+ path: 'path1',
+ namespace_id: namespace_1.id,
+ project_namespace_id: project_namespace_2.id,
+ visibility_level: 0
+ )
+ end
+
+ let!(:project_2) do
+ projects_table
+ .create!(
+ name: 'project2',
+ path: 'path2',
+ namespace_id: namespace_1.id,
+ project_namespace_id: project_namespace_3.id,
+ visibility_level: 0
+ )
+ end
+
+ let!(:project_3) do
+ projects_table
+ .create!(
+ name: 'project3',
+ path: 'path3',
+ namespace_id: namespace_1.id,
+ project_namespace_id: project_namespace_4.id,
+ visibility_level: 0
+ )
+ end
+
+ let!(:ci_cd_settings_3) do
+ ci_cd_settings_table.create!(project_id: project_3.id)
+ end
+
+ let!(:project_4) do
+ projects_table
+ .create!(
+ name: 'project4',
+ path: 'path4',
+ namespace_id: namespace_1.id,
+ project_namespace_id: project_namespace_5.id,
+ visibility_level: 0
+ )
+ end
+
+ subject(:perform_migration) do
+ described_class.new(start_id: projects_table.minimum(:id),
+ end_id: projects_table.maximum(:id),
+ batch_table: :projects,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: projects_table.connection)
+ .perform
+ end
+
+ it 'creates ci_cd_settings for projects without ci_cd_settings' do
+ expect { subject }.to change { ci_cd_settings_table.count }.from(1).to(4)
+ end
+
+ it 'creates ci_cd_settings with default values' do
+ ci_cd_settings_table.where.not(project_id: ci_cd_settings_3.project_id).each do |ci_cd_setting|
+ expect(ci_cd_setting.attributes.except('id', 'project_id')).to eq({
+ "group_runners_enabled" => true,
+ "merge_pipelines_enabled" => nil,
+ "default_git_depth" => 20,
+ "forward_deployment_enabled" => true,
+ "merge_trains_enabled" => false,
+ "auto_rollback_enabled" => false,
+ "keep_latest_artifact" => false,
+ "restrict_user_defined_variables" => false,
+ "job_token_scope_enabled" => false,
+ "runner_token_expiration_interval" => nil,
+ "separated_caches" => true,
+ "allow_fork_pipelines_to_run_in_parent_project" => true,
+ "inbound_job_token_scope_enabled" => true
+ })
+ end
+ end
+end
diff --git a/spec/migrations/20230628023103_queue_backfill_missing_ci_cd_settings_spec.rb b/spec/migrations/20230628023103_queue_backfill_missing_ci_cd_settings_spec.rb
new file mode 100644
index 00000000000..f6c470260ff
--- /dev/null
+++ b/spec/migrations/20230628023103_queue_backfill_missing_ci_cd_settings_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe QueueBackfillMissingCiCdSettings, feature_category: :source_code_management do
+ let!(:batched_migration) { described_class::MIGRATION }
+
+ it 'schedules a new batched migration' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+
+ migration.after -> {
+ expect(batched_migration).to have_scheduled_batched_migration(
+ table_name: :projects,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ }
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_update_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_update_spec.rb
index c1da231a4a6..3c3dcfc0a2d 100644
--- a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_update_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_update_spec.rb
@@ -9,6 +9,14 @@ RSpec.describe 'PipelineScheduleUpdate', feature_category: :continuous_integrati
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
+ let_it_be(:variable_one) do
+ create(:ci_pipeline_schedule_variable, key: 'foo', value: 'foovalue', pipeline_schedule: pipeline_schedule)
+ end
+
+ let_it_be(:variable_two) do
+ create(:ci_pipeline_schedule_variable, key: 'bar', value: 'barvalue', pipeline_schedule: pipeline_schedule)
+ end
+
let(:mutation) do
variables = {
id: pipeline_schedule.to_global_id.to_s,
@@ -30,6 +38,7 @@ RSpec.describe 'PipelineScheduleUpdate', feature_category: :continuous_integrati
nodes {
key
value
+ variableType
}
}
}
@@ -88,8 +97,37 @@ RSpec.describe 'PipelineScheduleUpdate', feature_category: :continuous_integrati
expect(mutation_response['pipelineSchedule']['refForDisplay']).to eq(pipeline_schedule_parameters[:ref])
- expect(mutation_response['pipelineSchedule']['variables']['nodes'][0]['key']).to eq('AAA')
- expect(mutation_response['pipelineSchedule']['variables']['nodes'][0]['value']).to eq('AAA123')
+ expect(mutation_response['pipelineSchedule']['variables']['nodes'][2]['key']).to eq('AAA')
+ expect(mutation_response['pipelineSchedule']['variables']['nodes'][2]['value']).to eq('AAA123')
+ end
+ end
+
+ context 'when updating and removing variables' do
+ let(:pipeline_schedule_parameters) do
+ {
+ variables: [
+ { key: 'ABC', value: "ABC123", variableType: 'ENV_VAR', destroy: false },
+ { id: variable_one.to_global_id.to_s,
+ key: 'foo', value: "foovalue",
+ variableType: 'ENV_VAR',
+ destroy: true },
+ { id: variable_two.to_global_id.to_s, key: 'newbar', value: "newbarvalue", variableType: 'ENV_VAR' }
+ ]
+ }
+ end
+
+ it 'processes variables correctly' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+
+ expect(mutation_response['pipelineSchedule']['variables']['nodes'])
+ .to match_array(
+ [
+ { "key" => 'newbar', "value" => 'newbarvalue', "variableType" => 'ENV_VAR' },
+ { "key" => 'ABC', "value" => "ABC123", "variableType" => 'ENV_VAR' }
+ ]
+ )
end
end
diff --git a/spec/services/ci/pipeline_schedules/update_service_spec.rb b/spec/services/ci/pipeline_schedules/update_service_spec.rb
index 6899f6c7d63..c31a652ed93 100644
--- a/spec/services/ci/pipeline_schedules/update_service_spec.rb
+++ b/spec/services/ci/pipeline_schedules/update_service_spec.rb
@@ -8,9 +8,16 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
+ let_it_be(:pipeline_schedule_variable) do
+ create(:ci_pipeline_schedule_variable,
+ key: 'foo', value: 'foovalue', pipeline_schedule: pipeline_schedule)
+ end
+
before_all do
project.add_maintainer(user)
project.add_reporter(reporter)
+
+ pipeline_schedule.reload
end
describe "execute" do
@@ -35,7 +42,10 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
description: 'updated_desc',
ref: 'patch-x',
active: false,
- cron: '*/1 * * * *'
+ cron: '*/1 * * * *',
+ variables_attributes: [
+ { id: pipeline_schedule_variable.id, key: 'bar', secret_value: 'barvalue' }
+ ]
}
end
@@ -47,6 +57,42 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
.and change { pipeline_schedule.ref }.from('master').to('patch-x')
.and change { pipeline_schedule.active }.from(true).to(false)
.and change { pipeline_schedule.cron }.from('0 1 * * *').to('*/1 * * * *')
+ .and change { pipeline_schedule.variables.last.key }.from('foo').to('bar')
+ .and change { pipeline_schedule.variables.last.value }.from('foovalue').to('barvalue')
+ end
+
+ context 'when creating a variable' do
+ let(:params) do
+ {
+ variables_attributes: [
+ { key: 'ABC', secret_value: 'ABC123' }
+ ]
+ }
+ end
+
+ it 'creates the new variable' do
+ expect { service.execute }.to change { Ci::PipelineScheduleVariable.count }.by(1)
+
+ expect(pipeline_schedule.variables.last.key).to eq('ABC')
+ expect(pipeline_schedule.variables.last.value).to eq('ABC123')
+ end
+ end
+
+ context 'when deleting a variable' do
+ let(:params) do
+ {
+ variables_attributes: [
+ {
+ id: pipeline_schedule_variable.id,
+ _destroy: true
+ }
+ ]
+ }
+ end
+
+ it 'deletes the existing variable' do
+ expect { service.execute }.to change { Ci::PipelineScheduleVariable.count }.by(-1)
+ end
end
it 'returns ServiceResponse.success' do