Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-06 15:07:34 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-06 15:07:34 +0300
commit4958d96e262f6b31b2850123e4949536555b2d29 (patch)
tree28fe9a1fed009a569806c705e4810a33979cbd6a /spec
parent95de7177f2d5844e4aa399fea9a59d4ba6b4b1f1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb60
-rw-r--r--spec/finders/template_finder_spec.rb4
-rw-r--r--spec/frontend/admin/abuse_report/components/report_actions_spec.js38
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js29
-rw-r--r--spec/frontend/diffs/store/actions_spec.js25
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml2
-rw-r--r--spec/frontend/groups/components/app_spec.js3
-rw-r--r--spec/frontend/groups/components/overview_tabs_spec.js3
-rw-r--r--spec/frontend/repository/components/fork_info_spec.js6
-rw-r--r--spec/frontend/work_items/components/work_item_description_spec.js294
-rw-r--r--spec/helpers/avatars_helper_spec.rb8
-rw-r--r--spec/lib/gitlab/template/metrics_dashboard_template_spec.rb26
-rw-r--r--spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb19
-rw-r--r--spec/models/blob_viewer/metrics_dashboard_yml_spec.rb136
-rw-r--r--spec/requests/api/graphql/mutations/projects/sync_fork_spec.rb18
15 files changed, 236 insertions, 435 deletions
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 2e63500d36e..62cd9fd9a56 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -579,66 +579,6 @@ RSpec.describe 'File blob', :js, feature_category: :groups_and_projects do
end
end
- describe '.gitlab/dashboards/custom-dashboard.yml' do
- let(:remove_monitor_metrics) { false }
-
- before do
- stub_feature_flags(remove_monitor_metrics: remove_monitor_metrics)
-
- project.add_maintainer(project.creator)
-
- Files::CreateService.new(
- project,
- project.creator,
- start_branch: 'master',
- branch_name: 'master',
- commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
- file_path: '.gitlab/dashboards/custom-dashboard.yml',
- file_content: file_content
- ).execute
-
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
- end
-
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
-
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
-
- context 'when metrics dashboard feature is unavailable' do
- let(:remove_monitor_metrics) { true }
-
- it 'displays the blob without an auxiliary viewer' do
- expect(page).to have_content('Environment metrics')
- expect(page).not_to have_content('Metrics Dashboard YAML definition', wait: 0)
- end
- end
- end
-
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
-
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
-
- # shows a learn more link
- expect(page).to have_link('Learn more')
- end
- end
- end
- end
-
context 'LICENSE' do
before do
visit_blob('LICENSE')
diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb
index c2b42cf0eb3..eacce0bd996 100644
--- a/spec/finders/template_finder_spec.rb
+++ b/spec/finders/template_finder_spec.rb
@@ -102,10 +102,6 @@ RSpec.describe TemplateFinder do
describe '#build' do
let(:project) { build_stubbed(:project) }
- before do
- stub_feature_flags(remove_monitor_metrics: false)
- end
-
where(:type, :expected_class) do
:dockerfiles | described_class
:gitignores | described_class
diff --git a/spec/frontend/admin/abuse_report/components/report_actions_spec.js b/spec/frontend/admin/abuse_report/components/report_actions_spec.js
index a1a78902b58..ec7dd31a046 100644
--- a/spec/frontend/admin/abuse_report/components/report_actions_spec.js
+++ b/spec/frontend/admin/abuse_report/components/report_actions_spec.js
@@ -15,6 +15,8 @@ import {
SUCCESS_ALERT,
FAILED_ALERT,
ERROR_MESSAGE,
+ NO_ACTION,
+ USER_ACTION_OPTIONS,
} from '~/admin/abuse_report/constants';
import { mockAbuseReport } from '../mock_data';
@@ -29,11 +31,12 @@ describe('ReportActions', () => {
reason: 'spam',
};
- const { report } = mockAbuseReport;
+ const { user, report } = mockAbuseReport;
const clickActionsButton = () => wrapper.findByTestId('actions-button').vm.$emit('click');
const isDrawerOpen = () => wrapper.findComponent(GlDrawer).props('open');
const findErrorFor = (id) => wrapper.findByTestId(id).find('.d-block.invalid-feedback');
+ const findUserActionOptions = () => wrapper.findByTestId('action-select');
const setCloseReport = (close) => wrapper.findByTestId('close').find('input').setChecked(close);
const setSelectOption = (id, value) =>
wrapper.findByTestId(`${id}-select`).find(`option[value=${value}]`).setSelected();
@@ -45,6 +48,7 @@ describe('ReportActions', () => {
const createComponent = (props = {}) => {
wrapper = mountExtended(ReportActions, {
propsData: {
+ user,
report,
...props,
},
@@ -64,6 +68,38 @@ describe('ReportActions', () => {
expect(isDrawerOpen()).toBe(false);
});
+ describe('actions', () => {
+ describe('when logged in user is not the user being reported', () => {
+ beforeEach(() => {
+ clickActionsButton();
+ });
+
+ it('shows "No action", "Block user", "Ban user" and "Delete user" options', () => {
+ const options = findUserActionOptions().findAll('option');
+
+ expect(options).toHaveLength(USER_ACTION_OPTIONS.length);
+
+ USER_ACTION_OPTIONS.forEach((action, index) => {
+ expect(options.at(index).text()).toBe(action.text);
+ });
+ });
+ });
+
+ describe('when logged in user is the user being reported', () => {
+ beforeEach(() => {
+ gon.current_username = user.username;
+ clickActionsButton();
+ });
+
+ it('only shows "No action" option', () => {
+ const options = findUserActionOptions().findAll('option');
+
+ expect(options).toHaveLength(1);
+ expect(options.at(0).text()).toBe(NO_ACTION.text);
+ });
+ });
+ });
+
describe('when clicking the actions button', () => {
beforeEach(() => {
clickActionsButton();
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index 3524973278c..fb271433762 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -115,6 +115,35 @@ describe('DiffContent', () => {
});
});
+ describe('with whitespace only change', () => {
+ afterEach(() => {
+ [isParallelViewGetterMock, isInlineViewGetterMock].forEach((m) => m.mockRestore());
+ });
+
+ const textDiffFile = {
+ ...defaultProps.diffFile,
+ viewer: { name: diffViewerModes.text, whitespace_only: true },
+ };
+
+ it('should render empty state', () => {
+ createComponent({
+ props: { diffFile: textDiffFile },
+ });
+
+ expect(wrapper.find('[data-testid="diff-whitespace-only-state"]').exists()).toBe(true);
+ });
+
+ it('emits load-file event when clicking show changes button', () => {
+ createComponent({
+ props: { diffFile: textDiffFile },
+ });
+
+ wrapper.find('[data-testid="diff-load-file-button"]').vm.$emit('click');
+
+ expect(wrapper.emitted('load-file')).toEqual([[{ w: '0' }]]);
+ });
+ });
+
describe('with empty files', () => {
const emptyDiffFile = {
...defaultProps.diffFile,
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index d32c2d4665d..f0061ad88d7 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -790,7 +790,7 @@ describe('DiffsStoreActions', () => {
mock.onGet(file.loadCollapsedDiffUrl).reply(HTTP_STATUS_OK, data);
return diffActions
- .loadCollapsedDiff({ commit, getters: { commitId: null }, state }, file)
+ .loadCollapsedDiff({ commit, getters: { commitId: null }, state }, { file })
.then(() => {
expect(commit).toHaveBeenCalledWith(types.ADD_COLLAPSED_DIFFS, { file, data });
});
@@ -804,13 +804,28 @@ describe('DiffsStoreActions', () => {
jest.spyOn(axios, 'get').mockReturnValue(Promise.resolve({ data: {} }));
- diffActions.loadCollapsedDiff({ commit() {}, getters, state }, file);
+ diffActions.loadCollapsedDiff({ commit() {}, getters, state }, { file });
expect(axios.get).toHaveBeenCalledWith(file.load_collapsed_diff_url, {
params: { commit_id: null, w: '0' },
});
});
+ it('should pass through params', () => {
+ const file = { load_collapsed_diff_url: '/load/collapsed/diff/url' };
+ const getters = {
+ commitId: null,
+ };
+
+ jest.spyOn(axios, 'get').mockReturnValue(Promise.resolve({ data: {} }));
+
+ diffActions.loadCollapsedDiff({ commit() {}, getters, state }, { file, params: { w: '1' } });
+
+ expect(axios.get).toHaveBeenCalledWith(file.load_collapsed_diff_url, {
+ params: { commit_id: null, w: '1' },
+ });
+ });
+
it('should fetch data with commit ID', () => {
const file = { load_collapsed_diff_url: '/load/collapsed/diff/url' };
const getters = {
@@ -819,7 +834,7 @@ describe('DiffsStoreActions', () => {
jest.spyOn(axios, 'get').mockReturnValue(Promise.resolve({ data: {} }));
- diffActions.loadCollapsedDiff({ commit() {}, getters, state }, file);
+ diffActions.loadCollapsedDiff({ commit() {}, getters, state }, { file });
expect(axios.get).toHaveBeenCalledWith(file.load_collapsed_diff_url, {
params: { commit_id: '123', w: '0' },
@@ -843,7 +858,7 @@ describe('DiffsStoreActions', () => {
});
it('fetches the data when there is no mergeRequestDiff', () => {
- diffActions.loadCollapsedDiff({ commit() {}, getters, state }, file);
+ diffActions.loadCollapsedDiff({ commit() {}, getters, state }, { file });
expect(axios.get).toHaveBeenCalledWith(file.load_collapsed_diff_url, {
params: expect.any(Object),
@@ -861,7 +876,7 @@ describe('DiffsStoreActions', () => {
diffActions.loadCollapsedDiff(
{ commit() {}, getters, state: { mergeRequestDiff: { version_path: versionPath } } },
- file,
+ { file },
);
expect(axios.get).toHaveBeenCalledWith(file.load_collapsed_diff_url, {
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
index 996a48f7bc6..ba4b0db908d 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
@@ -49,7 +49,7 @@ coverage-report-is-string:
coverage_report: cobertura
# invalid artifact:reports:performance
-# Superceded by: artifact:reports:browser_performance
+# Superseded by: artifact:reports:browser_performance
performance string path:
artifacts:
reports:
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index 0c265ec6cae..b474745790e 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -42,7 +42,7 @@ describe('AppComponent', () => {
let mock;
let getGroupsSpy;
- const store = new GroupsStore({ hideProjects: false });
+ const store = new GroupsStore({});
const service = new GroupsService(mockEndpoint);
const createShallowComponent = ({ propsData = {} } = {}) => {
@@ -51,7 +51,6 @@ describe('AppComponent', () => {
propsData: {
store,
service,
- hideProjects: false,
containerId: 'js-groups-tree',
...propsData,
},
diff --git a/spec/frontend/groups/components/overview_tabs_spec.js b/spec/frontend/groups/components/overview_tabs_spec.js
index 101dd06d578..ca852f398d0 100644
--- a/spec/frontend/groups/components/overview_tabs_spec.js
+++ b/spec/frontend/groups/components/overview_tabs_spec.js
@@ -93,7 +93,6 @@ describe('OverviewTabs', () => {
action: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
store: new GroupsStore({ showSchemaMarkup: true }),
service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
- hideProjects: false,
});
await waitForPromises();
@@ -117,7 +116,6 @@ describe('OverviewTabs', () => {
action: ACTIVE_TAB_SHARED,
store: new GroupsStore(),
service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_SHARED]),
- hideProjects: false,
});
expect(tabPanel.vm.$attrs.lazy).toBe(false);
@@ -143,7 +141,6 @@ describe('OverviewTabs', () => {
action: ACTIVE_TAB_ARCHIVED,
store: new GroupsStore(),
service: new GroupsService(defaultProvide.endpoints[ACTIVE_TAB_ARCHIVED]),
- hideProjects: false,
});
expect(tabPanel.vm.$attrs.lazy).toBe(false);
diff --git a/spec/frontend/repository/components/fork_info_spec.js b/spec/frontend/repository/components/fork_info_spec.js
index 62a66e59d24..23609c95ca0 100644
--- a/spec/frontend/repository/components/fork_info_spec.js
+++ b/spec/frontend/repository/components/fork_info_spec.js
@@ -27,7 +27,6 @@ describe('ForkInfo component', () => {
const forkInfoError = new Error('Something went wrong');
const projectId = 'gid://gitlab/Project/1';
const showMock = jest.fn();
- const synchronizeFork = true;
Vue.use(VueApollo);
@@ -72,11 +71,6 @@ describe('ForkInfo component', () => {
methods: { show: showMock },
}),
},
- provide: {
- glFeatures: {
- synchronizeFork,
- },
- },
});
return waitForPromises();
};
diff --git a/spec/frontend/work_items/components/work_item_description_spec.js b/spec/frontend/work_items/components/work_item_description_spec.js
index 62cbb1bacb6..b910e9854f8 100644
--- a/spec/frontend/work_items/components/work_item_description_spec.js
+++ b/spec/frontend/work_items/components/work_item_description_spec.js
@@ -1,3 +1,4 @@
+import { GlForm } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@@ -7,7 +8,6 @@ import waitForPromises from 'helpers/wait_for_promises';
import EditedAt from '~/issues/show/components/edited.vue';
import { updateDraft } from '~/lib/utils/autosave';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import WorkItemDescription from '~/work_items/components/work_item_description.vue';
import WorkItemDescriptionRendered from '~/work_items/components/work_item_description_rendered.vue';
@@ -36,22 +36,18 @@ describe('WorkItemDescription', () => {
const mutationSuccessHandler = jest.fn().mockResolvedValue(updateWorkItemMutationResponse);
const subscriptionHandler = jest.fn().mockResolvedValue(workItemDescriptionSubscriptionResponse);
let workItemResponseHandler;
- let workItemsMvc;
- const findMarkdownField = () => wrapper.findComponent(MarkdownField);
+ const findForm = () => wrapper.findComponent(GlForm);
const findMarkdownEditor = () => wrapper.findComponent(MarkdownEditor);
const findRenderedDescription = () => wrapper.findComponent(WorkItemDescriptionRendered);
const findEditedAt = () => wrapper.findComponent(EditedAt);
- const editDescription = (newText) => {
- if (workItemsMvc) {
- return findMarkdownEditor().vm.$emit('input', newText);
- }
- return wrapper.find('textarea').setValue(newText);
- };
+ const editDescription = (newText) => findMarkdownEditor().vm.$emit('input', newText);
- const clickCancel = () => wrapper.find('[data-testid="cancel"]').vm.$emit('click');
- const clickSave = () => wrapper.find('[data-testid="save-description"]').vm.$emit('click', {});
+ const findCancelButton = () => wrapper.find('[data-testid="cancel"]');
+ const findSubmitButton = () => wrapper.find('[data-testid="save-description"]');
+ const clickCancel = () => findForm().vm.$emit('reset', new Event('reset'));
+ const clickSave = () => findForm().vm.$emit('submit', new Event('submit'));
const createComponent = async ({
mutationHandler = mutationSuccessHandler,
@@ -75,12 +71,6 @@ describe('WorkItemDescription', () => {
},
provide: {
fullPath: 'test-project-path',
- glFeatures: {
- workItemsMvc,
- },
- },
- stubs: {
- MarkdownField,
},
});
@@ -93,11 +83,15 @@ describe('WorkItemDescription', () => {
}
};
- describe('editing description with workItemsMvc FF enabled', () => {
- beforeEach(() => {
- workItemsMvc = true;
+ it('has a subscription', async () => {
+ await createComponent();
+
+ expect(subscriptionHandler).toHaveBeenCalledWith({
+ issuableId: workItemQueryResponse.data.workItem.id,
});
+ });
+ describe('editing description', () => {
it('passes correct autocompletion data and preview markdown sources and enables quick actions', async () => {
const {
iid,
@@ -113,196 +107,162 @@ describe('WorkItemDescription', () => {
autocompleteDataSources: autocompleteDataSources(fullPath, iid),
});
});
- });
-
- describe('editing description with workItemsMvc FF disabled', () => {
- beforeEach(() => {
- workItemsMvc = false;
- });
-
- it('passes correct autocompletion data and preview markdown sources', async () => {
- const {
- iid,
- project: { fullPath },
- } = workItemQueryResponse.data.workItem;
-
- await createComponent({ isEditing: true });
+ it('shows edited by text', async () => {
+ const lastEditedAt = '2022-09-21T06:18:42Z';
+ const lastEditedBy = {
+ name: 'Administrator',
+ webPath: '/root',
+ };
+
+ await createComponent({
+ workItemResponse: workItemByIidResponseFactory({ lastEditedAt, lastEditedBy }),
+ });
- expect(findMarkdownField().props()).toMatchObject({
- autocompleteDataSources: autocompleteDataSources(fullPath, iid),
- markdownPreviewPath: markdownPreviewPath(fullPath, iid),
- quickActionsDocsPath: wrapper.vm.$options.quickActionsDocsPath,
+ expect(findEditedAt().props()).toMatchObject({
+ updatedAt: lastEditedAt,
+ updatedByName: lastEditedBy.name,
+ updatedByPath: lastEditedBy.webPath,
});
});
- });
- describe.each([true, false])(
- 'editing description with workItemsMvc %workItemsMvcEnabled',
- (workItemsMvcEnabled) => {
- beforeEach(() => {
- beforeEach(() => {
- workItemsMvc = workItemsMvcEnabled;
- });
- });
+ it('does not show edited by text', async () => {
+ await createComponent();
- it('has a subscription', async () => {
- await createComponent();
+ expect(findEditedAt().exists()).toBe(false);
+ });
- expect(subscriptionHandler).toHaveBeenCalledWith({
- issuableId: workItemQueryResponse.data.workItem.id,
- });
+ it('cancels when clicking cancel', async () => {
+ await createComponent({
+ isEditing: true,
});
- describe('editing description', () => {
- it('shows edited by text', async () => {
- const lastEditedAt = '2022-09-21T06:18:42Z';
- const lastEditedBy = {
- name: 'Administrator',
- webPath: '/root',
- };
+ clickCancel();
- await createComponent({
- workItemResponse: workItemByIidResponseFactory({ lastEditedAt, lastEditedBy }),
- });
+ await nextTick();
- expect(findEditedAt().props()).toMatchObject({
- updatedAt: lastEditedAt,
- updatedByName: lastEditedBy.name,
- updatedByPath: lastEditedBy.webPath,
- });
- });
+ expect(confirmAction).not.toHaveBeenCalled();
+ expect(findMarkdownEditor().exists()).toBe(false);
+ });
- it('does not show edited by text', async () => {
- await createComponent();
+ it('prompts for confirmation when clicking cancel after changes', async () => {
+ await createComponent({
+ isEditing: true,
+ });
- expect(findEditedAt().exists()).toBe(false);
- });
+ editDescription('updated desc');
- it('cancels when clicking cancel', async () => {
- await createComponent({
- isEditing: true,
- });
+ clickCancel();
- clickCancel();
+ await nextTick();
- await nextTick();
+ expect(confirmAction).toHaveBeenCalled();
+ });
- expect(confirmAction).not.toHaveBeenCalled();
- expect(findMarkdownField().exists()).toBe(false);
- });
+ it('calls update widgets mutation', async () => {
+ const updatedDesc = 'updated desc';
- it('prompts for confirmation when clicking cancel after changes', async () => {
- await createComponent({
- isEditing: true,
- });
+ await createComponent({
+ isEditing: true,
+ });
- editDescription('updated desc');
+ editDescription(updatedDesc);
- clickCancel();
+ clickSave();
- await nextTick();
+ await waitForPromises();
- expect(confirmAction).toHaveBeenCalled();
- });
+ expect(mutationSuccessHandler).toHaveBeenCalledWith({
+ input: {
+ id: workItemId,
+ descriptionWidget: {
+ description: updatedDesc,
+ },
+ },
+ });
+ });
- it('calls update widgets mutation', async () => {
- const updatedDesc = 'updated desc';
+ it('tracks editing description', async () => {
+ await createComponent({
+ isEditing: true,
+ markdownPreviewPath: '/preview',
+ });
+ const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- await createComponent({
- isEditing: true,
- });
+ clickSave();
- editDescription(updatedDesc);
+ await waitForPromises();
- clickSave();
+ expect(trackingSpy).toHaveBeenCalledWith(TRACKING_CATEGORY_SHOW, 'updated_description', {
+ category: TRACKING_CATEGORY_SHOW,
+ label: 'item_description',
+ property: 'type_Task',
+ });
+ });
- await waitForPromises();
+ it('emits error when mutation returns error', async () => {
+ const error = 'eror';
- expect(mutationSuccessHandler).toHaveBeenCalledWith({
- input: {
- id: workItemId,
- descriptionWidget: {
- description: updatedDesc,
- },
+ await createComponent({
+ isEditing: true,
+ mutationHandler: jest.fn().mockResolvedValue({
+ data: {
+ workItemUpdate: {
+ workItem: {},
+ errors: [error],
},
- });
- });
-
- it('tracks editing description', async () => {
- await createComponent({
- isEditing: true,
- markdownPreviewPath: '/preview',
- });
- const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
-
- clickSave();
-
- await waitForPromises();
-
- expect(trackingSpy).toHaveBeenCalledWith(TRACKING_CATEGORY_SHOW, 'updated_description', {
- category: TRACKING_CATEGORY_SHOW,
- label: 'item_description',
- property: 'type_Task',
- });
- });
-
- it('emits error when mutation returns error', async () => {
- const error = 'eror';
+ },
+ }),
+ });
- await createComponent({
- isEditing: true,
- mutationHandler: jest.fn().mockResolvedValue({
- data: {
- workItemUpdate: {
- workItem: {},
- errors: [error],
- },
- },
- }),
- });
+ editDescription('updated desc');
- editDescription('updated desc');
+ clickSave();
- clickSave();
+ await waitForPromises();
- await waitForPromises();
+ expect(wrapper.emitted('error')).toEqual([[error]]);
+ });
- expect(wrapper.emitted('error')).toEqual([[error]]);
- });
+ it('emits error when mutation fails', async () => {
+ const error = 'eror';
- it('emits error when mutation fails', async () => {
- const error = 'eror';
+ await createComponent({
+ isEditing: true,
+ mutationHandler: jest.fn().mockRejectedValue(new Error(error)),
+ });
- await createComponent({
- isEditing: true,
- mutationHandler: jest.fn().mockRejectedValue(new Error(error)),
- });
+ editDescription('updated desc');
- editDescription('updated desc');
+ clickSave();
- clickSave();
+ await waitForPromises();
- await waitForPromises();
+ expect(wrapper.emitted('error')).toEqual([[error]]);
+ });
- expect(wrapper.emitted('error')).toEqual([[error]]);
- });
+ it('autosaves description', async () => {
+ await createComponent({
+ isEditing: true,
+ });
- it('autosaves description', async () => {
- await createComponent({
- isEditing: true,
- });
+ editDescription('updated desc');
- editDescription('updated desc');
+ expect(updateDraft).toHaveBeenCalled();
+ });
- expect(updateDraft).toHaveBeenCalled();
- });
+ it('maps submit and cancel buttons to form actions', async () => {
+ await createComponent({
+ isEditing: true,
});
- it('calls the work item query', async () => {
- await createComponent();
+ expect(findCancelButton().attributes('type')).toBe('reset');
+ expect(findSubmitButton().attributes('type')).toBe('submit');
+ });
+ });
+
+ it('calls the work item query', async () => {
+ await createComponent();
- expect(workItemResponseHandler).toHaveBeenCalled();
- });
- },
- );
+ expect(workItemResponseHandler).toHaveBeenCalled();
+ });
});
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index dd0d6d1246f..2c12513c8ac 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -122,6 +122,14 @@ RSpec.describe AvatarsHelper, feature_category: :source_code_management do
end
end
+ context 'when by_commit_email is true' do
+ it 'returns a relative URL for the avatar' do
+ avatar = helper.avatar_icon_for_email(user.commit_email, by_commit_email: true).to_s
+
+ expect(avatar).to eq(user.avatar.url)
+ end
+ end
+
context 'when no user exists for the email' do
it 'calls gravatar_icon' do
expect(helper).to receive(:gravatar_icon).with('foo@example.com', 20, 2)
diff --git a/spec/lib/gitlab/template/metrics_dashboard_template_spec.rb b/spec/lib/gitlab/template/metrics_dashboard_template_spec.rb
deleted file mode 100644
index 4c2b3dea600..00000000000
--- a/spec/lib/gitlab/template/metrics_dashboard_template_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Template::MetricsDashboardTemplate do
- subject { described_class }
-
- describe '.all' do
- it 'combines the globals and rest' do
- all = subject.all.map(&:name)
-
- expect(all).to include('Default')
- end
- end
-
- describe '#content' do
- it 'loads the full file' do
- example_dashboard = subject.new(Rails.root.join('lib/gitlab/metrics/templates/Default.metrics-dashboard.yml'))
-
- expect(example_dashboard.name).to eq 'Default'
- expect(example_dashboard.content).to start_with('#')
- end
- end
-
- it_behaves_like 'file template shared examples', 'Default', '.metrics-dashboard.yml'
-end
diff --git a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
index 860206dc6af..b917208bac1 100644
--- a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
@@ -185,18 +185,25 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu, feature_catego
describe 'Model experiments' do
let(:item_id) { :model_experiments }
- context 'when :ml_experiment_tracking is enabled' do
- it 'shows the menu item' do
- stub_feature_flags(ml_experiment_tracking: true)
+ before do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?)
+ .with(user, :read_model_experiments, project)
+ .and_return(model_experiments_enabled)
+ end
+
+ context 'when user can access model experiments' do
+ let(:model_experiments_enabled) { true }
+ it 'shows the menu item' do
is_expected.not_to be_nil
end
end
- context 'when :ml_experiment_tracking is disabled' do
- it 'does not show the menu item' do
- stub_feature_flags(ml_experiment_tracking: false)
+ context 'when user does not have access model experiments' do
+ let(:model_experiments_enabled) { false }
+ it 'does not show the menu item' do
is_expected.to be_nil
end
end
diff --git a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
deleted file mode 100644
index c9ac13eefc0..00000000000
--- a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BlobViewer::MetricsDashboardYml, feature_category: :metrics do
- include FakeBlobHelpers
- include RepoHelpers
-
- let_it_be(:project) { create(:project, :repository) }
-
- let(:blob) { fake_blob(path: '.gitlab/dashboards/custom-dashboard.yml', data: data) }
- let(:sha) { sample_commit.id }
- let(:data) { fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
-
- subject(:viewer) { described_class.new(blob) }
-
- context 'when the definition is valid' do
- describe '#valid?' do
- before do
- allow(PerformanceMonitoring::PrometheusDashboard).to receive(:from_json)
- end
-
- it 'calls prepare! on the viewer' do
- expect(viewer).to receive(:prepare!)
-
- viewer.valid?
- end
-
- it 'processes dashboard yaml and returns true', :aggregate_failures do
- yml = ::Gitlab::Config::Loader::Yaml.new(data).load_raw!
-
- expect_next_instance_of(::Gitlab::Config::Loader::Yaml, data) do |loader|
- expect(loader).to receive(:load_raw!).and_call_original
- end
- expect(PerformanceMonitoring::PrometheusDashboard)
- .to receive(:from_json)
- .with(yml)
- .and_call_original
- expect(viewer.valid?).to be true
- end
- end
-
- describe '#errors' do
- it 'returns empty array' do
- expect(viewer.errors).to eq []
- end
- end
- end
-
- context 'when definition is invalid' do
- let(:error) { ActiveModel::ValidationError.new(PerformanceMonitoring::PrometheusDashboard.new.tap(&:validate)) }
- let(:data) do
- <<~YAML
- dashboard:
- YAML
- end
-
- describe '#valid?' do
- it 'returns false' do
- expect(PerformanceMonitoring::PrometheusDashboard)
- .to receive(:from_json).and_raise(error)
-
- expect(viewer.valid?).to be false
- end
- end
-
- describe '#errors' do
- it 'returns validation errors' do
- allow(PerformanceMonitoring::PrometheusDashboard)
- .to receive(:from_json).and_raise(error)
-
- expect(viewer.errors).to eq error.model.errors.messages.map { |messages| messages.join(': ') }
- end
- end
- end
-
- context 'when YAML syntax is invalid' do
- let(:data) do
- <<~YAML
- dashboard: 'empty metrics'
- panel_groups:
- - group: 'Group Title'
- YAML
- end
-
- describe '#valid?' do
- it 'returns false' do
- expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json)
- expect(viewer.valid?).to be false
- end
- end
-
- describe '#errors' do
- it 'returns validation errors' do
- expect(viewer.errors).to eq ["YAML syntax: (<unknown>): did not find expected key while parsing a block mapping at line 1 column 1"]
- end
- end
- end
-
- context 'when YAML loader raises error' do
- let(:data) do
- <<~YAML
- large yaml file
- YAML
- end
-
- before do
- allow(::Gitlab::Config::Loader::Yaml).to(
- receive(:new).and_raise(::Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big')
- )
- end
-
- it 'is invalid' do
- expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json)
- expect(viewer.valid?).to be false
- end
-
- it 'returns validation errors' do
- expect(viewer.errors).to eq ["YAML syntax: The parsed YAML is too big"]
- end
- end
-
- describe '.can_render?' do
- subject { described_class.can_render?(blob) }
-
- it { is_expected.to be false }
-
- context 'when metrics dashboard feature is available' do
- before do
- stub_feature_flags(remove_monitor_metrics: false)
- end
-
- it { is_expected.to be true }
- end
- end
-end
diff --git a/spec/requests/api/graphql/mutations/projects/sync_fork_spec.rb b/spec/requests/api/graphql/mutations/projects/sync_fork_spec.rb
index c5dc6f390d9..0745fb945bb 100644
--- a/spec/requests/api/graphql/mutations/projects/sync_fork_spec.rb
+++ b/spec/requests/api/graphql/mutations/projects/sync_fork_spec.rb
@@ -32,24 +32,6 @@ RSpec.describe "Sync project fork", feature_category: :source_code_management do
source_project.change_head('feature')
end
- context 'when synchronize_fork feature flag is disabled' do
- before do
- stub_feature_flags(synchronize_fork: false)
- end
-
- it 'does not call the sync service' do
- expect(::Projects::Forks::SyncWorker).not_to receive(:perform_async)
-
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(graphql_mutation_response(:project_sync_fork)).to eq(
- {
- 'details' => nil,
- 'errors' => ['Feature flag is disabled']
- })
- end
- end
-
context 'when the branch is protected', :use_clean_rails_redis_caching do
let_it_be(:protected_branch) do
create(:protected_branch, :no_one_can_push, project: project, name: target_branch)