diff options
Diffstat (limited to 'spec/frontend/ci')
7 files changed, 190 insertions, 212 deletions
diff --git a/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js b/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js index 9015031b6c8..a08a01009e2 100644 --- a/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js +++ b/spec/frontend/ci/pipeline_new/components/pipeline_new_form_spec.js @@ -4,7 +4,7 @@ import { GlForm, GlDropdownItem, GlSprintf, GlLoadingIcon } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import CreditCardValidationRequiredAlert from 'ee_component/billings/components/cc_validation_required_alert.vue'; import createMockApollo from 'helpers/mock_apollo_helper'; -import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { TEST_HOST } from 'helpers/test_constants'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; @@ -30,7 +30,6 @@ import { mockQueryParams, mockPostParams, mockProjectId, - mockRefs, mockYamlVariables, mockPipelineConfigButtonText, } from '../mock_data'; @@ -41,7 +40,6 @@ jest.mock('~/lib/utils/url_utility', () => ({ redirectTo: jest.fn(), })); -const projectRefsEndpoint = '/root/project/refs'; const pipelinesPath = '/root/project/-/pipelines'; const pipelinesEditorPath = '/root/project/-/ci/editor'; const projectPath = '/root/project/-/pipelines/config_variables'; @@ -91,21 +89,18 @@ describe('Pipeline New Form', () => { const changeKeyInputValue = async (keyInputIndex, value) => { const input = findKeyInputs().at(keyInputIndex); - input.element.value = value; - input.trigger('change'); + input.vm.$emit('input', value); + input.vm.$emit('change'); await nextTick(); }; - const createComponentWithApollo = ({ method = shallowMountExtended, props = {} } = {}) => { + const createComponentWithApollo = ({ props = {} } = {}) => { const handlers = [[ciConfigVariablesQuery, mockCiConfigVariables]]; mockApollo = createMockApollo(handlers, resolvers); - wrapper = method(PipelineNewForm, { + wrapper = shallowMountExtended(PipelineNewForm, { apolloProvider: mockApollo, - provide: { - projectRefsEndpoint, - }, propsData: { projectId: mockProjectId, pipelinesPath, @@ -124,7 +119,6 @@ describe('Pipeline New Form', () => { beforeEach(() => { mock = new MockAdapter(axios); mockCiConfigVariables = jest.fn(); - mock.onGet(projectRefsEndpoint).reply(HTTP_STATUS_OK, mockRefs); dummySubmitEvent = { preventDefault: jest.fn(), @@ -138,7 +132,7 @@ describe('Pipeline New Form', () => { describe('Form', () => { beforeEach(async () => { mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse); - createComponentWithApollo({ props: mockQueryParams, method: mountExtended }); + createComponentWithApollo({ props: mockQueryParams }); await waitForPromises(); }); @@ -150,13 +144,13 @@ describe('Pipeline New Form', () => { }); it('displays a variable from provided query params', () => { - expect(findKeyInputs().at(0).element.value).toBe('test_var'); - expect(findValueInputs().at(0).element.value).toBe('test_var_val'); + expect(findKeyInputs().at(0).attributes('value')).toBe('test_var'); + expect(findValueInputs().at(0).attributes('value')).toBe('test_var_val'); }); it('displays an empty variable for the user to fill out', () => { - expect(findKeyInputs().at(2).element.value).toBe(''); - expect(findValueInputs().at(2).element.value).toBe(''); + expect(findKeyInputs().at(2).attributes('value')).toBe(''); + expect(findValueInputs().at(2).attributes('value')).toBe(''); expect(findVariableTypes().at(2).props('text')).toBe('Variable'); }); @@ -165,7 +159,7 @@ describe('Pipeline New Form', () => { }); it('removes ci variable row on remove icon button click', async () => { - findRemoveIcons().at(1).trigger('click'); + findRemoveIcons().at(1).vm.$emit('click'); await nextTick(); @@ -174,14 +168,15 @@ describe('Pipeline New Form', () => { it('creates blank variable on input change event', async () => { const input = findKeyInputs().at(2); - input.element.value = 'test_var_2'; - input.trigger('change'); + + input.vm.$emit('input', 'test_var_2'); + input.vm.$emit('change'); await nextTick(); expect(findVariableRows()).toHaveLength(4); - expect(findKeyInputs().at(3).element.value).toBe(''); - expect(findValueInputs().at(3).element.value).toBe(''); + expect(findKeyInputs().at(3).attributes('value')).toBe(''); + expect(findValueInputs().at(3).attributes('value')).toBe(''); }); }); @@ -237,7 +232,7 @@ describe('Pipeline New Form', () => { describe('When the ref has been changed', () => { beforeEach(async () => { mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse); - createComponentWithApollo({ method: mountExtended }); + createComponentWithApollo(); await waitForPromises(); }); @@ -251,12 +246,12 @@ describe('Pipeline New Form', () => { await selectBranch('main'); - expect(findKeyInputs().at(0).element.value).toBe('build_var'); + expect(findKeyInputs().at(0).attributes('value')).toBe('build_var'); expect(findVariableRows().length).toBe(2); await selectBranch('branch-1'); - expect(findKeyInputs().at(0).element.value).toBe('deploy_var'); + expect(findKeyInputs().at(0).attributes('value')).toBe('deploy_var'); expect(findVariableRows().length).toBe(2); }); @@ -280,7 +275,7 @@ describe('Pipeline New Form', () => { describe('When there are no variables in the API cache', () => { beforeEach(async () => { mockCiConfigVariables.mockResolvedValue(mockNoCachedCiConfigVariablesResponse); - createComponentWithApollo({ method: mountExtended }); + createComponentWithApollo(); await waitForPromises(); }); @@ -330,7 +325,7 @@ describe('Pipeline New Form', () => { const testBehaviorWhenCacheIsPopulated = (queryResponse) => { beforeEach(() => { mockCiConfigVariables.mockResolvedValue(queryResponse); - createComponentWithApollo({ method: mountExtended }); + createComponentWithApollo(); }); it('does not poll for new values', async () => { @@ -345,6 +340,9 @@ describe('Pipeline New Form', () => { }); it('loading icon is shown when content is requested and hidden when received', async () => { + mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse); + createComponentWithApollo({ props: mockQueryParams }); + expect(findLoadingIcon().exists()).toBe(true); await waitForPromises(); @@ -358,11 +356,11 @@ describe('Pipeline New Form', () => { it('displays an empty form', async () => { mockCiConfigVariables.mockResolvedValue(mockEmptyCiConfigVariablesResponse); - createComponentWithApollo({ method: mountExtended }); + createComponentWithApollo(); await waitForPromises(); - expect(findKeyInputs().at(0).element.value).toBe(''); - expect(findValueInputs().at(0).element.value).toBe(''); + expect(findKeyInputs().at(0).attributes('value')).toBe(''); + expect(findValueInputs().at(0).attributes('value')).toBe(''); expect(findVariableTypes().at(0).props('text')).toBe('Variable'); }); }); @@ -373,12 +371,12 @@ describe('Pipeline New Form', () => { describe('with different predefined values', () => { beforeEach(async () => { mockCiConfigVariables.mockResolvedValue(mockCiConfigVariablesResponse); - createComponentWithApollo({ method: mountExtended }); + createComponentWithApollo(); await waitForPromises(); }); it('multi-line strings are added to the value field without removing line breaks', () => { - expect(findValueInputs().at(1).element.value).toBe(mockYamlVariables[1].value); + expect(findValueInputs().at(1).attributes('value')).toBe(mockYamlVariables[1].value); }); it('multiple predefined values are rendered as a dropdown', () => { @@ -402,7 +400,7 @@ describe('Pipeline New Form', () => { describe('with description', () => { beforeEach(async () => { mockCiConfigVariables.mockResolvedValue(mockCiConfigVariablesResponse); - createComponentWithApollo({ props: mockQueryParams, method: mountExtended }); + createComponentWithApollo({ props: mockQueryParams }); await waitForPromises(); }); @@ -411,15 +409,15 @@ describe('Pipeline New Form', () => { }); it('displays a variable from yml', () => { - expect(findKeyInputs().at(0).element.value).toBe(mockYamlVariables[0].key); - expect(findValueInputs().at(0).element.value).toBe(mockYamlVariables[0].value); + expect(findKeyInputs().at(0).attributes('value')).toBe(mockYamlVariables[0].key); + expect(findValueInputs().at(0).attributes('value')).toBe(mockYamlVariables[0].value); }); it('displays a variable from provided query params', () => { - expect(findKeyInputs().at(3).element.value).toBe( + expect(findKeyInputs().at(3).attributes('value')).toBe( Object.keys(mockQueryParams.variableParams)[0], ); - expect(findValueInputs().at(3).element.value).toBe( + expect(findValueInputs().at(3).attributes('value')).toBe( Object.values(mockQueryParams.fileParams)[0], ); }); @@ -429,7 +427,7 @@ describe('Pipeline New Form', () => { }); it('removes the description when a variable key changes', async () => { - findKeyInputs().at(0).element.value = 'yml_var_modified'; + findKeyInputs().at(0).vm.$emit('input', 'yml_var_modified'); findKeyInputs().at(0).trigger('change'); await nextTick(); @@ -441,7 +439,7 @@ describe('Pipeline New Form', () => { describe('without description', () => { beforeEach(async () => { mockCiConfigVariables.mockResolvedValue(mockCiConfigVariablesResponseWithoutDesc); - createComponentWithApollo({ method: mountExtended }); + createComponentWithApollo(); await waitForPromises(); }); @@ -460,7 +458,7 @@ describe('Pipeline New Form', () => { describe('when the refs cannot be loaded', () => { beforeEach(() => { mock - .onGet(projectRefsEndpoint, { params: { search: '' } }) + .onGet('/api/v4/projects/8/repository/branches', { params: { search: '' } }) .reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); findRefsDropdown().vm.$emit('loadingError'); diff --git a/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js b/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js index 82dac1358c5..01c7dd7eb84 100644 --- a/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js +++ b/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js @@ -1,35 +1,22 @@ -import { GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui'; -import MockAdapter from 'axios-mock-adapter'; -import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; -import waitForPromises from 'helpers/wait_for_promises'; -import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; +import { shallowMount } from '@vue/test-utils'; +import RefSelector from '~/ref/components/ref_selector.vue'; import RefsDropdown from '~/ci/pipeline_new/components/refs_dropdown.vue'; +import { REF_TYPE_BRANCHES, REF_TYPE_TAGS } from '~/ref/constants'; -import { mockBranches, mockRefs, mockFilteredRefs, mockTags } from '../mock_data'; - -const projectRefsEndpoint = '/root/project/refs'; +const projectId = '8'; const refShortName = 'main'; const refFullName = 'refs/heads/main'; -jest.mock('~/alert'); - describe('Pipeline New Form', () => { let wrapper; - let mock; - const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox); - const findRefsDropdownItems = () => wrapper.findAllComponents(GlListboxItem); - const findSearchBox = () => wrapper.findByTestId('listbox-search-input'); - const findListboxGroups = () => wrapper.findAll('ul[role="group"]'); + const findRefSelector = () => wrapper.findComponent(RefSelector); - const createComponent = (props = {}, mountFn = shallowMountExtended) => { - wrapper = mountFn(RefsDropdown, { - provide: { - projectRefsEndpoint, - }, + const createComponent = (props = {}) => { + wrapper = shallowMount(RefsDropdown, { propsData: { + projectId, value: { shortName: refShortName, fullName: refFullName, @@ -39,163 +26,54 @@ describe('Pipeline New Form', () => { }); }; - beforeEach(() => { - mock = new MockAdapter(axios); - mock.onGet(projectRefsEndpoint, { params: { search: '' } }).reply(HTTP_STATUS_OK, mockRefs); - }); - - beforeEach(() => { - createComponent(); - }); - - it('displays empty dropdown initially', () => { - findDropdown().vm.$emit('shown'); - - expect(findRefsDropdownItems()).toHaveLength(0); - }); - - it('does not make requests immediately', () => { - expect(mock.history.get).toHaveLength(0); - }); - describe('when user opens dropdown', () => { - beforeEach(async () => { - createComponent({}, mountExtended); - findDropdown().vm.$emit('shown'); - await waitForPromises(); + beforeEach(() => { + createComponent(); }); - it('requests unfiltered tags and branches', () => { - expect(mock.history.get).toHaveLength(1); - expect(mock.history.get[0].url).toBe(projectRefsEndpoint); - expect(mock.history.get[0].params).toEqual({ search: '' }); + it('has default selected branch', () => { + expect(findRefSelector().props('value')).toBe('main'); }); - it('displays dropdown with branches and tags', () => { - const refLength = mockRefs.Tags.length + mockRefs.Branches.length; - expect(findRefsDropdownItems()).toHaveLength(refLength); - }); - - it('displays the names of refs', () => { - // Branches - expect(findRefsDropdownItems().at(0).text()).toBe(mockRefs.Branches[0]); - - // Tags (appear after branches) - const firstTag = mockRefs.Branches.length; - expect(findRefsDropdownItems().at(firstTag).text()).toBe(mockRefs.Tags[0]); - }); - - it('when user shows dropdown a second time, only one request is done', () => { - expect(mock.history.get).toHaveLength(1); + it('has ref selector for branches and tags', () => { + expect(findRefSelector().props('enabledRefTypes')).toEqual([ + REF_TYPE_BRANCHES, + REF_TYPE_TAGS, + ]); }); describe('when user selects a value', () => { - const selectedIndex = 1; - - beforeEach(async () => { - findRefsDropdownItems().at(selectedIndex).vm.$emit('select', 'refs/heads/branch-1'); - await waitForPromises(); - }); + const fullName = `refs/heads/conflict-contains-conflict-markers`; it('component emits @input', () => { + findRefSelector().vm.$emit('input', fullName); + const inputs = wrapper.emitted('input'); expect(inputs).toHaveLength(1); - expect(inputs[0]).toEqual([{ shortName: 'branch-1', fullName: 'refs/heads/branch-1' }]); - }); - }); - - describe('when user types searches for a tag', () => { - const mockSearchTerm = 'my-search'; - - beforeEach(async () => { - mock - .onGet(projectRefsEndpoint, { params: { search: mockSearchTerm } }) - .reply(HTTP_STATUS_OK, mockFilteredRefs); - - await findSearchBox().vm.$emit('input', mockSearchTerm); - await waitForPromises(); - }); - - it('requests filtered tags and branches', () => { - expect(mock.history.get).toHaveLength(2); - expect(mock.history.get[1].params).toEqual({ - search: mockSearchTerm, - }); - }); - - it('displays dropdown with branches and tags', () => { - const filteredRefLength = mockFilteredRefs.Tags.length + mockFilteredRefs.Branches.length; - - expect(findRefsDropdownItems()).toHaveLength(filteredRefLength); + expect(inputs[0]).toEqual([ + { + shortName: 'conflict-contains-conflict-markers', + fullName: 'refs/heads/conflict-contains-conflict-markers', + }, + ]); }); }); }); describe('when user has selected a value', () => { - const selectedIndex = 1; - const mockShortName = mockRefs.Branches[selectedIndex]; + const mockShortName = 'conflict-contains-conflict-markers'; const mockFullName = `refs/heads/${mockShortName}`; - beforeEach(async () => { - mock - .onGet(projectRefsEndpoint, { - params: { ref: mockFullName }, - }) - .reply(HTTP_STATUS_OK, mockRefs); - - createComponent( - { - value: { - shortName: mockShortName, - fullName: mockFullName, - }, - }, - mountExtended, - ); - findDropdown().vm.$emit('shown'); - await waitForPromises(); - }); - it('branch is checked', () => { - expect(findRefsDropdownItems().at(selectedIndex).props('isSelected')).toBe(true); - }); - }); - - describe('when server returns an error', () => { - beforeEach(async () => { - mock - .onGet(projectRefsEndpoint, { params: { search: '' } }) - .reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); - - findDropdown().vm.$emit('shown'); - await waitForPromises(); - }); + createComponent({ + value: { + shortName: mockShortName, + fullName: mockFullName, + }, + }); - it('loading error event is emitted', () => { - expect(wrapper.emitted('loadingError')).toHaveLength(1); - expect(wrapper.emitted('loadingError')[0]).toEqual([expect.any(Error)]); + expect(findRefSelector().props('value')).toBe(mockShortName); }); }); - - describe('should display branches and tags based on its length', () => { - it.each` - mockData | expectedGroupLength | expectedListboxItemsLength - ${{ ...mockBranches, Tags: [] }} | ${1} | ${mockBranches.Branches.length} - ${{ Branches: [], ...mockTags }} | ${1} | ${mockTags.Tags.length} - ${{ ...mockRefs }} | ${2} | ${mockBranches.Branches.length + mockTags.Tags.length} - ${{ Branches: undefined, Tags: undefined }} | ${0} | ${0} - `( - 'should render branches and tags based on presence', - async ({ mockData, expectedGroupLength, expectedListboxItemsLength }) => { - mock.onGet(projectRefsEndpoint, { params: { search: '' } }).reply(HTTP_STATUS_OK, mockData); - createComponent({}, mountExtended); - findDropdown().vm.$emit('shown'); - await waitForPromises(); - - expect(findListboxGroups()).toHaveLength(expectedGroupLength); - expect(findRefsDropdownItems()).toHaveLength(expectedListboxItemsLength); - }, - ); - }); }); diff --git a/spec/frontend/ci/pipeline_new/mock_data.js b/spec/frontend/ci/pipeline_new/mock_data.js index 175f513217b..76a88f63298 100644 --- a/spec/frontend/ci/pipeline_new/mock_data.js +++ b/spec/frontend/ci/pipeline_new/mock_data.js @@ -1,16 +1,3 @@ -export const mockBranches = { - Branches: ['main', 'branch-1', 'branch-2'], -}; - -export const mockTags = { - Tags: ['1.0.0', '1.1.0', '1.2.0'], -}; - -export const mockRefs = { - ...mockBranches, - ...mockTags, -}; - export const mockFilteredRefs = { Branches: ['branch-1'], Tags: ['1.0.0', '1.1.0'], diff --git a/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js b/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js index 58a1c0bc18d..65336edd0d8 100644 --- a/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js +++ b/spec/frontend/ci/runner/admin_new_runner_app/admin_new_runner_app_spec.js @@ -79,6 +79,7 @@ describe('AdminNewRunnerApp', () => { expect(findRunnerCreateForm().props()).toEqual({ runnerType: INSTANCE_TYPE, groupId: null, + projectId: null, }); }); diff --git a/spec/frontend/ci/runner/components/runner_create_form_spec.js b/spec/frontend/ci/runner/components/runner_create_form_spec.js index a13a19db067..329dd2f73ee 100644 --- a/spec/frontend/ci/runner/components/runner_create_form_spec.js +++ b/spec/frontend/ci/runner/components/runner_create_form_spec.js @@ -6,7 +6,12 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue'; import RunnerFormFields from '~/ci/runner/components/runner_form_fields.vue'; -import { DEFAULT_ACCESS_LEVEL, INSTANCE_TYPE, GROUP_TYPE } from '~/ci/runner/constants'; +import { + DEFAULT_ACCESS_LEVEL, + INSTANCE_TYPE, + GROUP_TYPE, + PROJECT_TYPE, +} from '~/ci/runner/constants'; import runnerCreateMutation from '~/ci/runner/graphql/new/runner_create.mutation.graphql'; import { captureException } from '~/ci/runner/sentry_utils'; import { runnerCreateResult } from '../mock_data'; @@ -62,9 +67,10 @@ describe('RunnerCreateForm', () => { }); describe.each` - typeName | props | scopeData - ${'an instance runner'} | ${{ runnerType: INSTANCE_TYPE }} | ${{ runnerType: INSTANCE_TYPE }} - ${'a group runner'} | ${{ runnerType: GROUP_TYPE, groupId: 'gid://gitlab/Group/72' }} | ${{ runnerType: GROUP_TYPE, groupId: 'gid://gitlab/Group/72' }} + typeName | props | scopeData + ${'an instance runner'} | ${{ runnerType: INSTANCE_TYPE }} | ${{ runnerType: INSTANCE_TYPE }} + ${'a group runner'} | ${{ runnerType: GROUP_TYPE, groupId: 'gid://gitlab/Group/72' }} | ${{ runnerType: GROUP_TYPE, groupId: 'gid://gitlab/Group/72' }} + ${'a project runner'} | ${{ runnerType: PROJECT_TYPE, projectId: 'gid://gitlab/Project/42' }} | ${{ runnerType: PROJECT_TYPE, projectId: 'gid://gitlab/Project/42' }} `('when user submits $typeName', ({ props, scopeData }) => { let preventDefault; diff --git a/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js b/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js index 027196ab004..520c9eed003 100644 --- a/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js +++ b/spec/frontend/ci/runner/group_new_runner_app/group_new_runner_app_spec.js @@ -82,6 +82,7 @@ describe('GroupRunnerRunnerApp', () => { expect(findRunnerCreateForm().props()).toEqual({ runnerType: GROUP_TYPE, groupId: mockGroupId, + projectId: null, }); }); diff --git a/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js b/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js new file mode 100644 index 00000000000..701a93352ef --- /dev/null +++ b/spec/frontend/ci/runner/project_new_runner_app/project_new_runner_app_spec.js @@ -0,0 +1,107 @@ +import { GlSprintf } from '@gitlab/ui'; +import { s__ } from '~/locale'; + +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; +import { createAlert, VARIANT_SUCCESS } from '~/alert'; + +import ProjectRunnerRunnerApp from '~/ci/runner/project_new_runner/project_new_runner_app.vue'; +import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue'; +import RunnerPlatformsRadioGroup from '~/ci/runner/components/runner_platforms_radio_group.vue'; +import { PROJECT_TYPE, DEFAULT_PLATFORM } from '~/ci/runner/constants'; +import RunnerCreateForm from '~/ci/runner/components/runner_create_form.vue'; +import { runnerCreateResult, mockRegistrationToken } from '../mock_data'; + +const mockProjectId = 'gid://gitlab/Project/72'; + +jest.mock('~/ci/runner/local_storage_alert/save_alert_to_local_storage'); +jest.mock('~/alert'); +jest.mock('~/lib/utils/url_utility', () => ({ + ...jest.requireActual('~/lib/utils/url_utility'), + redirectTo: jest.fn(), +})); + +const mockCreatedRunner = runnerCreateResult.data.runnerCreate.runner; + +describe('ProjectRunnerRunnerApp', () => { + let wrapper; + + const findLegacyInstructionsLink = () => wrapper.findByTestId('legacy-instructions-link'); + const findRunnerInstructionsModal = () => wrapper.findComponent(RunnerInstructionsModal); + const findRunnerPlatformsRadioGroup = () => wrapper.findComponent(RunnerPlatformsRadioGroup); + const findRunnerCreateForm = () => wrapper.findComponent(RunnerCreateForm); + + const createComponent = () => { + wrapper = shallowMountExtended(ProjectRunnerRunnerApp, { + propsData: { + projectId: mockProjectId, + legacyRegistrationToken: mockRegistrationToken, + }, + directives: { + GlModal: createMockDirective('gl-modal'), + }, + stubs: { + GlSprintf, + }, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + describe('Shows legacy modal', () => { + it('passes legacy registration to modal', () => { + expect(findRunnerInstructionsModal().props('registrationToken')).toEqual( + mockRegistrationToken, + ); + }); + + it('opens a modal with the legacy instructions', () => { + const modalId = getBinding(findLegacyInstructionsLink().element, 'gl-modal').value; + + expect(findRunnerInstructionsModal().props('modalId')).toBe(modalId); + }); + }); + + describe('Platform', () => { + it('shows the platforms radio group', () => { + expect(findRunnerPlatformsRadioGroup().props('value')).toBe(DEFAULT_PLATFORM); + }); + }); + + describe('Runner form', () => { + it('shows the runner create form for an instance runner', () => { + expect(findRunnerCreateForm().props()).toEqual({ + runnerType: PROJECT_TYPE, + projectId: mockProjectId, + groupId: null, + }); + }); + + describe('When a runner is saved', () => { + beforeEach(() => { + findRunnerCreateForm().vm.$emit('saved', mockCreatedRunner); + }); + + it('shows an alert', () => { + expect(createAlert).toHaveBeenCalledWith({ + message: s__('Runners|Runner created.'), + variant: VARIANT_SUCCESS, + }); + }); + }); + + describe('When runner fails to save', () => { + const ERROR_MSG = 'Cannot save!'; + + beforeEach(() => { + findRunnerCreateForm().vm.$emit('error', new Error(ERROR_MSG)); + }); + + it('shows an error message', () => { + expect(createAlert).toHaveBeenCalledWith({ message: ERROR_MSG }); + }); + }); + }); +}); |