2021-10-22 18:13:20 +00:00
|
|
|
import { GlAlert, GlModal, GlButton, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
|
2021-04-30 15:09:50 +00:00
|
|
|
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
|
2021-12-08 09:13:01 +00:00
|
|
|
import { shallowMount } from '@vue/test-utils';
|
|
|
|
import Vue, { nextTick } from 'vue';
|
2021-04-07 18:09:45 +00:00
|
|
|
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 RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
|
|
|
|
|
|
|
|
import {
|
|
|
|
mockGraphqlRunnerPlatforms,
|
|
|
|
mockGraphqlInstructions,
|
|
|
|
mockGraphqlInstructionsWindows,
|
|
|
|
} from './mock_data';
|
|
|
|
|
2021-12-08 09:13:01 +00:00
|
|
|
Vue.use(VueApollo);
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2021-04-30 15:09:50 +00:00
|
|
|
let resizeCallback;
|
|
|
|
const MockResizeObserver = {
|
|
|
|
bind(el, { value }) {
|
|
|
|
resizeCallback = value;
|
|
|
|
},
|
|
|
|
mockResize(size) {
|
|
|
|
bp.getBreakpointSize.mockReturnValue(size);
|
|
|
|
resizeCallback();
|
|
|
|
},
|
|
|
|
unbind() {
|
|
|
|
resizeCallback = null;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2021-12-08 09:13:01 +00:00
|
|
|
Vue.directive('gl-resize-observer', MockResizeObserver);
|
2021-04-30 15:09:50 +00:00
|
|
|
|
|
|
|
jest.mock('@gitlab/ui/dist/utils');
|
|
|
|
|
2021-04-07 18:09:45 +00:00
|
|
|
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);
|
2022-05-02 09:10:46 +00:00
|
|
|
const findModal = () => wrapper.findComponent(GlModal);
|
2021-04-30 15:09:50 +00:00
|
|
|
const findPlatformButtonGroup = () => wrapper.findByTestId('platform-buttons');
|
|
|
|
const findPlatformButtons = () => findPlatformButtonGroup().findAllComponents(GlButton);
|
2021-04-07 18:09:45 +00:00
|
|
|
const findArchitectureDropdownItems = () => wrapper.findAllByTestId('architecture-dropdown-item');
|
2022-05-31 12:09:12 +00:00
|
|
|
const findBinaryDownloadButton = () => wrapper.findByTestId('binary-download-button');
|
2021-04-07 18:09:45 +00:00
|
|
|
const findBinaryInstructions = () => wrapper.findByTestId('binary-instructions');
|
|
|
|
const findRegisterCommand = () => wrapper.findByTestId('register-command');
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
const createComponent = ({ props, shown = true, ...options } = {}) => {
|
2021-04-07 18:09:45 +00:00
|
|
|
const requestHandlers = [
|
|
|
|
[getRunnerPlatformsQuery, runnerPlatformsHandler],
|
|
|
|
[getRunnerSetupInstructionsQuery, runnerSetupInstructionsHandler],
|
|
|
|
];
|
|
|
|
|
|
|
|
fakeApollo = createMockApollo(requestHandlers);
|
|
|
|
|
|
|
|
wrapper = extendedWrapper(
|
|
|
|
shallowMount(RunnerInstructionsModal, {
|
|
|
|
propsData: {
|
|
|
|
modalId: 'runner-instructions-modal',
|
2021-10-25 18:12:16 +00:00
|
|
|
registrationToken: 'MY_TOKEN',
|
|
|
|
...props,
|
2021-04-07 18:09:45 +00:00
|
|
|
},
|
|
|
|
apolloProvider: fakeApollo,
|
2021-10-22 18:13:20 +00:00
|
|
|
...options,
|
2021-04-07 18:09:45 +00:00
|
|
|
}),
|
|
|
|
);
|
2022-06-07 15:08:12 +00:00
|
|
|
|
|
|
|
// trigger open modal
|
|
|
|
if (shown) {
|
|
|
|
findModal().vm.$emit('shown');
|
|
|
|
}
|
2021-04-07 18:09:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
runnerPlatformsHandler = jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms);
|
|
|
|
runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockGraphqlInstructions);
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
describe('when the modal is shown', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
createComponent();
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('should not show alert', async () => {
|
|
|
|
expect(findAlert().exists()).toBe(false);
|
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('should contain a number of platforms buttons', () => {
|
|
|
|
expect(runnerPlatformsHandler).toHaveBeenCalledWith({});
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
const buttons = findPlatformButtons();
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(buttons).toHaveLength(mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes.length);
|
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('should contain a number of dropdown items for the architecture options', () => {
|
|
|
|
expect(findArchitectureDropdownItems()).toHaveLength(
|
|
|
|
mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length,
|
|
|
|
);
|
2021-04-07 18:09:45 +00:00
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
describe('should display default instructions', () => {
|
|
|
|
const {
|
|
|
|
installInstructions,
|
|
|
|
registerInstructions,
|
|
|
|
} = mockGraphqlInstructions.data.runnerSetup;
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('runner instructions are requested', () => {
|
|
|
|
expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({
|
|
|
|
platform: 'linux',
|
|
|
|
architecture: 'amd64',
|
|
|
|
});
|
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('binary instructions are shown', async () => {
|
|
|
|
const instructions = findBinaryInstructions().text();
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(instructions).toBe(installInstructions);
|
|
|
|
});
|
2021-10-25 18:12:16 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('register command is shown with a replaced token', async () => {
|
|
|
|
const command = findRegisterCommand().text();
|
|
|
|
|
|
|
|
expect(command).toBe(
|
|
|
|
'sudo gitlab-runner register --url http://gdk.test:3000/ --registration-token MY_TOKEN',
|
|
|
|
);
|
2021-10-25 18:12:16 +00:00
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
describe('when a register token is not shown', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
createComponent({ props: { registrationToken: undefined } });
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('register command is shown without a defined registration token', () => {
|
|
|
|
const instructions = findRegisterCommand().text();
|
2021-10-25 18:12:16 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(instructions).toBe(registerInstructions);
|
|
|
|
});
|
2021-10-25 18:12:16 +00:00
|
|
|
});
|
2022-05-02 09:10:46 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
describe('when providing a defaultPlatformName', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
createComponent({ props: { defaultPlatformName: 'osx' } });
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('runner instructions for the default selected platform are requested', () => {
|
|
|
|
expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({
|
|
|
|
platform: 'osx',
|
|
|
|
architecture: 'amd64',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('sets the focus on the default selected platform', () => {
|
|
|
|
const findOsxPlatformButton = () => wrapper.find({ ref: 'osx' });
|
2022-05-02 09:10:46 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
findOsxPlatformButton().element.focus = jest.fn();
|
2022-05-02 09:10:46 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
findModal().vm.$emit('shown');
|
|
|
|
|
|
|
|
expect(findOsxPlatformButton().element.focus).toHaveBeenCalled();
|
|
|
|
});
|
2022-05-02 09:10:46 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
describe('after a platform and architecture are selected', () => {
|
|
|
|
const windowsIndex = 2;
|
|
|
|
const { installInstructions } = mockGraphqlInstructionsWindows.data.runnerSetup;
|
|
|
|
|
2022-05-02 09:10:46 +00:00
|
|
|
beforeEach(async () => {
|
2022-06-07 15:08:12 +00:00
|
|
|
runnerSetupInstructionsHandler.mockResolvedValue(mockGraphqlInstructionsWindows);
|
|
|
|
|
|
|
|
findPlatformButtons().at(windowsIndex).vm.$emit('click');
|
2022-05-02 09:10:46 +00:00
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('runner instructions are requested', () => {
|
|
|
|
expect(runnerSetupInstructionsHandler).toHaveBeenLastCalledWith({
|
|
|
|
platform: 'windows',
|
2022-05-02 09:10:46 +00:00
|
|
|
architecture: 'amd64',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('architecture download link is updated', () => {
|
|
|
|
const architectures =
|
|
|
|
mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[windowsIndex].architectures.nodes;
|
2022-05-02 09:10:46 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(findBinaryDownloadButton().attributes('href')).toBe(
|
|
|
|
architectures[0].downloadLocation,
|
|
|
|
);
|
2022-05-02 09:10:46 +00:00
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('other binary instructions are shown', () => {
|
|
|
|
const instructions = findBinaryInstructions().text();
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(instructions).toBe(installInstructions);
|
2021-04-07 18:09:45 +00:00
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('register command is shown', () => {
|
|
|
|
const command = findRegisterCommand().text();
|
2022-05-31 12:09:12 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(command).toBe(
|
|
|
|
'./gitlab-runner.exe register --url http://gdk.test:3000/ --registration-token MY_TOKEN',
|
|
|
|
);
|
|
|
|
});
|
2022-05-31 12:09:12 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('runner instructions are requested with another architecture', async () => {
|
|
|
|
findArchitectureDropdownItems().at(1).vm.$emit('click');
|
|
|
|
await waitForPromises();
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(runnerSetupInstructionsHandler).toHaveBeenLastCalledWith({
|
|
|
|
platform: 'windows',
|
|
|
|
architecture: '386',
|
|
|
|
});
|
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
describe('when the modal resizes', () => {
|
|
|
|
it('to an xs viewport', async () => {
|
|
|
|
MockResizeObserver.mockResize('xs');
|
|
|
|
await nextTick();
|
2021-04-07 18:09:45 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(findPlatformButtonGroup().attributes('vertical')).toBeTruthy();
|
|
|
|
});
|
2022-05-31 12:09:12 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('to a non-xs viewport', async () => {
|
|
|
|
MockResizeObserver.mockResize('sm');
|
|
|
|
await nextTick();
|
2022-05-31 12:09:12 +00:00
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
expect(findPlatformButtonGroup().props('vertical')).toBeFalsy();
|
2022-05-31 12:09:12 +00:00
|
|
|
});
|
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
describe('when the modal is not shown', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
createComponent({ shown: false });
|
|
|
|
await waitForPromises();
|
2021-04-30 15:09:50 +00:00
|
|
|
});
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
it('does not fetch instructions', () => {
|
|
|
|
expect(runnerPlatformsHandler).not.toHaveBeenCalled();
|
|
|
|
expect(runnerSetupInstructionsHandler).not.toHaveBeenCalled();
|
2021-04-30 15:09:50 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2021-04-07 18:09:45 +00:00
|
|
|
describe('when apollo is loading', () => {
|
2022-06-07 15:08:12 +00:00
|
|
|
beforeEach(() => {
|
2021-04-07 18:09:45 +00:00
|
|
|
createComponent();
|
2022-06-07 15:08:12 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should show a skeleton loader', async () => {
|
2021-04-07 18:09:45 +00:00
|
|
|
expect(findSkeletonLoader().exists()).toBe(true);
|
|
|
|
expect(findGlLoadingIcon().exists()).toBe(false);
|
|
|
|
|
2022-06-07 15:08:12 +00:00
|
|
|
// wait on fetch of both `platforms` and `instructions`
|
2022-02-14 12:14:02 +00:00
|
|
|
await nextTick();
|
2022-01-24 21:14:06 +00:00
|
|
|
await nextTick();
|
2021-04-07 18:09:45 +00:00
|
|
|
|
|
|
|
expect(findGlLoadingIcon().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('once loaded, should not show a loading state', async () => {
|
2022-01-24 21:14:06 +00:00
|
|
|
await waitForPromises();
|
2021-04-07 18:09:45 +00:00
|
|
|
|
|
|
|
expect(findSkeletonLoader().exists()).toBe(false);
|
|
|
|
expect(findGlLoadingIcon().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when instructions cannot be loaded', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
runnerSetupInstructionsHandler.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);
|
|
|
|
});
|
|
|
|
});
|
2021-10-22 18:13:20 +00:00
|
|
|
|
|
|
|
describe('GlModal API', () => {
|
|
|
|
const getGlModalStub = (methods) => {
|
|
|
|
return {
|
|
|
|
...GlModal,
|
|
|
|
methods: {
|
|
|
|
...GlModal.methods,
|
|
|
|
...methods,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
describe('show()', () => {
|
|
|
|
let mockShow;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
mockShow = jest.fn();
|
|
|
|
|
|
|
|
createComponent({
|
2022-06-07 15:08:12 +00:00
|
|
|
shown: false,
|
2021-10-22 18:13:20 +00:00
|
|
|
stubs: {
|
|
|
|
GlModal: getGlModalStub({ show: mockShow }),
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('delegates show()', () => {
|
|
|
|
wrapper.vm.show();
|
|
|
|
|
|
|
|
expect(mockShow).toHaveBeenCalledTimes(1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2021-04-07 18:09:45 +00:00
|
|
|
});
|