summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/admin/users_controller_spec.rb6
-rw-r--r--spec/features/projects/user_uses_shortcuts_spec.rb12
-rw-r--r--spec/frontend/admin/abuse_reports/components/abuse_report_actions_spec.js6
-rw-r--r--spec/frontend/admin/abuse_reports/components/abuse_reports_filtered_search_bar_spec.js12
-rw-r--r--spec/frontend/admin/broadcast_messages/components/base_spec.js4
-rw-r--r--spec/frontend/analytics/shared/components/metric_tile_spec.js6
-rw-r--r--spec/frontend/authentication/password/components/password_input_spec.js2
-rw-r--r--spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js4
-rw-r--r--spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js6
-rw-r--r--spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js6
-rw-r--r--spec/frontend/ci/runner/admin_runner_show/admin_runner_show_app_spec.js4
-rw-r--r--spec/frontend/ci/runner/components/runner_update_form_spec.js6
-rw-r--r--spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js6
-rw-r--r--spec/frontend/ci/runner/group_runner_show/group_runner_show_app_spec.js4
-rw-r--r--spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js6
-rw-r--r--spec/frontend/gitlab_pages/new/pages/pages_pipeline_wizard_spec.js4
-rw-r--r--spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js4
-rw-r--r--spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js4
-rw-r--r--spec/frontend/jobs/components/job/manual_variables_form_spec.js6
-rw-r--r--spec/frontend/jobs/components/job/sidebar_detail_row_spec.js27
-rw-r--r--spec/frontend/jobs/components/table/cells/actions_cell_spec.js6
-rw-r--r--spec/frontend/listbox/redirect_behavior_spec.js6
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js9
-rw-r--r--spec/frontend/milestones/components/delete_milestone_modal_spec.js6
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap215
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/candidates/show/components/candidate_detail_row_spec.js49
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js139
-rw-r--r--spec/frontend/ml/experiment_tracking/routes/candidates/show/mock_data.js23
-rw-r--r--spec/frontend/monitoring/components/dashboard_actions_menu_spec.js6
-rw-r--r--spec/frontend/monitoring/components/dashboard_header_spec.js4
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js4
-rw-r--r--spec/frontend/pages/admin/jobs/components/cancel_jobs_modal_spec.js6
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_form_spec.js6
-rw-r--r--spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js4
-rw-r--r--spec/frontend/releases/stores/modules/detail/actions_spec.js6
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js4
-rw-r--r--spec/frontend/snippets/components/edit_spec.js8
-rw-r--r--spec/frontend/user_lists/components/edit_user_list_spec.js4
-rw-r--r--spec/frontend/user_lists/components/new_user_list_spec.js4
-rw-r--r--spec/frontend/user_lists/store/edit/actions_spec.js4
-rw-r--r--spec/frontend/user_lists/store/new/actions_spec.js4
-rw-r--r--spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js6
-rw-r--r--spec/lib/error_tracking/sentry_client/token_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/config/entry/cache_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb15
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb21
-rw-r--r--spec/lib/gitlab/config_checker/external_database_checker_spec.rb6
-rw-r--r--spec/lib/gitlab/database/partitioning_spec.rb15
-rw-r--r--spec/lib/gitlab/github_import/client_spec.rb10
-rw-r--r--spec/lib/gitlab/github_import/importer/collaborators_importer_spec.rb47
-rw-r--r--spec/lib/gitlab/github_import/settings_spec.rb15
-rw-r--r--spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb4
-rw-r--r--spec/models/ci/build_spec.rb138
-rw-r--r--spec/models/user_spec.rb14
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb13
-rw-r--r--spec/requests/api/users_spec.rb8
-rw-r--r--spec/serializers/runner_entity_spec.rb18
-rw-r--r--spec/services/ci/create_pipeline_service/cache_spec.rb15
-rw-r--r--spec/services/import/github_service_spec.rb3
-rw-r--r--spec/services/users/deactivate_service_spec.rb86
-rw-r--r--spec/workers/gitlab/github_import/stage/import_collaborators_worker_spec.rb19
63 files changed, 775 insertions, 411 deletions
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index ec2559550c3..9b00451de30 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -388,7 +388,7 @@ RSpec.describe Admin::UsersController do
put :deactivate, params: { id: user.username }
user.reload
expect(user.deactivated?).to be_falsey
- expect(flash[:notice]).to eq("The user you are trying to deactivate has been active in the past #{Gitlab::CurrentSettings.deactivate_dormant_users_period} days and cannot be deactivated")
+ expect(flash[:alert]).to eq("The user you are trying to deactivate has been active in the past #{Gitlab::CurrentSettings.deactivate_dormant_users_period} days and cannot be deactivated")
end
end
end
@@ -410,7 +410,7 @@ RSpec.describe Admin::UsersController do
put :deactivate, params: { id: user.username }
user.reload
expect(user.deactivated?).to be_falsey
- expect(flash[:notice]).to eq('Error occurred. A blocked user cannot be deactivated')
+ expect(flash[:alert]).to eq('Error occurred. A blocked user cannot be deactivated')
end
end
@@ -421,7 +421,7 @@ RSpec.describe Admin::UsersController do
put :deactivate, params: { id: internal_user.username }
expect(internal_user.reload.deactivated?).to be_falsey
- expect(flash[:notice]).to eq('Internal users cannot be deactivated')
+ expect(flash[:alert]).to eq('Internal users cannot be deactivated')
end
end
end
diff --git a/spec/features/projects/user_uses_shortcuts_spec.rb b/spec/features/projects/user_uses_shortcuts_spec.rb
index 1bad04382f4..1d4ab242308 100644
--- a/spec/features/projects/user_uses_shortcuts_spec.rb
+++ b/spec/features/projects/user_uses_shortcuts_spec.rb
@@ -69,11 +69,11 @@ RSpec.describe 'User uses shortcuts', :js, feature_category: :projects do
end
context 'when navigating to the Project pages' do
- it 'redirects to the project page' do
+ it 'redirects to the project overview page' do
visit project_issues_path(project)
find('body').native.send_key('g')
- find('body').native.send_key('p')
+ find('body').native.send_key('o')
expect(page).to have_active_navigation(project.name)
end
@@ -156,6 +156,14 @@ RSpec.describe 'User uses shortcuts', :js, feature_category: :projects do
end
context 'when navigating to the CI/CD pages' do
+ it 'redirects to the Pipelines page' do
+ find('body').native.send_key('g')
+ find('body').native.send_key('p')
+
+ expect(page).to have_active_navigation('CI/CD')
+ expect(page).to have_active_sub_navigation('Pipelines')
+ end
+
it 'redirects to the Jobs page' do
find('body').native.send_key('g')
find('body').native.send_key('j')
diff --git a/spec/frontend/admin/abuse_reports/components/abuse_report_actions_spec.js b/spec/frontend/admin/abuse_reports/components/abuse_report_actions_spec.js
index 571d01a2fb5..09b6b1edc44 100644
--- a/spec/frontend/admin/abuse_reports/components/abuse_report_actions_spec.js
+++ b/spec/frontend/admin/abuse_reports/components/abuse_report_actions_spec.js
@@ -5,7 +5,7 @@ import { GlDisclosureDropdown, GlDisclosureDropdownItem, GlModal } from '@gitlab
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import AbuseReportActions from '~/admin/abuse_reports/components/abuse_report_actions.vue';
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
-import { redirectTo, refreshCurrentPage } from '~/lib/utils/url_utility';
+import { redirectTo, refreshCurrentPage } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { createAlert, VARIANT_SUCCESS } from '~/alert';
import { sprintf } from '~/locale';
import { ACTIONS_I18N } from '~/admin/abuse_reports/constants';
@@ -115,7 +115,7 @@ describe('AbuseReportActions', () => {
findConfirmationModal().vm.$emit('primary');
await axios.waitForAll();
- expect(redirectTo).toHaveBeenCalledWith('/redirect_path');
+ expect(redirectTo).toHaveBeenCalledWith('/redirect_path'); // eslint-disable-line import/no-deprecated
});
});
});
@@ -194,7 +194,7 @@ describe('AbuseReportActions', () => {
await axios.waitForAll();
- expect(redirectTo).toHaveBeenCalledWith('/redirect_path');
+ expect(redirectTo).toHaveBeenCalledWith('/redirect_path'); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/admin/abuse_reports/components/abuse_reports_filtered_search_bar_spec.js b/spec/frontend/admin/abuse_reports/components/abuse_reports_filtered_search_bar_spec.js
index 990503c453d..1f3f2caa995 100644
--- a/spec/frontend/admin/abuse_reports/components/abuse_reports_filtered_search_bar_spec.js
+++ b/spec/frontend/admin/abuse_reports/components/abuse_reports_filtered_search_bar_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { redirectTo, updateHistory } from '~/lib/utils/url_utility';
+import { redirectTo, updateHistory } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import AbuseReportsFilteredSearchBar from '~/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue';
import {
FILTERED_SEARCH_TOKENS,
@@ -161,23 +161,24 @@ describe('AbuseReportsFilteredSearchBar', () => {
(filterToken) => {
createComponentAndFilter([filterToken]);
const { type, value } = filterToken;
- expect(redirectTo).toHaveBeenCalledWith(`https://localhost/?${type}=${value.data}`);
+ expect(redirectTo).toHaveBeenCalledWith(`https://localhost/?${type}=${value.data}`); // eslint-disable-line import/no-deprecated
},
);
it('ignores search query param', () => {
const searchFilterToken = { type: FILTERED_SEARCH_TERM, value: { data: 'ignored' } };
createComponentAndFilter([USER_FILTER_TOKEN, searchFilterToken]);
- expect(redirectTo).toHaveBeenCalledWith('https://localhost/?user=mr_abuser');
+ expect(redirectTo).toHaveBeenCalledWith('https://localhost/?user=mr_abuser'); // eslint-disable-line import/no-deprecated
});
it('redirects without page query param', () => {
createComponentAndFilter([USER_FILTER_TOKEN], '?page=2');
- expect(redirectTo).toHaveBeenCalledWith('https://localhost/?user=mr_abuser');
+ expect(redirectTo).toHaveBeenCalledWith('https://localhost/?user=mr_abuser'); // eslint-disable-line import/no-deprecated
});
it('redirects with existing sort query param', () => {
createComponentAndFilter([USER_FILTER_TOKEN], `?sort=${DEFAULT_SORT}`);
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
`https://localhost/?user=mr_abuser&sort=${DEFAULT_SORT}`,
);
@@ -197,6 +198,7 @@ describe('AbuseReportsFilteredSearchBar', () => {
it('redirects to URL with existing query params and the sort query param', () => {
createComponentAndSort(`?${EXISTING_QUERY}`);
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
`https://localhost/?${EXISTING_QUERY}&sort=${SORT_VALUE}`,
);
@@ -205,6 +207,7 @@ describe('AbuseReportsFilteredSearchBar', () => {
it('redirects without page query param', () => {
createComponentAndSort(`?${EXISTING_QUERY}&page=2`);
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
`https://localhost/?${EXISTING_QUERY}&sort=${SORT_VALUE}`,
);
@@ -213,6 +216,7 @@ describe('AbuseReportsFilteredSearchBar', () => {
it('redirects with existing sort query param replaced with the new one', () => {
createComponentAndSort(`?${EXISTING_QUERY}&sort=created_at_desc`);
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
`https://localhost/?${EXISTING_QUERY}&sort=${SORT_VALUE}`,
);
diff --git a/spec/frontend/admin/broadcast_messages/components/base_spec.js b/spec/frontend/admin/broadcast_messages/components/base_spec.js
index 50d8eeb563d..80577f86e3e 100644
--- a/spec/frontend/admin/broadcast_messages/components/base_spec.js
+++ b/spec/frontend/admin/broadcast_messages/components/base_spec.js
@@ -7,7 +7,7 @@ import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { createAlert } from '~/alert';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import BroadcastMessagesBase from '~/admin/broadcast_messages/components/base.vue';
import MessagesTable from '~/admin/broadcast_messages/components/messages_table.vue';
import { generateMockMessages, MOCK_MESSAGES } from '../mock_data';
@@ -107,6 +107,6 @@ describe('BroadcastMessagesBase', () => {
findTable().vm.$emit('delete-message', id);
await waitForPromises();
- expect(redirectTo).toHaveBeenCalledWith(`${TEST_HOST}/admin/broadcast_messages?page=1`);
+ expect(redirectTo).toHaveBeenCalledWith(`${TEST_HOST}/admin/broadcast_messages?page=1`); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/analytics/shared/components/metric_tile_spec.js b/spec/frontend/analytics/shared/components/metric_tile_spec.js
index 00e82cff0f0..9da5ed0fb07 100644
--- a/spec/frontend/analytics/shared/components/metric_tile_spec.js
+++ b/spec/frontend/analytics/shared/components/metric_tile_spec.js
@@ -2,7 +2,7 @@ import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
import MetricTile from '~/analytics/shared/components/metric_tile.vue';
import MetricPopover from '~/analytics/shared/components/metric_popover.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
jest.mock('~/lib/utils/url_utility');
@@ -34,7 +34,7 @@ describe('MetricTile', () => {
const singleStat = findSingleStat();
singleStat.vm.$emit('click');
- expect(redirectTo).toHaveBeenCalledWith('foo/bar');
+ expect(redirectTo).toHaveBeenCalledWith('foo/bar'); // eslint-disable-line import/no-deprecated
});
it("when the metric doesn't have links, it won't the user on click", () => {
@@ -43,7 +43,7 @@ describe('MetricTile', () => {
const singleStat = findSingleStat();
singleStat.vm.$emit('click');
- expect(redirectTo).not.toHaveBeenCalled();
+ expect(redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/authentication/password/components/password_input_spec.js b/spec/frontend/authentication/password/components/password_input_spec.js
index 9960539af10..5b2a9da993b 100644
--- a/spec/frontend/authentication/password/components/password_input_spec.js
+++ b/spec/frontend/authentication/password/components/password_input_spec.js
@@ -10,6 +10,7 @@ describe('PasswordInput', () => {
id: 'new_user_password',
minimumPasswordLength: '8',
qaSelector: 'new_user_password_field',
+ testid: 'new_user_password',
autocomplete: 'new-password',
name: 'new_user',
};
@@ -33,6 +34,7 @@ describe('PasswordInput', () => {
expect(findPasswordInput().attributes('name')).toBe(propsData.name);
expect(findPasswordInput().attributes('minlength')).toBe(propsData.minimumPasswordLength);
expect(findPasswordInput().attributes('data-qa-selector')).toBe(propsData.qaSelector);
+ expect(findPasswordInput().attributes('data-testid')).toBe(propsData.testid);
expect(findPasswordInput().attributes('title')).toBe(propsData.title);
});
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 8bac46a3e9c..cc4a022c2df 100644
--- a/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
@@ -6,7 +6,7 @@ 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 { objectToQuery, redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { resolvers } from '~/ci/pipeline_editor/graphql/resolvers';
import PipelineEditorTabs from '~/ci/pipeline_editor/components/pipeline_editor_tabs.vue';
import PipelineEditorEmptyState from '~/ci/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
@@ -434,7 +434,7 @@ describe('Pipeline editor app component', () => {
'merge_request[target_branch]': mockDefaultBranch,
});
- expect(redirectTo).toHaveBeenCalledWith(`${mockNewMergeRequestPath}?${branchesQuery}`);
+ expect(redirectTo).toHaveBeenCalledWith(`${mockNewMergeRequestPath}?${branchesQuery}`); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js b/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js
index a08a01009e2..1d4ae33c667 100644
--- a/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js
@@ -13,7 +13,7 @@ import {
HTTP_STATUS_INTERNAL_SERVER_ERROR,
HTTP_STATUS_OK,
} from '~/lib/utils/http_status';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import PipelineNewForm, {
POLLING_INTERVAL,
} from '~/ci/pipeline_new/components/pipeline_new_form.vue';
@@ -212,7 +212,7 @@ describe('Pipeline New Form', () => {
await waitForPromises();
expect(getFormPostParams().ref).toEqual(`refs/heads/${defaultBranch}`);
- expect(redirectTo).toHaveBeenCalledWith(`${pipelinesPath}/${newPipelinePostResponse.id}`);
+ expect(redirectTo).toHaveBeenCalledWith(`${pipelinesPath}/${newPipelinePostResponse.id}`); // eslint-disable-line import/no-deprecated
});
it('creates a pipeline with short ref and variables from the query params', async () => {
@@ -225,7 +225,7 @@ describe('Pipeline New Form', () => {
await waitForPromises();
expect(getFormPostParams()).toEqual(mockPostParams);
- expect(redirectTo).toHaveBeenCalledWith(`${pipelinesPath}/${newPipelinePostResponse.id}`);
+ expect(redirectTo).toHaveBeenCalledWith(`${pipelinesPath}/${newPipelinePostResponse.id}`); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js b/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js
index 62aba4e4be6..4c56dd74f1a 100644
--- a/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js
+++ b/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js
@@ -16,7 +16,7 @@ import {
WINDOWS_PLATFORM,
} from '~/ci/runner/constants';
import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { runnerCreateResult } from '../mock_data';
jest.mock('~/ci/runner/local_storage_alert/save_alert_to_local_storage');
@@ -87,7 +87,7 @@ describe('AdminNewRunnerApp', () => {
it('redirects to the registration page', () => {
const url = `${mockCreatedRunner.ephemeralRegisterUrl}?${PARAM_KEY_PLATFORM}=${DEFAULT_PLATFORM}`;
- expect(redirectTo).toHaveBeenCalledWith(url);
+ expect(redirectTo).toHaveBeenCalledWith(url); // eslint-disable-line import/no-deprecated
});
});
@@ -100,7 +100,7 @@ describe('AdminNewRunnerApp', () => {
it('redirects to the registration page with the platform', () => {
const url = `${mockCreatedRunner.ephemeralRegisterUrl}?${PARAM_KEY_PLATFORM}=${WINDOWS_PLATFORM}`;
- expect(redirectTo).toHaveBeenCalledWith(url);
+ expect(redirectTo).toHaveBeenCalledWith(url); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/ci/runner/admin_runner_show/admin_runner_show_app_spec.js b/spec/frontend/ci/runner/admin_runner_show/admin_runner_show_app_spec.js
index d1f95aef349..9787b1ef83f 100644
--- a/spec/frontend/ci/runner/admin_runner_show/admin_runner_show_app_spec.js
+++ b/spec/frontend/ci/runner/admin_runner_show/admin_runner_show_app_spec.js
@@ -5,7 +5,7 @@ import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_help
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert, VARIANT_SUCCESS } from '~/alert';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import RunnerHeader from '~/ci/runner/components/runner_header.vue';
@@ -180,7 +180,7 @@ describe('AdminRunnerShowApp', () => {
message: 'Runner deleted',
variant: VARIANT_SUCCESS,
});
- expect(redirectTo).toHaveBeenCalledWith(mockRunnersPath);
+ expect(redirectTo).toHaveBeenCalledWith(mockRunnersPath); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/ci/runner/components/runner_update_form_spec.js b/spec/frontend/ci/runner/components/runner_update_form_spec.js
index 620e2f85890..db4c236bfff 100644
--- a/spec/frontend/ci/runner/components/runner_update_form_spec.js
+++ b/spec/frontend/ci/runner/components/runner_update_form_spec.js
@@ -6,7 +6,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert, VARIANT_SUCCESS } from '~/alert';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import RunnerUpdateForm from '~/ci/runner/components/runner_update_form.vue';
import {
INSTANCE_TYPE,
@@ -86,7 +86,7 @@ describe('RunnerUpdateForm', () => {
variant: VARIANT_SUCCESS,
}),
);
- expect(redirectTo).toHaveBeenCalledWith(mockRunnerPath);
+ expect(redirectTo).toHaveBeenCalledWith(mockRunnerPath); // eslint-disable-line import/no-deprecated
};
beforeEach(() => {
@@ -278,7 +278,7 @@ describe('RunnerUpdateForm', () => {
expect(captureException).not.toHaveBeenCalled();
expect(saveAlertToLocalStorage).not.toHaveBeenCalled();
- expect(redirectTo).not.toHaveBeenCalled();
+ expect(redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js b/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js
index e2cf46023b1..1c052b00fc3 100644
--- a/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js
+++ b/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js
@@ -16,7 +16,7 @@ import {
WINDOWS_PLATFORM,
} from '~/ci/runner/constants';
import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { runnerCreateResult } from '../mock_data';
const mockGroupId = 'gid://gitlab/Group/72';
@@ -92,7 +92,7 @@ describe('GroupRunnerRunnerApp', () => {
it('redirects to the registration page', () => {
const url = `${mockCreatedRunner.ephemeralRegisterUrl}?${PARAM_KEY_PLATFORM}=${DEFAULT_PLATFORM}`;
- expect(redirectTo).toHaveBeenCalledWith(url);
+ expect(redirectTo).toHaveBeenCalledWith(url); // eslint-disable-line import/no-deprecated
});
});
@@ -105,7 +105,7 @@ describe('GroupRunnerRunnerApp', () => {
it('redirects to the registration page with the platform', () => {
const url = `${mockCreatedRunner.ephemeralRegisterUrl}?${PARAM_KEY_PLATFORM}=${WINDOWS_PLATFORM}`;
- expect(redirectTo).toHaveBeenCalledWith(url);
+ expect(redirectTo).toHaveBeenCalledWith(url); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/ci/runner/group_runner_show/group_runner_show_app_spec.js b/spec/frontend/ci/runner/group_runner_show/group_runner_show_app_spec.js
index 60f51704c0e..0c594e8005c 100644
--- a/spec/frontend/ci/runner/group_runner_show/group_runner_show_app_spec.js
+++ b/spec/frontend/ci/runner/group_runner_show/group_runner_show_app_spec.js
@@ -5,7 +5,7 @@ import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_help
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert, VARIANT_SUCCESS } from '~/alert';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import RunnerHeader from '~/ci/runner/components/runner_header.vue';
@@ -185,7 +185,7 @@ describe('GroupRunnerShowApp', () => {
message: 'Runner deleted',
variant: VARIANT_SUCCESS,
});
- expect(redirectTo).toHaveBeenCalledWith(mockRunnersPath);
+ expect(redirectTo).toHaveBeenCalledWith(mockRunnersPath); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js b/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js
index 4bb5b25fe15..5bfbbfdc074 100644
--- a/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js
+++ b/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js
@@ -16,7 +16,7 @@ import {
WINDOWS_PLATFORM,
} from '~/ci/runner/constants';
import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { runnerCreateResult, mockRegistrationToken } from '../mock_data';
const mockProjectId = 'gid://gitlab/Project/72';
@@ -93,7 +93,7 @@ describe('ProjectRunnerRunnerApp', () => {
it('redirects to the registration page', () => {
const url = `${mockCreatedRunner.ephemeralRegisterUrl}?${PARAM_KEY_PLATFORM}=${DEFAULT_PLATFORM}`;
- expect(redirectTo).toHaveBeenCalledWith(url);
+ expect(redirectTo).toHaveBeenCalledWith(url); // eslint-disable-line import/no-deprecated
});
});
@@ -106,7 +106,7 @@ describe('ProjectRunnerRunnerApp', () => {
it('redirects to the registration page with the platform', () => {
const url = `${mockCreatedRunner.ephemeralRegisterUrl}?${PARAM_KEY_PLATFORM}=${WINDOWS_PLATFORM}`;
- expect(redirectTo).toHaveBeenCalledWith(url);
+ expect(redirectTo).toHaveBeenCalledWith(url); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/gitlab_pages/new/pages/pages_pipeline_wizard_spec.js b/spec/frontend/gitlab_pages/new/pages/pages_pipeline_wizard_spec.js
index b1adc3f794a..289702a4263 100644
--- a/spec/frontend/gitlab_pages/new/pages/pages_pipeline_wizard_spec.js
+++ b/spec/frontend/gitlab_pages/new/pages/pages_pipeline_wizard_spec.js
@@ -7,7 +7,7 @@ import PagesPipelineWizard, { i18n } from '~/gitlab_pages/components/pages_pipel
import PipelineWizard from '~/pipeline_wizard/pipeline_wizard.vue';
import pagesTemplate from '~/pipeline_wizard/templates/pages.yml';
import pagesMarkOnboardingComplete from '~/gitlab_pages/queries/mark_onboarding_complete.graphql';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
Vue.use(VueApollo);
@@ -92,7 +92,7 @@ describe('PagesPipelineWizard', () => {
await waitForPromises();
- expect(redirectTo).toHaveBeenCalledWith(props.redirectToWhenDone);
+ expect(redirectTo).toHaveBeenCalledWith(props.redirectToWhenDone); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js b/spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js
index 2294d236e8b..29af6dc946f 100644
--- a/spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js
+++ b/spec/frontend/import_entities/import_projects/components/advanced_settings_spec.js
@@ -5,8 +5,8 @@ import AdvancedSettingsPanel from '~/import_entities/import_projects/components/
describe('Import Advanced Settings', () => {
let wrapper;
const OPTIONAL_STAGES = [
- { name: 'stage1', label: 'Stage 1' },
- { name: 'stage2', label: 'Stage 2', details: 'Extra details' },
+ { name: 'stage1', label: 'Stage 1', selected: false },
+ { name: 'stage2', label: 'Stage 2', details: 'Extra details', selected: false },
];
const createComponent = () => {
diff --git a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
index f7bc0e4a0e8..351bbe5ea28 100644
--- a/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
+++ b/spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
@@ -285,7 +285,7 @@ describe('ImportProjectsTable', () => {
});
it('should render advanced settings panel when no optional steps are passed', () => {
- const OPTIONAL_STAGES = [{ name: 'step1', label: 'Step 1' }];
+ const OPTIONAL_STAGES = [{ name: 'step1', label: 'Step 1', selected: true }];
createComponent({ state: { providerRepos: [providerRepo] }, optionalStages: OPTIONAL_STAGES });
expect(wrapper.findComponent(AdvancedSettingsPanel).exists()).toBe(true);
@@ -293,7 +293,7 @@ describe('ImportProjectsTable', () => {
OPTIONAL_STAGES,
);
expect(wrapper.findComponent(AdvancedSettingsPanel).props('value')).toStrictEqual({
- step1: false,
+ step1: true,
});
});
});
diff --git a/spec/frontend/jobs/components/job/manual_variables_form_spec.js b/spec/frontend/jobs/components/job/manual_variables_form_spec.js
index c8c865dd28e..a48155d93ac 100644
--- a/spec/frontend/jobs/components/job/manual_variables_form_spec.js
+++ b/spec/frontend/jobs/components/job/manual_variables_form_spec.js
@@ -9,7 +9,7 @@ import { TYPENAME_CI_BUILD } from '~/graphql_shared/constants';
import { JOB_GRAPHQL_ERRORS } from '~/jobs/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import waitForPromises from 'helpers/wait_for_promises';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import ManualVariablesForm from '~/jobs/components/job/manual_variables_form.vue';
import getJobQuery from '~/jobs/components/job/graphql/queries/get_job.query.graphql';
import playJobMutation from '~/jobs/components/job/graphql/mutations/job_play_with_variables.mutation.graphql';
@@ -192,7 +192,7 @@ describe('Manual Variables Form', () => {
await waitForPromises();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
- expect(redirectTo).toHaveBeenCalledWith(mockJobPlayMutationData.data.jobPlay.job.webPath);
+ expect(redirectTo).toHaveBeenCalledWith(mockJobPlayMutationData.data.jobPlay.job.webPath); // eslint-disable-line import/no-deprecated
});
});
@@ -227,7 +227,7 @@ describe('Manual Variables Form', () => {
await waitForPromises();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
- expect(redirectTo).toHaveBeenCalledWith(mockJobRetryMutationData.data.jobRetry.job.webPath);
+ expect(redirectTo).toHaveBeenCalledWith(mockJobRetryMutationData.data.jobRetry.job.webPath); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/jobs/components/job/sidebar_detail_row_spec.js b/spec/frontend/jobs/components/job/sidebar_detail_row_spec.js
index dd5a9e3491d..fd27004816a 100644
--- a/spec/frontend/jobs/components/job/sidebar_detail_row_spec.js
+++ b/spec/frontend/jobs/components/job/sidebar_detail_row_spec.js
@@ -1,5 +1,4 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SidebarDetailRow from '~/jobs/components/job/sidebar/sidebar_detail_row.vue';
describe('Sidebar detail row', () => {
@@ -8,18 +7,20 @@ describe('Sidebar detail row', () => {
const title = 'this is the title';
const value = 'this is the value';
const helpUrl = 'https://docs.gitlab.com/runner/register/index.html';
+ const path = 'path/to/value';
- const findHelpLink = () => wrapper.findComponent(GlLink);
+ const findHelpLink = () => wrapper.findByTestId('job-sidebar-help-link');
+ const findValueLink = () => wrapper.findByTestId('job-sidebar-value-link');
const createComponent = (props) => {
- wrapper = shallowMount(SidebarDetailRow, {
+ wrapper = shallowMountExtended(SidebarDetailRow, {
propsData: {
...props,
},
});
};
- describe('with title/value and without helpUrl', () => {
+ describe('with title/value and without helpUrl/path', () => {
beforeEach(() => {
createComponent({ title, value });
});
@@ -31,6 +32,10 @@ describe('Sidebar detail row', () => {
it('should not render the help link', () => {
expect(findHelpLink().exists()).toBe(false);
});
+
+ it('should not render the value link', () => {
+ expect(findValueLink().exists()).toBe(false);
+ });
});
describe('when helpUrl provided', () => {
@@ -47,4 +52,16 @@ describe('Sidebar detail row', () => {
expect(findHelpLink().attributes('href')).toBe(helpUrl);
});
});
+
+ describe('when path is provided', () => {
+ it('should render link to value', () => {
+ createComponent({
+ path,
+ title,
+ value,
+ });
+
+ expect(findValueLink().attributes('href')).toBe(path);
+ });
+ });
});
diff --git a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js b/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
index 79bc765f181..f2d249b6014 100644
--- a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
+++ b/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import ActionsCell from '~/jobs/components/table/cells/actions_cell.vue';
import eventHub from '~/jobs/components/table/event_hub';
import JobPlayMutation from '~/jobs/components/table/graphql/mutations/job_play.mutation.graphql';
@@ -146,7 +146,7 @@ describe('Job actions cell', () => {
await waitForPromises();
expect(eventHub.$emit).toHaveBeenCalledWith('jobActionPerformed');
- expect(redirectTo).not.toHaveBeenCalled();
+ expect(redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
},
);
@@ -165,7 +165,7 @@ describe('Job actions cell', () => {
await waitForPromises();
- expect(redirectTo).toHaveBeenCalledWith(redirectLink);
+ expect(redirectTo).toHaveBeenCalledWith(redirectLink); // eslint-disable-line import/no-deprecated
expect(eventHub.$emit).not.toHaveBeenCalled();
},
);
diff --git a/spec/frontend/listbox/redirect_behavior_spec.js b/spec/frontend/listbox/redirect_behavior_spec.js
index 7b2a40b65ce..c2479e71e4a 100644
--- a/spec/frontend/listbox/redirect_behavior_spec.js
+++ b/spec/frontend/listbox/redirect_behavior_spec.js
@@ -1,6 +1,6 @@
import { initListbox } from '~/listbox';
import { initRedirectListboxBehavior } from '~/listbox/redirect_behavior';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { getFixture, setHTMLFixture } from 'helpers/fixtures';
jest.mock('~/lib/utils/url_utility');
@@ -42,10 +42,10 @@ describe('initRedirectListboxBehavior', () => {
const { onChange } = firstCallArgs[1];
const mockItem = { href: '/foo' };
- expect(redirectTo).not.toHaveBeenCalled();
+ expect(redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
onChange(mockItem);
- expect(redirectTo).toHaveBeenCalledWith(mockItem.href);
+ expect(redirectTo).toHaveBeenCalledWith(mockItem.href); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
index f346967121c..29b7ceae0e3 100644
--- a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
+++ b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import MembersFilteredSearchBar from '~/members/components/filter_sort/members_filtered_search_bar.vue';
import {
MEMBER_TYPES,
@@ -167,7 +167,7 @@ describe('MembersFilteredSearchBar', () => {
{ type: FILTERED_SEARCH_TOKEN_TWO_FACTOR.type, value: { data: 'enabled', operator: '=' } },
]);
- expect(redirectTo).toHaveBeenCalledWith('https://localhost/?two_factor=enabled');
+ expect(redirectTo).toHaveBeenCalledWith('https://localhost/?two_factor=enabled'); // eslint-disable-line import/no-deprecated
});
it('adds search query param', () => {
@@ -178,6 +178,7 @@ describe('MembersFilteredSearchBar', () => {
{ type: FILTERED_SEARCH_TERM, value: { data: 'foobar' } },
]);
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
'https://localhost/?two_factor=enabled&search=foobar',
);
@@ -191,6 +192,7 @@ describe('MembersFilteredSearchBar', () => {
{ type: FILTERED_SEARCH_TERM, value: { data: 'foo bar baz' } },
]);
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
'https://localhost/?two_factor=enabled&search=foo+bar+baz',
);
@@ -206,6 +208,7 @@ describe('MembersFilteredSearchBar', () => {
{ type: FILTERED_SEARCH_TERM, value: { data: 'foobar' } },
]);
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
'https://localhost/?two_factor=enabled&search=foobar&sort=name_asc',
);
@@ -220,7 +223,7 @@ describe('MembersFilteredSearchBar', () => {
{ type: FILTERED_SEARCH_TERM, value: { data: 'foobar' } },
]);
- expect(redirectTo).toHaveBeenCalledWith('https://localhost/?search=foobar&tab=invited');
+ expect(redirectTo).toHaveBeenCalledWith('https://localhost/?search=foobar&tab=invited'); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/milestones/components/delete_milestone_modal_spec.js b/spec/frontend/milestones/components/delete_milestone_modal_spec.js
index f8730fd93a3..ad6aedaa8ff 100644
--- a/spec/frontend/milestones/components/delete_milestone_modal_spec.js
+++ b/spec/frontend/milestones/components/delete_milestone_modal_spec.js
@@ -5,7 +5,7 @@ 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 { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { createAlert } from '~/alert';
jest.mock('~/lib/utils/url_utility');
@@ -60,7 +60,7 @@ describe('Delete milestone modal', () => {
});
});
await findModal().vm.$emit('primary');
- expect(redirectTo).toHaveBeenCalledWith(responseURL);
+ expect(redirectTo).toHaveBeenCalledWith(responseURL); // eslint-disable-line import/no-deprecated
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: mockProps.milestoneUrl,
successful: true,
@@ -90,7 +90,7 @@ describe('Delete milestone modal', () => {
expect(createAlert).toHaveBeenCalledWith({
message: alertMessage,
});
- expect(redirectTo).not.toHaveBeenCalled();
+ expect(redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: mockProps.milestoneUrl,
successful: false,
diff --git a/spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap b/spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap
deleted file mode 100644
index 0d2615e3b80..00000000000
--- a/spec/frontend/ml/experiment_tracking/routes/candidates/show/__snapshots__/ml_candidates_show_spec.js.snap
+++ /dev/null
@@ -1,215 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`MlCandidatesShow renders correctly 1`] = `
-<div>
- <model-experiments-header-stub
- pagetitle="Model candidate details"
- >
- <delete-button-stub
- actionprimarytext="Delete candidate"
- deleteconfirmationtext="Deleting this candidate will delete the associated parameters, metrics, and metadata."
- deletepath="path_to_candidate"
- modaltitle="Delete candidate?"
- />
- </model-experiments-header-stub>
-
- <table
- class="candidate-details gl-w-full"
- >
- <tbody>
- <tr
- class="divider"
- />
-
- <tr>
- <td
- class="gl-text-secondary gl-font-weight-bold"
- >
- Info
- </td>
-
- <td
- class="gl-font-weight-bold"
- >
- ID
- </td>
-
- <td>
- candidate_iid
- </td>
- </tr>
-
- <tr>
- <td />
-
- <td
- class="gl-font-weight-bold"
- >
- MLflow run ID
- </td>
-
- <td>
- abcdefg
- </td>
- </tr>
-
- <tr>
- <td />
-
- <td
- class="gl-font-weight-bold"
- >
- Status
- </td>
-
- <td>
- SUCCESS
- </td>
- </tr>
-
- <tr>
- <td />
-
- <td
- class="gl-font-weight-bold"
- >
- Experiment
- </td>
-
- <td>
- <gl-link-stub>
- The Experiment
- </gl-link-stub>
- </td>
- </tr>
-
- <tr>
- <td />
-
- <td
- class="gl-font-weight-bold"
- >
- Artifacts
- </td>
-
- <td>
- <gl-link-stub
- href="path_to_artifact"
- >
- Artifacts
- </gl-link-stub>
- </td>
- </tr>
-
- <tr
- class="divider"
- />
-
- <tr>
- <td
- class="gl-text-secondary gl-font-weight-bold"
- >
-
- Parameters
-
- </td>
-
- <td
- class="gl-font-weight-bold"
- >
- Algorithm
- </td>
-
- <td>
- Decision Tree
- </td>
- </tr>
- <tr>
- <td />
-
- <td
- class="gl-font-weight-bold"
- >
- MaxDepth
- </td>
-
- <td>
- 3
- </td>
- </tr>
- <tr
- class="divider"
- />
-
- <tr>
- <td
- class="gl-text-secondary gl-font-weight-bold"
- >
-
- Metrics
-
- </td>
-
- <td
- class="gl-font-weight-bold"
- >
- AUC
- </td>
-
- <td>
- .55
- </td>
- </tr>
- <tr>
- <td />
-
- <td
- class="gl-font-weight-bold"
- >
- Accuracy
- </td>
-
- <td>
- .99
- </td>
- </tr>
- <tr
- class="divider"
- />
-
- <tr>
- <td
- class="gl-text-secondary gl-font-weight-bold"
- >
-
- Metadata
-
- </td>
-
- <td
- class="gl-font-weight-bold"
- >
- FileName
- </td>
-
- <td>
- test.py
- </td>
- </tr>
- <tr>
- <td />
-
- <td
- class="gl-font-weight-bold"
- >
- ExecutionTime
- </td>
-
- <td>
- .0856
- </td>
- </tr>
- </tbody>
- </table>
-</div>
-`;
diff --git a/spec/frontend/ml/experiment_tracking/routes/candidates/show/components/candidate_detail_row_spec.js b/spec/frontend/ml/experiment_tracking/routes/candidates/show/components/candidate_detail_row_spec.js
new file mode 100644
index 00000000000..8a39c5de2b3
--- /dev/null
+++ b/spec/frontend/ml/experiment_tracking/routes/candidates/show/components/candidate_detail_row_spec.js
@@ -0,0 +1,49 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
+import DetailRow from '~/ml/experiment_tracking/routes/candidates/show/components/candidate_detail_row.vue';
+
+describe('CandidateDetailRow', () => {
+ const SECTION_LABEL_CELL = 0;
+ const ROW_LABEL_CELL = 1;
+ const ROW_VALUE_CELL = 2;
+
+ let wrapper;
+
+ const createWrapper = (href = '') => {
+ wrapper = shallowMount(DetailRow, {
+ propsData: { sectionLabel: 'Section', label: 'Item', text: 'Text', href },
+ });
+ };
+
+ const findCellAt = (index) => wrapper.findAll('td').at(index);
+ const findLink = () => findCellAt(ROW_VALUE_CELL).findComponent(GlLink);
+
+ beforeEach(() => createWrapper());
+
+ it('renders section label', () => {
+ expect(findCellAt(SECTION_LABEL_CELL).text()).toBe('Section');
+ });
+
+ it('renders row label', () => {
+ expect(findCellAt(ROW_LABEL_CELL).text()).toBe('Item');
+ });
+
+ describe('No href', () => {
+ it('Renders text', () => {
+ expect(findCellAt(ROW_VALUE_CELL).text()).toBe('Text');
+ });
+
+ it('Does not render as link', () => {
+ expect(findLink().exists()).toBe(false);
+ });
+ });
+
+ describe('With href', () => {
+ beforeEach(() => createWrapper('LINK'));
+
+ it('Renders link', () => {
+ expect(findLink().attributes().href).toBe('LINK');
+ expect(findLink().text()).toBe('Text');
+ });
+ });
+});
diff --git a/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js b/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js
index d7044cbcd9b..9d1c22faa8f 100644
--- a/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js
+++ b/spec/frontend/ml/experiment_tracking/routes/candidates/show/ml_candidates_show_spec.js
@@ -1,58 +1,119 @@
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { shallowMount } from '@vue/test-utils';
import MlCandidatesShow from '~/ml/experiment_tracking/routes/candidates/show';
+import DetailRow from '~/ml/experiment_tracking/routes/candidates/show/components/candidate_detail_row.vue';
import { TITLE_LABEL } from '~/ml/experiment_tracking/routes/candidates/show/translations';
import DeleteButton from '~/ml/experiment_tracking/components/delete_button.vue';
import ModelExperimentsHeader from '~/ml/experiment_tracking/components/model_experiments_header.vue';
+import { newCandidate } from './mock_data';
describe('MlCandidatesShow', () => {
let wrapper;
+ const CANDIDATE = newCandidate();
- const createWrapper = () => {
- const candidate = {
- params: [
- { name: 'Algorithm', value: 'Decision Tree' },
- { name: 'MaxDepth', value: '3' },
- ],
- metrics: [
- { name: 'AUC', value: '.55' },
- { name: 'Accuracy', value: '.99' },
- ],
- metadata: [
- { name: 'FileName', value: 'test.py' },
- { name: 'ExecutionTime', value: '.0856' },
- ],
- info: {
- iid: 'candidate_iid',
- eid: 'abcdefg',
- path_to_artifact: 'path_to_artifact',
- experiment_name: 'The Experiment',
- experiment_path: 'path/to/experiment',
- status: 'SUCCESS',
- path: 'path_to_candidate',
- },
- };
-
- wrapper = shallowMountExtended(MlCandidatesShow, { propsData: { candidate } });
+ const createWrapper = (createCandidate = () => CANDIDATE) => {
+ wrapper = shallowMount(MlCandidatesShow, {
+ propsData: { candidate: createCandidate() },
+ });
};
- beforeEach(createWrapper);
-
const findDeleteButton = () => wrapper.findComponent(DeleteButton);
const findHeader = () => wrapper.findComponent(ModelExperimentsHeader);
+ const findNthDetailRow = (index) => wrapper.findAllComponents(DetailRow).at(index);
+ const findSectionLabel = (label) => wrapper.find(`[sectionLabel='${label}']`);
+ const findLabel = (label) => wrapper.find(`[label='${label}']`);
- it('shows delete button', () => {
- expect(findDeleteButton().exists()).toBe(true);
- });
+ describe('Header', () => {
+ beforeEach(() => createWrapper());
- it('passes the delete path to delete button', () => {
- expect(findDeleteButton().props('deletePath')).toBe('path_to_candidate');
- });
+ it('shows delete button', () => {
+ expect(findDeleteButton().exists()).toBe(true);
+ });
+
+ it('passes the delete path to delete button', () => {
+ expect(findDeleteButton().props('deletePath')).toBe('path_to_candidate');
+ });
- it('passes the right title', () => {
- expect(findHeader().props('pageTitle')).toBe(TITLE_LABEL);
+ it('passes the right title', () => {
+ expect(findHeader().props('pageTitle')).toBe(TITLE_LABEL);
+ });
});
- it('renders correctly', () => {
- expect(wrapper.element).toMatchSnapshot();
+ describe('Detail Table', () => {
+ describe('All info available', () => {
+ beforeEach(() => createWrapper());
+
+ const expectedTable = [
+ ['Info', 'ID', CANDIDATE.info.iid, ''],
+ ['', 'MLflow run ID', CANDIDATE.info.eid, ''],
+ ['', 'Status', CANDIDATE.info.status, ''],
+ ['', 'Experiment', CANDIDATE.info.experiment_name, CANDIDATE.info.path_to_experiment],
+ ['', 'Artifacts', 'Artifacts', CANDIDATE.info.path_to_artifact],
+ ['Parameters', CANDIDATE.params[0].name, CANDIDATE.params[0].value, ''],
+ ['', CANDIDATE.params[1].name, CANDIDATE.params[1].value, ''],
+ ['Metrics', CANDIDATE.metrics[0].name, CANDIDATE.metrics[0].value, ''],
+ ['', CANDIDATE.metrics[1].name, CANDIDATE.metrics[1].value, ''],
+ ['Metadata', CANDIDATE.metadata[0].name, CANDIDATE.metadata[0].value, ''],
+ ['', CANDIDATE.metadata[1].name, CANDIDATE.metadata[1].value, ''],
+ ].map((row, index) => [index, ...row]);
+
+ it.each(expectedTable)(
+ 'row %s is created correctly',
+ (index, sectionLabel, label, text, href) => {
+ const row = findNthDetailRow(index);
+
+ expect(row.props()).toMatchObject({ sectionLabel, label, text, href });
+ },
+ );
+ it('does not render params', () => {
+ expect(findSectionLabel('Parameters').exists()).toBe(true);
+ });
+
+ it('renders all conditional rows', () => {
+ // This is a bit of a duplicated test from the above table test, but having this makes sure that the
+ // tests that test the negatives are implemented correctly
+ expect(findLabel('Artifacts').exists()).toBe(true);
+ expect(findSectionLabel('Parameters').exists()).toBe(true);
+ expect(findSectionLabel('Metadata').exists()).toBe(true);
+ expect(findSectionLabel('Metrics').exists()).toBe(true);
+ });
+ });
+
+ describe('No artifact path', () => {
+ beforeEach(() =>
+ createWrapper(() => {
+ const candidate = newCandidate();
+ delete candidate.info.path_to_artifact;
+ return candidate;
+ }),
+ );
+
+ it('does not render artifact row', () => {
+ expect(findLabel('Artifacts').exists()).toBe(false);
+ });
+ });
+
+ describe('No params, metrics, ci or metadata available', () => {
+ beforeEach(() =>
+ createWrapper(() => {
+ const candidate = newCandidate();
+ delete candidate.params;
+ delete candidate.metrics;
+ delete candidate.metadata;
+ return candidate;
+ }),
+ );
+
+ it('does not render params', () => {
+ expect(findSectionLabel('Parameters').exists()).toBe(false);
+ });
+
+ it('does not render metadata', () => {
+ expect(findSectionLabel('Metadata').exists()).toBe(false);
+ });
+
+ it('does not render metrics', () => {
+ expect(findSectionLabel('Metrics').exists()).toBe(false);
+ });
+ });
});
});
diff --git a/spec/frontend/ml/experiment_tracking/routes/candidates/show/mock_data.js b/spec/frontend/ml/experiment_tracking/routes/candidates/show/mock_data.js
new file mode 100644
index 00000000000..cad2c03fc93
--- /dev/null
+++ b/spec/frontend/ml/experiment_tracking/routes/candidates/show/mock_data.js
@@ -0,0 +1,23 @@
+export const newCandidate = () => ({
+ params: [
+ { name: 'Algorithm', value: 'Decision Tree' },
+ { name: 'MaxDepth', value: '3' },
+ ],
+ metrics: [
+ { name: 'AUC', value: '.55' },
+ { name: 'Accuracy', value: '.99' },
+ ],
+ metadata: [
+ { name: 'FileName', value: 'test.py' },
+ { name: 'ExecutionTime', value: '.0856' },
+ ],
+ info: {
+ iid: 'candidate_iid',
+ eid: 'abcdefg',
+ path_to_artifact: 'path_to_artifact',
+ experiment_name: 'The Experiment',
+ path_to_experiment: 'path/to/experiment',
+ status: 'SUCCESS',
+ path: 'path_to_candidate',
+ },
+});
diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
index c54acf3cbee..4d290922707 100644
--- a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
@@ -2,7 +2,7 @@ import { GlDropdownItem, GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue';
import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from '~/monitoring/router/constants';
import { createStore } from '~/monitoring/stores';
@@ -292,8 +292,8 @@ describe('Actions menu', () => {
findDuplicateDashboardModal().vm.$emit('dashboardDuplicated', newDashboard);
await nextTick();
- expect(redirectTo).toHaveBeenCalled();
- expect(redirectTo).toHaveBeenCalledWith(newDashboardUrl);
+ expect(redirectTo).toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
+ expect(redirectTo).toHaveBeenCalledWith(newDashboardUrl); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js
index e54b87c307c..091e05ab271 100644
--- a/spec/frontend/monitoring/components/dashboard_header_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_header_spec.js
@@ -1,7 +1,7 @@
import { GlDropdownItem, GlSearchBoxByType, GlLoadingIcon, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import ActionsMenu from '~/monitoring/components/dashboard_actions_menu.vue';
import DashboardHeader from '~/monitoring/components/dashboard_header.vue';
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
@@ -74,6 +74,7 @@ describe('Dashboard header', () => {
display_name: 'A display name',
});
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(
`${mockProjectPath}/-/metrics/.gitlab%2Fdashboards%2Fdashboard%26copy.yml`,
);
@@ -85,6 +86,7 @@ describe('Dashboard header', () => {
display_name: 'dashboard&copy.yml',
});
+ // eslint-disable-next-line import/no-deprecated
expect(redirectTo).toHaveBeenCalledWith(`${mockProjectPath}/-/metrics/dashboard%26copy.yml`);
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index c43f6446b99..b123d1e7d79 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -5,7 +5,7 @@ import { createAlert } from '~/alert';
import axios from '~/lib/utils/axios_utils';
import {
queryToObject,
- redirectTo,
+ redirectTo, // eslint-disable-line import/no-deprecated
removeParams,
mergeUrlParams,
updateHistory,
@@ -136,7 +136,7 @@ describe('dashboard invalid url parameters', () => {
// redirect to with new parameters
expect(mergeUrlParams).toHaveBeenCalledWith({ duration_seconds: '120' }, toUrl);
- expect(redirectTo).toHaveBeenCalledTimes(1);
+ expect(redirectTo).toHaveBeenCalledTimes(1); // eslint-disable-line import/no-deprecated
});
it('changes the url when a panel moves the time slider', async () => {
diff --git a/spec/frontend/pages/admin/jobs/components/cancel_jobs_modal_spec.js b/spec/frontend/pages/admin/jobs/components/cancel_jobs_modal_spec.js
index afd7ee09ae8..b1d2e443d54 100644
--- a/spec/frontend/pages/admin/jobs/components/cancel_jobs_modal_spec.js
+++ b/spec/frontend/pages/admin/jobs/components/cancel_jobs_modal_spec.js
@@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import CancelJobsModal from '~/pages/admin/jobs/components/cancel_jobs_modal.vue';
jest.mock('~/lib/utils/url_utility', () => ({
@@ -41,7 +41,7 @@ describe('Cancel jobs modal', () => {
wrapper.findComponent(GlModal).vm.$emit('primary');
await nextTick();
- expect(redirectTo).toHaveBeenCalledWith(responseURL);
+ expect(redirectTo).toHaveBeenCalledWith(responseURL); // eslint-disable-line import/no-deprecated
});
it('displays error if canceling jobs failed', async () => {
@@ -60,7 +60,7 @@ describe('Cancel jobs modal', () => {
wrapper.findComponent(GlModal).vm.$emit('primary');
await nextTick();
- expect(redirectTo).not.toHaveBeenCalled();
+ expect(redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
index 9dce6fde6f6..722857a1420 100644
--- a/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
+++ b/spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
@@ -461,7 +461,7 @@ describe('ForkForm component', () => {
await submitForm();
- expect(urlUtility.redirectTo).not.toHaveBeenCalled();
+ expect(urlUtility.redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
});
it('does not make POST request if no visibility is checked', async () => {
@@ -549,7 +549,7 @@ describe('ForkForm component', () => {
setupComponent();
await submitForm();
- expect(urlUtility.redirectTo).toHaveBeenCalledWith(webUrl);
+ expect(urlUtility.redirectTo).toHaveBeenCalledWith(webUrl); // eslint-disable-line import/no-deprecated
});
it('displays an alert when POST is unsuccessful', async () => {
@@ -560,7 +560,7 @@ describe('ForkForm component', () => {
setupComponent();
await submitForm();
- expect(urlUtility.redirectTo).not.toHaveBeenCalled();
+ expect(urlUtility.redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
expect(createAlert).toHaveBeenCalledWith({
message: 'An error occurred while forking the project. Please try again.',
});
diff --git a/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js b/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js
index 071977c9481..d5307b87a11 100644
--- a/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js
+++ b/spec/frontend/pipelines/components/jobs/failed_jobs_table_spec.js
@@ -5,7 +5,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { createAlert } from '~/alert';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import FailedJobsTable from '~/pipelines/components/jobs/failed_jobs_table.vue';
import RetryFailedJobMutation from '~/pipelines/graphql/mutations/retry_failed_job.mutation.graphql';
import {
@@ -94,7 +94,7 @@ describe('Failed Jobs Table', () => {
await waitForPromises();
- expect(redirectTo).toHaveBeenCalledWith(job.detailedStatus.detailsPath);
+ expect(redirectTo).toHaveBeenCalledWith(job.detailedStatus.detailsPath); // eslint-disable-line import/no-deprecated
});
it('shows error message if the retry failed job mutation fails', async () => {
diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js
index 464fd3cb203..1d164b9f5c1 100644
--- a/spec/frontend/releases/stores/modules/detail/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js
@@ -3,7 +3,7 @@ import originalOneReleaseForEditingQueryResponse from 'test_fixtures/graphql/rel
import testAction from 'helpers/vuex_action_helper';
import { getTag } from '~/api/tags_api';
import { createAlert } from '~/alert';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import { s__ } from '~/locale';
import { ASSET_LINK_TYPE } from '~/releases/constants';
import createReleaseAssetLinkMutation from '~/releases/graphql/mutations/create_release_link.mutation.graphql';
@@ -306,8 +306,8 @@ describe('Release edit/new actions', () => {
it("redirects to the release's dedicated page", () => {
const { selfUrl } = releaseResponse.data.project.release.links;
actions.receiveSaveReleaseSuccess({ commit: jest.fn(), state }, selfUrl);
- expect(redirectTo).toHaveBeenCalledTimes(1);
- expect(redirectTo).toHaveBeenCalledWith(selfUrl);
+ expect(redirectTo).toHaveBeenCalledTimes(1); // eslint-disable-line import/no-deprecated
+ expect(redirectTo).toHaveBeenCalledWith(selfUrl); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index a588251c4bd..7e14d292946 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -551,12 +551,12 @@ describe('Blob content viewer component', () => {
it('simple edit redirects to the simple editor', () => {
findWebIdeLink().vm.$emit('edit', 'simple');
- expect(urlUtility.redirectTo).toHaveBeenCalledWith(simpleViewerMock.editBlobPath);
+ expect(urlUtility.redirectTo).toHaveBeenCalledWith(simpleViewerMock.editBlobPath); // eslint-disable-line import/no-deprecated
});
it('IDE edit redirects to the IDE editor', () => {
findWebIdeLink().vm.$emit('edit', 'ide');
- expect(urlUtility.redirectTo).toHaveBeenCalledWith(simpleViewerMock.ideEditPath);
+ expect(urlUtility.redirectTo).toHaveBeenCalledWith(simpleViewerMock.ideEditPath); // eslint-disable-line import/no-deprecated
});
it.each`
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index 957cfc0bc22..d17e20ac227 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -328,7 +328,7 @@ describe('Snippet Edit app', () => {
it('should redirect to snippet view on successful mutation', async () => {
await createComponentAndSubmit();
- expect(urlUtils.redirectTo).toHaveBeenCalledWith(TEST_WEB_URL);
+ expect(urlUtils.redirectTo).toHaveBeenCalledWith(TEST_WEB_URL); // eslint-disable-line import/no-deprecated
});
describe('when there are errors after creating a new snippet', () => {
@@ -349,7 +349,7 @@ describe('Snippet Edit app', () => {
await waitForPromises();
- expect(urlUtils.redirectTo).not.toHaveBeenCalled();
+ expect(urlUtils.redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
expect(createAlert).toHaveBeenCalledWith({
message: `Can't create snippet: ${TEST_MUTATION_ERROR}`,
});
@@ -373,7 +373,7 @@ describe('Snippet Edit app', () => {
},
});
- expect(urlUtils.redirectTo).not.toHaveBeenCalled();
+ expect(urlUtils.redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
expect(createAlert).toHaveBeenCalledWith({
message: `Can't update snippet: ${TEST_MUTATION_ERROR}`,
});
@@ -391,7 +391,7 @@ describe('Snippet Edit app', () => {
});
it('should not redirect', () => {
- expect(urlUtils.redirectTo).not.toHaveBeenCalled();
+ expect(urlUtils.redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
});
it('should alert', () => {
diff --git a/spec/frontend/user_lists/components/edit_user_list_spec.js b/spec/frontend/user_lists/components/edit_user_list_spec.js
index b5eb6313bed..21a883aefe0 100644
--- a/spec/frontend/user_lists/components/edit_user_list_spec.js
+++ b/spec/frontend/user_lists/components/edit_user_list_spec.js
@@ -4,7 +4,7 @@ import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import EditUserList from '~/user_lists/components/edit_user_list.vue';
import UserListForm from '~/user_lists/components/user_list_form.vue';
import createStore from '~/user_lists/store/edit';
@@ -114,7 +114,7 @@ describe('user_lists/components/edit_user_list', () => {
});
it('should redirect to the feature flag details page', () => {
- expect(redirectTo).toHaveBeenCalledWith(userList.path);
+ expect(redirectTo).toHaveBeenCalledWith(userList.path); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/user_lists/components/new_user_list_spec.js b/spec/frontend/user_lists/components/new_user_list_spec.js
index 8683cf2463c..004cfb6ca07 100644
--- a/spec/frontend/user_lists/components/new_user_list_spec.js
+++ b/spec/frontend/user_lists/components/new_user_list_spec.js
@@ -4,7 +4,7 @@ import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import NewUserList from '~/user_lists/components/new_user_list.vue';
import createStore from '~/user_lists/store/new';
import { userList } from 'jest/feature_flags/mock_data';
@@ -58,7 +58,7 @@ describe('user_lists/components/new_user_list', () => {
});
it('should redirect to the feature flag details page', () => {
- expect(redirectTo).toHaveBeenCalledWith(userList.path);
+ expect(redirectTo).toHaveBeenCalledWith(userList.path); // eslint-disable-line import/no-deprecated
});
});
diff --git a/spec/frontend/user_lists/store/edit/actions_spec.js b/spec/frontend/user_lists/store/edit/actions_spec.js
index ca56c935ea5..0fd08c1c052 100644
--- a/spec/frontend/user_lists/store/edit/actions_spec.js
+++ b/spec/frontend/user_lists/store/edit/actions_spec.js
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import * as actions from '~/user_lists/store/edit/actions';
import * as types from '~/user_lists/store/edit/mutation_types';
import createState from '~/user_lists/store/edit/state';
@@ -89,7 +89,7 @@ describe('User Lists Edit Actions', () => {
name: updatedList.name,
iid: updatedList.iid,
});
- expect(redirectTo).toHaveBeenCalledWith(userList.path);
+ expect(redirectTo).toHaveBeenCalledWith(userList.path); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/user_lists/store/new/actions_spec.js b/spec/frontend/user_lists/store/new/actions_spec.js
index fa69fa7fa66..7ecf05e380a 100644
--- a/spec/frontend/user_lists/store/new/actions_spec.js
+++ b/spec/frontend/user_lists/store/new/actions_spec.js
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import * as actions from '~/user_lists/store/new/actions';
import * as types from '~/user_lists/store/new/mutation_types';
import createState from '~/user_lists/store/new/state';
@@ -41,7 +41,7 @@ describe('User Lists Edit Actions', () => {
it('should redirect to the user list page', () => {
return testAction(actions.createUserList, createdList, state, [], [], () => {
expect(Api.createFeatureFlagUserList).toHaveBeenCalledWith('1', createdList);
- expect(redirectTo).toHaveBeenCalledWith(userList.path);
+ expect(redirectTo).toHaveBeenCalledWith(userList.path); // eslint-disable-line import/no-deprecated
});
});
});
diff --git a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
index 5cdb6612487..f3d0d66cdd1 100644
--- a/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
+++ b/spec/frontend/vue_shared/security_reports/components/manage_via_mr_spec.js
@@ -7,7 +7,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { humanize } from '~/lib/utils/text_utility';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import ManageViaMr, {
i18n,
} from '~/vue_shared/security_configuration/components/manage_via_mr.vue';
@@ -146,8 +146,8 @@ describe('ManageViaMr component', () => {
it('should call redirect helper with correct value', async () => {
await wrapper.trigger('click');
await waitForPromises();
- expect(redirectTo).toHaveBeenCalledTimes(1);
- expect(redirectTo).toHaveBeenCalledWith('testSuccessPath');
+ expect(redirectTo).toHaveBeenCalledTimes(1); // eslint-disable-line import/no-deprecated
+ expect(redirectTo).toHaveBeenCalledWith('testSuccessPath'); // eslint-disable-line import/no-deprecated
// This is done for UX reasons. If the loading prop is set to false
// on success, then there's a period where the button is clickable
// again. Instead, we want the button to display a loading indicator
diff --git a/spec/lib/error_tracking/sentry_client/token_spec.rb b/spec/lib/error_tracking/sentry_client/token_spec.rb
new file mode 100644
index 00000000000..c50ec42ed67
--- /dev/null
+++ b/spec/lib/error_tracking/sentry_client/token_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ErrorTracking::SentryClient::Token, feature_category: :error_tracking do
+ describe '.masked_token?' do
+ subject { described_class.masked_token?(token) }
+
+ context 'with masked token' do
+ let(:token) { '*********' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'without masked token' do
+ let(:token) { 'token' }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/cache_spec.rb b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
index 67252eed938..82db116fa0d 100644
--- a/spec/lib/gitlab/ci/config/entry/cache_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/cache_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
let(:key) { 'some key' }
let(:when_config) { nil }
let(:unprotect) { false }
+ let(:fallback_keys) { [] }
let(:config) do
{
@@ -27,13 +28,22 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
}.tap do |config|
config[:policy] = policy if policy
config[:when] = when_config if when_config
+ config[:fallback_keys] = fallback_keys if fallback_keys
end
end
describe '#value' do
shared_examples 'hash key value' do
it 'returns hash value' do
- expect(entry.value).to eq(key: key, untracked: true, paths: ['some/path/'], policy: 'pull-push', when: 'on_success', unprotect: false)
+ expect(entry.value).to eq(
+ key: key,
+ untracked: true,
+ paths: ['some/path/'],
+ policy: 'pull-push',
+ when: 'on_success',
+ unprotect: false,
+ fallback_keys: []
+ )
end
end
@@ -104,6 +114,20 @@ RSpec.describe Gitlab::Ci::Config::Entry::Cache do
expect(entry.value).to include(when: 'on_success')
end
end
+
+ context 'with `fallback_keys`' do
+ let(:fallback_keys) { %w[key-1 key-2] }
+
+ it 'matches the list of fallback keys' do
+ expect(entry.value).to match(a_hash_including(fallback_keys: %w[key-1 key-2]))
+ end
+ end
+
+ context 'without `fallback_keys`' do
+ it 'assigns an empty list' do
+ expect(entry.value).to match(a_hash_including(fallback_keys: []))
+ end
+ end
end
describe '#valid?' do
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index a06fc2d86c7..4be7c11fab0 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -664,7 +664,13 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job, feature_category: :pipeline_compo
it 'overrides default config' do
expect(entry[:image].value).to eq(name: 'some_image')
- expect(entry[:cache].value).to eq([key: 'test', policy: 'pull-push', when: 'on_success', unprotect: false])
+ expect(entry[:cache].value).to match_array([
+ key: 'test',
+ policy: 'pull-push',
+ when: 'on_success',
+ unprotect: false,
+ fallback_keys: []
+ ])
end
end
@@ -679,7 +685,13 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job, feature_category: :pipeline_compo
it 'uses config from default entry' do
expect(entry[:image].value).to eq 'specified'
- expect(entry[:cache].value).to eq([key: 'test', policy: 'pull-push', when: 'on_success', unprotect: false])
+ expect(entry[:cache].value).to match_array([
+ key: 'test',
+ policy: 'pull-push',
+ when: 'on_success',
+ unprotect: false,
+ fallback_keys: []
+ ])
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 9722609aef6..5fac5298e8e 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success',
- unprotect: false }],
+ unprotect: false, fallback_keys: [] }],
job_variables: {},
root_variables_inheritance: true,
ignore: false,
@@ -144,7 +144,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success',
- unprotect: false }],
+ unprotect: false, fallback_keys: [] }],
job_variables: {},
root_variables_inheritance: true,
ignore: false,
@@ -161,7 +161,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
image: { name: "image:1.0" },
services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }],
cache: [{ key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success',
- unprotect: false }],
+ unprotect: false, fallback_keys: [] }],
only: { refs: %w(branches tags) },
job_variables: { 'VAR' => { value: 'job' } },
root_variables_inheritance: true,
@@ -209,7 +209,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
image: { name: 'image:1.0' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
- cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success', unprotect: false }],
+ cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success', unprotect: false, fallback_keys: [] }],
job_variables: {},
root_variables_inheritance: true,
ignore: false,
@@ -222,7 +222,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
image: { name: 'image:1.0' },
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
- cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success', unprotect: false }],
+ cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success', unprotect: false, fallback_keys: [] }],
job_variables: { 'VAR' => { value: 'job' } },
root_variables_inheritance: true,
ignore: false,
@@ -277,7 +277,13 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
describe '#cache_value' do
it 'returns correct cache definition' do
- expect(root.cache_value).to eq([key: 'a', policy: 'pull-push', when: 'on_success', unprotect: false])
+ expect(root.cache_value).to match_array([
+ key: 'a',
+ policy: 'pull-push',
+ when: 'on_success',
+ unprotect: false,
+ fallback_keys: []
+ ])
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb
index 49511e14db6..07e2d6960bf 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb
@@ -220,6 +220,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build::Cache do
end
end
+ context 'with cache:fallback_keys' do
+ let(:config) do
+ {
+ key: 'ruby-branch-key',
+ paths: ['vendor/ruby'],
+ fallback_keys: ['ruby-default']
+ }
+ end
+
+ it { is_expected.to include(config) }
+ end
+
context 'with all cache option keys' do
let(:config) do
{
@@ -228,7 +240,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build::Cache do
untracked: true,
policy: 'push',
unprotect: true,
- when: 'on_success'
+ when: 'on_success',
+ fallback_keys: ['default-ruby']
}
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index f8c2889798f..2c020e76cb6 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -1870,7 +1870,8 @@ module Gitlab
key: 'key',
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
])
end
@@ -1895,7 +1896,8 @@ module Gitlab
key: { files: ['file'] },
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
])
end
@@ -1922,7 +1924,8 @@ module Gitlab
key: 'keya',
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
},
{
paths: ['logs/', 'binaries/'],
@@ -1930,7 +1933,8 @@ module Gitlab
key: 'key',
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
}
]
)
@@ -1958,7 +1962,8 @@ module Gitlab
key: { files: ['file'] },
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
])
end
@@ -1984,7 +1989,8 @@ module Gitlab
key: { files: ['file'], prefix: 'prefix' },
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
])
end
@@ -2008,7 +2014,8 @@ module Gitlab
key: 'local',
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
])
end
end
diff --git a/spec/lib/gitlab/config_checker/external_database_checker_spec.rb b/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
index c962b9ad393..6379a5edb90 100644
--- a/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
+++ b/spec/lib/gitlab/config_checker/external_database_checker_spec.rb
@@ -89,9 +89,9 @@ RSpec.describe Gitlab::ConfigChecker::ExternalDatabaseChecker do
{
type: 'warning',
message: _('Database \'%{database_name}\' is using PostgreSQL %{pg_version_current}, ' \
- 'but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. ' \
- 'Please upgrade your environment to a supported PostgreSQL version, ' \
- 'see %{pg_requirements_url} for details.') % \
+ 'but this version of GitLab requires PostgreSQL %{pg_version_minimum}. ' \
+ 'Please upgrade your environment to a supported PostgreSQL version. ' \
+ 'See %{pg_requirements_url} for details.') % \
{
database_name: database_name,
pg_version_current: database_version,
diff --git a/spec/lib/gitlab/database/partitioning_spec.rb b/spec/lib/gitlab/database/partitioning_spec.rb
index 4a82cd43fbb..9df238a0024 100644
--- a/spec/lib/gitlab/database/partitioning_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_spec.rb
@@ -171,6 +171,21 @@ RSpec.describe Gitlab::Database::Partitioning, feature_category: :database do
expect(find_partitions(ci_model.table_name, conn: main_connection).size).to eq(0)
end
end
+
+ context 'when partition_manager_sync_partitions feature flag is disabled' do
+ before do
+ described_class.register_models(models)
+ stub_feature_flags(partition_manager_sync_partitions: false)
+ end
+
+ it 'skips sync_partitions' do
+ expect(described_class::PartitionManager).not_to receive(:new)
+ expect(described_class).to receive(:sync_partitions)
+ .and_call_original
+
+ described_class.sync_partitions(models)
+ end
+ end
end
describe '.report_metrics' do
diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb
index aa1205663e1..c9f7fd4f748 100644
--- a/spec/lib/gitlab/github_import/client_spec.rb
+++ b/spec/lib/gitlab/github_import/client_spec.rb
@@ -131,6 +131,16 @@ RSpec.describe Gitlab::GithubImport::Client, feature_category: :importers do
end
end
+ describe '#collaborators' do
+ it 'returns the collaborators' do
+ expect(client)
+ .to receive(:each_object)
+ .with(:collaborators, 'foo/bar')
+
+ client.collaborators('foo/bar')
+ end
+ end
+
describe '#branch_protection' do
it 'returns the protection details for the given branch' do
expect(client.octokit)
diff --git a/spec/lib/gitlab/github_import/importer/collaborators_importer_spec.rb b/spec/lib/gitlab/github_import/importer/collaborators_importer_spec.rb
index e48b562279e..dcb02f32a28 100644
--- a/spec/lib/gitlab/github_import/importer/collaborators_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/collaborators_importer_spec.rb
@@ -73,12 +73,11 @@ RSpec.describe Gitlab::GithubImport::Importer::CollaboratorsImporter, feature_ca
end
describe '#parallel_import', :clean_gitlab_redis_cache do
- let(:page_struct) { Struct.new(:objects, :number, keyword_init: true) }
-
before do
- allow(client).to receive(:each_page)
- .with(:collaborators, project.import_source, { page: 1 })
- .and_yield(page_struct.new(number: 1, objects: [github_collaborator]))
+ allow(client).to receive(:collaborators).with(project.import_source, affiliation: 'direct')
+ .and_return([github_collaborator])
+ allow(client).to receive(:collaborators).with(project.import_source, affiliation: 'outside')
+ .and_return([])
end
it 'imports each collaborator in parallel' do
@@ -110,6 +109,44 @@ RSpec.describe Gitlab::GithubImport::Importer::CollaboratorsImporter, feature_ca
end
end
+ describe '#each_object_to_import', :clean_gitlab_redis_cache do
+ let(:github_collaborator_2) { { id: 100501, login: 'alice', role_name: 'owner' } }
+ let(:github_collaborator_3) { { id: 100502, login: 'tom', role_name: 'guest' } }
+
+ before do
+ allow(client).to receive(:collaborators).with(project.import_source, affiliation: 'direct')
+ .and_return([github_collaborator, github_collaborator_2, github_collaborator_3])
+ allow(client).to receive(:collaborators).with(project.import_source, affiliation: 'outside')
+ .and_return([github_collaborator_3])
+ allow(Gitlab::GithubImport::ObjectCounter).to receive(:increment)
+ .with(project, :collaborator, :fetched)
+ end
+
+ it 'yields every direct collaborator who is not an outside collaborator to the supplied block' do
+ expect { |b| importer.each_object_to_import(&b) }
+ .to yield_successive_args(github_collaborator, github_collaborator_2)
+
+ expect(Gitlab::GithubImport::ObjectCounter).to have_received(:increment).twice
+ end
+
+ context 'when a collaborator has been already imported' do
+ before do
+ allow(importer).to receive(:already_imported?).and_return(true)
+ end
+
+ it 'does not yield anything' do
+ expect(Gitlab::GithubImport::ObjectCounter)
+ .not_to receive(:increment)
+
+ expect(importer)
+ .not_to receive(:mark_as_imported)
+
+ expect { |b| importer.each_object_to_import(&b) }
+ .not_to yield_control
+ end
+ end
+ end
+
describe '#id_for_already_imported_cache' do
it 'returns the ID of the given note' do
expect(importer.id_for_already_imported_cache(github_collaborator))
diff --git a/spec/lib/gitlab/github_import/settings_spec.rb b/spec/lib/gitlab/github_import/settings_spec.rb
index ad0c47e8e8a..43e096863b8 100644
--- a/spec/lib/gitlab/github_import/settings_spec.rb
+++ b/spec/lib/gitlab/github_import/settings_spec.rb
@@ -11,7 +11,8 @@ RSpec.describe Gitlab::GithubImport::Settings do
{
single_endpoint_issue_events_import: true,
single_endpoint_notes_import: false,
- attachments_import: false
+ attachments_import: false,
+ collaborators_import: false
}
end
@@ -22,17 +23,26 @@ RSpec.describe Gitlab::GithubImport::Settings do
{
name: 'single_endpoint_issue_events_import',
label: stages[:single_endpoint_issue_events_import][:label],
+ selected: false,
details: stages[:single_endpoint_issue_events_import][:details]
},
{
name: 'single_endpoint_notes_import',
label: stages[:single_endpoint_notes_import][:label],
+ selected: false,
details: stages[:single_endpoint_notes_import][:details]
},
{
name: 'attachments_import',
label: stages[:attachments_import][:label].strip,
+ selected: false,
details: stages[:attachments_import][:details]
+ },
+ {
+ name: 'collaborators_import',
+ label: stages[:collaborators_import][:label].strip,
+ selected: true,
+ details: stages[:collaborators_import][:details]
}
]
end
@@ -48,6 +58,7 @@ RSpec.describe Gitlab::GithubImport::Settings do
single_endpoint_issue_events_import: true,
single_endpoint_notes_import: 'false',
attachments_import: nil,
+ collaborators_import: false,
foo: :bar
}.stringify_keys
end
@@ -67,6 +78,7 @@ RSpec.describe Gitlab::GithubImport::Settings do
expect(settings.enabled?(:single_endpoint_issue_events_import)).to eq true
expect(settings.enabled?(:single_endpoint_notes_import)).to eq false
expect(settings.enabled?(:attachments_import)).to eq false
+ expect(settings.enabled?(:collaborators_import)).to eq false
end
end
@@ -77,6 +89,7 @@ RSpec.describe Gitlab::GithubImport::Settings do
expect(settings.disabled?(:single_endpoint_issue_events_import)).to eq false
expect(settings.disabled?(:single_endpoint_notes_import)).to eq true
expect(settings.disabled?(:attachments_import)).to eq true
+ expect(settings.disabled?(:collaborators_import)).to eq true
end
end
end
diff --git a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
index 1731da9b752..2d4c6d1cc56 100644
--- a/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb
@@ -76,7 +76,9 @@ RSpec.describe Gitlab::Metrics::Subscribers::RailsCache do
it 'observes multi-key count' do
expect(transaction).to receive(:observe)
- .with(:gitlab_cache_read_multikey_count, event.payload[:key].size)
+ .with(:gitlab_cache_read_multikey_count,
+ event.payload[:key].size,
+ { store: store_label })
subject
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 7c32c6d74c8..e3e78acb7e5 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1152,6 +1152,12 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
{ cache: [{ key: "key", paths: ["public"], policy: "pull-push" }] }
end
+ let(:options_with_fallback_keys) do
+ { cache: [
+ { key: "key", paths: ["public"], policy: "pull-push", fallback_keys: %w(key1 key2) }
+ ] }
+ end
+
subject { build.cache }
context 'when build has cache' do
@@ -1167,6 +1173,13 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
] }
end
+ let(:options_with_fallback_keys) do
+ { cache: [
+ { key: "key", paths: ["public"], policy: "pull-push", fallback_keys: %w(key3 key4) },
+ { key: "key2", paths: ["public"], policy: "pull-push", fallback_keys: %w(key5 key6) }
+ ] }
+ end
+
before do
allow_any_instance_of(Project).to receive(:jobs_cache_index).and_return(1)
end
@@ -1178,8 +1191,21 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
allow(build.pipeline).to receive(:protected_ref?).and_return(true)
end
- it do
- is_expected.to all(a_hash_including(key: a_string_matching(/-protected$/)))
+ context 'without the `unprotect` option' do
+ it do
+ is_expected.to all(a_hash_including(key: a_string_matching(/-protected$/)))
+ end
+
+ context 'and the caches have fallback keys' do
+ let(:options) { options_with_fallback_keys }
+
+ it do
+ is_expected.to all(a_hash_including({
+ key: a_string_matching(/-protected$/),
+ fallback_keys: array_including(a_string_matching(/-protected$/))
+ }))
+ end
+ end
end
context 'and the cache has the `unprotect` option' do
@@ -1193,6 +1219,20 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
it do
is_expected.to all(a_hash_including(key: a_string_matching(/-non_protected$/)))
end
+
+ context 'and the caches have fallback keys' do
+ let(:options) do
+ options_with_fallback_keys[:cache].each { |entry| entry[:unprotect] = true }
+ options_with_fallback_keys
+ end
+
+ it do
+ is_expected.to all(a_hash_including({
+ key: a_string_matching(/-non_protected$/),
+ fallback_keys: array_including(a_string_matching(/-non_protected$/))
+ }))
+ end
+ end
end
end
@@ -1204,6 +1244,17 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
it do
is_expected.to all(a_hash_including(key: a_string_matching(/-non_protected$/)))
end
+
+ context 'and the caches have fallback keys' do
+ let(:options) { options_with_fallback_keys }
+
+ it do
+ is_expected.to all(a_hash_including({
+ key: a_string_matching(/-non_protected$/),
+ fallback_keys: array_including(a_string_matching(/-non_protected$/))
+ }))
+ end
+ end
end
context 'when separated caches are disabled' do
@@ -1219,6 +1270,23 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
it 'is expected to have no type suffix' do
is_expected.to match([a_hash_including(key: 'key-1'), a_hash_including(key: 'key2-1')])
end
+
+ context 'and the caches have fallback keys' do
+ let(:options) { options_with_fallback_keys }
+
+ it do
+ is_expected.to match([
+ a_hash_including({
+ key: 'key-1',
+ fallback_keys: %w(key3-1 key4-1)
+ }),
+ a_hash_including({
+ key: 'key2-1',
+ fallback_keys: %w(key5-1 key6-1)
+ })
+ ])
+ end
+ end
end
context 'running on not protected ref' do
@@ -1229,6 +1297,23 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
it 'is expected to have no type suffix' do
is_expected.to match([a_hash_including(key: 'key-1'), a_hash_including(key: 'key2-1')])
end
+
+ context 'and the caches have fallback keys' do
+ let(:options) { options_with_fallback_keys }
+
+ it do
+ is_expected.to match([
+ a_hash_including({
+ key: 'key-1',
+ fallback_keys: %w(key3-1 key4-1)
+ }),
+ a_hash_including({
+ key: 'key2-1',
+ fallback_keys: %w(key5-1 key6-1)
+ })
+ ])
+ end
+ end
end
end
end
@@ -1239,6 +1324,17 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
end
it { is_expected.to be_an(Array).and all(include(key: a_string_matching(/^key-1-(?>protected|non_protected)/))) }
+
+ context 'and the cache have fallback keys' do
+ let(:options) { options_with_fallback_keys }
+
+ it do
+ is_expected.to be_an(Array).and all(include({
+ key: a_string_matching(/^key-1-(?>protected|non_protected)/),
+ fallback_keys: array_including(a_string_matching(/^key\d-1-(?>protected|non_protected)/))
+ }))
+ end
+ end
end
context 'when project does not have jobs_cache_index' do
@@ -1249,6 +1345,21 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
it do
is_expected.to eq(options[:cache].map { |entry| entry.merge(key: "#{entry[:key]}-non_protected") })
end
+
+ context 'and the cache have fallback keys' do
+ let(:options) { options_with_fallback_keys }
+
+ it do
+ is_expected.to eq(
+ options[:cache].map do |entry|
+ entry[:key] = "#{entry[:key]}-non_protected"
+ entry[:fallback_keys].map! { |key| "#{key}-non_protected" }
+
+ entry
+ end
+ )
+ end
+ end
end
end
@@ -1261,6 +1372,29 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
end
end
+ describe '#fallback_cache_keys_defined?' do
+ subject { build }
+
+ it 'returns false when fallback keys are not defined' do
+ expect(subject.fallback_cache_keys_defined?).to be false
+ end
+
+ context "with fallbacks keys" do
+ before do
+ allow(build).to receive(:options).and_return({
+ cache: [{
+ key: "key1",
+ fallback_keys: %w(key2)
+ }]
+ })
+ end
+
+ it 'returns true when fallback keys are defined' do
+ expect(subject.fallback_cache_keys_defined?).to be true
+ end
+ end
+ end
+
describe '#triggered_by?' do
subject { build.triggered_by?(user) }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index eaf4ecda635..c73dac7251e 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2224,20 +2224,6 @@ RSpec.describe User, feature_category: :user_profile do
end
end
- describe '#sign_in_with_codes_allowed?' do
- let_it_be(:user) { create(:user, :two_factor_via_webauthn) }
-
- context 'when `webauthn_without_totp` disabled' do
- before do
- stub_feature_flags(webauthn_without_totp: false)
- end
-
- it { expect(user.sign_in_with_codes_allowed?).to eq(false) }
- end
-
- it { expect(user.sign_in_with_codes_allowed?).to eq(true) }
- end
-
describe '#two_factor_otp_enabled?' do
let_it_be(:user) { create(:user) }
diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
index 39b8b489019..0164eda7680 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -230,11 +230,14 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
end
let(:expected_cache) do
- [{ 'key' => a_string_matching(/^cache_key-(?>protected|non_protected)$/),
- 'untracked' => false,
- 'paths' => ['vendor/*'],
- 'policy' => 'pull-push',
- 'when' => 'on_success' }]
+ [{
+ 'key' => a_string_matching(/^cache_key-(?>protected|non_protected)$/),
+ 'untracked' => false,
+ 'paths' => ['vendor/*'],
+ 'policy' => 'pull-push',
+ 'when' => 'on_success',
+ 'fallback_keys' => []
+ }]
end
let(:expected_features) do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 3ecd012be12..cc8be312c71 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -3558,7 +3558,7 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq("403 Forbidden - The user you are trying to deactivate has been active in the past #{Gitlab::CurrentSettings.deactivate_dormant_users_period} days and cannot be deactivated")
+ expect(json_response['message']).to eq("The user you are trying to deactivate has been active in the past #{Gitlab::CurrentSettings.deactivate_dormant_users_period} days and cannot be deactivated")
expect(user.reload.state).to eq('active')
end
end
@@ -3582,7 +3582,7 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
+ expect(json_response['message']).to eq('Error occurred. A blocked user cannot be deactivated')
expect(blocked_user.reload.state).to eq('blocked')
end
end
@@ -3596,7 +3596,7 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
+ expect(json_response['message']).to eq('Error occurred. A blocked user cannot be deactivated')
expect(user.reload.state).to eq('ldap_blocked')
end
end
@@ -3608,7 +3608,7 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
deactivate
expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response['message']).to eq('403 Forbidden - An internal user cannot be deactivated by the API')
+ expect(json_response['message']).to eq('Internal users cannot be deactivated')
end
end
diff --git a/spec/serializers/runner_entity_spec.rb b/spec/serializers/runner_entity_spec.rb
index f34cb794834..b94e1e225ed 100644
--- a/spec/serializers/runner_entity_spec.rb
+++ b/spec/serializers/runner_entity_spec.rb
@@ -22,5 +22,23 @@ RSpec.describe RunnerEntity do
expect(subject).to include(:edit_path)
expect(subject).to include(:short_sha)
end
+
+ context 'without admin permissions' do
+ it 'does not contain admin_path field' do
+ expect(subject).not_to include(:admin_path)
+ end
+ end
+
+ context 'with admin permissions' do
+ let_it_be(:user) { create(:user, :admin) }
+
+ before do
+ allow(user).to receive(:can_admin_all_resources?).and_return(true)
+ end
+
+ it 'contains admin_path field' do
+ expect(subject).to include(:admin_path)
+ end
+ end
end
end
diff --git a/spec/services/ci/create_pipeline_service/cache_spec.rb b/spec/services/ci/create_pipeline_service/cache_spec.rb
index e8d9cec6695..2a65f92bfd6 100644
--- a/spec/services/ci/create_pipeline_service/cache_spec.rb
+++ b/spec/services/ci/create_pipeline_service/cache_spec.rb
@@ -39,7 +39,8 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
policy: 'pull-push',
untracked: true,
unprotect: false,
- when: 'on_success'
+ when: 'on_success',
+ fallback_keys: []
}
expect(pipeline).to be_persisted
@@ -72,7 +73,8 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
paths: ['logs/'],
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
}
expect(pipeline).to be_persisted
@@ -89,7 +91,8 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
paths: ['logs/'],
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
}
expect(pipeline).to be_persisted
@@ -123,7 +126,8 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
paths: ['logs/'],
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
}
expect(pipeline).to be_persisted
@@ -140,7 +144,8 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
paths: ['logs/'],
policy: 'pull-push',
when: 'on_success',
- unprotect: false
+ unprotect: false,
+ fallback_keys: []
}
expect(pipeline).to be_persisted
diff --git a/spec/services/import/github_service_spec.rb b/spec/services/import/github_service_spec.rb
index a8928fb5c09..fa8b2489599 100644
--- a/spec/services/import/github_service_spec.rb
+++ b/spec/services/import/github_service_spec.rb
@@ -152,7 +152,8 @@ RSpec.describe Import::GithubService, feature_category: :importers do
{
single_endpoint_issue_events_import: true,
single_endpoint_notes_import: 'false',
- attachments_import: false
+ attachments_import: false,
+ collaborators_import: true
}
end
diff --git a/spec/services/users/deactivate_service_spec.rb b/spec/services/users/deactivate_service_spec.rb
new file mode 100644
index 00000000000..0bb6e51a3b1
--- /dev/null
+++ b/spec/services/users/deactivate_service_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::DeactivateService, feature_category: :user_management do
+ let_it_be(:current_user) { build(:admin) }
+ let_it_be(:user) { build(:user) }
+
+ subject(:service) { described_class.new(current_user) }
+
+ describe '#execute' do
+ subject(:operation) { service.execute(user) }
+
+ context 'when successful', :enable_admin_mode do
+ let(:user) { create(:user) }
+
+ it 'returns success status' do
+ expect(operation[:status]).to eq(:success)
+ end
+
+ it "changes the user's state" do
+ expect { operation }.to change { user.state }.to('deactivated')
+ end
+
+ it 'creates a log entry' do
+ expect(Gitlab::AppLogger).to receive(:info).with(message: "User deactivated", user: user.username,
+ email: user.email, deactivated_by: current_user.username, ip_address: current_user.current_sign_in_ip.to_s)
+
+ operation
+ end
+ end
+
+ context 'when the user is already deactivated', :enable_admin_mode do
+ let(:user) { create(:user, :deactivated) }
+
+ it 'returns error result' do
+ aggregate_failures 'error result' do
+ expect(operation[:status]).to eq(:success)
+ expect(operation[:message]).to eq('User has already been deactivated')
+ end
+ end
+
+ it "does not change the user's state" do
+ expect { operation }.not_to change { user.state }
+ end
+ end
+
+ context 'when internal user', :enable_admin_mode do
+ let(:user) { create(:user, :bot) }
+
+ it 'returns an error message' do
+ expect(operation[:status]).to eq(:error)
+ expect(operation[:message]).to eq('Internal users cannot be deactivated')
+ expect(operation.reason).to eq :forbidden
+ end
+ end
+
+ context 'when user is blocked', :enable_admin_mode do
+ let(:user) { create(:user, :blocked) }
+
+ it 'returns an error message' do
+ expect(operation[:status]).to eq(:error)
+ expect(operation[:message]).to eq('Error occurred. A blocked user cannot be deactivated')
+ expect(operation.reason).to eq :forbidden
+ end
+ end
+
+ context 'when user is not an admin' do
+ it 'returns permissions error message' do
+ expect(operation[:status]).to eq(:error)
+ expect(operation[:message]).to eq("You are not authorized to perform this action")
+ expect(operation.reason).to eq :forbidden
+ end
+ end
+
+ context 'when skip_authorization is true' do
+ let(:non_admin_user) { create(:user) }
+ let(:user_to_deactivate) { create(:user) }
+ let(:skip_authorization_service) { described_class.new(non_admin_user, skip_authorization: true) }
+
+ it 'deactivates the user even if the current user is not an admin' do
+ expect(skip_authorization_service.execute(user_to_deactivate)[:status]).to eq(:success)
+ end
+ end
+ end
+end
diff --git a/spec/workers/gitlab/github_import/stage/import_collaborators_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_collaborators_worker_spec.rb
index 0eac9f21b77..33ecf848997 100644
--- a/spec/workers/gitlab/github_import/stage/import_collaborators_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_collaborators_worker_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Stage::ImportCollaboratorsWorker, feature_category: :importers do
let_it_be(:project) { create(:project) }
let_it_be(:import_state) { create(:import_state, project: project) }
+ let(:settings) { Gitlab::GithubImport::Settings.new(project) }
+ let(:stage_enabled) { true }
let(:worker) { described_class.new }
let(:importer) { instance_double(Gitlab::GithubImport::Importer::CollaboratorsImporter) }
@@ -14,12 +16,13 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportCollaboratorsWorker, feature_c
let(:push_rights_granted) { true }
before do
+ settings.write({ collaborators_import: stage_enabled })
allow(client).to receive(:repository).with(project.import_source)
.and_return({ permissions: { push: push_rights_granted } })
end
context 'when user has push access for this repo' do
- it 'imports all the pull requests' do
+ it 'imports all collaborators' do
waiter = Gitlab::JobWaiter.new(2, '123')
expect(Gitlab::GithubImport::Importer::CollaboratorsImporter)
@@ -52,6 +55,20 @@ RSpec.describe Gitlab::GithubImport::Stage::ImportCollaboratorsWorker, feature_c
end
end
+ context 'when stage is disabled' do
+ let(:stage_enabled) { false }
+
+ it 'skips collaborators import and calls next stage' do
+ expect(Gitlab::GithubImport::Importer::CollaboratorsImporter).not_to receive(:new)
+
+ expect(Gitlab::GithubImport::AdvanceStageWorker)
+ .to receive(:perform_async)
+ .with(project.id, {}, :pull_requests_merged_by)
+
+ worker.import(client, project)
+ end
+ end
+
it 'raises an error' do
exception = StandardError.new('_some_error_')