diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/runner_instructions')
8 files changed, 417 insertions, 140 deletions
diff --git a/spec/frontend/vue_shared/components/runner_instructions/instructions/__snapshots__/runner_docker_instructions_spec.js.snap b/spec/frontend/vue_shared/components/runner_instructions/instructions/__snapshots__/runner_docker_instructions_spec.js.snap new file mode 100644 index 00000000000..d14f66df8a1 --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/instructions/__snapshots__/runner_docker_instructions_spec.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RunnerDockerInstructions renders contents 1`] = `"To install Runner in a container follow the instructions described in the GitLab documentation View installation instructions Close"`; diff --git a/spec/frontend/vue_shared/components/runner_instructions/instructions/__snapshots__/runner_kubernetes_instructions_spec.js.snap b/spec/frontend/vue_shared/components/runner_instructions/instructions/__snapshots__/runner_kubernetes_instructions_spec.js.snap new file mode 100644 index 00000000000..1172bf07dff --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/instructions/__snapshots__/runner_kubernetes_instructions_spec.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RunnerKubernetesInstructions renders contents 1`] = `"To install Runner in Kubernetes follow the instructions described in the GitLab documentation. View installation instructions Close"`; diff --git a/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_aws_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_aws_instructions_spec.js new file mode 100644 index 00000000000..4d566dbec0c --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_aws_instructions_spec.js @@ -0,0 +1,117 @@ +import { + GlAccordion, + GlAccordionItem, + GlButton, + GlFormRadio, + GlFormRadioGroup, + GlLink, + GlSprintf, +} from '@gitlab/ui'; +import { getBaseURL, visitUrl } from '~/lib/utils/url_utility'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { mockTracking } from 'helpers/tracking_helper'; +import { + AWS_README_URL, + AWS_CF_BASE_URL, + AWS_TEMPLATES_BASE_URL, + AWS_EASY_BUTTONS, +} from '~/vue_shared/components/runner_instructions/constants'; +import RunnerAwsInstructions from '~/vue_shared/components/runner_instructions/instructions/runner_aws_instructions.vue'; +import { __ } from '~/locale'; + +jest.mock('~/lib/utils/url_utility', () => ({ + ...jest.requireActual('~/lib/utils/url_utility'), + visitUrl: jest.fn(), +})); + +describe('RunnerAwsInstructions', () => { + let wrapper; + + const findEasyButtonsRadioGroup = () => wrapper.findComponent(GlFormRadioGroup); + const findEasyButtons = () => wrapper.findAllComponents(GlFormRadio); + const findEasyButtonAt = (i) => findEasyButtons().at(i); + const findLink = () => wrapper.findComponent(GlLink); + const findOkButton = () => + wrapper + .findAllComponents(GlButton) + .filter((w) => w.props('variant') === 'confirm') + .at(0); + const findCloseButton = () => wrapper.findByText(__('Close')); + + const createComponent = () => { + wrapper = shallowMountExtended(RunnerAwsInstructions, { + stubs: { + GlSprintf, + }, + }); + }; + + beforeEach(() => { + createComponent(); + }); + + it('should contain every button', () => { + expect(findEasyButtons()).toHaveLength(AWS_EASY_BUTTONS.length); + }); + + const AWS_EASY_BUTTONS_PARAMS = AWS_EASY_BUTTONS.map((val, idx) => ({ ...val, idx })); + + describe.each(AWS_EASY_BUTTONS_PARAMS)( + 'easy button %#', + ({ idx, description, moreDetails1, moreDetails2, templateName, stackName }) => { + it('should contain button description', () => { + const text = findEasyButtonAt(idx).text(); + + expect(text).toContain(description); + expect(text).toContain(moreDetails1); + expect(text).toContain(moreDetails2); + }); + + it('should show more details', () => { + const accordion = findEasyButtonAt(idx).findComponent(GlAccordion); + const accordionItem = accordion.findComponent(GlAccordionItem); + + expect(accordion.props('headerLevel')).toBe(3); + expect(accordionItem.props('title')).toBe(__('More Details')); + expect(accordionItem.props('titleVisible')).toBe(__('Less Details')); + }); + + describe('when clicked', () => { + let trackingSpy; + + beforeEach(() => { + trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + + findEasyButtonsRadioGroup().vm.$emit('input', idx); + findOkButton().vm.$emit('click'); + }); + + it('should contain the correct link', () => { + const templateUrl = encodeURIComponent(AWS_TEMPLATES_BASE_URL + templateName); + const instanceUrl = encodeURIComponent(getBaseURL()); + const url = `${AWS_CF_BASE_URL}templateURL=${templateUrl}&stackName=${stackName}¶m_3GITLABRunnerInstanceURL=${instanceUrl}`; + + expect(visitUrl).toHaveBeenCalledTimes(1); + expect(visitUrl).toHaveBeenCalledWith(url, true); + }); + + it('should track an event when clicked', () => { + expect(trackingSpy).toHaveBeenCalledTimes(1); + expect(trackingSpy).toHaveBeenCalledWith(undefined, 'template_clicked', { + label: stackName, + }); + }); + }); + }, + ); + + it('displays link with more information', () => { + expect(findLink().attributes('href')).toBe(AWS_README_URL); + }); + + it('triggers the modal to close', () => { + findCloseButton().vm.$emit('click'); + + expect(wrapper.emitted('close')).toHaveLength(1); + }); +}); diff --git a/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_cli_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_cli_instructions_spec.js new file mode 100644 index 00000000000..f9d700fe67f --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_cli_instructions_spec.js @@ -0,0 +1,169 @@ +import { GlAlert, GlLoadingIcon } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import getRunnerSetupInstructionsQuery from '~/vue_shared/components/runner_instructions/graphql/get_runner_setup.query.graphql'; +import RunnerCliInstructions from '~/vue_shared/components/runner_instructions/instructions/runner_cli_instructions.vue'; + +import { mockRunnerPlatforms, mockInstructions, mockInstructionsWindows } from '../mock_data'; + +Vue.use(VueApollo); + +jest.mock('@gitlab/ui/dist/utils'); + +const mockPlatforms = mockRunnerPlatforms.data.runnerPlatforms.nodes.map( + ({ name, humanReadableName, architectures }) => ({ + name, + humanReadableName, + architectures: architectures?.nodes || [], + }), +); + +const [mockPlatform, mockPlatform2] = mockPlatforms; +const mockArchitectures = mockPlatform.architectures; + +describe('RunnerCliInstructions component', () => { + let wrapper; + let fakeApollo; + let runnerSetupInstructionsHandler; + + const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + const findAlert = () => wrapper.findComponent(GlAlert); + const findArchitectureDropdownItems = () => wrapper.findAllByTestId('architecture-dropdown-item'); + const findBinaryDownloadButton = () => wrapper.findByTestId('binary-download-button'); + const findBinaryInstructions = () => wrapper.findByTestId('binary-instructions'); + const findRegisterCommand = () => wrapper.findByTestId('register-command'); + + const createComponent = ({ props, ...options } = {}) => { + const requestHandlers = [[getRunnerSetupInstructionsQuery, runnerSetupInstructionsHandler]]; + + fakeApollo = createMockApollo(requestHandlers); + + wrapper = extendedWrapper( + shallowMount(RunnerCliInstructions, { + propsData: { + platform: mockPlatform, + registrationToken: 'MY_TOKEN', + ...props, + }, + apolloProvider: fakeApollo, + ...options, + }), + ); + }; + + beforeEach(() => { + runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockInstructions); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when the instructions are shown', () => { + beforeEach(async () => { + createComponent(); + await waitForPromises(); + }); + + it('should not show alert', async () => { + expect(findAlert().exists()).toBe(false); + }); + + it('should contain a number of dropdown items for the architecture options', () => { + expect(findArchitectureDropdownItems()).toHaveLength( + mockRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length, + ); + }); + + describe('should display instructions', () => { + const { installInstructions } = mockInstructions.data.runnerSetup; + + it('runner instructions are requested', () => { + expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({ + platform: 'linux', + architecture: 'amd64', + }); + }); + + it('binary instructions are shown', async () => { + const instructions = findBinaryInstructions().text(); + + expect(instructions).toBe(installInstructions.trim()); + }); + + it('register command is shown with a replaced token', async () => { + const command = findRegisterCommand().text(); + + expect(command).toBe( + 'sudo gitlab-runner register --url http://localhost/ --registration-token MY_TOKEN', + ); + }); + + it('architecture download link is shown', () => { + expect(findBinaryDownloadButton().attributes('href')).toBe( + mockArchitectures[0].downloadLocation, + ); + }); + }); + + describe('after another platform and architecture are selected', () => { + beforeEach(async () => { + runnerSetupInstructionsHandler.mockResolvedValue(mockInstructionsWindows); + + findArchitectureDropdownItems().at(1).vm.$emit('click'); + + wrapper.setProps({ platform: mockPlatform2 }); + await waitForPromises(); + }); + + it('runner instructions are requested', () => { + expect(runnerSetupInstructionsHandler).toHaveBeenLastCalledWith({ + platform: mockPlatform2.name, + architecture: mockPlatform2.architectures[0].name, + }); + }); + }); + }); + + describe('when a register token is not known', () => { + beforeEach(async () => { + createComponent({ props: { registrationToken: undefined } }); + await waitForPromises(); + }); + + it('register command is shown without a defined registration token', () => { + const instructions = findRegisterCommand().text(); + + expect(instructions).toBe(mockInstructions.data.runnerSetup.registerInstructions); + }); + }); + + describe('when apollo is loading', () => { + it('should show a loading icon', async () => { + createComponent(); + + expect(findGlLoadingIcon().exists()).toBe(true); + + await waitForPromises(); + + expect(findGlLoadingIcon().exists()).toBe(false); + }); + }); + + describe('when instructions cannot be loaded', () => { + beforeEach(async () => { + runnerSetupInstructionsHandler.mockRejectedValue(); + + createComponent(); + await waitForPromises(); + }); + + it('should show alert', () => { + expect(wrapper.emitted()).toEqual({ error: [[]] }); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_docker_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_docker_instructions_spec.js new file mode 100644 index 00000000000..2922d261b24 --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_docker_instructions_spec.js @@ -0,0 +1,28 @@ +import { shallowMount } from '@vue/test-utils'; + +import { GlButton } from '@gitlab/ui'; +import RunnerDockerInstructions from '~/vue_shared/components/runner_instructions/instructions/runner_docker_instructions.vue'; + +describe('RunnerDockerInstructions', () => { + let wrapper; + + const createComponent = () => { + wrapper = shallowMount(RunnerDockerInstructions, {}); + }; + + const findButton = () => wrapper.findComponent(GlButton); + + beforeEach(() => { + createComponent(); + }); + + it('renders contents', () => { + expect(wrapper.text().replace(/\s+/g, ' ')).toMatchSnapshot(); + }); + + it('renders link', () => { + expect(findButton().attributes('href')).toBe( + 'https://docs.gitlab.com/runner/install/docker.html', + ); + }); +}); diff --git a/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_kubernetes_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_kubernetes_instructions_spec.js new file mode 100644 index 00000000000..0bfcc0e3d86 --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/instructions/runner_kubernetes_instructions_spec.js @@ -0,0 +1,28 @@ +import { shallowMount } from '@vue/test-utils'; + +import { GlButton } from '@gitlab/ui'; +import RunnerKubernetesInstructions from '~/vue_shared/components/runner_instructions/instructions/runner_kubernetes_instructions.vue'; + +describe('RunnerKubernetesInstructions', () => { + let wrapper; + + const createComponent = () => { + wrapper = shallowMount(RunnerKubernetesInstructions, {}); + }; + + const findButton = () => wrapper.findComponent(GlButton); + + beforeEach(() => { + createComponent(); + }); + + it('renders contents', () => { + expect(wrapper.text().replace(/\s+/g, ' ')).toMatchSnapshot(); + }); + + it('renders link', () => { + expect(findButton().attributes('href')).toBe( + 'https://docs.gitlab.com/runner/install/kubernetes.html', + ); + }); +}); diff --git a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js index 79cacadd6af..add334f166c 100644 --- a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js +++ b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js @@ -1,5 +1,5 @@ -import mockGraphqlRunnerPlatforms from 'test_fixtures/graphql/runner_instructions/get_runner_platforms.query.graphql.json'; -import mockGraphqlInstructions from 'test_fixtures/graphql/runner_instructions/get_runner_setup.query.graphql.json'; -import mockGraphqlInstructionsWindows from 'test_fixtures/graphql/runner_instructions/get_runner_setup.query.graphql.windows.json'; +import mockRunnerPlatforms from 'test_fixtures/graphql/runner_instructions/get_runner_platforms.query.graphql.json'; +import mockInstructions from 'test_fixtures/graphql/runner_instructions/get_runner_setup.query.graphql.json'; +import mockInstructionsWindows from 'test_fixtures/graphql/runner_instructions/get_runner_setup.query.graphql.windows.json'; -export { mockGraphqlRunnerPlatforms, mockGraphqlInstructions, mockGraphqlInstructionsWindows }; +export { mockRunnerPlatforms, mockInstructions, mockInstructionsWindows }; diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js index ae9157591c5..19f2dd137ff 100644 --- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js +++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js @@ -1,4 +1,4 @@ -import { GlAlert, GlModal, GlButton, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui'; +import { GlAlert, GlModal, GlButton, GlSkeletonLoader } from '@gitlab/ui'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; @@ -6,15 +6,13 @@ import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; -import getRunnerPlatformsQuery from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql'; -import getRunnerSetupInstructionsQuery from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql'; +import getRunnerPlatformsQuery from '~/vue_shared/components/runner_instructions/graphql/get_runner_platforms.query.graphql'; import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue'; +import RunnerCliInstructions from '~/vue_shared/components/runner_instructions/instructions/runner_cli_instructions.vue'; +import RunnerDockerInstructions from '~/vue_shared/components/runner_instructions/instructions/runner_docker_instructions.vue'; +import RunnerKubernetesInstructions from '~/vue_shared/components/runner_instructions/instructions/runner_kubernetes_instructions.vue'; -import { - mockGraphqlRunnerPlatforms, - mockGraphqlInstructions, - mockGraphqlInstructionsWindows, -} from './mock_data'; +import { mockRunnerPlatforms } from './mock_data'; Vue.use(VueApollo); @@ -40,24 +38,16 @@ describe('RunnerInstructionsModal component', () => { let wrapper; let fakeApollo; let runnerPlatformsHandler; - let runnerSetupInstructionsHandler; const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader); - const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findAlert = () => wrapper.findComponent(GlAlert); const findModal = () => wrapper.findComponent(GlModal); const findPlatformButtonGroup = () => wrapper.findByTestId('platform-buttons'); const findPlatformButtons = () => findPlatformButtonGroup().findAllComponents(GlButton); - const findArchitectureDropdownItems = () => wrapper.findAllByTestId('architecture-dropdown-item'); - const findBinaryDownloadButton = () => wrapper.findByTestId('binary-download-button'); - const findBinaryInstructions = () => wrapper.findByTestId('binary-instructions'); - const findRegisterCommand = () => wrapper.findByTestId('register-command'); + const findRunnerCliInstructions = () => wrapper.findComponent(RunnerCliInstructions); const createComponent = ({ props, shown = true, ...options } = {}) => { - const requestHandlers = [ - [getRunnerPlatformsQuery, runnerPlatformsHandler], - [getRunnerSetupInstructionsQuery, runnerSetupInstructionsHandler], - ]; + const requestHandlers = [[getRunnerPlatformsQuery, runnerPlatformsHandler]]; fakeApollo = createMockApollo(requestHandlers); @@ -80,8 +70,7 @@ describe('RunnerInstructionsModal component', () => { }; beforeEach(() => { - runnerPlatformsHandler = jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms); - runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockGraphqlInstructions); + runnerPlatformsHandler = jest.fn().mockResolvedValue(mockRunnerPlatforms); }); afterEach(() => { @@ -103,90 +92,15 @@ describe('RunnerInstructionsModal component', () => { const buttons = findPlatformButtons(); - expect(buttons).toHaveLength(mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes.length); + expect(buttons).toHaveLength(mockRunnerPlatforms.data.runnerPlatforms.nodes.length); }); - it('should contain a number of dropdown items for the architecture options', () => { - expect(findArchitectureDropdownItems()).toHaveLength( - mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length, - ); - }); - - describe('should display default instructions', () => { - const { installInstructions } = mockGraphqlInstructions.data.runnerSetup; - - it('runner instructions are requested', () => { - expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({ - platform: 'linux', - architecture: 'amd64', - }); - }); - - it('binary instructions are shown', async () => { - const instructions = findBinaryInstructions().text(); - - expect(instructions).toBe(installInstructions.trim()); - }); - - it('register command is shown with a replaced token', async () => { - const command = findRegisterCommand().text(); - - expect(command).toBe( - 'sudo gitlab-runner register --url http://localhost/ --registration-token MY_TOKEN', - ); - }); - }); - - describe('after a platform and architecture are selected', () => { - const windowsIndex = 2; - const { installInstructions } = mockGraphqlInstructionsWindows.data.runnerSetup; - - beforeEach(async () => { - runnerSetupInstructionsHandler.mockResolvedValue(mockGraphqlInstructionsWindows); - - findPlatformButtons().at(windowsIndex).vm.$emit('click'); - await waitForPromises(); - }); + it('should display architecture options', () => { + const { architectures } = findRunnerCliInstructions().props('platform'); - it('runner instructions are requested', () => { - expect(runnerSetupInstructionsHandler).toHaveBeenLastCalledWith({ - platform: 'windows', - architecture: 'amd64', - }); - }); - - it('architecture download link is updated', () => { - const architectures = - mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[windowsIndex].architectures.nodes; - - expect(findBinaryDownloadButton().attributes('href')).toBe( - architectures[0].downloadLocation, - ); - }); - - it('other binary instructions are shown', () => { - const instructions = findBinaryInstructions().text(); - - expect(instructions).toBe(installInstructions.trim()); - }); - - it('register command is shown', () => { - const command = findRegisterCommand().text(); - - expect(command).toBe( - './gitlab-runner.exe register --url http://localhost/ --registration-token MY_TOKEN', - ); - }); - - it('runner instructions are requested with another architecture', async () => { - findArchitectureDropdownItems().at(1).vm.$emit('click'); - await waitForPromises(); - - expect(runnerSetupInstructionsHandler).toHaveBeenLastCalledWith({ - platform: 'windows', - architecture: '386', - }); - }); + expect(architectures).toEqual( + mockRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes, + ); }); describe('when the modal resizes', () => { @@ -206,16 +120,14 @@ describe('RunnerInstructionsModal component', () => { }); }); - describe('when a register token is not known', () => { + describe.each([null, 'DEFINED'])('when registration token is %p', (token) => { beforeEach(async () => { - createComponent({ props: { registrationToken: undefined } }); + createComponent({ props: { registrationToken: token } }); await waitForPromises(); }); it('register command is shown without a defined registration token', () => { - const instructions = findRegisterCommand().text(); - - expect(instructions).toBe(mockGraphqlInstructions.data.runnerSetup.registerInstructions); + expect(findRunnerCliInstructions().props('registrationToken')).toBe(token); }); }); @@ -225,21 +137,33 @@ describe('RunnerInstructionsModal component', () => { await waitForPromises(); }); - it('runner instructions for the default selected platform are requested', () => { - expect(runnerSetupInstructionsHandler).toHaveBeenLastCalledWith({ - platform: 'osx', - architecture: 'amd64', - }); + it('should preselect', () => { + const selected = findPlatformButtons() + .filter((btn) => btn.props('selected')) + .at(0); + + expect(selected.text()).toBe('macOS'); }); - it('sets the focus on the default selected platform', () => { - const findOsxPlatformButton = () => wrapper.findComponent({ ref: 'osx' }); + it('runner instructions for the default selected platform are requested', () => { + const { name } = findRunnerCliInstructions().props('platform'); - findOsxPlatformButton().element.focus = jest.fn(); + expect(name).toBe('osx'); + }); + }); - findModal().vm.$emit('shown'); + describe.each` + platform | component + ${'docker'} | ${RunnerDockerInstructions} + ${'kubernetes'} | ${RunnerKubernetesInstructions} + `('with platform "$platform"', ({ platform, component }) => { + beforeEach(async () => { + createComponent({ props: { defaultPlatformName: platform } }); + await waitForPromises(); + }); - expect(findOsxPlatformButton().element.focus).toHaveBeenCalled(); + it(`runner instructions for ${platform} are shown`, () => { + expect(wrapper.findComponent(component).exists()).toBe(true); }); }); @@ -251,7 +175,6 @@ describe('RunnerInstructionsModal component', () => { it('does not fetch instructions', () => { expect(runnerPlatformsHandler).not.toHaveBeenCalled(); - expect(runnerSetupInstructionsHandler).not.toHaveBeenCalled(); }); }); @@ -259,43 +182,41 @@ describe('RunnerInstructionsModal component', () => { it('should show a skeleton loader', async () => { createComponent(); await nextTick(); - await nextTick(); expect(findSkeletonLoader().exists()).toBe(true); - expect(findGlLoadingIcon().exists()).toBe(false); - - // wait on fetch of both `platforms` and `instructions` - await nextTick(); - await nextTick(); - - expect(findGlLoadingIcon().exists()).toBe(true); }); it('once loaded, should not show a loading state', async () => { createComponent(); - await waitForPromises(); expect(findSkeletonLoader().exists()).toBe(false); - expect(findGlLoadingIcon().exists()).toBe(false); }); }); - describe('when instructions cannot be loaded', () => { - beforeEach(async () => { - runnerSetupInstructionsHandler.mockRejectedValue(); + describe('errors', () => { + it('should show an alert when platforms cannot be loaded', async () => { + runnerPlatformsHandler.mockRejectedValue(); createComponent(); await waitForPromises(); - }); - it('should show alert', () => { expect(findAlert().exists()).toBe(true); }); - it('should not show instructions', () => { - expect(findBinaryInstructions().exists()).toBe(false); - expect(findRegisterCommand().exists()).toBe(false); + it('should show alert when instructions cannot be loaded', async () => { + createComponent(); + await waitForPromises(); + + findRunnerCliInstructions().vm.$emit('error'); + await waitForPromises(); + + expect(findAlert().exists()).toBe(true); + + findAlert().vm.$emit('dismiss'); + await nextTick(); + + expect(findAlert().exists()).toBe(false); }); }); @@ -312,14 +233,16 @@ describe('RunnerInstructionsModal component', () => { describe('show()', () => { let mockShow; + let mockClose; beforeEach(() => { mockShow = jest.fn(); + mockClose = jest.fn(); createComponent({ shown: false, stubs: { - GlModal: getGlModalStub({ show: mockShow }), + GlModal: getGlModalStub({ show: mockShow, close: mockClose }), }, }); }); @@ -329,6 +252,12 @@ describe('RunnerInstructionsModal component', () => { expect(mockShow).toHaveBeenCalledTimes(1); }); + + it('delegates close()', () => { + wrapper.vm.close(); + + expect(mockClose).toHaveBeenCalledTimes(1); + }); }); }); }); |