diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-06 15:07:34 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-06 15:07:34 +0300 |
commit | 4958d96e262f6b31b2850123e4949536555b2d29 (patch) | |
tree | 28fe9a1fed009a569806c705e4810a33979cbd6a /spec | |
parent | 95de7177f2d5844e4aa399fea9a59d4ba6b4b1f1 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
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) |