diff options
Diffstat (limited to 'spec')
61 files changed, 521 insertions, 149 deletions
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index 3d1d28945f7..0c97f11090d 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -1355,8 +1355,8 @@ RSpec.describe Projects::PipelinesController do .and_return(service) end - context 'when sending a valid sha' do - let(:sha) { 'master' } + context 'when sending a valid ref' do + let(:ref) { 'master' } let(:ci_config) do { variables: { @@ -1381,8 +1381,8 @@ RSpec.describe Projects::PipelinesController do end end - context 'when sending an invalid sha' do - let(:sha) { 'invalid-sha' } + context 'when sending an invalid ref' do + let(:ref) { 'invalid-ref' } before do synchronous_reactive_cache(service) @@ -1397,7 +1397,7 @@ RSpec.describe Projects::PipelinesController do end context 'when sending an invalid config' do - let(:sha) { 'master' } + let(:ref) { 'master' } let(:ci_config) do { variables: { @@ -1423,7 +1423,7 @@ RSpec.describe Projects::PipelinesController do end context 'when the cache is empty' do - let(:sha) { 'master' } + let(:ref) { 'master' } let(:ci_config) do { variables: { @@ -1446,7 +1446,7 @@ RSpec.describe Projects::PipelinesController do context 'when project uses external project ci config' do let(:other_project) { create(:project, :custom_repo, files: other_project_files) } let(:other_project_files) { { '.gitlab-ci.yml' => YAML.dump(other_project_ci_config) } } - let(:sha) { 'master' } + let(:ref) { 'master' } let(:other_project_ci_config) do { @@ -1479,7 +1479,7 @@ RSpec.describe Projects::PipelinesController do def get_config_variables get :config_variables, params: { namespace_id: project.namespace, project_id: project, - sha: sha }, + sha: ref }, format: :json end end diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 4af901e4cf6..9b839873fbb 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -38,7 +38,7 @@ RSpec.describe 'Database schema', feature_category: :database do ci_build_trace_chunks: %w[partition_id], ci_build_trace_metadata: %w[partition_id], ci_builds: %w[erased_by_id trigger_request_id partition_id], - ci_builds_runner_session: %w[partition_id], + ci_builds_runner_session: %w[partition_id build_id], p_ci_builds_metadata: %w[partition_id], ci_job_artifacts: %w[partition_id], ci_job_variables: %w[partition_id], diff --git a/spec/factories/ci/runner_machines.rb b/spec/factories/ci/runner_machines.rb index 09bf5d0844e..c382ebdcb26 100644 --- a/spec/factories/ci/runner_machines.rb +++ b/spec/factories/ci/runner_machines.rb @@ -4,5 +4,10 @@ FactoryBot.define do factory :ci_runner_machine, class: 'Ci::RunnerMachine' do runner factory: :ci_runner machine_xid { "r_#{SecureRandom.hex.slice(0, 10)}" } + + trait :stale do + created_at { 1.year.ago } + contacted_at { Ci::RunnerMachine::STALE_TIMEOUT.ago } + end end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 2b53a469841..e641f925758 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -180,6 +180,10 @@ FactoryBot.define do provider { 'ldapmain' } end end + + trait :unconfirmed do + confirmed_at { nil } + end end factory :atlassian_user do diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb index 5acc59b190f..8d4666dcb50 100644 --- a/spec/features/profiles/keys_spec.rb +++ b/spec/features/profiles/keys_spec.rb @@ -76,35 +76,74 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do expect(page).to have_content(key.title) end + def destroy_key(path, action, confirmation_button) + visit path + + page.click_button(action) + + page.within('.modal') do + page.click_button(confirmation_button) + end + + expect(page).to have_content('Your SSH keys (0)') + end + describe 'User removes a key', :js do - shared_examples 'removes key' do - it 'removes key' do - visit path - find('[data-testid=remove-icon]').click + let!(:key) { create(:key, user: user) } - page.within('.modal') do - page.click_button('Delete') - end + context 'via the key index' do + it 'removes key' do + destroy_key(profile_keys_path, 'Remove', 'Delete') + end + end - expect(page).to have_content('Your SSH keys (0)') + context 'via its details page' do + it 'removes key' do + destroy_key(profile_keys_path(key), 'Remove', 'Delete') end end + end + + describe 'User revokes a key', :js do + context 'when a commit is signed using SSH key' do + let!(:project) { create(:project, :repository) } + let!(:key) { create(:key, user: user) } + let!(:commit) { project.commit('ssh-signed-commit') } + + let!(:signature) do + create(:ssh_signature, + project: project, + key: key, + key_fingerprint_sha256: key.fingerprint_sha256, + commit_sha: commit.sha) + end - context 'via the key index' do before do - create(:key, user: user) + project.add_developer(user) end - let(:path) { profile_keys_path } + it 'revoking the SSH key marks commits as unverified' do + visit project_commit_path(project, commit) - it_behaves_like 'removes key' - end + find('a.gpg-status-box', text: 'Verified').click - context 'via its details page' do - let(:key) { create(:key, user: user) } - let(:path) { profile_keys_path(key) } + within('.popover') do + expect(page).to have_content("Verified commit") + expect(page).to have_content("SSH key fingerprint: #{key.fingerprint_sha256}") + end + + destroy_key(profile_keys_path, 'Revoke', 'Revoke') + + visit project_commit_path(project, commit) - it_behaves_like 'removes key' + find('a.gpg-status-box', text: 'Unverified').click + + within('.popover') do + expect(page).to have_content("Unverified signature") + expect(page).to have_content('This commit was signed with a key that was revoked.') + expect(page).to have_content("SSH key fingerprint: #{signature.key_fingerprint_sha256}") + end + end end end end diff --git a/spec/frontend/admin/broadcast_messages/components/base_spec.js b/spec/frontend/admin/broadcast_messages/components/base_spec.js index 79bde54286e..d69bf4a22bf 100644 --- a/spec/frontend/admin/broadcast_messages/components/base_spec.js +++ b/spec/frontend/admin/broadcast_messages/components/base_spec.js @@ -6,7 +6,7 @@ import waitForPromises from 'helpers/wait_for_promises'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { redirectTo } from '~/lib/utils/url_utility'; import BroadcastMessagesBase from '~/admin/broadcast_messages/components/base.vue'; import MessagesTable from '~/admin/broadcast_messages/components/messages_table.vue'; @@ -71,7 +71,7 @@ describe('BroadcastMessagesBase', () => { it('does not remove a deleted message if the request fails', async () => { createComponent(); const { id, delete_path } = MOCK_MESSAGES[0]; - axiosMock.onDelete(delete_path).replyOnce(500); + axiosMock.onDelete(delete_path).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); findTable().vm.$emit('delete-message', id); await waitForPromises(); diff --git a/spec/frontend/admin/statistics_panel/store/actions_spec.js b/spec/frontend/admin/statistics_panel/store/actions_spec.js index e7cdb5feb6a..bf97699b1fc 100644 --- a/spec/frontend/admin/statistics_panel/store/actions_spec.js +++ b/spec/frontend/admin/statistics_panel/store/actions_spec.js @@ -5,6 +5,7 @@ import * as actions from '~/admin/statistics_panel/store/actions'; import * as types from '~/admin/statistics_panel/store/mutation_types'; import getInitialState from '~/admin/statistics_panel/store/state'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import mockStatistics from '../mock_data'; describe('Admin statistics panel actions', () => { @@ -43,7 +44,9 @@ describe('Admin statistics panel actions', () => { describe('error', () => { beforeEach(() => { - mock.onGet(/api\/(.*)\/application\/statistics/).replyOnce(500); + mock + .onGet(/api\/(.*)\/application\/statistics/) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); }); it('dispatches error', () => { @@ -99,12 +102,12 @@ describe('Admin statistics panel actions', () => { it('should commit error', () => { return testAction( actions.receiveStatisticsError, - 500, + HTTP_STATUS_INTERNAL_SERVER_ERROR, state, [ { type: types.RECEIVE_STATISTICS_ERROR, - payload: 500, + payload: HTTP_STATUS_INTERNAL_SERVER_ERROR, }, ], [], diff --git a/spec/frontend/admin/statistics_panel/store/mutations_spec.js b/spec/frontend/admin/statistics_panel/store/mutations_spec.js index 0a3dad09c9a..70c1e723f08 100644 --- a/spec/frontend/admin/statistics_panel/store/mutations_spec.js +++ b/spec/frontend/admin/statistics_panel/store/mutations_spec.js @@ -1,6 +1,7 @@ import * as types from '~/admin/statistics_panel/store/mutation_types'; import mutations from '~/admin/statistics_panel/store/mutations'; import getInitialState from '~/admin/statistics_panel/store/state'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import mockStatistics from '../mock_data'; describe('Admin statistics panel mutations', () => { @@ -30,11 +31,10 @@ describe('Admin statistics panel mutations', () => { describe(`${types.RECEIVE_STATISTICS_ERROR}`, () => { it('sets error and clears data', () => { - const error = 500; - mutations[types.RECEIVE_STATISTICS_ERROR](state, error); + mutations[types.RECEIVE_STATISTICS_ERROR](state, HTTP_STATUS_INTERNAL_SERVER_ERROR); expect(state.isLoading).toBe(false); - expect(state.error).toBe(error); + expect(state.error).toBe(HTTP_STATUS_INTERNAL_SERVER_ERROR); expect(state.statistics).toEqual(null); }); }); diff --git a/spec/frontend/badges/store/actions_spec.js b/spec/frontend/badges/store/actions_spec.js index b799273ff63..4e8d7aaaca9 100644 --- a/spec/frontend/badges/store/actions_spec.js +++ b/spec/frontend/badges/store/actions_spec.js @@ -5,6 +5,7 @@ import actions, { transformBackendBadge } from '~/badges/store/actions'; import mutationTypes from '~/badges/store/mutation_types'; import createState from '~/badges/store/state'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { createDummyBadge, createDummyBadgeResponse } from '../dummy_badge'; describe('Badges store actions', () => { @@ -119,7 +120,7 @@ describe('Badges store actions', () => { expect(dispatch.mock.calls).toEqual([['requestNewBadge']]); dispatch.mockClear(); - return [500, '']; + return [HTTP_STATUS_INTERNAL_SERVER_ERROR, '']; }); await expect(actions.addBadge({ state, dispatch })).rejects.toThrow(); @@ -187,7 +188,7 @@ describe('Badges store actions', () => { endpointMock.replyOnce(() => { expect(dispatch.mock.calls).toEqual([['requestDeleteBadge', badgeId]]); dispatch.mockClear(); - return [500, '']; + return [HTTP_STATUS_INTERNAL_SERVER_ERROR, '']; }); await expect(actions.deleteBadge({ state, dispatch }, { id: badgeId })).rejects.toThrow(); @@ -279,7 +280,7 @@ describe('Badges store actions', () => { endpointMock.replyOnce(() => { expect(dispatch.mock.calls).toEqual([['requestLoadBadges', dummyData]]); dispatch.mockClear(); - return [500, '']; + return [HTTP_STATUS_INTERNAL_SERVER_ERROR, '']; }); await expect(actions.loadBadges({ state, dispatch }, dummyData)).rejects.toThrow(); @@ -393,7 +394,7 @@ describe('Badges store actions', () => { endpointMock.replyOnce(() => { expect(dispatch.mock.calls).toEqual([['requestRenderedBadge']]); dispatch.mockClear(); - return [500, '']; + return [HTTP_STATUS_INTERNAL_SERVER_ERROR, '']; }); await expect(actions.renderBadge({ state, dispatch })).rejects.toThrow(); @@ -487,7 +488,7 @@ describe('Badges store actions', () => { expect(dispatch.mock.calls).toEqual([['requestUpdatedBadge']]); dispatch.mockClear(); - return [500, '']; + return [HTTP_STATUS_INTERNAL_SERVER_ERROR, '']; }); await expect(actions.saveBadge({ state, dispatch })).rejects.toThrow(); diff --git a/spec/frontend/blob/notebook/notebook_viever_spec.js b/spec/frontend/blob/notebook/notebook_viever_spec.js index ea4badc03fb..e6480c8d874 100644 --- a/spec/frontend/blob/notebook/notebook_viever_spec.js +++ b/spec/frontend/blob/notebook/notebook_viever_spec.js @@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter'; import waitForPromises from 'helpers/wait_for_promises'; import component from '~/blob/notebook/notebook_viewer.vue'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import NotebookLab from '~/notebook/index.vue'; describe('iPython notebook renderer', () => { @@ -90,7 +91,7 @@ describe('iPython notebook renderer', () => { describe('error getting file', () => { beforeEach(() => { - mock.onGet(endpoint).reply(500, ''); + mock.onGet(endpoint).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, ''); mountComponent(); return waitForPromises(); diff --git a/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js index 2246d0bbf7e..a103acb33bc 100644 --- a/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js +++ b/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js @@ -5,6 +5,7 @@ import createMockApollo from 'helpers/mock_apollo_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; import waitForPromises from 'helpers/wait_for_promises'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { objectToQuery, redirectTo } from '~/lib/utils/url_utility'; import { resolvers } from '~/ci/pipeline_editor/graphql/resolvers'; import PipelineEditorTabs from '~/ci/pipeline_editor/components/pipeline_editor_tabs.vue'; @@ -343,7 +344,7 @@ describe('Pipeline editor app component', () => { describe('when the lint query returns a 500 error', () => { beforeEach(async () => { - mockCiConfigData.mockRejectedValueOnce(new Error(500)); + mockCiConfigData.mockRejectedValueOnce(new Error(HTTP_STATUS_INTERNAL_SERVER_ERROR)); await createComponentWithApollo({ stubs: { PipelineEditorHome, PipelineEditorHeader, ValidationSegment }, }); diff --git a/spec/frontend/code_navigation/store/actions_spec.js b/spec/frontend/code_navigation/store/actions_spec.js index 8eee61d1342..3cedb2fe232 100644 --- a/spec/frontend/code_navigation/store/actions_spec.js +++ b/spec/frontend/code_navigation/store/actions_spec.js @@ -4,6 +4,7 @@ import testAction from 'helpers/vuex_action_helper'; import actions from '~/code_navigation/store/actions'; import { setCurrentHoverElement, addInteractionClass } from '~/code_navigation/utils'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; jest.mock('~/code_navigation/utils'); @@ -124,7 +125,7 @@ describe('Code navigation actions', () => { describe('error', () => { beforeEach(() => { - mock.onGet(codeNavigationPath).replyOnce(500); + mock.onGet(codeNavigationPath).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); }); it('dispatches requestDataError', () => { diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js index 6865b721441..6ad1c308b01 100644 --- a/spec/frontend/commit/pipelines/pipelines_table_spec.js +++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js @@ -337,7 +337,7 @@ describe('Pipelines table in Commits and Merge requests', () => { describe('unsuccessfull request', () => { beforeEach(async () => { - mock.onGet('endpoint.json').reply(500, []); + mock.onGet('endpoint.json').reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, []); createComponent(); diff --git a/spec/frontend/deploy_tokens/components/new_deploy_token_spec.js b/spec/frontend/deploy_tokens/components/new_deploy_token_spec.js index 0bf69acd251..0b82cb32dc4 100644 --- a/spec/frontend/deploy_tokens/components/new_deploy_token_spec.js +++ b/spec/frontend/deploy_tokens/components/new_deploy_token_spec.js @@ -3,6 +3,7 @@ import { nextTick } from 'vue'; import { GlButton, GlFormCheckbox, GlFormInput, GlFormInputGroup, GlDatepicker } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { TEST_HOST } from 'helpers/test_constants'; import NewDeployToken from '~/deploy_tokens/components/new_deploy_token.vue'; import waitForPromises from 'helpers/wait_for_promises'; @@ -131,7 +132,7 @@ describe('New Deploy Token', () => { write_package_registry: true, }, }) - .replyOnce(500, { message: expectedErrorMessage }); + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, { message: expectedErrorMessage }); wrapper.findAllComponents(GlButton).at(0).vm.$emit('click'); diff --git a/spec/frontend/environments/folder/environments_folder_view_spec.js b/spec/frontend/environments/folder/environments_folder_view_spec.js index f8b8465cf6f..9c1f463ec3f 100644 --- a/spec/frontend/environments/folder/environments_folder_view_spec.js +++ b/spec/frontend/environments/folder/environments_folder_view_spec.js @@ -5,6 +5,7 @@ import { removeBreakLine, removeWhitespace } from 'helpers/text_helper'; import EnvironmentTable from '~/environments/components/environments_table.vue'; import EnvironmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { environmentsList } from '../mock_data'; describe('Environments Folder View', () => { @@ -120,7 +121,7 @@ describe('Environments Folder View', () => { describe('unsuccessfull request', () => { beforeEach(() => { - mock.onGet(mockData.endpoint).reply(500, { environments: [] }); + mock.onGet(mockData.endpoint).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, { environments: [] }); createWrapper(); return axios.waitForAll(); }); diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js index d27b23c5cd1..4ed17234971 100644 --- a/spec/frontend/feature_flags/components/feature_flags_spec.js +++ b/spec/frontend/feature_flags/components/feature_flags_spec.js @@ -11,6 +11,7 @@ import FeatureFlagsComponent from '~/feature_flags/components/feature_flags.vue' import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue'; import createStore from '~/feature_flags/store/index'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue'; import { getRequestData } from '../mock_data'; @@ -271,7 +272,9 @@ describe('Feature flags', () => { describe('unsuccessful request', () => { beforeEach(() => { - mock.onGet(mockState.endpoint, { params: { page: '1' } }).replyOnce(500, {}); + mock + .onGet(mockState.endpoint, { params: { page: '1' } }) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}); factory(); return waitForPromises(); diff --git a/spec/frontend/feature_flags/store/edit/actions_spec.js b/spec/frontend/feature_flags/store/edit/actions_spec.js index bcacfa9fda9..8b9b42f4eb1 100644 --- a/spec/frontend/feature_flags/store/edit/actions_spec.js +++ b/spec/frontend/feature_flags/store/edit/actions_spec.js @@ -17,7 +17,7 @@ import * as types from '~/feature_flags/store/edit/mutation_types'; import state from '~/feature_flags/store/edit/state'; import { mapStrategiesToRails } from '~/feature_flags/store/helpers'; import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; jest.mock('~/lib/utils/url_utility'); @@ -79,7 +79,9 @@ describe('Feature flags Edit Module actions', () => { describe('error', () => { it('dispatches requestUpdateFeatureFlag and receiveUpdateFeatureFlagError', () => { - mock.onPut(`${TEST_HOST}/endpoint.json`).replyOnce(500, { message: [] }); + mock + .onPut(`${TEST_HOST}/endpoint.json`) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, { message: [] }); return testAction( updateFeatureFlag, @@ -180,7 +182,9 @@ describe('Feature flags Edit Module actions', () => { describe('error', () => { it('dispatches requestFeatureFlag and receiveUpdateFeatureFlagError', () => { - mock.onGet(`${TEST_HOST}/endpoint.json`, {}).replyOnce(500, {}); + mock + .onGet(`${TEST_HOST}/endpoint.json`, {}) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}); return testAction( fetchFeatureFlag, diff --git a/spec/frontend/feature_flags/store/index/actions_spec.js b/spec/frontend/feature_flags/store/index/actions_spec.js index 96a7d868316..a7a8793c82c 100644 --- a/spec/frontend/feature_flags/store/index/actions_spec.js +++ b/spec/frontend/feature_flags/store/index/actions_spec.js @@ -20,6 +20,7 @@ import { import * as types from '~/feature_flags/store/index/mutation_types'; import state from '~/feature_flags/store/index/state'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { getRequestData, rotateData, featureFlag } from '../../mock_data'; jest.mock('~/api.js'); @@ -79,7 +80,9 @@ describe('Feature flags actions', () => { describe('error', () => { it('dispatches requestFeatureFlags and receiveFeatureFlagsError', () => { - mock.onGet(`${TEST_HOST}/endpoint.json`, {}).replyOnce(500, {}); + mock + .onGet(`${TEST_HOST}/endpoint.json`, {}) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}); return testAction( fetchFeatureFlags, @@ -176,7 +179,9 @@ describe('Feature flags actions', () => { describe('error', () => { it('dispatches requestRotateInstanceId and receiveRotateInstanceIdError', () => { - mock.onGet(`${TEST_HOST}/endpoint.json`, {}).replyOnce(500, {}); + mock + .onGet(`${TEST_HOST}/endpoint.json`, {}) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}); return testAction( rotateInstanceId, @@ -275,7 +280,7 @@ describe('Feature flags actions', () => { describe('error', () => { it('dispatches updateFeatureFlag and receiveUpdateFeatureFlagSuccess', () => { - mock.onPut(featureFlag.update_path).replyOnce(500); + mock.onPut(featureFlag.update_path).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); return testAction( toggleFeatureFlag, diff --git a/spec/frontend/feature_flags/store/new/actions_spec.js b/spec/frontend/feature_flags/store/new/actions_spec.js index c8bf05e4dbd..01b6ab4d5ed 100644 --- a/spec/frontend/feature_flags/store/new/actions_spec.js +++ b/spec/frontend/feature_flags/store/new/actions_spec.js @@ -11,7 +11,7 @@ import { import * as types from '~/feature_flags/store/new/mutation_types'; import state from '~/feature_flags/store/new/state'; import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; jest.mock('~/lib/utils/url_utility'); @@ -88,7 +88,7 @@ describe('Feature flags New Module Actions', () => { }; mock .onPost(mockedState.endpoint, mapStrategiesToRails(actionParams)) - .replyOnce(500, { message: [] }); + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, { message: [] }); return testAction( createFeatureFlag, diff --git a/spec/frontend/frequent_items/store/actions_spec.js b/spec/frontend/frequent_items/store/actions_spec.js index 4f998cc26da..15905d71a21 100644 --- a/spec/frontend/frequent_items/store/actions_spec.js +++ b/spec/frontend/frequent_items/store/actions_spec.js @@ -5,6 +5,7 @@ import * as types from '~/frequent_items/store/mutation_types'; import state from '~/frequent_items/store/state'; import AccessorUtilities from '~/lib/utils/accessor'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import { mockNamespace, @@ -192,7 +193,7 @@ describe('Frequent Items Dropdown Store Actions', () => { it('should dispatch `receiveSearchedItemsError`', () => { gon.api_version = 'v4'; - mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(500); + mock.onGet(/\/api\/v4\/projects.json(.*)$/).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); return testAction( actions.fetchSearchedItems, diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js index fea3b547977..eca56325366 100644 --- a/spec/frontend/groups/components/app_spec.js +++ b/spec/frontend/groups/components/app_spec.js @@ -11,7 +11,11 @@ import eventHub from '~/groups/event_hub'; import GroupsService from '~/groups/service/groups_service'; import GroupsStore from '~/groups/store/groups_store'; import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_FORBIDDEN } from '~/lib/utils/http_status'; +import { + HTTP_STATUS_BAD_REQUEST, + HTTP_STATUS_FORBIDDEN, + HTTP_STATUS_INTERNAL_SERVER_ERROR, +} from '~/lib/utils/http_status'; import * as urlUtilities from '~/lib/utils/url_utility'; import setWindowLocation from 'helpers/set_window_location_helper'; @@ -322,7 +326,9 @@ describe('AppComponent', () => { it('should show error flash message if request failed to leave group', () => { const message = 'An error occurred. Please try again.'; - jest.spyOn(vm.service, 'leaveGroup').mockRejectedValue({ status: 500 }); + jest + .spyOn(vm.service, 'leaveGroup') + .mockRejectedValue({ status: HTTP_STATUS_INTERNAL_SERVER_ERROR }); jest.spyOn(vm.store, 'removeGroup'); vm.leaveGroup(); diff --git a/spec/frontend/ide/lib/mirror_spec.js b/spec/frontend/ide/lib/mirror_spec.js index 8f417ea54dc..33dd0fefc6c 100644 --- a/spec/frontend/ide/lib/mirror_spec.js +++ b/spec/frontend/ide/lib/mirror_spec.js @@ -7,6 +7,7 @@ import { MSG_CONNECTION_ERROR, SERVICE_DELAY, } from '~/ide/lib/mirror'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { getWebSocketUrl } from '~/lib/utils/url_utility'; jest.mock('~/ide/lib/create_diff', () => jest.fn()); @@ -26,7 +27,7 @@ const TEST_ERROR_RESPONSE = { const TEST_ERROR_PAYLOAD_RESPONSE = { data: JSON.stringify({ error: { code: 0 }, - payload: { status_code: 500, error_message: TEST_ERROR }, + payload: { status_code: HTTP_STATUS_INTERNAL_SERVER_ERROR, error_message: TEST_ERROR }, }), }; diff --git a/spec/frontend/ide/stores/actions/tree_spec.js b/spec/frontend/ide/stores/actions/tree_spec.js index 6e8a03b47ad..4551a7a21f1 100644 --- a/spec/frontend/ide/stores/actions/tree_spec.js +++ b/spec/frontend/ide/stores/actions/tree_spec.js @@ -8,6 +8,7 @@ import { createStore } from '~/ide/stores'; import { showTreeEntry, getFiles, setDirectoryData } from '~/ide/stores/actions/tree'; import * as types from '~/ide/stores/mutation_types'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { file, createEntriesFromPaths } from '../../helpers'; describe('Multi-file store tree actions', () => { @@ -98,7 +99,7 @@ describe('Multi-file store tree actions', () => { findBranch: () => store.state.projects['abc/def'].branches['main-testing'], }; - mock.onGet(/(.*)/).replyOnce(500); + mock.onGet(/(.*)/).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); await expect( getFiles( diff --git a/spec/frontend/ide/stores/modules/branches/actions_spec.js b/spec/frontend/ide/stores/modules/branches/actions_spec.js index 306330e3ba2..38a2e1ac12f 100644 --- a/spec/frontend/ide/stores/modules/branches/actions_spec.js +++ b/spec/frontend/ide/stores/modules/branches/actions_spec.js @@ -10,6 +10,7 @@ import { import * as types from '~/ide/stores/modules/branches/mutation_types'; import state from '~/ide/stores/modules/branches/state'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { branches, projectData } from '../../../mock_data'; describe('IDE branches actions', () => { @@ -124,7 +125,9 @@ describe('IDE branches actions', () => { describe('error', () => { beforeEach(() => { - mock.onGet(/\/api\/v4\/projects\/\d+\/repository\/branches(.*)$/).replyOnce(500); + mock + .onGet(/\/api\/v4\/projects\/\d+\/repository\/branches(.*)$/) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); }); it('dispatches error', () => { diff --git a/spec/frontend/ide/stores/modules/file_templates/actions_spec.js b/spec/frontend/ide/stores/modules/file_templates/actions_spec.js index 1080a30d2d8..0a99496a147 100644 --- a/spec/frontend/ide/stores/modules/file_templates/actions_spec.js +++ b/spec/frontend/ide/stores/modules/file_templates/actions_spec.js @@ -4,6 +4,7 @@ import * as actions from '~/ide/stores/modules/file_templates/actions'; import * as types from '~/ide/stores/modules/file_templates/mutation_types'; import createState from '~/ide/stores/modules/file_templates/state'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; describe('IDE file templates actions', () => { let state; @@ -108,7 +109,7 @@ describe('IDE file templates actions', () => { describe('error', () => { beforeEach(() => { - mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(500); + mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); }); it('dispatches actions', () => { @@ -248,7 +249,9 @@ describe('IDE file templates actions', () => { describe('error', () => { beforeEach(() => { - mock.onGet(/api\/(.*)\/templates\/licenses\/mit/).replyOnce(500); + mock + .onGet(/api\/(.*)\/templates\/licenses\/mit/) + .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); }); it('dispatches error', () => { diff --git a/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js b/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js index 344fe3a41c3..5d3bf063ac8 100644 --- a/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js +++ b/spec/frontend/ide/stores/modules/merge_requests/actions_spec.js @@ -10,6 +10,7 @@ import { import * as types from '~/ide/stores/modules/merge_requests/mutation_types'; import state from '~/ide/stores/modules/merge_requests/state'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { mergeRequests } from '../../../mock_data'; describe('IDE merge requests actions', () => { @@ -169,7 +170,7 @@ describe('IDE merge requests actions', () => { describe('error', () => { beforeEach(() => { - mock.onGet(/\/api\/v4\/merge_requests(.*)$/).replyOnce(500); + mock.onGet(/\/api\/v4\/merge_requests(.*)$/).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); }); it('dispatches error', () => { diff --git a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js index bf57373dd03..f541e579810 100644 --- a/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js +++ b/spec/frontend/ide/stores/modules/terminal/actions/checks_spec.js @@ -13,6 +13,7 @@ import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_FORBIDDEN, + HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_NOT_FOUND, HTTP_STATUS_UNPROCESSABLE_ENTITY, } from '~/lib/utils/http_status'; @@ -277,7 +278,9 @@ describe('IDE store terminal check actions', () => { }); it('dispatches request and receive, when error', () => { - mock.onGet(/api\/.*\/projects\/.*\/runners/, { params: { scope: 'active' } }).reply(500, []); + mock + .onGet(/api\/.*\/projects\/.*\/runners/, { params: { scope: 'active' } }) + .reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, []); return testAction( actions.fetchRunnersCheck, diff --git a/spec/frontend/labels/components/promote_label_modal_spec.js b/spec/frontend/labels/components/promote_label_modal_spec.js index 8953e3cbcd8..9dd6f1ca64c 100644 --- a/spec/frontend/labels/components/promote_label_modal_spec.js +++ b/spec/frontend/labels/components/promote_label_modal_spec.js @@ -6,6 +6,7 @@ import { TEST_HOST } from 'helpers/test_constants'; import { stubComponent } from 'helpers/stub_component'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import PromoteLabelModal from '~/labels/components/promote_label_modal.vue'; import eventHub from '~/labels/event_hub'; @@ -85,8 +86,10 @@ describe('Promote label modal', () => { it('displays an error if promoting a label failed', async () => { const dummyError = new Error('promoting label failed'); - dummyError.response = { status: 500 }; - axiosMock.onPost(labelMockData.url).reply(500, { error: dummyError }); + dummyError.response = { status: HTTP_STATUS_INTERNAL_SERVER_ERROR }; + axiosMock + .onPost(labelMockData.url) + .reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, { error: dummyError }); wrapper.findComponent(GlModal).vm.$emit('primary'); diff --git a/spec/frontend/lib/utils/favicon_ci_spec.js b/spec/frontend/lib/utils/favicon_ci_spec.js index e35b008b862..6385af952e7 100644 --- a/spec/frontend/lib/utils/favicon_ci_spec.js +++ b/spec/frontend/lib/utils/favicon_ci_spec.js @@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; import { setFaviconOverlay, resetFavicon } from '~/lib/utils/favicon'; import { setCiStatusFavicon } from '~/lib/utils/favicon_ci'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; jest.mock('~/lib/utils/favicon'); @@ -41,7 +42,7 @@ describe('~/lib/utils/favicon_ci', () => { ); it('with error', async () => { - mock.onGet(TEST_URL).replyOnce(500); + mock.onGet(TEST_URL).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); await expect(setCiStatusFavicon(TEST_URL)).rejects.toEqual(expect.any(Error)); expect(resetFavicon).toHaveBeenCalled(); diff --git a/spec/frontend/lib/utils/poll_spec.js b/spec/frontend/lib/utils/poll_spec.js index 94a5f5385b7..0e6c08bf033 100644 --- a/spec/frontend/lib/utils/poll_spec.js +++ b/spec/frontend/lib/utils/poll_spec.js @@ -1,5 +1,5 @@ import waitForPromises from 'helpers/wait_for_promises'; -import { successCodes } from '~/lib/utils/http_status'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR, successCodes } from '~/lib/utils/http_status'; import Poll from '~/lib/utils/poll'; describe('Poll', () => { @@ -61,7 +61,7 @@ describe('Poll', () => { }); it('calls the error callback when the http request returns an error', () => { - mockServiceCall({ status: 500 }, true); + mockServiceCall({ status: HTTP_STATUS_INTERNAL_SERVER_ERROR }, true); setup(); return waitForAllCallsToFinish(1, () => { diff --git a/spec/frontend/milestones/components/milestone_combobox_spec.js b/spec/frontend/milestones/components/milestone_combobox_spec.js index c20c51db75e..27485f3d51d 100644 --- a/spec/frontend/milestones/components/milestone_combobox_spec.js +++ b/spec/frontend/milestones/components/milestone_combobox_spec.js @@ -4,6 +4,7 @@ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { ENTER_KEY } from '~/lib/utils/keys'; import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue'; import createStore from '~/milestones/stores/'; @@ -314,8 +315,10 @@ describe('Milestone combobox component', () => { describe('when the project milestones search returns an error', () => { beforeEach(() => { - projectMilestonesApiCallSpy = jest.fn().mockReturnValue([500]); - searchApiCallSpy = jest.fn().mockReturnValue([500]); + projectMilestonesApiCallSpy = jest + .fn() + .mockReturnValue([HTTP_STATUS_INTERNAL_SERVER_ERROR]); + searchApiCallSpy = jest.fn().mockReturnValue([HTTP_STATUS_INTERNAL_SERVER_ERROR]); createComponent({ value: [] }); @@ -441,8 +444,10 @@ describe('Milestone combobox component', () => { describe('when the group milestones search returns an error', () => { beforeEach(() => { - groupMilestonesApiCallSpy = jest.fn().mockReturnValue([500]); - searchApiCallSpy = jest.fn().mockReturnValue([500]); + groupMilestonesApiCallSpy = jest + .fn() + .mockReturnValue([HTTP_STATUS_INTERNAL_SERVER_ERROR]); + searchApiCallSpy = jest.fn().mockReturnValue([HTTP_STATUS_INTERNAL_SERVER_ERROR]); createComponent({ value: [] }); diff --git a/spec/frontend/milestones/components/promote_milestone_modal_spec.js b/spec/frontend/milestones/components/promote_milestone_modal_spec.js index 60657fbc9b8..d7ad3d29d0a 100644 --- a/spec/frontend/milestones/components/promote_milestone_modal_spec.js +++ b/spec/frontend/milestones/components/promote_milestone_modal_spec.js @@ -5,6 +5,7 @@ import { TEST_HOST } from 'helpers/test_constants'; import waitForPromises from 'helpers/wait_for_promises'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import * as urlUtils from '~/lib/utils/url_utility'; import PromoteMilestoneModal from '~/milestones/components/promote_milestone_modal.vue'; @@ -94,7 +95,7 @@ describe('Promote milestone modal', () => { it('displays an error if promoting a milestone failed', async () => { const dummyError = new Error('promoting milestone failed'); - dummyError.response = { status: 500 }; + dummyError.response = { status: HTTP_STATUS_INTERNAL_SERVER_ERROR }; jest.spyOn(axios, 'post').mockImplementation((url) => { expect(url).toBe(milestoneMockData.url); return Promise.reject(dummyError); diff --git a/spec/frontend/pipelines/pipeline_multi_actions_spec.js b/spec/frontend/pipelines/pipeline_multi_actions_spec.js index f0dae8ebcbe..544a33b10db 100644 --- a/spec/frontend/pipelines/pipeline_multi_actions_spec.js +++ b/spec/frontend/pipelines/pipeline_multi_actions_spec.js @@ -5,6 +5,7 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import PipelineMultiActions, { i18n, } from '~/pipelines/components/pipelines_list/pipeline_multi_actions.vue'; @@ -140,7 +141,7 @@ describe('Pipeline Multi Actions Dropdown', () => { describe('with a failing request', () => { it('should render an error message', async () => { const endpoint = artifactsEndpoint.replace(artifactsEndpointPlaceholder, pipelineId); - mockAxios.onGet(endpoint).replyOnce(500); + mockAxios.onGet(endpoint).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); createComponent(); findDropdown().vm.$emit('show'); await waitForPromises(); diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index 351572fc83a..17ff0969b30 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -13,6 +13,7 @@ import waitForPromises from 'helpers/wait_for_promises'; import Api from '~/api'; import { createAlert, VARIANT_WARNING } from '~/flash'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import NavigationControls from '~/pipelines/components/pipelines_list/nav_controls.vue'; import PipelinesComponent from '~/pipelines/components/pipelines_list/pipelines.vue'; import PipelinesCiTemplates from '~/pipelines/components/pipelines_list/empty_state/pipelines_ci_templates.vue'; @@ -702,7 +703,7 @@ describe('Pipelines', () => { describe('when pipelines cannot be loaded', () => { beforeEach(async () => { - mock.onGet(mockPipelinesEndpoint).reply(500, {}); + mock.onGet(mockPipelinesEndpoint).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}); }); describe('when user has no permissions', () => { diff --git a/spec/frontend/projects/commit_box/info/load_branches_spec.js b/spec/frontend/projects/commit_box/info/load_branches_spec.js index 9456e6ef5f5..50e305dea7f 100644 --- a/spec/frontend/projects/commit_box/info/load_branches_spec.js +++ b/spec/frontend/projects/commit_box/info/load_branches_spec.js @@ -2,6 +2,7 @@ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import { setHTMLFixture } from 'helpers/fixtures'; import waitForPromises from 'helpers/wait_for_promises'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { loadBranches } from '~/projects/commit_box/info/load_branches'; const mockCommitPath = '/commit/abcd/branches'; @@ -60,7 +61,7 @@ describe('~/projects/commit_box/info/load_branches', () => { describe('when branches request fails', () => { beforeEach(() => { - mock.onGet(mockCommitPath).reply(500, 'Error!'); + mock.onGet(mockCommitPath).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, 'Error!'); }); it('attempts to load and renders an error', async () => { diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js index 930b801af71..64eba056c6f 100644 --- a/spec/frontend/projects/commits/store/actions_spec.js +++ b/spec/frontend/projects/commits/store/actions_spec.js @@ -2,6 +2,7 @@ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import testAction from 'helpers/vuex_action_helper'; import { createAlert } from '~/flash'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import actions from '~/projects/commits/store/actions'; import * as types from '~/projects/commits/store/mutation_types'; import createState from '~/projects/commits/store/state'; @@ -63,7 +64,7 @@ describe('Project commits actions', () => { it('dispatches request/receive on error', () => { const path = '/-/autocomplete/users.json'; - mock.onGet(path).replyOnce(500); + mock.onGet(path).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); testAction(actions.fetchAuthors, null, state, [], [{ type: 'receiveAuthorsError' }]); }); diff --git a/spec/frontend/protected_branches/protected_branch_edit_spec.js b/spec/frontend/protected_branches/protected_branch_edit_spec.js index 0aec4fbc037..8e1a09500c7 100644 --- a/spec/frontend/protected_branches/protected_branch_edit_spec.js +++ b/spec/frontend/protected_branches/protected_branch_edit_spec.js @@ -4,6 +4,7 @@ import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import { TEST_HOST } from 'helpers/test_constants'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import ProtectedBranchEdit from '~/protected_branches/protected_branch_edit'; jest.mock('~/flash'); @@ -142,7 +143,7 @@ describe('ProtectedBranchEdit', () => { describe('when clicked and BE error', () => { beforeEach(() => { - mock.onPatch(TEST_URL).replyOnce(500); + mock.onPatch(TEST_URL).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); toggle.click(); }); diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js index ac588248f15..e12659a0eff 100644 --- a/spec/frontend/ref/components/ref_selector_spec.js +++ b/spec/frontend/ref/components/ref_selector_spec.js @@ -9,7 +9,7 @@ import commit from 'test_fixtures/api/commits/commit.json'; import branches from 'test_fixtures/api/branches/branches.json'; import tags from 'test_fixtures/api/tags/tags.json'; import { trimText } from 'helpers/text_helper'; -import { HTTP_STATUS_NOT_FOUND } from '~/lib/utils/http_status'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_NOT_FOUND } from '~/lib/utils/http_status'; import { ENTER_KEY } from '~/lib/utils/keys'; import { sprintf } from '~/locale'; import RefSelector from '~/ref/components/ref_selector.vue'; @@ -400,7 +400,7 @@ describe('Ref selector component', () => { describe('when the branches search returns an error', () => { beforeEach(() => { - branchesApiCallSpy = jest.fn().mockReturnValue([500]); + branchesApiCallSpy = jest.fn().mockReturnValue([HTTP_STATUS_INTERNAL_SERVER_ERROR]); createComponent(); @@ -465,7 +465,7 @@ describe('Ref selector component', () => { describe('when the tags search returns an error', () => { beforeEach(() => { - tagsApiCallSpy = jest.fn().mockReturnValue([500]); + tagsApiCallSpy = jest.fn().mockReturnValue([HTTP_STATUS_INTERNAL_SERVER_ERROR]); createComponent(); @@ -531,7 +531,7 @@ describe('Ref selector component', () => { describe('when the commit search returns an error (other than a 404)', () => { beforeEach(() => { - commitApiCallSpy = jest.fn().mockReturnValue([500]); + commitApiCallSpy = jest.fn().mockReturnValue([HTTP_STATUS_INTERNAL_SERVER_ERROR]); createComponent(); diff --git a/spec/frontend/repository/components/fork_info_spec.js b/spec/frontend/repository/components/fork_info_spec.js index c23d5ae5823..f327a8cfae7 100644 --- a/spec/frontend/repository/components/fork_info_spec.js +++ b/spec/frontend/repository/components/fork_info_spec.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; -import { GlSkeletonLoader, GlIcon, GlLink } from '@gitlab/ui'; +import { GlSkeletonLoader, GlIcon, GlLink, GlSprintf } from '@gitlab/ui'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -16,13 +16,14 @@ describe('ForkInfo component', () => { let wrapper; let mockResolver; const forkInfoError = new Error('Something went wrong'); + const projectId = 'gid://gitlab/Project/1'; Vue.use(VueApollo); const createCommitData = ({ ahead = 3, behind = 7 }) => { return { data: { - project: { id: '1', forkDetails: { ahead, behind, __typename: 'ForkDetails' } }, + project: { id: projectId, forkDetails: { ahead, behind, __typename: 'ForkDetails' } }, }, }; }; @@ -35,6 +36,7 @@ describe('ForkInfo component', () => { wrapper = shallowMountExtended(ForkInfo, { apolloProvider: createMockApollo([[forkDetailsQuery, mockResolver]]), propsData: { ...propsForkInfo, ...props }, + stubs: { GlSprintf }, }); return waitForPromises(); }; @@ -42,8 +44,10 @@ describe('ForkInfo component', () => { const findLink = () => wrapper.findComponent(GlLink); const findSkeleton = () => wrapper.findComponent(GlSkeletonLoader); const findIcon = () => wrapper.findComponent(GlIcon); - const findDivergenceMessage = () => wrapper.find('.gl-text-secondary'); + const findDivergenceMessage = () => wrapper.findByTestId('divergence-message'); const findInaccessibleMessage = () => wrapper.findByTestId('inaccessible-project'); + const findCompareLinks = () => findDivergenceMessage().findAllComponents(GlLink); + it('displays a skeleton while loading data', async () => { createComponent(); expect(findSkeleton().exists()).toBe(true); @@ -88,28 +92,54 @@ describe('ForkInfo component', () => { expect(findDivergenceMessage().text()).toBe(i18n.unknown); }); - it('shows correct divergence message when data is present', async () => { - await createComponent(); - expect(findDivergenceMessage().text()).toMatchInterpolatedText( - '7 commits behind, 3 commits ahead of the upstream repository.', - ); - }); - it('renders up to date message when divergence is unknown', async () => { await createComponent({}, { ahead: 0, behind: 0 }); expect(findDivergenceMessage().text()).toBe(i18n.upToDate); }); - it('renders commits ahead message', async () => { - await createComponent({}, { behind: 0 }); - expect(findDivergenceMessage().text()).toBe('3 commits ahead of the upstream repository.'); - }); - - it('renders commits behind message', async () => { - await createComponent({}, { ahead: 0 }); - - expect(findDivergenceMessage().text()).toBe('7 commits behind the upstream repository.'); - }); + describe.each([ + { + ahead: 7, + behind: 3, + message: '3 commits behind, 7 commits ahead of the upstream repository.', + firstLink: propsForkInfo.behindComparePath, + secondLink: propsForkInfo.aheadComparePath, + }, + { + ahead: 7, + behind: 0, + message: '7 commits ahead of the upstream repository.', + firstLink: propsForkInfo.aheadComparePath, + secondLink: '', + }, + { + ahead: 0, + behind: 3, + message: '3 commits behind the upstream repository.', + firstLink: propsForkInfo.behindComparePath, + secondLink: '', + }, + ])( + 'renders correct divergence message for ahead: $ahead, behind: $behind divergence commits', + ({ ahead, behind, message, firstLink, secondLink }) => { + beforeEach(async () => { + await createComponent({}, { ahead, behind }); + }); + + it('displays correct text', () => { + expect(findDivergenceMessage().text()).toBe(message); + }); + + it('adds correct links', () => { + const links = findCompareLinks(); + expect(links.at(0).attributes('href')).toBe(firstLink); + + if (secondLink) { + expect(links.at(1).attributes('href')).toBe(secondLink); + } + }); + }, + ); it('renders alert with error message when request fails', async () => { await createComponent({}, {}, true); diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js index d85434a9148..04ffe52bc3f 100644 --- a/spec/frontend/repository/mock_data.js +++ b/spec/frontend/repository/mock_data.js @@ -120,7 +120,9 @@ export const graphQLErrors = [ export const propsForkInfo = { projectPath: 'nataliia/myGitLab', - selectedRef: 'main', + selectedBranch: 'main', sourceName: 'gitLab', sourcePath: 'gitlab-org/gitlab', + aheadComparePath: '/nataliia/myGitLab/-/compare/main...ref?from_project_id=1', + behindComparePath: 'gitlab-org/gitlab/-/compare/ref...main?from_project_id=2', }; diff --git a/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js b/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js index 0e0024aa6c2..56d516bf589 100644 --- a/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js +++ b/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js @@ -3,6 +3,7 @@ import MockAdapter from 'axios-mock-adapter'; import testAction from 'helpers/vuex_action_helper'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import * as actions from '~/sidebar/components/labels/labels_select_vue/store/actions'; import * as types from '~/sidebar/components/labels/labels_select_vue/store/mutation_types'; import defaultState from '~/sidebar/components/labels/labels_select_vue/store/state'; @@ -135,7 +136,7 @@ describe('LabelsSelect Actions', () => { describe('on failure', () => { it('dispatches `requestLabels` & `receiveLabelsFailure` actions', () => { - mock.onGet(/labels.json/).replyOnce(500, {}); + mock.onGet(/labels.json/).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}); return testAction( actions.fetchLabels, @@ -224,7 +225,7 @@ describe('LabelsSelect Actions', () => { describe('on failure', () => { it('dispatches `requestCreateLabel` & `receiveCreateLabelFailure` actions', () => { - mock.onPost(/labels.json/).replyOnce(500, {}); + mock.onPost(/labels.json/).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}); return testAction( actions.createLabel, diff --git a/spec/frontend/snippets/components/snippet_blob_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_edit_spec.js index 33b8e2be969..ad5fca760f4 100644 --- a/spec/frontend/snippets/components/snippet_blob_edit_spec.js +++ b/spec/frontend/snippets/components/snippet_blob_edit_spec.js @@ -6,6 +6,7 @@ import waitForPromises from 'helpers/wait_for_promises'; import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import { joinPaths } from '~/lib/utils/url_utility'; import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue'; import SourceEditor from '~/vue_shared/components/source_editor.vue'; @@ -118,7 +119,7 @@ describe('Snippet Blob Edit component', () => { describe('with error', () => { beforeEach(() => { axiosMock.reset(); - axiosMock.onGet(TEST_FULL_PATH).replyOnce(500); + axiosMock.onGet(TEST_FULL_PATH).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR); createComponent(); }); diff --git a/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js b/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js index 73fa4b7b08f..f993b82026d 100644 --- a/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js @@ -5,6 +5,7 @@ import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { TEST_HOST as FAKE_ENDPOINT } from 'helpers/test_constants'; import axios from '~/lib/utils/axios_utils'; +import { HTTP_STATUS_INTERNAL_SERVER_ERROR } from '~/lib/utils/http_status'; import ArtifactsListApp from '~/vue_merge_request_widget/components/artifacts_list_app.vue'; import { getStoreConfig } from '~/vue_merge_request_widget/stores/artifacts_list'; import { artifacts } from '../mock_data'; @@ -109,7 +110,7 @@ describe('Merge Requests Artifacts list app', () => { describe('with error', () => { beforeEach(() => { createComponent(); - mock.onGet(FAKE_ENDPOINT).reply(500, {}, {}); + mock.onGet(FAKE_ENDPOINT).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, {}, {}); store.dispatch('receiveArtifactsError'); return nextTick(); }); diff --git a/spec/graphql/types/commit_signatures/verification_status_enum_spec.rb b/spec/graphql/types/commit_signatures/verification_status_enum_spec.rb index cb7ce19c9fc..a0d99f5f0c1 100644 --- a/spec/graphql/types/commit_signatures/verification_status_enum_spec.rb +++ b/spec/graphql/types/commit_signatures/verification_status_enum_spec.rb @@ -10,7 +10,7 @@ RSpec.describe GitlabSchema.types['VerificationStatus'] do .to match_array(%w[ UNVERIFIED UNVERIFIED_KEY VERIFIED SAME_USER_DIFFERENT_EMAIL OTHER_USER UNKNOWN_KEY - MULTIPLE_SIGNATURES + MULTIPLE_SIGNATURES REVOKED_KEY ]) end end diff --git a/spec/lib/gitlab/search/found_blob_spec.rb b/spec/lib/gitlab/search/found_blob_spec.rb index c41a051bc42..8efbe053155 100644 --- a/spec/lib/gitlab/search/found_blob_spec.rb +++ b/spec/lib/gitlab/search/found_blob_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Search::FoundBlob do +RSpec.describe Gitlab::Search::FoundBlob, feature_category: :global_search do let(:project) { create(:project, :public, :repository) } describe 'parsing content results' do @@ -17,6 +17,7 @@ RSpec.describe Gitlab::Search::FoundBlob do expect(subject.path).to eq('CHANGELOG') expect(subject.basename).to eq('CHANGELOG') expect(subject.ref).to eq('master') + expect(subject.matched_lines_count).to be_nil expect(subject.startline).to eq(188) expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n") end diff --git a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb index 032a5e78385..33e0d446fca 100644 --- a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb @@ -284,6 +284,16 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git end end + context 'for Issue design comment removed actions' do + it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do + let(:action) { described_class::ISSUE_DESIGN_COMMENT_REMOVED } + + def track_action(params) + described_class.track_issue_design_comment_removed_action(**params) + end + end + end + it 'can return the count of actions per user deduplicated', :aggregate_failures do described_class.track_issue_title_changed_action(author: user1, project: project) described_class.track_issue_description_changed_action(author: user1, project: project) diff --git a/spec/models/ci/runner_machine_spec.rb b/spec/models/ci/runner_machine_spec.rb index 9fc35006233..c658058c131 100644 --- a/spec/models/ci/runner_machine_spec.rb +++ b/spec/models/ci/runner_machine_spec.rb @@ -38,10 +38,11 @@ RSpec.describe Ci::RunnerMachine, feature_category: :runner_fleet, type: :model describe '.stale', :freeze_time do subject { described_class.stale.ids } - let!(:runner_machine1) { create(:ci_runner_machine, created_at: 8.days.ago, contacted_at: 7.days.ago) } - let!(:runner_machine2) { create(:ci_runner_machine, created_at: 7.days.ago, contacted_at: nil) } - let!(:runner_machine3) { create(:ci_runner_machine, created_at: 5.days.ago, contacted_at: nil) } - let!(:runner_machine4) do + let!(:runner_machine1) { create(:ci_runner_machine, :stale) } + let!(:runner_machine2) { create(:ci_runner_machine, :stale, contacted_at: nil) } + let!(:runner_machine3) { create(:ci_runner_machine, created_at: 6.months.ago, contacted_at: Time.current) } + let!(:runner_machine4) { create(:ci_runner_machine, created_at: 5.days.ago) } + let!(:runner_machine5) do create(:ci_runner_machine, created_at: (7.days - 1.second).ago, contacted_at: (7.days - 1.second).ago) end diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 0fde9e5f187..7b79b4c8a6d 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -261,14 +261,14 @@ RSpec.describe Ci::Runner, feature_category: :runner do describe '.belonging_to_project' do it 'returns the project runner' do # own - specific_project = create(:project) - specific_runner = create(:ci_runner, :project, projects: [specific_project]) + own_project = create(:project) + own_runner = create(:ci_runner, :project, projects: [own_project]) # other other_project = create(:project) create(:ci_runner, :project, projects: [other_project]) - expect(described_class.belonging_to_project(specific_project.id)).to eq [specific_runner] + expect(described_class.belonging_to_project(own_project.id)).to eq [own_runner] end end diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 92f4d6d8531..f1bc7b41cee 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -489,4 +489,12 @@ RSpec.describe Key, :mailer do end end end + + describe '#signing?' do + it 'returns whether a key can be used for signing' do + expect(build(:key, usage_type: :signing)).to be_signing + expect(build(:key, usage_type: :auth_and_signing)).to be_signing + expect(build(:key, usage_type: :auth)).not_to be_signing + end + end end diff --git a/spec/requests/api/graphql/ci/config_variables_spec.rb b/spec/requests/api/graphql/ci/config_variables_spec.rb index e6d73701b8f..f76bb8ff837 100644 --- a/spec/requests/api/graphql/ci/config_variables_spec.rb +++ b/spec/requests/api/graphql/ci/config_variables_spec.rb @@ -14,13 +14,13 @@ RSpec.describe 'Query.project(fullPath).ciConfigVariables(sha)', feature_categor let_it_be(:user) { create(:user) } let(:service) { Ci::ListConfigVariablesService.new(project, user) } - let(:sha) { project.repository.commit.sha } + let(:ref) { project.default_branch } let(:query) do %( query { project(fullPath: "#{project.full_path}") { - ciConfigVariables(sha: "#{sha}") { + ciConfigVariables(sha: "#{ref}") { key value valueOptions @@ -47,7 +47,7 @@ RSpec.describe 'Query.project(fullPath).ciConfigVariables(sha)', feature_categor it 'returns the CI variables for the config' do expect(service) .to receive(:execute) - .with(sha) + .with(ref) .and_call_original post_graphql(query, current_user: user) diff --git a/spec/requests/profiles/keys_controller_spec.rb b/spec/requests/profiles/keys_controller_spec.rb new file mode 100644 index 00000000000..48c382e6230 --- /dev/null +++ b/spec/requests/profiles/keys_controller_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Profiles::KeysController, feature_category: :source_code_management do + let_it_be(:user) { create(:user) } + + before do + login_as(user) + end + + describe 'DELETE /-/profile/keys/:id/revoke' do + it 'returns 404 if a key not found' do + delete revoke_profile_key_path(non_existing_record_id) + + expect(response).to have_gitlab_http_status(:not_found) + end + + it 'revokes ssh commit signatures' do + key = create(:key, user: user) + signature = create(:ssh_signature, key: key) + + expect do + delete revoke_profile_key_path(signature.key) + end.to change { signature.reload.key }.from(signature.key).to(nil) + .and change { signature.verification_status }.from('verified').to('revoked_key') + + expect(response).to have_gitlab_http_status(:found) + end + end +end diff --git a/spec/rubocop/migration_helpers_spec.rb b/spec/rubocop/migration_helpers_spec.rb index 6e6c3a7a0b9..56b7b6aa76b 100644 --- a/spec/rubocop/migration_helpers_spec.rb +++ b/spec/rubocop/migration_helpers_spec.rb @@ -2,6 +2,7 @@ require 'fast_spec_helper' require 'rspec-parameterized' +require 'rubocop/ast' require_relative '../../rubocop/migration_helpers' @@ -69,4 +70,27 @@ RSpec.describe RuboCop::MigrationHelpers do it { expect(fake_cop.time_enforced?(node)).to eq(expected) } end end + + describe '#array_column?' do + let(:name) { nil } + let(:node) { double(:node, each_descendant: [pair_node]) } + let(:pair_node) { double(child_nodes: child_nodes) } + + context 'when it matches array: true' do + let(:child_nodes) do + [ + RuboCop::AST::SymbolNode.new(:sym, [:array]), + RuboCop::AST::Node.new(:true) # rubocop:disable Lint/BooleanSymbol + ] + end + + it { expect(fake_cop.array_column?(node)).to eq(true) } + end + + context 'when it matches a variable => 100' do + let(:child_nodes) { [RuboCop::AST::Node.new(:lvar, [:variable]), RuboCop::AST::IntNode.new(:int, [100])] } + + it { expect(fake_cop.array_column?(node)).to eq(false) } + end + end end diff --git a/spec/services/ci/list_config_variables_service_spec.rb b/spec/services/ci/list_config_variables_service_spec.rb index 5b865914d1b..e2bbdefef7f 100644 --- a/spec/services/ci/list_config_variables_service_spec.rb +++ b/spec/services/ci/list_config_variables_service_spec.rb @@ -2,19 +2,21 @@ require 'spec_helper' -RSpec.describe Ci::ListConfigVariablesService, :use_clean_rails_memory_store_caching do +RSpec.describe Ci::ListConfigVariablesService, +:use_clean_rails_memory_store_caching, feature_category: :pipeline_authoring do include ReactiveCachingHelpers let(:ci_config) { {} } let(:files) { { '.gitlab-ci.yml' => YAML.dump(ci_config) } } let(:project) { create(:project, :custom_repo, :auto_devops_disabled, files: files) } let(:user) { project.creator } - let(:sha) { project.default_branch } + let(:ref) { project.default_branch } + let(:sha) { project.commit(ref).sha } let(:service) { described_class.new(project, user) } - subject(:result) { service.execute(sha) } + subject(:result) { service.execute(ref) } - context 'when sending a valid sha' do + context 'when sending a valid ref' do let(:ci_config) do { variables: { @@ -109,8 +111,8 @@ RSpec.describe Ci::ListConfigVariablesService, :use_clean_rails_memory_store_cac end end - context 'when sending an invalid sha' do - let(:sha) { 'invalid-sha' } + context 'when sending an invalid ref' do + let(:ref) { 'invalid-ref' } let(:ci_config) { nil } before do diff --git a/spec/services/ci/runners/stale_machines_cleanup_service_spec.rb b/spec/services/ci/runners/stale_machines_cleanup_service_spec.rb new file mode 100644 index 00000000000..456dbcebb84 --- /dev/null +++ b/spec/services/ci/runners/stale_machines_cleanup_service_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::Runners::StaleMachinesCleanupService, feature_category: :runner_fleet do + let(:service) { described_class.new } + let!(:runner_machine3) { create(:ci_runner_machine, created_at: 6.months.ago, contacted_at: Time.current) } + + subject(:response) { service.execute } + + context 'with no stale runner machines' do + it 'does not clean any runner machines and returns :success status' do + expect do + expect(response).to be_success + expect(response.payload).to match({ deleted_machines: false }) + end.not_to change { Ci::RunnerMachine.count }.from(1) + end + end + + context 'with some stale runner machines' do + before do + create(:ci_runner_machine, :stale) + create(:ci_runner_machine, :stale, contacted_at: nil) + end + + it 'only leaves non-stale runners' do + expect(response).to be_success + expect(response.payload).to match({ deleted_machines: true }) + expect(Ci::RunnerMachine.all).to contain_exactly(runner_machine3) + end + + context 'with more stale runners than MAX_DELETIONS' do + before do + stub_const("#{described_class}::MAX_DELETIONS", 1) + end + + it 'only leaves non-stale runners' do + expect do + expect(response).to be_success + expect(response.payload).to match({ deleted_machines: true }) + end.to change { Ci::RunnerMachine.count }.by(-Ci::Runners::StaleMachinesCleanupService::MAX_DELETIONS) + end + end + end +end diff --git a/spec/services/keys/revoke_service_spec.rb b/spec/services/keys/revoke_service_spec.rb new file mode 100644 index 00000000000..ec07701b4b7 --- /dev/null +++ b/spec/services/keys/revoke_service_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Keys::RevokeService, feature_category: :source_code_management do + let(:user) { create(:user) } + + subject(:service) { described_class.new(user) } + + it 'destroys a key' do + key = create(:key) + + expect { service.execute(key) }.to change { key.persisted? }.from(true).to(false) + end + + it 'unverifies associated signatures' do + key = create(:key) + signature = create(:ssh_signature, key: key) + + expect do + service.execute(key) + end.to change { signature.reload.key }.from(key).to(nil) + .and change { signature.reload.verification_status }.from('verified').to('revoked_key') + end + + it 'does not unverifies signatures if destroy fails' do + key = create(:key) + signature = create(:ssh_signature, key: key) + + expect(key).to receive(:destroy).and_return(false) + + expect { service.execute(key) }.not_to change { signature.reload.verification_status } + expect(key).to be_persisted + end + + context 'when revoke_ssh_signatures disabled' do + before do + stub_feature_flags(revoke_ssh_signatures: false) + end + + it 'does not unverifies signatures' do + key = create(:key) + signature = create(:ssh_signature, key: key) + + expect { service.execute(key) }.not_to change { signature.reload.verification_status } + end + end +end diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb index 82caec52aee..744808525f5 100644 --- a/spec/services/notes/destroy_service_spec.rb +++ b/spec/services/notes/destroy_service_spec.rb @@ -91,5 +91,13 @@ RSpec.describe Notes::DestroyService do end end end + + it 'tracks design comment removal' do + note = create(:note_on_design, project: project) + expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_design_comment_removed_action).with(author: note.author, + project: project) + + described_class.new(project, user).execute(note) + end end end diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index 6cba9332347..e50b08d8fbe 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -1674,7 +1674,6 @@ - './ee/spec/models/broadcast_message_spec.rb' - './ee/spec/models/burndown_spec.rb' - './ee/spec/models/ci/bridge_spec.rb' -- './ee/spec/models/ci/build_spec.rb' - './ee/spec/models/ci/daily_build_group_report_result_spec.rb' - './ee/spec/models/ci/minutes/additional_pack_spec.rb' - './ee/spec/models/ci/minutes/context_spec.rb' diff --git a/spec/views/profiles/keys/_key.html.haml_spec.rb b/spec/views/profiles/keys/_key.html.haml_spec.rb index d2e27bd2ee0..09053a29fe0 100644 --- a/spec/views/profiles/keys/_key.html.haml_spec.rb +++ b/spec/views/profiles/keys/_key.html.haml_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'profiles/keys/_key.html.haml' do +RSpec.describe 'profiles/keys/_key.html.haml', feature_category: :authentication_and_authorization do let_it_be(:user) { create(:user) } before do @@ -27,15 +27,18 @@ RSpec.describe 'profiles/keys/_key.html.haml' do expect(rendered).to have_text(l(key.last_used_at, format: "%b %d, %Y")) expect(rendered).to have_text(l(key.created_at, format: "%b %d, %Y")) expect(rendered).to have_text(key.expires_at.to_date) - expect(response).to render_template(partial: 'shared/ssh_keys/_key_delete') + expect(rendered).to have_button('Remove') end context 'displays the usage type' do - where(:usage_type, :usage_type_text) do + where(:usage_type, :usage_type_text, :displayed_buttons, :hidden_buttons, :revoke_ssh_signatures_ff) do [ - [:auth, 'Authentication'], - [:auth_and_signing, 'Authentication & Signing'], - [:signing, 'Signing'] + [:auth, 'Authentication', ['Remove'], ['Revoke'], true], + [:auth_and_signing, 'Authentication & Signing', %w[Remove Revoke], [], true], + [:signing, 'Signing', %w[Remove Revoke], [], true], + [:auth, 'Authentication', ['Remove'], ['Revoke'], false], + [:auth_and_signing, 'Authentication & Signing', %w[Remove], ['Revoke'], false], + [:signing, 'Signing', %w[Remove], ['Revoke'], false] ] end @@ -47,6 +50,20 @@ RSpec.describe 'profiles/keys/_key.html.haml' do expect(rendered).to have_text(usage_type_text) end + + it 'renders remove/revoke buttons', :aggregate_failures do + stub_feature_flags(revoke_ssh_signatures: revoke_ssh_signatures_ff) + + render + + displayed_buttons.each do |button| + expect(rendered).to have_text(button) + end + + hidden_buttons.each do |button| + expect(rendered).not_to have_text(button) + end + end end end @@ -98,7 +115,8 @@ RSpec.describe 'profiles/keys/_key.html.haml' do it 'does not render the partial' do render - expect(response).not_to render_template(partial: 'shared/ssh_keys/_key_delete') + expect(response).not_to have_text('Remove') + expect(response).not_to have_text('Revoke') end end diff --git a/spec/views/shared/ssh_keys/_key_delete.html.haml_spec.rb b/spec/views/shared/ssh_keys/_key_delete.html.haml_spec.rb index c9bdcabb4b6..5cef3a949d3 100644 --- a/spec/views/shared/ssh_keys/_key_delete.html.haml_spec.rb +++ b/spec/views/shared/ssh_keys/_key_delete.html.haml_spec.rb @@ -2,21 +2,9 @@ require 'spec_helper' RSpec.describe 'shared/ssh_keys/_key_delete.html.haml' do - context 'when the icon parameter is used' do - it 'has text' do - render partial: 'shared/ssh_keys/key_delete', formats: :html, locals: { icon: true, button_data: '' } + it 'has text' do + render partial: 'shared/ssh_keys/key_delete', formats: :html, locals: { button_data: '' } - expect(rendered).not_to have_button('Delete') - expect(rendered).to have_selector('[data-testid=remove-icon]') - end - end - - context 'when the icon parameter is not used' do - it 'does not have text' do - render partial: 'shared/ssh_keys/key_delete', formats: :html, locals: { button_data: '' } - - expect(rendered).to have_button('Delete') - expect(rendered).not_to have_selector('[data-testid=remove-icon]') - end + expect(rendered).to have_button('Delete') end end diff --git a/spec/workers/ci/runners/stale_machines_cleanup_cron_worker_spec.rb b/spec/workers/ci/runners/stale_machines_cleanup_cron_worker_spec.rb new file mode 100644 index 00000000000..d8f620bc024 --- /dev/null +++ b/spec/workers/ci/runners/stale_machines_cleanup_cron_worker_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::Runners::StaleMachinesCleanupCronWorker, feature_category: :runner_fleet do + let(:worker) { described_class.new } + + describe '#perform', :freeze_time do + subject(:perform) { worker.perform } + + let!(:runner_machine1) do + create(:ci_runner_machine, created_at: 7.days.ago, contacted_at: 7.days.ago) + end + + let!(:runner_machine2) { create(:ci_runner_machine) } + let!(:runner_machine3) { create(:ci_runner_machine, created_at: 6.days.ago) } + + it_behaves_like 'an idempotent worker' do + it 'delegates to Ci::Runners::StaleMachinesCleanupService' do + expect_next_instance_of(Ci::Runners::StaleMachinesCleanupService) do |service| + expect(service) + .to receive(:execute).and_call_original + end + + perform + + expect(worker.logging_extras).to eq({ + "extra.ci_runners_stale_machines_cleanup_cron_worker.status" => :success, + "extra.ci_runners_stale_machines_cleanup_cron_worker.deleted_machines" => true + }) + end + + it 'cleans up stale runner machines', :aggregate_failures do + expect(Ci::RunnerMachine.stale.count).to eq 1 + + expect { perform }.to change { Ci::RunnerMachine.count }.from(3).to(2) + + expect(Ci::RunnerMachine.all).to match_array [runner_machine2, runner_machine3] + end + end + end +end diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb index 5fde54b98f0..0abb029f146 100644 --- a/spec/workers/concerns/application_worker_spec.rb +++ b/spec/workers/concerns/application_worker_spec.rb @@ -103,6 +103,15 @@ RSpec.describe ApplicationWorker do expect(instance.logging_extras).to eq({ 'extra.gitlab_foo_bar_dummy_worker.key1' => "value1", 'extra.gitlab_foo_bar_dummy_worker.key2' => "value2" }) end + it 'returns extra data to be logged that was set from #log_hash_metadata_on_done' do + instance.log_hash_metadata_on_done({ key1: 'value0', key2: 'value1' }) + + expect(instance.logging_extras).to match_array({ + 'extra.gitlab_foo_bar_dummy_worker.key1' => 'value0', + 'extra.gitlab_foo_bar_dummy_worker.key2' => 'value1' + }) + end + context 'when nothing is set' do it 'returns {}' do expect(instance.logging_extras).to eq({}) |