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-01-19 00:10:01 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-01-19 00:10:01 +0300
commit75d101a1c2684059ea22cea9f00ca74d2db78b38 (patch)
tree67798118ceb61bc22c0825bd670b0448282dbed5 /spec
parent830a1f59e2a0f2aab22def4d7463a1c30532764d (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/dashboard_controller_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb1
-rw-r--r--spec/features/users/zuora_csp_spec.rb20
-rw-r--r--spec/frontend/admin/statistics_panel/components/app_spec.js3
-rw-r--r--spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js15
-rw-r--r--spec/frontend/blob/openapi/index_spec.js3
-rw-r--r--spec/frontend/clusters/clusters_bundle_spec.js3
-rw-r--r--spec/frontend/emoji/awards_app/store/actions_spec.js3
-rw-r--r--spec/frontend/environments/graphql/resolvers_spec.js21
-rw-r--r--spec/frontend/error_tracking_settings/store/actions_spec.js3
-rw-r--r--spec/frontend/filtered_search/filtered_search_dropdown_manager_spec.js3
-rw-r--r--spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js3
-rw-r--r--spec/frontend/ide/services/index_spec.js3
-rw-r--r--spec/frontend/ide/stores/actions_spec.js3
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_spec.js4
-rw-r--r--spec/frontend/import_entities/import_projects/store/actions_spec.js3
-rw-r--r--spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js2
-rw-r--r--spec/frontend/issues/list/components/issues_list_app_spec.js2
-rw-r--r--spec/frontend/issues/list/components/new_issue_dropdown_spec.js133
-rw-r--r--spec/frontend/issues/list/mock_data.js46
-rw-r--r--spec/frontend/issues/show/issue_spec.js3
-rw-r--r--spec/frontend/lib/utils/axios_utils_spec.js5
-rw-r--r--spec/frontend/milestones/components/delete_milestone_modal_spec.js7
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js4
-rw-r--r--spec/frontend/nav/components/new_nav_toggle_spec.js3
-rw-r--r--spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js5
-rw-r--r--spec/frontend/pipelines/graph/action_component_spec.js3
-rw-r--r--spec/frontend/pipelines/pipelines_actions_spec.js7
-rw-r--r--spec/frontend/projects/settings/components/shared_runners_toggle_spec.js3
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js3
-rw-r--r--spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/new_issue_dropdown/mock_data.js57
-rw-r--r--spec/frontend/vue_shared/components/new_issue_dropdown/new_issue_dropdown_spec.js149
-rw-r--r--spec/frontend/zen_mode_spec.js3
-rw-r--r--spec/lib/gitlab/content_security_policy/config_loader_spec.rb20
-rw-r--r--spec/models/merge_request_spec.rb9
36 files changed, 309 insertions, 251 deletions
diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb
index ea12b0c5ad7..b0a080a768a 100644
--- a/spec/controllers/dashboard_controller_spec.rb
+++ b/spec/controllers/dashboard_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe DashboardController do
+RSpec.describe DashboardController, feature_category: :code_review_workflow do
context 'signed in' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 237f361bd72..0297bb5b935 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
end
before do
+ stub_feature_flags(refactor_security_extension: false)
project.add_maintainer(user)
project_only_mwps.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/users/zuora_csp_spec.rb b/spec/features/users/zuora_csp_spec.rb
deleted file mode 100644
index b07c923fa54..00000000000
--- a/spec/features/users/zuora_csp_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Zuora content security policy', feature_category: :purchase do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
-
- before do
- project.add_developer(user)
- sign_in(user)
- end
-
- it 'has proper Content Security Policy headers' do
- visit pipeline_path(pipeline)
-
- expect(response_headers['Content-Security-Policy']).to include('https://*.zuora.com')
- end
-end
diff --git a/spec/frontend/admin/statistics_panel/components/app_spec.js b/spec/frontend/admin/statistics_panel/components/app_spec.js
index 190f0eb94a0..4c362a31068 100644
--- a/spec/frontend/admin/statistics_panel/components/app_spec.js
+++ b/spec/frontend/admin/statistics_panel/components/app_spec.js
@@ -8,6 +8,7 @@ import statisticsLabels from '~/admin/statistics_panel/constants';
import createStore from '~/admin/statistics_panel/store';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import mockStatistics from '../mock_data';
Vue.use(Vuex);
@@ -25,7 +26,7 @@ describe('Admin statistics app', () => {
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
- axiosMock.onGet(/api\/(.*)\/application\/statistics/).reply(200);
+ axiosMock.onGet(/api\/(.*)\/application\/statistics/).reply(HTTP_STATUS_OK);
store = createStore();
});
diff --git a/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js b/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
index 6369ea9aa15..23e4ff86f9a 100644
--- a/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
+++ b/spec/frontend/batch_comments/stores/modules/batch_comments/actions_spec.js
@@ -4,6 +4,7 @@ import testAction from 'helpers/vuex_action_helper';
import service from '~/batch_comments/services/drafts_service';
import * as actions from '~/batch_comments/stores/modules/batch_comments/actions';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
describe('Batch comments store actions', () => {
let res = {};
@@ -31,7 +32,7 @@ describe('Batch comments store actions', () => {
describe('addDraftToDiscussion', () => {
it('commits ADD_NEW_DRAFT if no errors returned', () => {
res = { id: 1 };
- mock.onAny().reply(200, res);
+ mock.onAny().reply(HTTP_STATUS_OK, res);
return testAction(
actions.addDraftToDiscussion,
@@ -58,7 +59,7 @@ describe('Batch comments store actions', () => {
describe('createNewDraft', () => {
it('commits ADD_NEW_DRAFT if no errors returned', () => {
res = { id: 1 };
- mock.onAny().reply(200, res);
+ mock.onAny().reply(HTTP_STATUS_OK, res);
return testAction(
actions.createNewDraft,
@@ -100,7 +101,7 @@ describe('Batch comments store actions', () => {
commit,
};
res = { id: 1 };
- mock.onAny().reply(200);
+ mock.onAny().reply(HTTP_STATUS_OK);
return actions.deleteDraft(context, { id: 1 }).then(() => {
expect(commit).toHaveBeenCalledWith('DELETE_DRAFT', 1);
@@ -144,7 +145,7 @@ describe('Batch comments store actions', () => {
},
};
res = { id: 1 };
- mock.onAny().reply(200, res);
+ mock.onAny().reply(HTTP_STATUS_OK, res);
return actions.fetchDrafts(context).then(() => {
expect(commit).toHaveBeenCalledWith('SET_BATCH_COMMENTS_DRAFTS', { id: 1 });
@@ -169,7 +170,7 @@ describe('Batch comments store actions', () => {
});
it('dispatches actions & commits', () => {
- mock.onAny().reply(200);
+ mock.onAny().reply(HTTP_STATUS_OK);
return actions.publishReview({ dispatch, commit, getters, rootGetters }).then(() => {
expect(commit.mock.calls[0]).toEqual(['REQUEST_PUBLISH_REVIEW']);
@@ -180,7 +181,7 @@ describe('Batch comments store actions', () => {
});
it('calls service with notes data', () => {
- mock.onAny().reply(200);
+ mock.onAny().reply(HTTP_STATUS_OK);
jest.spyOn(axios, 'post');
return actions
@@ -221,7 +222,7 @@ describe('Batch comments store actions', () => {
commit,
};
res = { id: 1 };
- mock.onAny().reply(200, res);
+ mock.onAny().reply(HTTP_STATUS_OK, res);
params = { note: { id: 1 }, noteText: 'test' };
});
diff --git a/spec/frontend/blob/openapi/index_spec.js b/spec/frontend/blob/openapi/index_spec.js
index d9d65258516..4b5cedcaee9 100644
--- a/spec/frontend/blob/openapi/index_spec.js
+++ b/spec/frontend/blob/openapi/index_spec.js
@@ -2,6 +2,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import renderOpenApi from '~/blob/openapi';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
describe('OpenAPI blob viewer', () => {
const id = 'js-openapi-viewer';
@@ -10,7 +11,7 @@ describe('OpenAPI blob viewer', () => {
beforeEach(async () => {
setHTMLFixture(`<div id="${id}" data-endpoint="${mockEndpoint}"></div>`);
- mock = new MockAdapter(axios).onGet().reply(200);
+ mock = new MockAdapter(axios).onGet().reply(HTTP_STATUS_OK);
await renderOpenApi();
});
diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js
index ad2aa4acbaf..114cf5a9856 100644
--- a/spec/frontend/clusters/clusters_bundle_spec.js
+++ b/spec/frontend/clusters/clusters_bundle_spec.js
@@ -3,6 +3,7 @@ import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import Clusters from '~/clusters/clusters_bundle';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import initProjectSelectDropdown from '~/project_select';
jest.mock('~/lib/utils/poll');
@@ -19,7 +20,7 @@ describe('Clusters', () => {
mock = new MockAdapter(axios);
- mock.onGet(statusPath).reply(200);
+ mock.onGet(statusPath).reply(HTTP_STATUS_OK);
};
beforeEach(() => {
diff --git a/spec/frontend/emoji/awards_app/store/actions_spec.js b/spec/frontend/emoji/awards_app/store/actions_spec.js
index cd3dfab30d4..4183652d20f 100644
--- a/spec/frontend/emoji/awards_app/store/actions_spec.js
+++ b/spec/frontend/emoji/awards_app/store/actions_spec.js
@@ -3,6 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import * as actions from '~/emoji/awards_app/store/actions';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
jest.mock('@sentry/browser');
jest.mock('~/vue_shared/plugins/global_toast');
@@ -152,7 +153,7 @@ describe('Awards app actions', () => {
describe('success', () => {
beforeEach(() => {
- mock.onDelete(`${relativeRootUrl || ''}/awards/1`).reply(200);
+ mock.onDelete(`${relativeRootUrl || ''}/awards/1`).reply(HTTP_STATUS_OK);
});
it('commits REMOVE_AWARD', async () => {
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js
index 7684cca2303..6aadbd6b558 100644
--- a/spec/frontend/environments/graphql/resolvers_spec.js
+++ b/spec/frontend/environments/graphql/resolvers_spec.js
@@ -1,6 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { resolvers } from '~/environments/graphql/resolvers';
import environmentToRollback from '~/environments/graphql/queries/environment_to_rollback.query.graphql';
import environmentToDelete from '~/environments/graphql/queries/environment_to_delete.query.graphql';
@@ -44,7 +45,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
const search = '';
mock
.onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search } })
- .reply(200, environmentsApp, {});
+ .reply(HTTP_STATUS_OK, environmentsApp, {});
const app = await mockResolvers.Query.environmentApp(
null,
@@ -63,7 +64,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
const interval = 3000;
mock
.onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } })
- .reply(200, environmentsApp, {
+ .reply(HTTP_STATUS_OK, environmentsApp, {
'poll-interval': interval,
});
@@ -78,7 +79,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
const scope = 'stopped';
mock
.onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } })
- .reply(200, environmentsApp, {
+ .reply(HTTP_STATUS_OK, environmentsApp, {
'x-next-page': '2',
'x-page': '1',
'X-Per-Page': '2',
@@ -108,7 +109,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
const scope = 'stopped';
mock
.onGet(ENDPOINT, { params: { nested: true, scope, page: 1, search: '' } })
- .reply(200, environmentsApp, {});
+ .reply(HTTP_STATUS_OK, environmentsApp, {});
await mockResolvers.Query.environmentApp(null, { scope, page: 1, search: '' }, { cache });
expect(cache.writeQuery).toHaveBeenCalledWith({
@@ -131,7 +132,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should fetch the folder url passed to it', async () => {
mock
.onGet(ENDPOINT, { params: { per_page: 3, scope: 'available', search: '' } })
- .reply(200, folder);
+ .reply(HTTP_STATUS_OK, folder);
const environmentFolder = await mockResolvers.Query.folder(null, {
environment: { folderPath: ENDPOINT },
@@ -144,7 +145,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
describe('stopEnvironment', () => {
it('should post to the stop environment path', async () => {
- mock.onPost(ENDPOINT).reply(200);
+ mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK);
const client = { writeQuery: jest.fn() };
const environment = { stopPath: ENDPOINT };
@@ -180,7 +181,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
describe('rollbackEnvironment', () => {
it('should post to the retry environment path', async () => {
- mock.onPost(ENDPOINT).reply(200);
+ mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK);
await mockResolvers.Mutation.rollbackEnvironment(null, {
environment: { retryUrl: ENDPOINT },
@@ -193,7 +194,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
describe('deleteEnvironment', () => {
it('should DELETE to the delete environment path', async () => {
- mock.onDelete(ENDPOINT).reply(200);
+ mock.onDelete(ENDPOINT).reply(HTTP_STATUS_OK);
await mockResolvers.Mutation.deleteEnvironment(null, {
environment: { deletePath: ENDPOINT },
@@ -206,7 +207,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
describe('cancelAutoStop', () => {
it('should post to the auto stop path', async () => {
- mock.onPost(ENDPOINT).reply(200);
+ mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK);
await mockResolvers.Mutation.cancelAutoStop(null, { autoStopUrl: ENDPOINT });
@@ -262,7 +263,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
describe('action', () => {
it('should POST to the given path', async () => {
- mock.onPost(ENDPOINT).reply(200);
+ mock.onPost(ENDPOINT).reply(HTTP_STATUS_OK);
const errors = await mockResolvers.Mutation.action(null, { action: { playPath: ENDPOINT } });
expect(errors).toEqual({ __typename: 'LocalEnvironmentErrors', errors: [] });
diff --git a/spec/frontend/error_tracking_settings/store/actions_spec.js b/spec/frontend/error_tracking_settings/store/actions_spec.js
index bcd816c2ae0..cb335bdbaf6 100644
--- a/spec/frontend/error_tracking_settings/store/actions_spec.js
+++ b/spec/frontend/error_tracking_settings/store/actions_spec.js
@@ -6,6 +6,7 @@ import * as types from '~/error_tracking_settings/store/mutation_types';
import defaultState from '~/error_tracking_settings/store/state';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { projectList } from '../mock';
@@ -118,7 +119,7 @@ describe('error tracking settings actions', () => {
});
it('should save the page', async () => {
- mock.onPatch(TEST_HOST).reply(200);
+ mock.onPatch(TEST_HOST).reply(HTTP_STATUS_OK);
await testAction(actions.updateSettings, null, state, [], [{ type: 'requestSettings' }]);
expect(mock.history.patch.length).toBe(1);
expect(refreshCurrentPage).toHaveBeenCalled();
diff --git a/spec/frontend/filtered_search/filtered_search_dropdown_manager_spec.js b/spec/frontend/filtered_search/filtered_search_dropdown_manager_spec.js
index dff6d11a320..30e1bfe94b5 100644
--- a/spec/frontend/filtered_search/filtered_search_dropdown_manager_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_dropdown_manager_spec.js
@@ -2,13 +2,14 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
describe('Filtered Search Dropdown Manager', () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onGet().reply(200);
+ mock.onGet().reply(HTTP_STATUS_OK);
});
describe('addWordToInput', () => {
diff --git a/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js b/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
index 28fcf0b7ec7..ec0c712f959 100644
--- a/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
+++ b/spec/frontend/filtered_search/filtered_search_visual_tokens_spec.js
@@ -4,6 +4,7 @@ import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import FilteredSearchSpecHelper from 'helpers/filtered_search_spec_helper';
import waitForPromises from 'helpers/wait_for_promises';
import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual_tokens';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
describe('Filtered Search Visual Tokens', () => {
@@ -24,7 +25,7 @@ describe('Filtered Search Visual Tokens', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onGet().reply(200);
+ mock.onGet().reply(HTTP_STATUS_OK);
setHTMLFixture(`
<ul class="tokens-container">
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index 5847e8e1518..cf373ed46de 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -5,6 +5,7 @@ import Api from '~/api';
import dismissUserCallout from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
import services from '~/ide/services';
import { query, mutate } from '~/ide/services/gql';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { escapeFileUrl } from '~/lib/utils/url_utility';
import ciConfig from '~/ci/pipeline_editor/graphql/queries/ci_config.query.graphql';
import { projectData } from '../mock_data';
@@ -271,7 +272,7 @@ describe('IDE services', () => {
const TEST_PROJECT_PATH = 'foo/bar';
const axiosURL = `${TEST_RELATIVE_URL_ROOT}/${TEST_PROJECT_PATH}/service_ping/web_ide_pipelines_count`;
- mock.onPost(axiosURL).reply(200);
+ mock.onPost(axiosURL).reply(HTTP_STATUS_OK);
return services.pingUsage(TEST_PROJECT_PATH).then(() => {
expect(axios.post).toHaveBeenCalledWith(axiosURL);
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index fd2c3d18813..7b5561bf35e 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -23,6 +23,7 @@ import {
} from '~/ide/stores/actions';
import * as types from '~/ide/stores/mutation_types';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_IM_A_TEAPOT } from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
import { file, createTriggerRenameAction, createTriggerChangeAction } from '../helpers';
@@ -927,7 +928,7 @@ describe('Multi-file store actions', () => {
});
it('does not pass the error further and flashes an alert if error is not 404', async () => {
- mock.onGet(/(.*)/).replyOnce(418);
+ mock.onGet(/(.*)/).replyOnce(HTTP_STATUS_IM_A_TEAPOT);
await expect(getBranchData(...callParams)).rejects.toEqual(
new Error('Branch not loaded - <strong>abc/def/main-testing</strong>'),
diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
index bd79e20e698..32c035e7a86 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
@@ -7,7 +7,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { createAlert } from '~/flash';
-import { HTTP_STATUS_BAD_REQUEST } from '~/lib/utils/http_status';
+import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import axios from '~/lib/utils/axios_utils';
import { STATUSES } from '~/import_entities/constants';
import { i18n, ROOT_NAMESPACE } from '~/import_entities/import_groups/constants';
@@ -113,7 +113,7 @@ describe('import table', () => {
beforeEach(() => {
axiosMock = new MockAdapter(axios);
- axiosMock.onGet(/.*\/exists$/, () => []).reply(200);
+ axiosMock.onGet(/.*\/exists$/, () => []).reply(HTTP_STATUS_OK);
});
afterEach(() => {
diff --git a/spec/frontend/import_entities/import_projects/store/actions_spec.js b/spec/frontend/import_entities/import_projects/store/actions_spec.js
index 4b34c21daa3..5607eee9f43 100644
--- a/spec/frontend/import_entities/import_projects/store/actions_spec.js
+++ b/spec/frontend/import_entities/import_projects/store/actions_spec.js
@@ -21,6 +21,7 @@ import {
import state from '~/import_entities/import_projects/store/state';
import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
jest.mock('~/flash');
@@ -433,7 +434,7 @@ describe('import_projects store actions', () => {
afterEach(() => mock.restore());
it('commits CANCEL_IMPORT_SUCCESS on success', async () => {
- mock.onPost(MOCK_ENDPOINT).reply(200);
+ mock.onPost(MOCK_ENDPOINT).reply(HTTP_STATUS_OK);
await testAction(
cancelImport,
diff --git a/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js b/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
index 065139f10f4..f2d12511707 100644
--- a/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
+++ b/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
@@ -2,7 +2,7 @@ import { GlEmptyState, GlLink } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import EmptyStateWithoutAnyIssues from '~/issues/list/components/empty_state_without_any_issues.vue';
-import NewIssueDropdown from '~/issues/list/components/new_issue_dropdown.vue';
+import NewIssueDropdown from '~/vue_shared/components/new_issue_dropdown/new_issue_dropdown.vue';
import { i18n } from '~/issues/list/constants';
describe('EmptyStateWithoutAnyIssues component', () => {
diff --git a/spec/frontend/issues/list/components/issues_list_app_spec.js b/spec/frontend/issues/list/components/issues_list_app_spec.js
index 4c5d8ce3cd1..89fa5b793b4 100644
--- a/spec/frontend/issues/list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues/list/components/issues_list_app_spec.js
@@ -30,7 +30,7 @@ import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/con
import EmptyStateWithAnyIssues from '~/issues/list/components/empty_state_with_any_issues.vue';
import EmptyStateWithoutAnyIssues from '~/issues/list/components/empty_state_without_any_issues.vue';
import IssuesListApp from '~/issues/list/components/issues_list_app.vue';
-import NewIssueDropdown from '~/issues/list/components/new_issue_dropdown.vue';
+import NewIssueDropdown from '~/vue_shared/components/new_issue_dropdown/new_issue_dropdown.vue';
import {
CREATED_DESC,
RELATIVE_POSITION,
diff --git a/spec/frontend/issues/list/components/new_issue_dropdown_spec.js b/spec/frontend/issues/list/components/new_issue_dropdown_spec.js
deleted file mode 100644
index 2c8cf9caf5d..00000000000
--- a/spec/frontend/issues/list/components/new_issue_dropdown_spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import NewIssueDropdown from '~/issues/list/components/new_issue_dropdown.vue';
-import searchProjectsQuery from '~/issues/list/queries/search_projects.query.graphql';
-import { DASH_SCOPE, joinPaths } from '~/lib/utils/url_utility';
-import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
-import {
- emptySearchProjectsQueryResponse,
- project1,
- project3,
- searchProjectsQueryResponse,
-} from '../mock_data';
-
-describe('NewIssueDropdown component', () => {
- let wrapper;
-
- Vue.use(VueApollo);
-
- const mountComponent = ({
- search = '',
- queryResponse = searchProjectsQueryResponse,
- mountFn = shallowMount,
- } = {}) => {
- const requestHandlers = [[searchProjectsQuery, jest.fn().mockResolvedValue(queryResponse)]];
- const apolloProvider = createMockApollo(requestHandlers);
-
- return mountFn(NewIssueDropdown, {
- apolloProvider,
- provide: {
- fullPath: 'mushroom-kingdom',
- },
- data() {
- return { search };
- },
- });
- };
-
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findInput = () => wrapper.findComponent(GlSearchBoxByType);
- const showDropdown = async () => {
- findDropdown().vm.$emit('shown');
- await waitForPromises();
- jest.advanceTimersByTime(DEBOUNCE_DELAY);
- await waitForPromises();
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders a split dropdown', () => {
- wrapper = mountComponent();
-
- expect(findDropdown().props('split')).toBe(true);
- });
-
- it('renders a label for the dropdown toggle button', () => {
- wrapper = mountComponent();
-
- expect(findDropdown().attributes('toggle-text')).toBe(NewIssueDropdown.i18n.toggleButtonLabel);
- });
-
- it('focuses on input when dropdown is shown', async () => {
- wrapper = mountComponent({ mountFn: mount });
-
- const inputSpy = jest.spyOn(findInput().vm, 'focusInput');
-
- await showDropdown();
-
- expect(inputSpy).toHaveBeenCalledTimes(1);
- });
-
- it('renders projects with issues enabled', async () => {
- wrapper = mountComponent({ mountFn: mount });
- await showDropdown();
-
- const listItems = wrapper.findAll('li');
-
- expect(listItems.at(0).text()).toBe(project1.nameWithNamespace);
- expect(listItems.at(1).text()).toBe(project3.nameWithNamespace);
- });
-
- it('renders `No matches found` when there are no matches', async () => {
- wrapper = mountComponent({
- search: 'no matches',
- queryResponse: emptySearchProjectsQueryResponse,
- mountFn: mount,
- });
-
- await showDropdown();
-
- expect(wrapper.find('li').text()).toBe(NewIssueDropdown.i18n.noMatchesFound);
- });
-
- describe('when no project is selected', () => {
- beforeEach(() => {
- wrapper = mountComponent();
- });
-
- it('dropdown button is not a link', () => {
- expect(findDropdown().attributes('split-href')).toBeUndefined();
- });
-
- it('displays default text on the dropdown button', () => {
- expect(findDropdown().props('text')).toBe(NewIssueDropdown.i18n.defaultDropdownText);
- });
- });
-
- describe('when a project is selected', () => {
- beforeEach(async () => {
- wrapper = mountComponent({ mountFn: mount });
- await waitForPromises();
- await showDropdown();
-
- wrapper.findComponent(GlDropdownItem).vm.$emit('click', project1);
- await waitForPromises();
- });
-
- it('dropdown button is a link', () => {
- const href = joinPaths(project1.webUrl, DASH_SCOPE, 'issues/new');
-
- expect(findDropdown().attributes('split-href')).toBe(href);
- });
-
- it('displays project name on the dropdown button', () => {
- expect(findDropdown().props('text')).toBe(`New issue in ${project1.name}`);
- });
- });
-});
diff --git a/spec/frontend/issues/list/mock_data.js b/spec/frontend/issues/list/mock_data.js
index 70b1521ff70..fc67d2e7605 100644
--- a/spec/frontend/issues/list/mock_data.js
+++ b/spec/frontend/issues/list/mock_data.js
@@ -343,49 +343,3 @@ export const urlParamsWithSpecialValues = {
weight: 'None',
health_status: 'None',
};
-
-export const project1 = {
- id: 'gid://gitlab/Group/26',
- issuesEnabled: true,
- name: 'Super Mario Project',
- nameWithNamespace: 'Mushroom Kingdom / Super Mario Project',
- webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/super-mario-project',
-};
-
-export const project2 = {
- id: 'gid://gitlab/Group/59',
- issuesEnabled: false,
- name: 'Mario Kart Project',
- nameWithNamespace: 'Mushroom Kingdom / Mario Kart Project',
- webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/mario-kart-project',
-};
-
-export const project3 = {
- id: 'gid://gitlab/Group/103',
- issuesEnabled: true,
- name: 'Mario Party Project',
- nameWithNamespace: 'Mushroom Kingdom / Mario Party Project',
- webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/mario-party-project',
-};
-
-export const searchProjectsQueryResponse = {
- data: {
- group: {
- id: '1',
- projects: {
- nodes: [project1, project2, project3],
- },
- },
- },
-};
-
-export const emptySearchProjectsQueryResponse = {
- data: {
- group: {
- id: '1',
- projects: {
- nodes: [],
- },
- },
- },
-};
diff --git a/spec/frontend/issues/show/issue_spec.js b/spec/frontend/issues/show/issue_spec.js
index 68c2e3768c7..892c5d79181 100644
--- a/spec/frontend/issues/show/issue_spec.js
+++ b/spec/frontend/issues/show/issue_spec.js
@@ -3,11 +3,12 @@ import waitForPromises from 'helpers/wait_for_promises';
import { initIssueApp } from '~/issues/show';
import * as parseData from '~/issues/show/utils/parse_data';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import createStore from '~/notes/stores';
import { appProps } from './mock_data/mock_data';
const mock = new MockAdapter(axios);
-mock.onGet().reply(200);
+mock.onGet().reply(HTTP_STATUS_OK);
jest.mock('~/lib/utils/poll');
diff --git a/spec/frontend/lib/utils/axios_utils_spec.js b/spec/frontend/lib/utils/axios_utils_spec.js
index 1585a38ae86..27c580a4d8b 100644
--- a/spec/frontend/lib/utils/axios_utils_spec.js
+++ b/spec/frontend/lib/utils/axios_utils_spec.js
@@ -3,14 +3,15 @@
import AxiosMockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
describe('axios_utils', () => {
let mock;
beforeEach(() => {
mock = new AxiosMockAdapter(axios);
- mock.onAny('/ok').reply(200);
- mock.onAny('/err').reply(500);
+ mock.onAny('/ok').reply(HTTP_STATUS_OK);
+ mock.onAny('/err').reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
// eslint-disable-next-line jest/no-standalone-expect
expect(axios.countActiveRequests()).toBe(0);
});
diff --git a/spec/frontend/milestones/components/delete_milestone_modal_spec.js b/spec/frontend/milestones/components/delete_milestone_modal_spec.js
index 6692a3b9347..87235fa843a 100644
--- a/spec/frontend/milestones/components/delete_milestone_modal_spec.js
+++ b/spec/frontend/milestones/components/delete_milestone_modal_spec.js
@@ -4,6 +4,7 @@ import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import DeleteMilestoneModal from '~/milestones/components/delete_milestone_modal.vue';
import eventHub from '~/milestones/event_hub';
+import { HTTP_STATUS_IM_A_TEAPOT, HTTP_STATUS_NOT_FOUND } from '~/lib/utils/http_status';
import { redirectTo } from '~/lib/utils/url_utility';
import { createAlert } from '~/flash';
@@ -71,9 +72,9 @@ describe('Delete milestone modal', () => {
});
it.each`
- statusCode | alertMessage
- ${418} | ${`Failed to delete milestone ${mockProps.milestoneTitle}`}
- ${404} | ${`Milestone ${mockProps.milestoneTitle} was not found`}
+ statusCode | alertMessage
+ ${HTTP_STATUS_IM_A_TEAPOT} | ${`Failed to delete milestone ${mockProps.milestoneTitle}`}
+ ${HTTP_STATUS_NOT_FOUND} | ${`Milestone ${mockProps.milestoneTitle} was not found`}
`(
'displays error if deleting milestone failed with code $statusCode',
async ({ statusCode, alertMessage }) => {
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index fbe030b1a7d..60e05483141 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -918,7 +918,7 @@ describe('Monitoring store actions', () => {
it('stars dashboard if it is not starred', () => {
state.selectedDashboard = unstarredDashboard;
- mock.onPost(unstarredDashboard.user_starred_path).reply(200);
+ mock.onPost(unstarredDashboard.user_starred_path).reply(HTTP_STATUS_OK);
return testAction(toggleStarredValue, null, state, [
{ type: types.REQUEST_DASHBOARD_STARRING },
@@ -934,7 +934,7 @@ describe('Monitoring store actions', () => {
it('unstars dashboard if it is starred', () => {
state.selectedDashboard = starredDashboard;
- mock.onPost(starredDashboard.user_starred_path).reply(200);
+ mock.onPost(starredDashboard.user_starred_path).reply(HTTP_STATUS_OK);
return testAction(toggleStarredValue, null, state, [
{ type: types.REQUEST_DASHBOARD_STARRING },
diff --git a/spec/frontend/nav/components/new_nav_toggle_spec.js b/spec/frontend/nav/components/new_nav_toggle_spec.js
index ee75dfb70e4..d6ca634ea9e 100644
--- a/spec/frontend/nav/components/new_nav_toggle_spec.js
+++ b/spec/frontend/nav/components/new_nav_toggle_spec.js
@@ -3,6 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import { getByText as getByTextHelper } from '@testing-library/dom';
import { GlToggle } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import NewNavToggle from '~/nav/components/new_nav_toggle.vue';
import waitForPromises from 'helpers/wait_for_promises';
@@ -74,7 +75,7 @@ describe('NewNavToggle', () => {
});
it('reloads the page on success', async () => {
- mock.onPut(TEST_ENDPONT).reply(200);
+ mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_OK);
actFn();
await waitForPromises();
diff --git a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js
index b7a9297d856..4d81803a9c0 100644
--- a/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js
+++ b/spec/frontend/pipelines/components/pipeline_mini_graph/pipeline_stage_spec.js
@@ -4,6 +4,7 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import PipelineStage from '~/pipelines/components/pipeline_mini_graph/pipeline_stage.vue';
import eventHub from '~/pipelines/event_hub';
import waitForPromises from 'helpers/wait_for_promises';
@@ -188,8 +189,8 @@ describe('Pipelines stage component', () => {
describe('job update in dropdown', () => {
beforeEach(async () => {
- mock.onGet(dropdownPath).reply(200, stageReply);
- mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
+ mock.onGet(dropdownPath).reply(HTTP_STATUS_OK, stageReply);
+ mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(HTTP_STATUS_OK);
createComponent();
await waitForPromises();
diff --git a/spec/frontend/pipelines/graph/action_component_spec.js b/spec/frontend/pipelines/graph/action_component_spec.js
index a823e029281..225a095fb3b 100644
--- a/spec/frontend/pipelines/graph/action_component_spec.js
+++ b/spec/frontend/pipelines/graph/action_component_spec.js
@@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import ActionComponent from '~/pipelines/components/jobs_shared/action_component.vue';
describe('pipeline graph action component', () => {
@@ -15,7 +16,7 @@ describe('pipeline graph action component', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onPost('foo.json').reply(200);
+ mock.onPost('foo.json').reply(HTTP_STATUS_OK);
wrapper = mount(ActionComponent, {
propsData: {
diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js
index a70ef10aa7b..384c48b99c6 100644
--- a/spec/frontend/pipelines/pipelines_actions_spec.js
+++ b/spec/frontend/pipelines/pipelines_actions_spec.js
@@ -7,6 +7,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { TEST_HOST } from 'spec/test_constants';
import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import PipelinesManualActions from '~/pipelines/components/pipelines_list/pipelines_manual_actions.vue';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
@@ -70,7 +71,7 @@ describe('Pipelines Actions dropdown', () => {
describe('on click', () => {
it('makes a request and toggles the loading state', async () => {
- mock.onPost(mockActions.path).reply(200);
+ mock.onPost(mockActions.path).reply(HTTP_STATUS_OK);
findAllDropdownItems().at(0).vm.$emit('click');
@@ -132,7 +133,7 @@ describe('Pipelines Actions dropdown', () => {
});
it('makes post request after confirming', async () => {
- mock.onPost(scheduledJobAction.path).reply(200);
+ mock.onPost(scheduledJobAction.path).reply(HTTP_STATUS_OK);
confirmAction.mockResolvedValueOnce(true);
findAllDropdownItems().at(0).vm.$emit('click');
@@ -145,7 +146,7 @@ describe('Pipelines Actions dropdown', () => {
});
it('does not make post request if confirmation is cancelled', async () => {
- mock.onPost(scheduledJobAction.path).reply(200);
+ mock.onPost(scheduledJobAction.path).reply(HTTP_STATUS_OK);
confirmAction.mockResolvedValueOnce(false);
findAllDropdownItems().at(0).vm.$emit('click');
diff --git a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
index 329060b9d10..dfaa1944cbe 100644
--- a/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
+++ b/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
@@ -4,6 +4,7 @@ import MockAxiosAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
const TEST_UPDATE_PATH = '/test/update_shared_runners';
@@ -36,7 +37,7 @@ describe('projects/settings/components/shared_runners', () => {
beforeEach(() => {
mockAxios = new MockAxiosAdapter(axios);
- mockAxios.onPost(TEST_UPDATE_PATH).reply(200);
+ mockAxios.onPost(TEST_UPDATE_PATH).reply(HTTP_STATUS_OK);
});
afterEach(() => {
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js
index 193a16bae8d..4775a0673b5 100644
--- a/spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js
@@ -2,6 +2,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import MemoryUsage from '~/vue_merge_request_widget/components/deployment/memory_usage.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
@@ -66,7 +67,7 @@ describe('MemoryUsage', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onGet(`${url}.json`).reply(200);
+ mock.onGet(`${url}.json`).reply(HTTP_STATUS_OK);
vm = createComponent();
el = vm.$el;
diff --git a/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js b/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js
index 683858b331d..a2d7f373c66 100644
--- a/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js
@@ -11,6 +11,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import { securityReportMergeRequestDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data';
import api from '~/api';
import axios from '~/lib/utils/axios_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import Poll from '~/lib/utils/poll';
import { setFaviconOverlay } from '~/lib/utils/favicon';
import notify from '~/lib/utils/notify';
@@ -837,7 +838,7 @@ describe('MrWidgetOptions', () => {
describe('suggestPipeline', () => {
beforeEach(() => {
- mock.onAny().reply(200);
+ mock.onAny().reply(HTTP_STATUS_OK);
});
describe('given feature flag is enabled', () => {
diff --git a/spec/frontend/vue_shared/components/new_issue_dropdown/mock_data.js b/spec/frontend/vue_shared/components/new_issue_dropdown/mock_data.js
new file mode 100644
index 00000000000..792506cda7a
--- /dev/null
+++ b/spec/frontend/vue_shared/components/new_issue_dropdown/mock_data.js
@@ -0,0 +1,57 @@
+export const emptySearchProjectsQueryResponse = {
+ data: {
+ projects: {
+ nodes: [],
+ },
+ },
+};
+
+export const emptySearchProjectsWithinGroupQueryResponse = {
+ data: {
+ group: {
+ id: '1',
+ projects: emptySearchProjectsQueryResponse.data.projects,
+ },
+ },
+};
+
+export const project1 = {
+ id: 'gid://gitlab/Group/26',
+ issuesEnabled: true,
+ name: 'Super Mario Project',
+ nameWithNamespace: 'Mushroom Kingdom / Super Mario Project',
+ webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/super-mario-project',
+};
+
+export const project2 = {
+ id: 'gid://gitlab/Group/59',
+ issuesEnabled: false,
+ name: 'Mario Kart Project',
+ nameWithNamespace: 'Mushroom Kingdom / Mario Kart Project',
+ webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/mario-kart-project',
+};
+
+export const project3 = {
+ id: 'gid://gitlab/Group/103',
+ issuesEnabled: true,
+ name: 'Mario Party Project',
+ nameWithNamespace: 'Mushroom Kingdom / Mario Party Project',
+ webUrl: 'https://127.0.0.1:3000/mushroom-kingdom/mario-party-project',
+};
+
+export const searchProjectsQueryResponse = {
+ data: {
+ projects: {
+ nodes: [project1, project2, project3],
+ },
+ },
+};
+
+export const searchProjectsWithinGroupQueryResponse = {
+ data: {
+ group: {
+ id: '1',
+ projects: searchProjectsQueryResponse.data.projects,
+ },
+ },
+};
diff --git a/spec/frontend/vue_shared/components/new_issue_dropdown/new_issue_dropdown_spec.js b/spec/frontend/vue_shared/components/new_issue_dropdown/new_issue_dropdown_spec.js
new file mode 100644
index 00000000000..5af4e5d3346
--- /dev/null
+++ b/spec/frontend/vue_shared/components/new_issue_dropdown/new_issue_dropdown_spec.js
@@ -0,0 +1,149 @@
+import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import NewIssueDropdown from '~/vue_shared/components/new_issue_dropdown/new_issue_dropdown.vue';
+import searchUserProjectsQuery from '~/vue_shared/components/new_issue_dropdown/graphql/search_user_projects.query.graphql';
+import searchProjectsWithinGroupQuery from '~/issues/list/queries/search_projects.query.graphql';
+import { DASH_SCOPE, joinPaths } from '~/lib/utils/url_utility';
+import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
+import {
+ emptySearchProjectsQueryResponse,
+ emptySearchProjectsWithinGroupQueryResponse,
+ project1,
+ project3,
+ searchProjectsQueryResponse,
+ searchProjectsWithinGroupQueryResponse,
+} from './mock_data';
+
+describe('NewIssueDropdown component', () => {
+ let wrapper;
+
+ Vue.use(VueApollo);
+
+ // Props
+ const withinGroupProps = {
+ query: searchProjectsWithinGroupQuery,
+ queryVariables: { fullPath: 'mushroom-kingdom' },
+ extractProjects: (data) => data.group.projects.nodes,
+ };
+
+ const mountComponent = ({
+ search = '',
+ query = searchUserProjectsQuery,
+ queryResponse = searchProjectsQueryResponse,
+ mountFn = shallowMount,
+ propsData = {},
+ } = {}) => {
+ const requestHandlers = [[query, jest.fn().mockResolvedValue(queryResponse)]];
+ const apolloProvider = createMockApollo(requestHandlers);
+
+ return mountFn(NewIssueDropdown, {
+ apolloProvider,
+ propsData,
+ data() {
+ return { search };
+ },
+ });
+ };
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findInput = () => wrapper.findComponent(GlSearchBoxByType);
+ const showDropdown = async () => {
+ findDropdown().vm.$emit('shown');
+ await waitForPromises();
+ jest.advanceTimersByTime(DEBOUNCE_DELAY);
+ await waitForPromises();
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a split dropdown', () => {
+ wrapper = mountComponent();
+
+ expect(findDropdown().props('split')).toBe(true);
+ });
+
+ it('renders a label for the dropdown toggle button', () => {
+ wrapper = mountComponent();
+
+ expect(findDropdown().attributes('toggle-text')).toBe(NewIssueDropdown.i18n.toggleButtonLabel);
+ });
+
+ it('focuses on input when dropdown is shown', async () => {
+ wrapper = mountComponent({ mountFn: mount });
+
+ const inputSpy = jest.spyOn(findInput().vm, 'focusInput');
+
+ await showDropdown();
+
+ expect(inputSpy).toHaveBeenCalledTimes(1);
+ });
+
+ describe.each`
+ description | propsData | query | queryResponse | emptyResponse
+ ${'by default'} | ${undefined} | ${searchUserProjectsQuery} | ${searchProjectsQueryResponse} | ${emptySearchProjectsQueryResponse}
+ ${'within a group'} | ${withinGroupProps} | ${searchProjectsWithinGroupQuery} | ${searchProjectsWithinGroupQueryResponse} | ${emptySearchProjectsWithinGroupQueryResponse}
+ `('$description', ({ propsData, query, queryResponse, emptyResponse }) => {
+ it('renders projects with issues enabled', async () => {
+ wrapper = mountComponent({ mountFn: mount, query, queryResponse, propsData });
+ await showDropdown();
+
+ const listItems = wrapper.findAll('li');
+
+ expect(listItems.at(0).text()).toBe(project1.nameWithNamespace);
+ expect(listItems.at(1).text()).toBe(project3.nameWithNamespace);
+ });
+
+ it('renders `No matches found` when there are no matches', async () => {
+ wrapper = mountComponent({
+ search: 'no matches',
+ query,
+ queryResponse: emptyResponse,
+ mountFn: mount,
+ propsData,
+ });
+
+ await showDropdown();
+
+ expect(wrapper.find('li').text()).toBe(NewIssueDropdown.i18n.noMatchesFound);
+ });
+
+ describe('when no project is selected', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({ query, queryResponse, propsData });
+ });
+
+ it('dropdown button is not a link', () => {
+ expect(findDropdown().attributes('split-href')).toBeUndefined();
+ });
+
+ it('displays default text on the dropdown button', () => {
+ expect(findDropdown().props('text')).toBe(NewIssueDropdown.i18n.defaultDropdownText);
+ });
+ });
+
+ describe('when a project is selected', () => {
+ beforeEach(async () => {
+ wrapper = mountComponent({ mountFn: mount, query, queryResponse, propsData });
+ await showDropdown();
+
+ wrapper.findComponent(GlDropdownItem).vm.$emit('click', project1);
+ });
+
+ it('dropdown button is a link', () => {
+ const href = joinPaths(project1.webUrl, DASH_SCOPE, 'issues/new');
+
+ expect(findDropdown().attributes('split-href')).toBe(href);
+ });
+
+ it('displays project name on the dropdown button', () => {
+ expect(findDropdown().props('text')).toBe(`New issue in ${project1.name}`);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/zen_mode_spec.js b/spec/frontend/zen_mode_spec.js
index a88910b2613..85f1dbdc305 100644
--- a/spec/frontend/zen_mode_spec.js
+++ b/spec/frontend/zen_mode_spec.js
@@ -6,6 +6,7 @@ import Mousetrap from 'mousetrap';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import GLForm from '~/gl_form';
import * as utils from '~/lib/utils/common_utils';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import ZenMode from '~/zen_mode';
describe('ZenMode', () => {
@@ -32,7 +33,7 @@ describe('ZenMode', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onGet().reply(200);
+ mock.onGet().reply(HTTP_STATUS_OK);
loadHTMLFixture(fixtureName);
diff --git a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
index 88bffd41947..f298890623f 100644
--- a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
+++ b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
@@ -94,13 +94,31 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
it 'adds CDN host to CSP' do
expect(directives['script_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.script_src + " https://cdn.example.com")
- expect(directives['style_src']).to eq("'self' 'unsafe-inline' https://cdn.example.com")
+ expect(directives['style_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.style_src + " https://cdn.example.com")
expect(directives['font_src']).to eq("'self' https://cdn.example.com")
expect(directives['worker_src']).to eq('http://localhost/assets/ blob: data: https://cdn.example.com')
expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " https://cdn.example.com http://localhost/admin/ http://localhost/assets/ http://localhost/-/speedscope/index.html http://localhost/-/sandbox/")
end
end
+ describe 'Zuora directives' do
+ context 'when is Gitlab.com?' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(true)
+ end
+
+ it 'adds Zuora host to CSP' do
+ expect(directives['frame_src']).to include('https://*.zuora.com/apps/PublicHostedPageLite.do')
+ end
+ end
+
+ context 'when is not Gitlab.com?' do
+ it 'does not add Zuora host to CSP' do
+ expect(directives['frame_src']).not_to include('https://*.zuora.com/apps/PublicHostedPageLite.do')
+ end
+ end
+ end
+
context 'when sentry is configured' do
let(:legacy_dsn) { 'dummy://abc@legacy-sentry.example.com/1' }
let(:dsn) { 'dummy://def@sentry.example.com/2' }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index a059d5cae9b..2d61bb80c56 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -135,6 +135,15 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
let_it_be(:merge_request3) { create(:merge_request, :unique_branches, reviewers: []) }
let_it_be(:merge_request4) { create(:merge_request, :draft_merge_request) }
+ describe '.preload_target_project_with_namespace' do
+ subject(:mr) { described_class.preload_target_project_with_namespace.first }
+
+ it 'returns MR with the target project\'s namespace preloaded' do
+ expect(mr.association(:target_project)).to be_loaded
+ expect(mr.target_project.association(:namespace)).to be_loaded
+ end
+ end
+
describe '.review_requested' do
it 'returns MRs that have any review requests' do
expect(described_class.review_requested).to eq([merge_request1, merge_request2])