diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-24 12:10:17 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-24 12:10:17 +0000 |
commit | 4b9bde7848d9538c1635ffe7a5385ba013487b4a (patch) | |
tree | 5aad1d5d94ea233a36c8ac2850e099236e1c2cdc /spec | |
parent | 2f752481c2e727834216a93dee82df9f8e2acb2e (diff) | |
download | gitlab-ce-4b9bde7848d9538c1635ffe7a5385ba013487b4a.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
44 files changed, 549 insertions, 232 deletions
diff --git a/spec/controllers/projects/badges_controller_spec.rb b/spec/controllers/projects/badges_controller_spec.rb index 7e7a630921f..242b2fd3ec6 100644 --- a/spec/controllers/projects/badges_controller_spec.rb +++ b/spec/controllers/projects/badges_controller_spec.rb @@ -3,9 +3,9 @@ require 'spec_helper' RSpec.describe Projects::BadgesController do - let(:project) { pipeline.project } - let!(:pipeline) { create(:ci_empty_pipeline) } - let(:user) { create(:user) } + let_it_be(:project, reload: true) { create(:project, :repository) } + let_it_be(:pipeline, reload: true) { create(:ci_empty_pipeline, project: project) } + let_it_be(:user) { create(:user) } shared_examples 'a badge resource' do |badge_type| context 'when pipelines are public' do @@ -137,6 +137,26 @@ RSpec.describe Projects::BadgesController do describe '#pipeline' do it_behaves_like 'a badge resource', :pipeline + + context 'with ignore_skipped param' do + render_views + + before do + pipeline.update!(status: :skipped) + project.add_maintainer(user) + sign_in(user) + end + + it 'returns skipped badge if set to false' do + get_badge(:pipeline, ignore_skipped: false) + expect(response.body).to include('skipped') + end + + it 'does not return skipped badge if set to true' do + get_badge(:pipeline, ignore_skipped: true) + expect(response.body).to include('unknown') + end + end end describe '#coverage' do @@ -148,7 +168,7 @@ RSpec.describe Projects::BadgesController do namespace_id: project.namespace.to_param, project_id: project, ref: pipeline.ref - }.merge(args.slice(:style, :key_text, :key_width)) + }.merge(args.slice(:style, :key_text, :key_width, :ignore_skipped)) get badge, params: params, format: :svg end diff --git a/spec/factories/project_statistics.rb b/spec/factories/project_statistics.rb index 78e80a92b3a..ea003b67db0 100644 --- a/spec/factories/project_statistics.rb +++ b/spec/factories/project_statistics.rb @@ -22,6 +22,7 @@ FactoryBot.define do project_statistics.build_artifacts_size = evaluator.size_multiplier * 4 project_statistics.packages_size = evaluator.size_multiplier * 5 project_statistics.snippets_size = evaluator.size_multiplier * 6 + project_statistics.pipeline_artifacts_size = evaluator.size_multiplier * 7 end end end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index f5b05c76e90..c281ba3aab9 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -525,6 +525,7 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n end def check_all_events + page.check('Active') page.check('Push') page.check('Issue') page.check('Confidential Issue') diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index efa1f8cfc0d..f434ea0c66f 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -130,24 +130,43 @@ RSpec.describe 'Issue Boards new issue', :js do context 'group boards' do let_it_be(:group) { create(:group, :public) } - let_it_be(:project) { create(:project, namespace: group) } + let_it_be(:project) { create(:project, :public, namespace: group) } let_it_be(:group_board) { create(:board, group: group) } - let_it_be(:list) { create(:list, board: group_board, position: 0) } + let_it_be(:project_label) { create(:label, project: project, name: 'label') } + let_it_be(:list) { create(:list, board: group_board, label: project_label, position: 0) } context 'for unauthorized users' do - before do - sign_in(user) - visit group_board_path(group, group_board) - wait_for_requests - end + context 'when backlog does not exist' do + before do + sign_in(user) + visit group_board_path(group, group_board) + wait_for_requests + end - it 'displays new issue button in open list' do - expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1) + it 'does not display new issue button in label list' do + page.within('.board.is-draggable') do + expect(page).not_to have_selector('.issue-count-badge-add-button') + end + end end - it 'does not display new issue button in label list' do - page.within('.board.is-draggable') do - expect(page).not_to have_selector('.issue-count-badge-add-button') + context 'when backlog list already exists' do + let!(:backlog_list) { create(:backlog_list, board: group_board) } + + before do + sign_in(user) + visit group_board_path(group, group_board) + wait_for_requests + end + + it 'displays new issue button in open list' do + expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1) + end + + it 'does not display new issue button in label list' do + page.within('.board.is-draggable') do + expect(page).not_to have_selector('.issue-count-badge-add-button') + end end end end diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb index 1545cb36e9b..51dcf57eb94 100644 --- a/spec/features/labels_hierarchy_spec.rb +++ b/spec/features/labels_hierarchy_spec.rb @@ -296,6 +296,7 @@ RSpec.describe 'Labels Hierarchy', :js do let(:board) { create(:board, group: parent) } before do + stub_feature_flags(graphql_board_lists: false) parent.add_developer(user) visit group_board_path(parent, board) find('.js-new-board-list').click diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 8747b3ab54c..a9c196bb84b 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -311,7 +311,7 @@ RSpec.describe 'Pipelines', :js do let!(:delayed_job) do create(:ci_build, :scheduled, pipeline: pipeline, - name: 'delayed job', + name: 'delayed job 1', stage: 'test') end @@ -327,7 +327,7 @@ RSpec.describe 'Pipelines', :js do find('.js-pipeline-dropdown-manual-actions').click time_diff = [0, delayed_job.scheduled_at - Time.now].max - expect(page).to have_button('delayed job') + expect(page).to have_button('delayed job 1') expect(page).to have_content(Time.at(time_diff).utc.strftime("%H:%M:%S")) end @@ -335,7 +335,7 @@ RSpec.describe 'Pipelines', :js do let!(:delayed_job) do create(:ci_build, :expired_scheduled, pipeline: pipeline, - name: 'delayed job', + name: 'delayed job 1', stage: 'test') end @@ -349,7 +349,7 @@ RSpec.describe 'Pipelines', :js do context 'when user played a delayed job immediately' do before do find('.js-pipeline-dropdown-manual-actions').click - page.accept_confirm { click_button('delayed job') } + page.accept_confirm { click_button('delayed job 1') } wait_for_requests end diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/services/user_activates_issue_tracker_spec.rb index 4f25794d058..c7389460a07 100644 --- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb +++ b/spec/features/projects/services/user_activates_issue_tracker_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'User activates issue tracker', :js do let(:url) { 'http://tracker.example.com' } def fill_form(disable: false, skip_new_issue_url: false) - click_active_toggle if disable + click_active_checkbox if disable fill_in 'service_project_url', with: url fill_in 'service_issues_url', with: "#{url}/:id" diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb index 6ddffb710a8..1b94856d640 100644 --- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb +++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb @@ -28,7 +28,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js do token = ('a'..'z').to_a.join fill_in 'service_token', with: token - click_active_toggle + click_active_checkbox click_on 'Save changes' expect(current_path).to eq(edit_project_service_path(project, :mattermost_slash_commands)) diff --git a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb index afe6855d6ad..7a0b56027fe 100644 --- a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb +++ b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb @@ -21,7 +21,7 @@ RSpec.describe 'Slack slash commands', :js do it 'redirects to the integrations page after saving but not activating' do fill_in 'Token', with: 'token' - click_active_toggle + click_active_checkbox click_on 'Save' expect(current_path).to eq(edit_project_service_path(project, :slack_slash_commands)) diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb index 1d443e0b339..50d7b353c46 100644 --- a/spec/features/projects/user_sees_sidebar_spec.rb +++ b/spec/features/projects/user_sees_sidebar_spec.rb @@ -6,10 +6,6 @@ RSpec.describe 'Projects > User sees sidebar' do let(:user) { create(:user) } let(:project) { create(:project, :private, public_builds: false, namespace: user.namespace) } - before do - stub_feature_flags(vue_issuables_list: false) - end - # NOTE: See documented behaviour https://design.gitlab.com/regions/navigation#contextual-navigation context 'on different viewports', :js do include MobileHelpers @@ -134,6 +130,7 @@ RSpec.describe 'Projects > User sees sidebar' do context 'as guest' do let(:guest) { create(:user) } + let!(:issue) { create(:issue, :opened, project: project, author: guest) } before do project.add_guest(guest) diff --git a/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js b/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js index 2814b5ce357..ea7b4584a63 100644 --- a/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js +++ b/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js @@ -1,6 +1,7 @@ import { mount } from '@vue/test-utils'; import SidebarTodo from '~/alert_management/components/sidebar/sidebar_todo.vue'; -import AlertMarkTodo from '~/alert_management/graphql/mutations/alert_todo_create.mutation.graphql'; +import createAlertTodoMutation from '~/alert_management/graphql/mutations/alert_todo_create.mutation.graphql'; +import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql'; import mockAlerts from '../mocks/alerts.json'; const mockAlert = mockAlerts[0]; @@ -61,14 +62,14 @@ describe('Alert Details Sidebar To Do', () => { expect(findToDoButton().text()).toBe('Add a To-Do'); }); - it('calls `$apollo.mutate` with `AlertMarkTodo` mutation and variables containing `iid`, `todoEvent`, & `projectPath`', async () => { + it('calls `$apollo.mutate` with `createAlertTodoMutation` mutation and variables containing `iid`, `todoEvent`, & `projectPath`', async () => { jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult); findToDoButton().trigger('click'); await wrapper.vm.$nextTick(); expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({ - mutation: AlertMarkTodo, + mutation: createAlertTodoMutation, variables: { iid: '1527542', projectPath: 'projectPath', @@ -76,6 +77,7 @@ describe('Alert Details Sidebar To Do', () => { }); }); }); + describe('removing a todo', () => { beforeEach(() => { mountComponent({ @@ -91,12 +93,19 @@ describe('Alert Details Sidebar To Do', () => { expect(findToDoButton().text()).toBe('Mark as done'); }); - it('calls `$apollo.mutate` with `AlertMarkTodoDone` mutation and variables containing `id`', async () => { + it('calls `$apollo.mutate` with `todoMarkDoneMutation` mutation and variables containing `id`', async () => { jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult); findToDoButton().trigger('click'); await wrapper.vm.$nextTick(); - expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1); + + expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({ + mutation: todoMarkDoneMutation, + update: expect.anything(), + variables: { + id: '1234', + }, + }); }); }); }); diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index 71e62a4ac5d..54b8d499324 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -1,7 +1,7 @@ import testAction from 'helpers/vuex_action_helper'; -import actions from '~/boards/stores/actions'; +import actions, { gqlClient } from '~/boards/stores/actions'; import * as types from '~/boards/stores/mutation_types'; -import { inactiveId } from '~/boards/constants'; +import { inactiveId, ListType } from '~/boards/constants'; const expectNotImplemented = action => { it('is not implemented', () => { @@ -62,8 +62,31 @@ describe('setActiveId', () => { }); }); -describe('fetchLists', () => { - expectNotImplemented(actions.fetchLists); +describe('showWelcomeList', () => { + it('should dispatch addList action', done => { + const state = { + endpoints: { fullPath: 'gitlab-org', boardId: '1' }, + boardType: 'group', + disabled: false, + boardLists: [{ type: 'backlog' }, { type: 'closed' }], + }; + + const blankList = { + id: 'blank', + listType: ListType.blank, + title: 'Welcome to your issue board!', + position: 0, + }; + + testAction( + actions.showWelcomeList, + {}, + state, + [], + [{ type: 'addList', payload: blankList }], + done, + ); + }); }); describe('generateDefaultLists', () => { @@ -71,7 +94,70 @@ describe('generateDefaultLists', () => { }); describe('createList', () => { - expectNotImplemented(actions.createList); + it('should dispatch addList action when creating backlog list', done => { + const backlogList = { + id: 'gid://gitlab/List/1', + listType: 'backlog', + title: 'Open', + position: 0, + }; + + jest.spyOn(gqlClient, 'mutate').mockReturnValue( + Promise.resolve({ + data: { + boardListCreate: { + list: backlogList, + errors: [], + }, + }, + }), + ); + + const state = { + endpoints: { fullPath: 'gitlab-org', boardId: '1' }, + boardType: 'group', + disabled: false, + boardLists: [{ type: 'closed' }], + }; + + testAction( + actions.createList, + { backlog: true }, + state, + [], + [{ type: 'addList', payload: { ...backlogList, id: 1 } }], + done, + ); + }); + + it('should commit CREATE_LIST_FAILURE mutation when API returns an error', done => { + jest.spyOn(gqlClient, 'mutate').mockReturnValue( + Promise.resolve({ + data: { + boardListCreate: { + list: {}, + errors: [{ foo: 'bar' }], + }, + }, + }), + ); + + const state = { + endpoints: { fullPath: 'gitlab-org', boardId: '1' }, + boardType: 'group', + disabled: false, + boardLists: [{ type: 'closed' }], + }; + + testAction( + actions.createList, + { backlog: true }, + state, + [{ type: types.CREATE_LIST_FAILURE }], + [], + done, + ); + }); }); describe('updateList', () => { diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js index e5b26e9994e..51833241b37 100644 --- a/spec/frontend/boards/stores/mutations_spec.js +++ b/spec/frontend/boards/stores/mutations_spec.js @@ -1,6 +1,7 @@ import mutations from '~/boards/stores/mutations'; +import * as types from '~/boards/stores/mutation_types'; import defaultState from '~/boards/stores/state'; -import { mockIssue } from '../mock_data'; +import { listObj, listObjDuplicate, mockIssue } from '../mock_data'; const expectNotImplemented = action => { it('is not implemented', () => { @@ -26,11 +27,30 @@ describe('Board Store Mutations', () => { fullPath: 'gitlab-org', }; const boardType = 'group'; + const disabled = false; + const showPromotion = false; - mutations.SET_INITIAL_BOARD_DATA(state, { ...endpoints, boardType }); + mutations[types.SET_INITIAL_BOARD_DATA](state, { + ...endpoints, + boardType, + disabled, + showPromotion, + }); expect(state.endpoints).toEqual(endpoints); expect(state.boardType).toEqual(boardType); + expect(state.disabled).toEqual(disabled); + expect(state.showPromotion).toEqual(showPromotion); + }); + }); + + describe('RECEIVE_LISTS', () => { + it('Should set boardLists to state', () => { + const lists = [listObj, listObjDuplicate]; + + mutations[types.RECEIVE_LISTS](state, lists); + + expect(state.boardLists).toEqual(lists); }); }); diff --git a/spec/frontend/helpers/fake_date.js b/spec/frontend/helpers/fake_date.js new file mode 100644 index 00000000000..8417b1c520a --- /dev/null +++ b/spec/frontend/helpers/fake_date.js @@ -0,0 +1,49 @@ +// Frida Kahlo's birthday (6 = July) +export const DEFAULT_ARGS = [2020, 6, 6]; + +const RealDate = Date; + +const isMocked = val => Boolean(val.mock); + +export const createFakeDateClass = ctorDefault => { + const FakeDate = new Proxy(RealDate, { + construct: (target, argArray) => { + const ctorArgs = argArray.length ? argArray : ctorDefault; + + return new RealDate(...ctorArgs); + }, + apply: (target, thisArg, argArray) => { + const ctorArgs = argArray.length ? argArray : ctorDefault; + + return RealDate(...ctorArgs); + }, + // We want to overwrite the default 'now', but only if it's not already mocked + get: (target, prop) => { + if (prop === 'now' && !isMocked(target[prop])) { + return () => new RealDate(...ctorDefault).getTime(); + } + + return target[prop]; + }, + getPrototypeOf: target => { + return target.prototype; + }, + // We need to be able to set props so that `jest.spyOn` will work. + set: (target, prop, value) => { + // eslint-disable-next-line no-param-reassign + target[prop] = value; + return true; + }, + }); + + return FakeDate; +}; + +export const useFakeDate = (...args) => { + const FakeDate = createFakeDateClass(args.length ? args : DEFAULT_ARGS); + global.Date = FakeDate; +}; + +export const useRealDate = () => { + global.Date = RealDate; +}; diff --git a/spec/frontend/helpers/fake_date_spec.js b/spec/frontend/helpers/fake_date_spec.js new file mode 100644 index 00000000000..8afc8225f9b --- /dev/null +++ b/spec/frontend/helpers/fake_date_spec.js @@ -0,0 +1,33 @@ +import { createFakeDateClass, DEFAULT_ARGS, useRealDate } from './fake_date'; + +describe('spec/helpers/fake_date', () => { + describe('createFakeDateClass', () => { + let FakeDate; + + beforeAll(() => { + useRealDate(); + }); + + beforeEach(() => { + FakeDate = createFakeDateClass(DEFAULT_ARGS); + }); + + it('should use default args', () => { + expect(new FakeDate()).toEqual(new Date(...DEFAULT_ARGS)); + expect(FakeDate()).toEqual(Date(...DEFAULT_ARGS)); + }); + + it('should have deterministic now()', () => { + expect(FakeDate.now()).not.toBe(Date.now()); + expect(FakeDate.now()).toBe(new Date(...DEFAULT_ARGS).getTime()); + }); + + it('should be instanceof Date', () => { + expect(new FakeDate()).toBeInstanceOf(Date); + }); + + it('should be instanceof self', () => { + expect(new FakeDate()).toBeInstanceOf(FakeDate); + }); + }); +}); diff --git a/spec/frontend/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_projects/components/import_projects_table_spec.js index b217242968a..7ae4d650e36 100644 --- a/spec/frontend/import_projects/components/import_projects_table_spec.js +++ b/spec/frontend/import_projects/components/import_projects_table_spec.js @@ -110,8 +110,8 @@ describe('ImportProjectsTable', () => { wrapper .findAll('th') .filter(w => w.text() === `From ${providerTitle}`) - .isEmpty(), - ).toBe(false); + .exists(), + ).toBe(true); expect(wrapper.contains(ProviderRepoTableRow)).toBe(true); expect(wrapper.contains(ImportedProjectTableRow)).toBe(true); diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js new file mode 100644 index 00000000000..38bcb1e0aab --- /dev/null +++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js @@ -0,0 +1,76 @@ +import { mount } from '@vue/test-utils'; +import { GlFormCheckbox } from '@gitlab/ui'; +import { createStore } from '~/integrations/edit/store'; + +import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue'; + +describe('ActiveCheckbox', () => { + let wrapper; + + const createComponent = (customStateProps = {}, isInheriting = false) => { + wrapper = mount(ActiveCheckbox, { + store: createStore({ + customState: { ...customStateProps }, + }), + computed: { + isInheriting: () => isInheriting, + }, + }); + }; + + afterEach(() => { + if (wrapper) { + wrapper.destroy(); + wrapper = null; + } + }); + + const findGlFormCheckbox = () => wrapper.find(GlFormCheckbox); + const findInputInCheckbox = () => findGlFormCheckbox().find('input'); + + describe('template', () => { + describe('is inheriting adminSettings', () => { + it('renders GlFormCheckbox as disabled', () => { + createComponent({}, true); + + expect(findGlFormCheckbox().exists()).toBe(true); + expect(findInputInCheckbox().attributes('disabled')).toBe('disabled'); + }); + }); + + describe('initialActivated is false', () => { + it('renders GlFormCheckbox as unchecked', () => { + createComponent({ + initialActivated: false, + }); + + expect(findGlFormCheckbox().exists()).toBe(true); + expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false); + expect(findInputInCheckbox().attributes('disabled')).toBeUndefined(); + }); + }); + + describe('initialActivated is true', () => { + beforeEach(() => { + createComponent({ + initialActivated: true, + }); + }); + + it('renders GlFormCheckbox as checked', () => { + expect(findGlFormCheckbox().exists()).toBe(true); + expect(findGlFormCheckbox().vm.$attrs.checked).toBe(true); + }); + + describe('on checkbox click', () => { + it('switches the form value', async () => { + findInputInCheckbox().trigger('click'); + + await wrapper.vm.$nextTick(); + + expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false); + }); + }); + }); + }); +}); diff --git a/spec/frontend/integrations/edit/components/active_toggle_spec.js b/spec/frontend/integrations/edit/components/active_toggle_spec.js deleted file mode 100644 index 228d8f5fc30..00000000000 --- a/spec/frontend/integrations/edit/components/active_toggle_spec.js +++ /dev/null @@ -1,81 +0,0 @@ -import { mount } from '@vue/test-utils'; -import { GlToggle } from '@gitlab/ui'; - -import ActiveToggle from '~/integrations/edit/components/active_toggle.vue'; - -const GL_TOGGLE_ACTIVE_CLASS = 'is-checked'; -const GL_TOGGLE_DISABLED_CLASS = 'is-disabled'; - -describe('ActiveToggle', () => { - let wrapper; - - const defaultProps = { - initialActivated: true, - }; - - const createComponent = (props = {}, isInheriting = false) => { - wrapper = mount(ActiveToggle, { - propsData: { ...defaultProps, ...props }, - computed: { - isInheriting: () => isInheriting, - }, - }); - }; - - afterEach(() => { - if (wrapper) { - wrapper.destroy(); - wrapper = null; - } - }); - - const findGlToggle = () => wrapper.find(GlToggle); - const findButtonInToggle = () => findGlToggle().find('button'); - const findInputInToggle = () => findGlToggle().find('input'); - - describe('template', () => { - describe('is inheriting adminSettings', () => { - it('renders GlToggle as disabled', () => { - createComponent({}, true); - - expect(findGlToggle().exists()).toBe(true); - expect(findButtonInToggle().classes()).toContain(GL_TOGGLE_DISABLED_CLASS); - }); - }); - - describe('initialActivated is false', () => { - it('renders GlToggle as inactive', () => { - createComponent({ - initialActivated: false, - }); - - expect(findGlToggle().exists()).toBe(true); - expect(findButtonInToggle().classes()).not.toContain(GL_TOGGLE_ACTIVE_CLASS); - expect(findInputInToggle().attributes('value')).toBe('false'); - }); - }); - - describe('initialActivated is true', () => { - beforeEach(() => { - createComponent(); - }); - - it('renders GlToggle as active', () => { - expect(findGlToggle().exists()).toBe(true); - expect(findButtonInToggle().classes()).toContain(GL_TOGGLE_ACTIVE_CLASS); - expect(findInputInToggle().attributes('value')).toBe('true'); - }); - - describe('on toggle click', () => { - it('switches the form value', () => { - findButtonInToggle().trigger('click'); - - wrapper.vm.$nextTick(() => { - expect(findButtonInToggle().classes()).not.toContain(GL_TOGGLE_ACTIVE_CLASS); - expect(findInputInToggle().attributes('value')).toBe('false'); - }); - }); - }); - }); - }); -}); diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js index f8e2eb5e7f4..fccb56f4597 100644 --- a/spec/frontend/integrations/edit/components/integration_form_spec.js +++ b/spec/frontend/integrations/edit/components/integration_form_spec.js @@ -3,7 +3,7 @@ import { mockIntegrationProps } from 'jest/integrations/edit/mock_data'; import { createStore } from '~/integrations/edit/store'; import IntegrationForm from '~/integrations/edit/components/integration_form.vue'; import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue'; -import ActiveToggle from '~/integrations/edit/components/active_toggle.vue'; +import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue'; import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue'; import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue'; import TriggerFields from '~/integrations/edit/components/trigger_fields.vue'; @@ -21,7 +21,7 @@ describe('IntegrationForm', () => { }), stubs: { OverrideDropdown, - ActiveToggle, + ActiveCheckbox, JiraTriggerFields, TriggerFields, }, @@ -39,27 +39,27 @@ describe('IntegrationForm', () => { }); const findOverrideDropdown = () => wrapper.find(OverrideDropdown); - const findActiveToggle = () => wrapper.find(ActiveToggle); + const findActiveCheckbox = () => wrapper.find(ActiveCheckbox); const findJiraTriggerFields = () => wrapper.find(JiraTriggerFields); const findJiraIssuesFields = () => wrapper.find(JiraIssuesFields); const findTriggerFields = () => wrapper.find(TriggerFields); describe('template', () => { describe('showActive is true', () => { - it('renders ActiveToggle', () => { + it('renders ActiveCheckbox', () => { createComponent(); - expect(findActiveToggle().exists()).toBe(true); + expect(findActiveCheckbox().exists()).toBe(true); }); }); describe('showActive is false', () => { - it('does not render ActiveToggle', () => { + it('does not render ActiveCheckbox', () => { createComponent({ showActive: false, }); - expect(findActiveToggle().exists()).toBe(false); + expect(findActiveCheckbox().exists()).toBe(false); }); }); diff --git a/spec/frontend/integrations/edit/mock_data.js b/spec/frontend/integrations/edit/mock_data.js index 0886290c908..821972b7698 100644 --- a/spec/frontend/integrations/edit/mock_data.js +++ b/spec/frontend/integrations/edit/mock_data.js @@ -1,8 +1,6 @@ export const mockIntegrationProps = { id: 25, - activeToggleProps: { - initialActivated: true, - }, + initialActivated: true, showActive: true, triggerFieldsProps: { initialTriggerCommit: false, diff --git a/spec/frontend/issuable_suggestions/components/app_spec.js b/spec/frontend/issuable_suggestions/components/app_spec.js index d51c89807be..015bd1b1efb 100644 --- a/spec/frontend/issuable_suggestions/components/app_spec.js +++ b/spec/frontend/issuable_suggestions/components/app_spec.js @@ -41,7 +41,7 @@ describe('Issuable suggestions app component', () => { wrapper.setData(data); return wrapper.vm.$nextTick(() => { - expect(wrapper.isEmpty()).toBe(false); + expect(wrapper.findAll('li').length).toBe(data.issues.length); }); }); diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js index 6421aca684f..c998fbfaf41 100644 --- a/spec/frontend/logs/components/environment_logs_spec.js +++ b/spec/frontend/logs/components/environment_logs_spec.js @@ -122,7 +122,6 @@ describe('EnvironmentLogs', () => { initWrapper(); expect(wrapper.isVueInstance()).toBe(true); - expect(wrapper.isEmpty()).toBe(false); expect(findEnvironmentsDropdown().is(GlDeprecatedDropdown)).toBe(true); expect(findSimpleFilters().exists()).toBe(true); diff --git a/spec/frontend/logs/components/log_advanced_filters_spec.js b/spec/frontend/logs/components/log_advanced_filters_spec.js index 007c5000e16..af472790a18 100644 --- a/spec/frontend/logs/components/log_advanced_filters_spec.js +++ b/spec/frontend/logs/components/log_advanced_filters_spec.js @@ -69,7 +69,6 @@ describe('LogAdvancedFilters', () => { initWrapper(); expect(wrapper.isVueInstance()).toBe(true); - expect(wrapper.isEmpty()).toBe(false); expect(findFilteredSearch().exists()).toBe(true); expect(findTimeRangePicker().exists()).toBe(true); diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js index 38e568f569f..9b3e2ebbafa 100644 --- a/spec/frontend/logs/components/log_control_buttons_spec.js +++ b/spec/frontend/logs/components/log_control_buttons_spec.js @@ -29,7 +29,6 @@ describe('LogControlButtons', () => { initWrapper(); expect(wrapper.isVueInstance()).toBe(true); - expect(wrapper.isEmpty()).toBe(false); expect(findScrollToTop().is(GlButton)).toBe(true); expect(findScrollToBottom().is(GlButton)).toBe(true); diff --git a/spec/frontend/logs/components/log_simple_filters_spec.js b/spec/frontend/logs/components/log_simple_filters_spec.js index e739621431e..c7908dc2cc5 100644 --- a/spec/frontend/logs/components/log_simple_filters_spec.js +++ b/spec/frontend/logs/components/log_simple_filters_spec.js @@ -60,7 +60,6 @@ describe('LogSimpleFilters', () => { initWrapper(); expect(wrapper.isVueInstance()).toBe(true); - expect(wrapper.isEmpty()).toBe(false); expect(findPodsDropdown().exists()).toBe(true); }); diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js index f37d95317ab..ca01f821da3 100644 --- a/spec/frontend/monitoring/components/dashboard_spec.js +++ b/spec/frontend/monitoring/components/dashboard_spec.js @@ -668,7 +668,11 @@ describe('Dashboard', () => { }); it('shows a remove button, which removes a panel', () => { - expect(findFirstDraggableRemoveButton().isEmpty()).toBe(false); + expect( + findFirstDraggableRemoveButton() + .find('a') + .exists(), + ).toBe(true); expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount); findFirstDraggableRemoveButton().trigger('click'); diff --git a/spec/frontend/packages/details/components/package_history_spec.js b/spec/frontend/packages/details/components/package_history_spec.js index e293e119585..28bcbbb2b1b 100644 --- a/spec/frontend/packages/details/components/package_history_spec.js +++ b/spec/frontend/packages/details/components/package_history_spec.js @@ -1,6 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import { GlLink, GlSprintf } from '@gitlab/ui'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; +import HistoryElement from '~/packages/details/components/history_element.vue'; import component from '~/packages/details/components/package_history.vue'; import { mavenPackage, mockPipelineInfo } from '../../mock_data'; @@ -16,7 +17,10 @@ describe('Package History', () => { wrapper = shallowMount(component, { propsData: { ...defaultProps, ...props }, stubs: { - HistoryElement: '<div data-testid="history-element"><slot></slot></div>', + HistoryElement: { + props: HistoryElement.props, + template: '<div data-testid="history-element"><slot></slot></div>', + }, GlSprintf, }, }); diff --git a/spec/frontend/performance_bar/services/performance_bar_service_spec.js b/spec/frontend/performance_bar/services/performance_bar_service_spec.js index 5e7a52ba734..36bfd575c12 100644 --- a/spec/frontend/performance_bar/services/performance_bar_service_spec.js +++ b/spec/frontend/performance_bar/services/performance_bar_service_spec.js @@ -8,13 +8,13 @@ describe('PerformanceBarService', () => { } it('returns false when the request URL is the peek URL', () => { - expect(fireCallback({ headers: { 'x-request-id': '123' }, url: '/peek' }, '/peek')).toBe( - false, - ); + expect( + fireCallback({ headers: { 'x-request-id': '123' }, config: { url: '/peek' } }, '/peek'), + ).toBe(false); }); it('returns false when there is no request ID', () => { - expect(fireCallback({ headers: {}, url: '/request' }, '/peek')).toBe(false); + expect(fireCallback({ headers: {}, config: { url: '/request' } }, '/peek')).toBe(false); }); it('returns false when the response is from the cache', () => { @@ -27,15 +27,18 @@ describe('PerformanceBarService', () => { }); it('returns true when the request is an API request', () => { - expect(fireCallback({ headers: { 'x-request-id': '123' }, url: '/api/' }, '/peek')).toBe( - true, - ); + expect( + fireCallback({ headers: { 'x-request-id': '123' }, config: { url: '/api/' } }, '/peek'), + ).toBe(true); }); it('returns true for all other requests', () => { - expect(fireCallback({ headers: { 'x-request-id': '123' }, url: '/request' }, '/peek')).toBe( - true, - ); + expect( + fireCallback( + { headers: { 'x-request-id': '123' }, config: { url: '/request' } }, + '/peek', + ), + ).toBe(true); }); }); @@ -45,7 +48,7 @@ describe('PerformanceBarService', () => { } it('gets the request ID from the headers', () => { - expect(requestId({ headers: { 'x-request-id': '123' } }, '/peek')).toEqual('123'); + expect(requestId({ headers: { 'x-request-id': '123' } }, '/peek')).toBe('123'); }); }); @@ -54,14 +57,10 @@ describe('PerformanceBarService', () => { return PerformanceBarService.callbackParams(response, peekUrl)[2]; } - it('gets the request URL from the response object', () => { - expect(requestUrl({ headers: {}, url: '/request' }, '/peek')).toEqual('/request'); - }); - - it('gets the request URL from response.config if present', () => { - expect( - requestUrl({ headers: {}, config: { url: '/config-url' }, url: '/request' }, '/peek'), - ).toEqual('/config-url'); + it('gets the request URL from response.config', () => { + expect(requestUrl({ headers: {}, config: { url: '/config-url' } }, '/peek')).toBe( + '/config-url', + ); }); }); }); diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js index c5b7318d3af..3c9982ecee3 100644 --- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js +++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js @@ -48,7 +48,6 @@ describe('Pipelines filtered search', () => { it('displays UI elements', () => { expect(wrapper.isVueInstance()).toBe(true); - expect(wrapper.isEmpty()).toBe(false); expect(findFilteredSearch().exists()).toBe(true); }); diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js index cce4c2dfa7b..071a2b24889 100644 --- a/spec/frontend/pipelines/pipelines_actions_spec.js +++ b/spec/frontend/pipelines/pipelines_actions_spec.js @@ -1,7 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import { TEST_HOST } from 'spec/test_constants'; -import { GlDeprecatedButton } from '@gitlab/ui'; +import { GlButton } from '@gitlab/ui'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; import PipelinesActions from '~/pipelines/components/pipelines_list/pipelines_actions.vue'; @@ -19,7 +19,7 @@ describe('Pipelines Actions dropdown', () => { }); }; - const findAllDropdownItems = () => wrapper.findAll(GlDeprecatedButton); + const findAllDropdownItems = () => wrapper.findAll(GlButton); const findAllCountdowns = () => wrapper.findAll(GlCountdown); beforeEach(() => { @@ -66,7 +66,7 @@ describe('Pipelines Actions dropdown', () => { it('makes a request and toggles the loading state', () => { mock.onPost(mockActions.path).reply(200); - wrapper.find(GlDeprecatedButton).vm.$emit('click'); + wrapper.find(GlButton).vm.$emit('click'); expect(wrapper.vm.isLoading).toBe(true); diff --git a/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js index 096e4cd97f6..b53955ab743 100644 --- a/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js +++ b/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js @@ -5,16 +5,17 @@ import PipelineStatusToken from '~/pipelines/components/pipelines_list/tokens/pi describe('Pipeline Status Token', () => { let wrapper; - const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken); - const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); - const findAllGlIcons = () => wrapper.findAll(GlIcon); - const stubs = { GlFilteredSearchToken: { + props: GlFilteredSearchToken.props, template: `<div><slot name="suggestions"></slot></div>`, }, }; + const findFilteredSearchToken = () => wrapper.find(stubs.GlFilteredSearchToken); + const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + const findAllGlIcons = () => wrapper.findAll(GlIcon); + const defaultProps = { config: { type: 'status', @@ -27,12 +28,12 @@ describe('Pipeline Status Token', () => { }, }; - const createComponent = options => { + const createComponent = () => { wrapper = shallowMount(PipelineStatusToken, { propsData: { ...defaultProps, }, - ...options, + stubs, }); }; @@ -50,10 +51,6 @@ describe('Pipeline Status Token', () => { }); describe('shows statuses correctly', () => { - beforeEach(() => { - createComponent({ stubs }); - }); - it('renders all pipeline statuses available', () => { expect(findAllFilteredSearchSuggestions()).toHaveLength(wrapper.vm.statuses.length); expect(findAllGlIcons()).toHaveLength(wrapper.vm.statuses.length); diff --git a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js index c95d2ea1b7b..9363944a719 100644 --- a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js +++ b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js @@ -7,16 +7,17 @@ import { users } from '../mock_data'; describe('Pipeline Trigger Author Token', () => { let wrapper; - const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken); - const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); - const findLoadingIcon = () => wrapper.find(GlLoadingIcon); - const stubs = { GlFilteredSearchToken: { + props: GlFilteredSearchToken.props, template: `<div><slot name="suggestions"></slot></div>`, }, }; + const findFilteredSearchToken = () => wrapper.find(stubs.GlFilteredSearchToken); + const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + const findLoadingIcon = () => wrapper.find(GlLoadingIcon); + const defaultProps = { config: { type: 'username', @@ -31,7 +32,7 @@ describe('Pipeline Trigger Author Token', () => { }, }; - const createComponent = (options, data) => { + const createComponent = data => { wrapper = shallowMount(PipelineTriggerAuthorToken, { propsData: { ...defaultProps, @@ -41,7 +42,7 @@ describe('Pipeline Trigger Author Token', () => { ...data, }; }, - ...options, + stubs, }); }; @@ -69,13 +70,13 @@ describe('Pipeline Trigger Author Token', () => { describe('displays loading icon correctly', () => { it('shows loading icon', () => { - createComponent({ stubs }, { loading: true }); + createComponent({ loading: true }); expect(findLoadingIcon().exists()).toBe(true); }); it('does not show loading icon', () => { - createComponent({ stubs }, { loading: false }); + createComponent({ loading: false }); expect(findLoadingIcon().exists()).toBe(false); }); @@ -85,22 +86,17 @@ describe('Pipeline Trigger Author Token', () => { beforeEach(() => {}); it('renders all trigger authors', () => { - createComponent({ stubs }, { users, loading: false }); + createComponent({ users, loading: false }); // should have length of all users plus the static 'Any' option expect(findAllFilteredSearchSuggestions()).toHaveLength(users.length + 1); }); it('renders only the trigger author searched for', () => { - createComponent( - { stubs }, - { - users: [ - { name: 'Arnold', username: 'admin', state: 'active', avatar_url: 'avatar-link' }, - ], - loading: false, - }, - ); + createComponent({ + users: [{ name: 'Arnold', username: 'admin', state: 'active', avatar_url: 'avatar-link' }], + loading: false, + }); expect(findAllFilteredSearchSuggestions()).toHaveLength(2); }); diff --git a/spec/frontend/vue_shared/components/table_pagination_spec.js b/spec/frontend/vue_shared/components/table_pagination_spec.js index ef3ae088eec..2a4672c2647 100644 --- a/spec/frontend/vue_shared/components/table_pagination_spec.js +++ b/spec/frontend/vue_shared/components/table_pagination_spec.js @@ -50,7 +50,7 @@ describe('Pagination component', () => { change: spy, }); - expect(wrapper.isEmpty()).toBe(false); + expect(wrapper.find(GlPagination).exists()).toBe(true); }); it('renders if there is a prev page', () => { @@ -66,7 +66,7 @@ describe('Pagination component', () => { change: spy, }); - expect(wrapper.isEmpty()).toBe(false); + expect(wrapper.find(GlPagination).exists()).toBe(true); }); }); diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb index 6f1f358af83..a42be3c87fb 100644 --- a/spec/helpers/user_callouts_helper_spec.rb +++ b/spec/helpers/user_callouts_helper_spec.rb @@ -81,6 +81,26 @@ RSpec.describe UserCalloutsHelper do end end + describe '.show_service_templates_deprecated?' do + subject { helper.show_service_templates_deprecated? } + + context 'when user has not dismissed' do + before do + allow(helper).to receive(:user_dismissed?).with(described_class::SERVICE_TEMPLATES_DEPRECATED) { false } + end + + it { is_expected.to be true } + end + + context 'when user dismissed' do + before do + allow(helper).to receive(:user_dismissed?).with(described_class::SERVICE_TEMPLATES_DEPRECATED) { true } + end + + it { is_expected.to be false } + end + end + describe '.show_customize_homepage_banner?' do let(:customize_homepage) { true } diff --git a/spec/lib/gitlab/badge/pipeline/status_spec.rb b/spec/lib/gitlab/badge/pipeline/status_spec.rb index fcc0d4030fd..b5dabca0477 100644 --- a/spec/lib/gitlab/badge/pipeline/status_spec.rb +++ b/spec/lib/gitlab/badge/pipeline/status_spec.rb @@ -78,6 +78,34 @@ RSpec.describe Gitlab::Badge::Pipeline::Status do expect(badge.status).to eq 'success' end end + + context 'when ignored_skipped is set to true' do + let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: true }) } + + before do + pipeline.skip! + end + + describe '#status' do + it 'uses latest non-skipped status' do + expect(new_badge.status).not_to eq 'skipped' + end + end + end + + context 'when ignored_skipped is set to false' do + let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: false }) } + + before do + pipeline.skip! + end + + describe '#status' do + it 'uses latest status' do + expect(new_badge.status).to eq 'skipped' + end + end + end end context 'build does not exist' do diff --git a/spec/models/ci/pipeline_artifact_spec.rb b/spec/models/ci/pipeline_artifact_spec.rb index 9d2172d7572..3a7aa9d33b7 100644 --- a/spec/models/ci/pipeline_artifact_spec.rb +++ b/spec/models/ci/pipeline_artifact_spec.rb @@ -12,6 +12,10 @@ RSpec.describe Ci::PipelineArtifact, type: :model do it_behaves_like 'having unique enum values' + it_behaves_like 'UpdateProjectStatistics' do + subject { build(:ci_pipeline_artifact) } + end + describe 'validations' do it { is_expected.to validate_presence_of(:pipeline) } it { is_expected.to validate_presence_of(:project) } diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb index 5f66de3a63c..383fabcfffb 100644 --- a/spec/models/project_statistics_spec.rb +++ b/spec/models/project_statistics_spec.rb @@ -32,8 +32,9 @@ RSpec.describe ProjectStatistics do repository_size: 2.exabytes, wiki_size: 1.exabytes, lfs_objects_size: 2.exabytes, - build_artifacts_size: 2.exabytes - 1, - snippets_size: 1.exabyte + build_artifacts_size: 1.exabyte, + snippets_size: 1.exabyte, + pipeline_artifacts_size: 1.exabyte - 1 ) statistics.reload @@ -42,9 +43,10 @@ RSpec.describe ProjectStatistics do expect(statistics.repository_size).to eq(2.exabytes) expect(statistics.wiki_size).to eq(1.exabytes) expect(statistics.lfs_objects_size).to eq(2.exabytes) - expect(statistics.build_artifacts_size).to eq(2.exabytes - 1) + expect(statistics.build_artifacts_size).to eq(1.exabyte) expect(statistics.storage_size).to eq(8.exabytes - 1) expect(statistics.snippets_size).to eq(1.exabyte) + expect(statistics.pipeline_artifacts_size).to eq(1.exabyte - 1) end end @@ -282,12 +284,13 @@ RSpec.describe ProjectStatistics do repository_size: 2, wiki_size: 4, lfs_objects_size: 3, - snippets_size: 2 + snippets_size: 2, + pipeline_artifacts_size: 3 ) statistics.reload - expect(statistics.storage_size).to eq 11 + expect(statistics.storage_size).to eq 14 end it 'works during wiki_size backfill' do @@ -339,6 +342,12 @@ RSpec.describe ProjectStatistics do it_behaves_like 'a statistic that increases storage_size' end + context 'when adjusting :pipeline_artifacts_size' do + let(:stat) { :pipeline_artifacts_size } + + it_behaves_like 'a statistic that increases storage_size' + end + context 'when adjusting :packages_size' do let(:stat) { :packages_size } diff --git a/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb b/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb index db931c50bdf..df8130b9c5d 100644 --- a/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb +++ b/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb @@ -10,7 +10,7 @@ require_relative '../../../../rubocop/cop/usage_data/distinct_count_by_large_for RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey, type: :rubocop do include CopHelper - let(:allowed_foreign_keys) { %i[author_id user_id] } + let(:allowed_foreign_keys) { [:author_id, :user_id, :'merge_requests.target_project_id'] } let(:config) do RuboCop::Config.new('UsageData/DistinctCountByLargeForeignKey' => { @@ -29,10 +29,16 @@ RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey, type: :r end context 'when calling by allowed key' do - it 'does not register an offence' do + it 'does not register an offence with symbol' do inspect_source('distinct_count(Issue, :author_id)') expect(cop.offenses).to be_empty end + + it 'does not register an offence with string' do + inspect_source("distinct_count(Issue, 'merge_requests.target_project_id')") + + expect(cop.offenses).to be_empty + end end end diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index 641ed24207e..a64871ca75b 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -247,9 +247,8 @@ module TestEnv 'GitLab Workhorse', install_dir: workhorse_dir, version: Gitlab::Workhorse.version, - task: "gitlab:workhorse:install[#{install_workhorse_args}]") do - Gitlab::SetupHelper::Workhorse.create_configuration(workhorse_dir, nil) - end + task: "gitlab:workhorse:install[#{install_workhorse_args}]" + ) end def workhorse_dir @@ -260,14 +259,6 @@ module TestEnv host = "[#{host}]" if host.include?(':') listen_addr = [host, port].join(':') - config_path = Gitlab::SetupHelper::Workhorse.get_config_path(workhorse_dir) - - # This should be set up in setup_workhorse, but since - # component_needs_update? only checks that versions are consistent, - # we need to ensure the config file exists. This line can be removed - # later after a new Workhorse version is updated. - Gitlab::SetupHelper::Workhorse.create_configuration(workhorse_dir, nil) unless File.exist?(config_path) - workhorse_pid = spawn( { 'PATH' => "#{ENV['PATH']}:#{workhorse_dir}" }, File.join(workhorse_dir, 'gitlab-workhorse'), @@ -275,7 +266,10 @@ module TestEnv '-documentRoot', Rails.root.join('public').to_s, '-listenAddr', listen_addr, '-secretPath', Gitlab::Workhorse.secret_path.to_s, - '-config', config_path, + # TODO: Needed for workhorse + redis features. + # https://gitlab.com/gitlab-org/gitlab/-/issues/209245 + # + # '-config', '', '-logFile', 'log/workhorse-test.log', '-logFormat', 'structured', '-developmentMode' # to serve assets and rich error messages diff --git a/spec/support/shared_contexts/project_service_jira_context.rb b/spec/support/shared_contexts/project_service_jira_context.rb index 4ca5c99323a..8e01de70846 100644 --- a/spec/support/shared_contexts/project_service_jira_context.rb +++ b/spec/support/shared_contexts/project_service_jira_context.rb @@ -5,7 +5,7 @@ RSpec.shared_context 'project service Jira context' do let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' } def fill_form(disable: false) - click_active_toggle if disable + click_active_checkbox if disable fill_in 'service_url', with: url fill_in 'service_username', with: 'username' diff --git a/spec/support/shared_contexts/project_service_shared_context.rb b/spec/support/shared_contexts/project_service_shared_context.rb index a72d4901b72..36cc81f6689 100644 --- a/spec/support/shared_contexts/project_service_shared_context.rb +++ b/spec/support/shared_contexts/project_service_shared_context.rb @@ -18,8 +18,8 @@ RSpec.shared_context 'project service activation' do click_link(name) end - def click_active_toggle - find('input[name="service[active]"] + button').click + def click_active_checkbox + find('input[name="service[active]"]').click end def click_test_integration diff --git a/spec/views/admin/services/index.html.haml_spec.rb b/spec/views/admin/services/index.html.haml_spec.rb new file mode 100644 index 00000000000..e8cd2dde67e --- /dev/null +++ b/spec/views/admin/services/index.html.haml_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'admin/services/index.html.haml' do + before do + assign(:services, build_stubbed_list(:service, 1)) + assign(:existing_instance_types, []) + end + + context 'user has not dismissed Service Templates deprecation message' do + it 'shows the message' do + allow(view).to receive(:show_service_templates_deprecated?).and_return(true) + + render + + expect(rendered).to have_content('Service Templates will soon be deprecated.') + end + end + + context 'user has dismissed Service Templates deprecation message' do + it 'does not show the message' do + allow(view).to receive(:show_service_templates_deprecated?).and_return(false) + + render + + expect(rendered).not_to have_content('Service Templates will soon be deprecated.') + end + end +end diff --git a/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb b/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb index d9f2dd326dd..f510852e753 100644 --- a/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb +++ b/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb @@ -29,10 +29,8 @@ RSpec.describe Ci::RefDeleteUnlockArtifactsWorker do context 'when user exists' do let(:user_id) { project.creator.id } - context 'when ci ref exists' do - before do - create(:ci_ref, ref_path: ref) - end + context 'when ci ref exists for project' do + let!(:ci_ref) { create(:ci_ref, ref_path: ref, project: project) } it 'calls the service' do service = spy(Ci::UnlockArtifactsService) @@ -40,17 +38,33 @@ RSpec.describe Ci::RefDeleteUnlockArtifactsWorker do perform - expect(service).to have_received(:execute) + expect(service).to have_received(:execute).with(ci_ref) end end - context 'when ci ref does not exist' do + context 'when ci ref does not exist for the given project' do + let!(:another_ci_ref) { create(:ci_ref, ref_path: ref) } + it 'does not call the service' do expect(Ci::UnlockArtifactsService).not_to receive(:new) perform end end + + context 'when same ref path exists for a different project' do + let!(:another_ci_ref) { create(:ci_ref, ref_path: ref) } + let!(:ci_ref) { create(:ci_ref, ref_path: ref, project: project) } + + it 'calls the service with the correct ref_id' do + service = spy(Ci::UnlockArtifactsService) + expect(Ci::UnlockArtifactsService).to receive(:new).and_return(service) + + perform + + expect(service).to have_received(:execute).with(ci_ref) + end + end end context 'when user does not exist' do diff --git a/spec/workers/deployments/finished_worker_spec.rb b/spec/workers/deployments/finished_worker_spec.rb index e1ec2d89e0a..d0a26ae1547 100644 --- a/spec/workers/deployments/finished_worker_spec.rb +++ b/spec/workers/deployments/finished_worker_spec.rb @@ -61,17 +61,5 @@ RSpec.describe Deployments::FinishedWorker do worker.perform(deployment.id) end - - it 'does not execute webhooks if feature flag is disabled' do - stub_feature_flags(deployment_webhooks: false) - - deployment = create(:deployment) - project = deployment.project - create(:project_hook, deployment_events: true, project: project) - - expect(WebHookService).not_to receive(:new) - - worker.perform(deployment.id) - end end end |