diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-20 15:08:18 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-20 15:08:18 +0300 |
commit | d00cd98a2b1b3f0899677f61257821c94cde8e31 (patch) | |
tree | 602dc6d5ca71906ff282d87808c0c1d04b853aeb /spec | |
parent | edf0e5b64384499283b406f9087e890ac4fad13f (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
22 files changed, 383 insertions, 95 deletions
diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index a927f0fb501..c3ae0279c05 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -90,10 +90,19 @@ FactoryBot.define do end end + factory :bamboo_integration, class: 'Integrations::Bamboo' do + project + active { true } + bamboo_url { 'https://bamboo.example.com' } + build_key { 'foo' } + username { 'mic' } + password { 'password' } + end + factory :drone_ci_integration, class: 'Integrations::DroneCi' do project active { true } - drone_url { 'https://bamboo.example.com' } + drone_url { 'https://drone.example.com' } token { 'test' } end diff --git a/spec/frontend/contribution_events/components/contribution_event/contribution_event_approved_spec.js b/spec/frontend/contribution_events/components/contribution_event/contribution_event_approved_spec.js index 6672d3eb18b..fb27e160897 100644 --- a/spec/frontend/contribution_events/components/contribution_event/contribution_event_approved_spec.js +++ b/spec/frontend/contribution_events/components/contribution_event/contribution_event_approved_spec.js @@ -1,21 +1,21 @@ import events from 'test_fixtures/controller/users/activity.json'; import { mountExtended } from 'helpers/vue_test_utils_helper'; -import { EVENT_TYPE_APPROVED } from '~/contribution_events/constants'; import ContributionEventApproved from '~/contribution_events/components/contribution_event/contribution_event_approved.vue'; import ContributionEventBase from '~/contribution_events/components/contribution_event/contribution_event_base.vue'; import TargetLink from '~/contribution_events/components/target_link.vue'; import ResourceParentLink from '~/contribution_events/components/resource_parent_link.vue'; +import { eventApproved } from '../../utils'; -const eventApproved = events.find((event) => event.action === EVENT_TYPE_APPROVED); +const defaultPropsData = { + event: eventApproved(events), +}; describe('ContributionEventApproved', () => { let wrapper; const createComponent = () => { wrapper = mountExtended(ContributionEventApproved, { - propsData: { - event: eventApproved, - }, + propsData: defaultPropsData, }); }; @@ -25,7 +25,7 @@ describe('ContributionEventApproved', () => { it('renders `ContributionEventBase`', () => { expect(wrapper.findComponent(ContributionEventBase).props()).toEqual({ - event: eventApproved, + event: defaultPropsData.event, iconName: 'approval-solid', iconClass: 'gl-text-green-500', }); @@ -33,15 +33,17 @@ describe('ContributionEventApproved', () => { it('renders message', () => { expect(wrapper.findByTestId('event-body').text()).toBe( - `Approved merge request ${eventApproved.target.reference_link_text} in ${eventApproved.resource_parent.full_name}.`, + `Approved merge request ${defaultPropsData.event.target.reference_link_text} in ${defaultPropsData.event.resource_parent.full_name}.`, ); }); it('renders target link', () => { - expect(wrapper.findComponent(TargetLink).props('event')).toEqual(eventApproved); + expect(wrapper.findComponent(TargetLink).props('event')).toEqual(defaultPropsData.event); }); it('renders resource parent link', () => { - expect(wrapper.findComponent(ResourceParentLink).props('event')).toEqual(eventApproved); + expect(wrapper.findComponent(ResourceParentLink).props('event')).toEqual( + defaultPropsData.event, + ); }); }); diff --git a/spec/frontend/contribution_events/components/contribution_event/contribution_event_expired_spec.js b/spec/frontend/contribution_events/components/contribution_event/contribution_event_expired_spec.js new file mode 100644 index 00000000000..90cb7161952 --- /dev/null +++ b/spec/frontend/contribution_events/components/contribution_event/contribution_event_expired_spec.js @@ -0,0 +1,43 @@ +import events from 'test_fixtures/controller/users/activity.json'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import ContributionEventExpired from '~/contribution_events/components/contribution_event/contribution_event_expired.vue'; +import ContributionEventBase from '~/contribution_events/components/contribution_event/contribution_event_base.vue'; +import ResourceParentLink from '~/contribution_events/components/resource_parent_link.vue'; +import { eventExpired } from '../../utils'; + +const defaultPropsData = { + event: eventExpired(events), +}; + +describe('ContributionEventExpired', () => { + let wrapper; + + const createComponent = () => { + wrapper = mountExtended(ContributionEventExpired, { + propsData: defaultPropsData, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + it('renders `ContributionEventBase`', () => { + expect(wrapper.findComponent(ContributionEventBase).props()).toMatchObject({ + event: defaultPropsData.event, + iconName: 'expire', + }); + }); + + it('renders message', () => { + expect(wrapper.findByTestId('event-body').text()).toBe( + `Removed due to membership expiration from ${defaultPropsData.event.resource_parent.full_name}.`, + ); + }); + + it('renders resource parent link', () => { + expect(wrapper.findComponent(ResourceParentLink).props('event')).toEqual( + defaultPropsData.event, + ); + }); +}); diff --git a/spec/frontend/contribution_events/components/contribution_event/contribution_event_joined_spec.js b/spec/frontend/contribution_events/components/contribution_event/contribution_event_joined_spec.js new file mode 100644 index 00000000000..511972e35dd --- /dev/null +++ b/spec/frontend/contribution_events/components/contribution_event/contribution_event_joined_spec.js @@ -0,0 +1,43 @@ +import events from 'test_fixtures/controller/users/activity.json'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import ContributionEventJoined from '~/contribution_events/components/contribution_event/contribution_event_joined.vue'; +import ContributionEventBase from '~/contribution_events/components/contribution_event/contribution_event_base.vue'; +import ResourceParentLink from '~/contribution_events/components/resource_parent_link.vue'; +import { eventJoined } from '../../utils'; + +const defaultPropsData = { + event: eventJoined(events), +}; + +describe('ContributionEventJoined', () => { + let wrapper; + + const createComponent = () => { + wrapper = mountExtended(ContributionEventJoined, { + propsData: defaultPropsData, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + it('renders `ContributionEventBase`', () => { + expect(wrapper.findComponent(ContributionEventBase).props()).toMatchObject({ + event: defaultPropsData.event, + iconName: 'users', + }); + }); + + it('renders message', () => { + expect(wrapper.findByTestId('event-body').text()).toBe( + `Joined project ${defaultPropsData.event.resource_parent.full_name}.`, + ); + }); + + it('renders resource parent link', () => { + expect(wrapper.findComponent(ResourceParentLink).props('event')).toEqual( + defaultPropsData.event, + ); + }); +}); diff --git a/spec/frontend/contribution_events/components/contribution_event/contribution_event_left_spec.js b/spec/frontend/contribution_events/components/contribution_event/contribution_event_left_spec.js new file mode 100644 index 00000000000..2e82addcda2 --- /dev/null +++ b/spec/frontend/contribution_events/components/contribution_event/contribution_event_left_spec.js @@ -0,0 +1,43 @@ +import events from 'test_fixtures/controller/users/activity.json'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import ContributionEventLeft from '~/contribution_events/components/contribution_event/contribution_event_left.vue'; +import ContributionEventBase from '~/contribution_events/components/contribution_event/contribution_event_base.vue'; +import ResourceParentLink from '~/contribution_events/components/resource_parent_link.vue'; +import { eventLeft } from '../../utils'; + +const defaultPropsData = { + event: eventLeft(events), +}; + +describe('ContributionEventLeft', () => { + let wrapper; + + const createComponent = () => { + wrapper = mountExtended(ContributionEventLeft, { + propsData: defaultPropsData, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + it('renders `ContributionEventBase`', () => { + expect(wrapper.findComponent(ContributionEventBase).props()).toMatchObject({ + event: defaultPropsData.event, + iconName: 'leave', + }); + }); + + it('renders message', () => { + expect(wrapper.findByTestId('event-body').text()).toBe( + `Left project ${defaultPropsData.event.resource_parent.full_name}.`, + ); + }); + + it('renders resource parent link', () => { + expect(wrapper.findComponent(ResourceParentLink).props('event')).toEqual( + defaultPropsData.event, + ); + }); +}); diff --git a/spec/frontend/contribution_events/components/contribution_events_spec.js b/spec/frontend/contribution_events/components/contribution_events_spec.js index 4bc354c393f..dcea9bacb78 100644 --- a/spec/frontend/contribution_events/components/contribution_events_spec.js +++ b/spec/frontend/contribution_events/components/contribution_events_spec.js @@ -1,10 +1,11 @@ import events from 'test_fixtures/controller/users/activity.json'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import { EVENT_TYPE_APPROVED } from '~/contribution_events/constants'; import ContributionEvents from '~/contribution_events/components/contribution_events.vue'; import ContributionEventApproved from '~/contribution_events/components/contribution_event/contribution_event_approved.vue'; - -const eventApproved = events.find((event) => event.action === EVENT_TYPE_APPROVED); +import ContributionEventExpired from '~/contribution_events/components/contribution_event/contribution_event_expired.vue'; +import ContributionEventJoined from '~/contribution_events/components/contribution_event/contribution_event_joined.vue'; +import ContributionEventLeft from '~/contribution_events/components/contribution_event/contribution_event_left.vue'; +import { eventApproved, eventExpired, eventJoined, eventLeft } from '../utils'; describe('ContributionEvents', () => { let wrapper; @@ -19,7 +20,10 @@ describe('ContributionEvents', () => { it.each` expectedComponent | expectedEvent - ${ContributionEventApproved} | ${eventApproved} + ${ContributionEventApproved} | ${eventApproved(events)} + ${ContributionEventExpired} | ${eventExpired(events)} + ${ContributionEventJoined} | ${eventJoined(events)} + ${ContributionEventLeft} | ${eventLeft(events)} `( 'renders `$expectedComponent.name` component and passes expected event', ({ expectedComponent, expectedEvent }) => { diff --git a/spec/frontend/contribution_events/utils.js b/spec/frontend/contribution_events/utils.js new file mode 100644 index 00000000000..0887a178e5c --- /dev/null +++ b/spec/frontend/contribution_events/utils.js @@ -0,0 +1,15 @@ +import { + EVENT_TYPE_APPROVED, + EVENT_TYPE_EXPIRED, + EVENT_TYPE_JOINED, + EVENT_TYPE_LEFT, +} from '~/contribution_events/constants'; + +export const eventApproved = (events) => + events.find((event) => event.action === EVENT_TYPE_APPROVED); + +export const eventExpired = (events) => events.find((event) => event.action === EVENT_TYPE_EXPIRED); + +export const eventJoined = (events) => events.find((event) => event.action === EVENT_TYPE_JOINED); + +export const eventLeft = (events) => events.find((event) => event.action === EVENT_TYPE_LEFT); diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js index 2b60684e60a..21d1c870880 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js @@ -1,4 +1,13 @@ -import { GlAlert, GlDropdown, GlButton, GlFormCheckbox, GlLoadingIcon, GlModal } from '@gitlab/ui'; +import { + GlAlert, + GlDropdown, + GlButton, + GlFormCheckbox, + GlLoadingIcon, + GlModal, + GlKeysetPagination, +} from '@gitlab/ui'; +import * as Sentry from '@sentry/browser'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import { stubComponent } from 'helpers/stub_component'; @@ -13,6 +22,7 @@ import { packageFilesQuery, packageDestroyFilesMutation, packageDestroyFilesMutationError, + pagination, } from 'jest/packages_and_registries/package_registry/mock_data'; import { DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION, @@ -22,16 +32,22 @@ import { DELETE_PACKAGE_FILE_ERROR_MESSAGE, DELETE_PACKAGE_FILES_SUCCESS_MESSAGE, DELETE_PACKAGE_FILES_ERROR_MESSAGE, + GRAPHQL_PACKAGE_FILES_PAGE_SIZE, } from '~/packages_and_registries/package_registry/constants'; +import { NEXT, PREV } from '~/vue_shared/components/pagination/constants'; import PackageFiles from '~/packages_and_registries/package_registry/components/details/package_files.vue'; import FileIcon from '~/vue_shared/components/file_icon.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; - +import { scrollToElement } from '~/lib/utils/common_utils'; import getPackageFiles from '~/packages_and_registries/package_registry/graphql/queries/get_package_files.query.graphql'; import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql'; Vue.use(VueApollo); jest.mock('~/alert'); +jest.mock('~/lib/utils/common_utils', () => ({ + ...jest.requireActual('~/lib/utils/common_utils'), + scrollToElement: jest.fn(), +})); describe('Package Files', () => { let wrapper; @@ -43,6 +59,7 @@ describe('Package Files', () => { const findFirstRow = () => extendedWrapper(findAllRows().at(0)); const findSecondRow = () => extendedWrapper(findAllRows().at(1)); const findPackageFilesAlert = () => wrapper.findComponent(GlAlert); + const findPagination = () => wrapper.findComponent(GlKeysetPagination); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findFirstRowDownloadLink = () => findFirstRow().findByTestId('download-link'); const findFirstRowFileIcon = () => findFirstRow().findComponent(FileIcon); @@ -68,6 +85,7 @@ describe('Package Files', () => { stubs, resolver = jest.fn().mockResolvedValue(packageFilesQuery({ files: [file] })), filesDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFilesMutation()), + options = {}, } = {}) => { const requestHandlers = [ [getPackageFiles, resolver], @@ -92,9 +110,14 @@ describe('Package Files', () => { }), ...stubs, }, + ...options, }); }; + beforeEach(() => { + jest.spyOn(Sentry, 'captureException').mockImplementation(); + }); + describe('rows', () => { it('do not get rendered when query is loading', () => { createComponent(); @@ -123,6 +146,7 @@ describe('Package Files', () => { await waitForPromises(); expect(findPackageFilesAlert().exists()).toBe(false); + expect(Sentry.captureException).not.toHaveBeenCalled(); }); it('renders gl-alert if load fails', async () => { @@ -133,6 +157,40 @@ describe('Package Files', () => { expect(findPackageFilesAlert().text()).toBe( s__('PackageRegistry|Something went wrong while fetching package assets.'), ); + expect(Sentry.captureException).toHaveBeenCalled(); + }); + + it('renders pagination', async () => { + createComponent({ resolver: jest.fn().mockResolvedValue(packageFilesQuery()) }); + await waitForPromises(); + + const { endCursor, startCursor, hasNextPage, hasPreviousPage } = pagination(); + + expect(findPagination().props()).toMatchObject({ + endCursor, + startCursor, + hasNextPage, + hasPreviousPage, + prevText: PREV, + nextText: NEXT, + disabled: false, + }); + }); + + it('hides pagination when only one page', async () => { + createComponent({ + resolver: jest.fn().mockResolvedValue( + packageFilesQuery({ + extendPagination: { + hasNextPage: false, + hasPreviousPage: false, + }, + }), + ), + }); + await waitForPromises(); + + expect(findPagination().exists()).toBe(false); }); }); @@ -354,7 +412,7 @@ describe('Package Files', () => { resolver: jest.fn().mockResolvedValue( packageFilesQuery({ files: [file], - pageInfo: { + extendPagination: { hasNextPage: false, }, }), @@ -379,7 +437,7 @@ describe('Package Files', () => { createComponent({ resolver: jest.fn().mockResolvedValue( packageFilesQuery({ - pageInfo: { + extendPagination: { hasNextPage: false, }, }), @@ -421,6 +479,69 @@ describe('Package Files', () => { }); }); + describe('when user interacts with pagination', () => { + const resolver = jest.fn().mockResolvedValue(packageFilesQuery()); + + beforeEach(async () => { + createComponent({ resolver, options: { attachTo: document.body } }); + await waitForPromises(); + }); + + describe('when list emits next event', () => { + beforeEach(() => { + findPagination().vm.$emit('next'); + }); + + it('fetches the next set of files', () => { + expect(resolver).toHaveBeenLastCalledWith( + expect.objectContaining({ + after: pagination().endCursor, + first: GRAPHQL_PACKAGE_FILES_PAGE_SIZE, + }), + ); + }); + + it('scrolls to top of package files component', async () => { + await waitForPromises(); + + expect(scrollToElement).toHaveBeenCalledWith(wrapper.vm.$el); + }); + + it('first row is the active element', async () => { + await waitForPromises(); + + expect(findFirstRow().element).toBe(document.activeElement); + }); + }); + + describe('when list emits prev event', () => { + beforeEach(() => { + findPagination().vm.$emit('prev'); + }); + + it('fetches the previous set of files', () => { + expect(resolver).toHaveBeenLastCalledWith( + expect.objectContaining({ + before: pagination().startCursor, + last: GRAPHQL_PACKAGE_FILES_PAGE_SIZE, + }), + ); + }); + + it('scrolls to top of package files component', async () => { + await waitForPromises(); + + expect(scrollToElement).toHaveBeenCalledWith(wrapper.vm.$el); + }); + + it('first row is the active element', async () => { + await waitForPromises(); + + expect(findFirstRow().element).toBe(document.activeElement); + }); + }); + }); + describe('deleting a file', () => { const doDeleteFile = async () => { const first = findAllRowCheckboxes().at(0); @@ -442,6 +563,7 @@ describe('Package Files', () => { await nextTick(); expect(findLoadingIcon().exists()).toBe(true); + expect(findPagination().props('disabled')).toBe(true); }); it('confirming on the modal deletes the file and shows a success message', async () => { @@ -474,7 +596,7 @@ describe('Package Files', () => { expect(resolver).toHaveBeenCalledTimes(2); expect(resolver).toHaveBeenCalledWith({ id: '1', - first: 100, + first: GRAPHQL_PACKAGE_FILES_PAGE_SIZE, }); }); @@ -534,6 +656,7 @@ describe('Package Files', () => { await nextTick(); expect(findLoadingIcon().exists()).toBe(true); + expect(findPagination().props('disabled')).toBe(true); }); it('confirming on the modal deletes the file and shows a success message', async () => { @@ -566,7 +689,7 @@ describe('Package Files', () => { expect(resolver).toHaveBeenCalledTimes(2); expect(resolver).toHaveBeenCalledWith({ id: '1', - first: 100, + first: GRAPHQL_PACKAGE_FILES_PAGE_SIZE, }); }); diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js index 6995a4cc635..11539b925b6 100644 --- a/spec/frontend/packages_and_registries/package_registry/mock_data.js +++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js @@ -278,15 +278,12 @@ export const packagePipelinesQuery = (pipelines = packagePipelines()) => ({ }, }); -export const packageFilesQuery = ({ files = packageFiles(), pageInfo = {} } = {}) => ({ +export const packageFilesQuery = ({ files = packageFiles(), extendPagination = {} } = {}) => ({ data: { package: { id: 'gid://gitlab/Packages::Package/111', packageFiles: { - pageInfo: { - hasNextPage: true, - ...pageInfo, - }, + pageInfo: pagination(extendPagination), nodes: files, __typename: 'PackageFileConnection', }, diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js index e4febda1daa..b0f9f123950 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js @@ -1,22 +1,22 @@ -import { GlDropdownItem } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { GlDisclosureDropdown, GlDisclosureDropdownItem } from '@gitlab/ui'; +import { mount } from '@vue/test-utils'; + import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue'; const commits = [ { title: 'Commit 1', - short_id: '78d5b7', + shortId: '78d5b7', message: 'Update test.txt', }, { title: 'Commit 2', - short_id: '34cbe28b', + shortId: '34cbe28b', message: 'Fixed test', }, { title: 'Commit 3', - short_id: 'fa42932a', + shortId: 'fa42932a', message: 'Added changelog', }, ]; @@ -25,10 +25,14 @@ describe('Commits message dropdown component', () => { let wrapper; const createComponent = () => { - wrapper = shallowMount(CommitMessageDropdown, { + wrapper = mount(CommitMessageDropdown, { propsData: { commits, }, + stubs: { + GlDisclosureDropdown, + GlDisclosureDropdownItem, + }, }); }; @@ -36,7 +40,7 @@ describe('Commits message dropdown component', () => { createComponent(); }); - const findDropdownElements = () => wrapper.findAllComponents(GlDropdownItem); + const findDropdownElements = () => wrapper.findAllComponents(GlDisclosureDropdownItem); const findFirstDropdownElement = () => findDropdownElements().at(0); it('should have 3 elements in dropdown list', () => { @@ -48,10 +52,9 @@ describe('Commits message dropdown component', () => { expect(findFirstDropdownElement().text()).toContain('Commit 1'); }); - it('should emit a commit title on selecting commit', async () => { - findFirstDropdownElement().vm.$emit('click'); + it('should emit a commit title on selecting commit', () => { + findFirstDropdownElement().find('button').trigger('click'); - await nextTick(); expect(wrapper.emitted().input[0]).toEqual(['Update test.txt']); }); }); diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js index 9d2bf002d73..45fef09aa84 100644 --- a/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js +++ b/spec/frontend/vue_shared/components/source_viewer/plugins/wrap_child_nodes_spec.js @@ -8,14 +8,15 @@ describe('Highlight.js plugin for wrapping _emitter nodes', () => { children: [ { scope: 'string', children: ['Text 1'] }, { scope: 'string', children: ['Text 2', { scope: 'comment', children: ['Text 3'] }] }, - { scope: undefined, sublanguage: true, children: ['Text 3 (sublanguage)'] }, - 'Text4\nText5', + { scope: undefined, sublanguage: true, children: ['Text 4 (sublanguage)'] }, + { scope: undefined, sublanguage: undefined, children: ['Text 5'] }, + 'Text6\nText7', ], }, }, }; - const outputValue = `<span class="hljs-string">Text 1</span><span class="hljs-string"><span class="hljs-string">Text 2</span><span class="hljs-comment">Text 3</span></span><span class="">Text 3 (sublanguage)</span><span class="">Text4</span>\n<span class="">Text5</span>`; + const outputValue = `<span class="hljs-string">Text 1</span><span class="hljs-string"><span class="hljs-string">Text 2</span><span class="hljs-comment">Text 3</span></span><span class="">Text 4 (sublanguage)</span><span class="">Text 5</span><span class="">Text6</span>\n<span class="">Text7</span>`; wrapChildNodes(hljsResultMock); expect(hljsResultMock.value).toBe(outputValue); diff --git a/spec/models/integrations/asana_spec.rb b/spec/models/integrations/asana_spec.rb index 43e876a4f47..376aec1088e 100644 --- a/spec/models/integrations/asana_spec.rb +++ b/spec/models/integrations/asana_spec.rb @@ -2,20 +2,24 @@ require 'spec_helper' -RSpec.describe Integrations::Asana do +RSpec.describe Integrations::Asana, feature_category: :integrations do describe 'Validations' do - context 'active' do + context 'when active' do before do subject.active = true end it { is_expected.to validate_presence_of :api_key } end + + context 'when inactive' do + it { is_expected.not_to validate_presence_of :api_key } + end end - describe 'Execute' do - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } + describe '#execute' do + let_it_be(:user) { build(:user) } + let_it_be(:project) { build(:project) } let(:gid) { "123456789ABCD" } let(:asana_task) { double(::Asana::Resources::Task) } diff --git a/spec/models/integrations/assembla_spec.rb b/spec/models/integrations/assembla_spec.rb index e9f4274952d..28cda0a1e75 100644 --- a/spec/models/integrations/assembla_spec.rb +++ b/spec/models/integrations/assembla_spec.rb @@ -2,34 +2,49 @@ require 'spec_helper' -RSpec.describe Integrations::Assembla do +RSpec.describe Integrations::Assembla, feature_category: :integrations do include StubRequests it_behaves_like Integrations::ResetSecretFields do let(:integration) { described_class.new } end - describe "Execute" do - let(:user) { create(:user) } - let(:project) { create(:project, :repository) } + describe 'Validations' do + context 'when active' do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of :token } + end + + context 'when inactive' do + it { is_expected.not_to validate_presence_of :token } + end + end + + describe "#execute" do + let_it_be(:user) { build(:user) } + let_it_be(:project) { create(:project, :repository) } + + let(:assembla_integration) { described_class.new } + let(:sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) } + let(:api_url) { 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret' } before do - @assembla_integration = described_class.new - allow(@assembla_integration).to receive_messages( + allow(assembla_integration).to receive_messages( project_id: project.id, project: project, token: 'verySecret', subdomain: 'project_name' ) - @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user) - @api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret' - stub_full_request(@api_url, method: :post) + stub_full_request(api_url, method: :post) end it "calls Assembla API" do - @assembla_integration.execute(@sample_data) - expect(WebMock).to have_requested(:post, stubbed_hostname(@api_url)).with( - body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/ + assembla_integration.execute(sample_data) + expect(WebMock).to have_requested(:post, stubbed_hostname(api_url)).with( + body: /#{sample_data[:before]}.*#{sample_data[:after]}.*#{project.path}/ ).once end end diff --git a/spec/models/integrations/bamboo_spec.rb b/spec/models/integrations/bamboo_spec.rb index 1d2c90dad51..3b459ab9d5b 100644 --- a/spec/models/integrations/bamboo_spec.rb +++ b/spec/models/integrations/bamboo_spec.rb @@ -2,26 +2,15 @@ require 'spec_helper' -RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching do +RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching, feature_category: :integrations do include ReactiveCachingHelpers include StubRequests let(:bamboo_url) { 'http://gitlab.com/bamboo' } - let_it_be(:project) { create(:project) } - - subject(:integration) do - described_class.create!( - active: true, - project: project, - properties: { - bamboo_url: bamboo_url, - username: 'mic', - password: 'password', - build_key: 'foo' - } - ) - end + let_it_be(:project) { build(:project) } + + subject(:integration) { build(:bamboo_integration, project: project, bamboo_url: bamboo_url) } it_behaves_like Integrations::BaseCi diff --git a/spec/models/integrations/base_chat_notification_spec.rb b/spec/models/integrations/base_chat_notification_spec.rb index 13dd9e03ab1..675035095c5 100644 --- a/spec/models/integrations/base_chat_notification_spec.rb +++ b/spec/models/integrations/base_chat_notification_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Integrations::BaseChatNotification, feature_category: :integratio it { expect(subject.category).to eq(:chat) } end - describe 'validations' do + describe 'Validations' do before do subject.active = active @@ -112,9 +112,9 @@ RSpec.describe Integrations::BaseChatNotification, feature_category: :integratio end context 'when the data object has a label' do - let_it_be(:label) { create(:label, project: project, name: 'Bug') } - let_it_be(:label_2) { create(:label, project: project, name: 'Community contribution') } - let_it_be(:label_3) { create(:label, project: project, name: 'Backend') } + let_it_be(:label) { build(:label, project: project, name: 'Bug') } + let_it_be(:label_2) { build(:label, project: project, name: 'Community contribution') } + let_it_be(:label_3) { build(:label, project: project, name: 'Backend') } let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label, label_2, label_3]) } let_it_be(:note) { create(:note, noteable: issue, project: project) } diff --git a/spec/models/integrations/base_issue_tracker_spec.rb b/spec/models/integrations/base_issue_tracker_spec.rb index e1a764cd7cb..1bb24876222 100644 --- a/spec/models/integrations/base_issue_tracker_spec.rb +++ b/spec/models/integrations/base_issue_tracker_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -RSpec.describe Integrations::BaseIssueTracker do - let(:integration) { Integrations::Redmine.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) } +RSpec.describe Integrations::BaseIssueTracker, feature_category: :integrations do + let(:integration) { build(:redmine_integration, project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) } - let_it_be_with_refind(:project) { create :project } + let_it_be_with_refind(:project) { create(:project) } describe 'default values' do it { expect(subject.category).to eq(:issue_tracker) } diff --git a/spec/models/integrations/base_slack_notification_spec.rb b/spec/models/integrations/base_slack_notification_spec.rb index 8f7f4e8858d..ab977ca8fcc 100644 --- a/spec/models/integrations/base_slack_notification_spec.rb +++ b/spec/models/integrations/base_slack_notification_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::BaseSlackNotification do +RSpec.describe Integrations::BaseSlackNotification, feature_category: :integrations do # This spec should only contain tests that cannot be tested through # `base_slack_notification_shared_examples.rb`. diff --git a/spec/models/integrations/base_third_party_wiki_spec.rb b/spec/models/integrations/base_third_party_wiki_spec.rb index dbead636cb9..763f7131b94 100644 --- a/spec/models/integrations/base_third_party_wiki_spec.rb +++ b/spec/models/integrations/base_third_party_wiki_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::BaseThirdPartyWiki do +RSpec.describe Integrations::BaseThirdPartyWiki, feature_category: :integrations do describe 'default values' do it { expect(subject.category).to eq(:third_party_wiki) } end @@ -11,7 +11,7 @@ RSpec.describe Integrations::BaseThirdPartyWiki do let_it_be_with_reload(:project) { create(:project) } describe 'only one third party wiki per project' do - subject(:integration) { create(:shimo_integration, project: project, active: true) } + subject(:integration) { build(:shimo_integration, project: project, active: true) } before_all do create(:confluence_integration, project: project, active: true) @@ -35,7 +35,7 @@ RSpec.describe Integrations::BaseThirdPartyWiki do end context 'when integration is not on the project level' do - subject(:integration) { create(:shimo_integration, :instance, active: true) } + subject(:integration) { build(:shimo_integration, :instance, active: true) } it 'executes the validation' do expect(integration.valid?(:manual_change)).to be_truthy diff --git a/spec/models/integrations/bugzilla_spec.rb b/spec/models/integrations/bugzilla_spec.rb index f05bc26d066..cef58589231 100644 --- a/spec/models/integrations/bugzilla_spec.rb +++ b/spec/models/integrations/bugzilla_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::Bugzilla do +RSpec.describe Integrations::Bugzilla, feature_category: :integrations do describe 'Validations' do context 'when integration is active' do before do diff --git a/spec/models/integrations/buildkite_spec.rb b/spec/models/integrations/buildkite_spec.rb index 29c649af6c6..f3231d50eae 100644 --- a/spec/models/integrations/buildkite_spec.rb +++ b/spec/models/integrations/buildkite_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do +RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching, feature_category: :integrations do include ReactiveCachingHelpers include StubRequests @@ -71,9 +71,7 @@ RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do describe '#hook_url' do it 'returns the webhook url' do - expect(integration.hook_url).to eq( - 'https://webhook.buildkite.com/deliver/{webhook_token}' - ) + expect(integration.hook_url).to eq('https://webhook.buildkite.com/deliver/{webhook_token}') end end @@ -103,9 +101,7 @@ RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do describe '#calculate_reactive_cache' do describe '#commit_status' do - let(:buildkite_full_url) do - 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123' - end + let(:buildkite_full_url) { 'https://gitlab.buildkite.com/status/secret-sauce-status-token.json?commit=123' } subject { integration.calculate_reactive_cache('123', 'unused')[:commit_status] } diff --git a/spec/models/integrations/confluence_spec.rb b/spec/models/integrations/confluence_spec.rb index 999a532527d..d267e4a71c2 100644 --- a/spec/models/integrations/confluence_spec.rb +++ b/spec/models/integrations/confluence_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::Confluence do +RSpec.describe Integrations::Confluence, feature_category: :integrations do let_it_be(:project) { create(:project) } describe 'Validations' do @@ -49,10 +49,11 @@ RSpec.describe Integrations::Confluence do end context 'when the project wiki is not enabled' do - it 'returns nil when both active or inactive', :aggregate_failures do - project = create(:project, :wiki_disabled) - subject.project = project + before do + allow(project).to receive(:wiki_enabled?).and_return(false) + end + it 'returns nil when both active or inactive', :aggregate_failures do [true, false].each do |active| subject.active = active diff --git a/spec/models/integrations/custom_issue_tracker_spec.rb b/spec/models/integrations/custom_issue_tracker_spec.rb index 11f98b99bbe..4be95a25a43 100644 --- a/spec/models/integrations/custom_issue_tracker_spec.rb +++ b/spec/models/integrations/custom_issue_tracker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::CustomIssueTracker do +RSpec.describe Integrations::CustomIssueTracker, feature_category: :integrations do describe 'Validations' do context 'when integration is active' do before do |