Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/ci/runner/components/runner_pause_button_spec.js')
-rw-r--r--spec/frontend/ci/runner/components/runner_pause_button_spec.js282
1 files changed, 86 insertions, 196 deletions
diff --git a/spec/frontend/ci/runner/components/runner_pause_button_spec.js b/spec/frontend/ci/runner/components/runner_pause_button_spec.js
index 1ea870e004a..f1ceecd4ae4 100644
--- a/spec/frontend/ci/runner/components/runner_pause_button_spec.js
+++ b/spec/frontend/ci/runner/components/runner_pause_button_spec.js
@@ -1,13 +1,7 @@
-import Vue, { nextTick } from 'vue';
import { GlButton } from '@gitlab/ui';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
+import { stubComponent } from 'helpers/stub_component';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
-import runnerTogglePausedMutation from '~/ci/runner/graphql/shared/runner_toggle_paused.mutation.graphql';
-import waitForPromises from 'helpers/wait_for_promises';
-import { captureException } from '~/ci/runner/sentry_utils';
-import { createAlert } from '~/alert';
import {
I18N_PAUSE,
I18N_PAUSE_TOOLTIP,
@@ -16,244 +10,140 @@ import {
} from '~/ci/runner/constants';
import RunnerPauseButton from '~/ci/runner/components/runner_pause_button.vue';
-import { allRunnersData } from '../mock_data';
-
-const mockRunner = allRunnersData.data.runners.nodes[0];
-
-Vue.use(VueApollo);
-
-jest.mock('~/alert');
-jest.mock('~/ci/runner/sentry_utils');
+import RunnerPauseAction from '~/ci/runner/components/runner_pause_action.vue';
describe('RunnerPauseButton', () => {
let wrapper;
- let runnerTogglePausedHandler;
const getTooltip = () => getBinding(wrapper.element, 'gl-tooltip').value;
+ const findRunnerPauseAction = () => wrapper.findComponent(RunnerPauseAction);
const findBtn = () => wrapper.findComponent(GlButton);
- const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => {
- const { runner, ...propsData } = props;
-
+ const createComponent = ({
+ props = {},
+ loading,
+ onClick = jest.fn(),
+ mountFn = shallowMountExtended,
+ } = {}) => {
wrapper = mountFn(RunnerPauseButton, {
propsData: {
- runner: {
- id: mockRunner.id,
- paused: mockRunner.paused,
- ...runner,
- },
- ...propsData,
+ runner: {},
+ ...props,
},
- apolloProvider: createMockApollo([[runnerTogglePausedMutation, runnerTogglePausedHandler]]),
directives: {
GlTooltip: createMockDirective('gl-tooltip'),
},
+ stubs: {
+ RunnerPauseAction: stubComponent(RunnerPauseAction, {
+ render() {
+ return this.$scopedSlots.default({
+ loading,
+ onClick,
+ });
+ },
+ }),
+ },
});
};
- const clickAndWait = async () => {
- findBtn().vm.$emit('click');
- await waitForPromises();
- };
-
beforeEach(() => {
- runnerTogglePausedHandler = jest.fn().mockImplementation(({ input }) => {
- return Promise.resolve({
- data: {
- runnerUpdate: {
- runner: {
- id: input.id,
- paused: !input.paused,
- },
- errors: [],
- },
- },
- });
- });
-
createComponent();
});
- describe('Pause/Resume action', () => {
+ describe('Pause/Resume button', () => {
describe.each`
- runnerState | icon | content | tooltip | isPaused | newPausedValue
- ${'paused'} | ${'play'} | ${I18N_RESUME} | ${I18N_RESUME_TOOLTIP} | ${true} | ${false}
- ${'active'} | ${'pause'} | ${I18N_PAUSE} | ${I18N_PAUSE_TOOLTIP} | ${false} | ${true}
- `('When the runner is $runnerState', ({ icon, content, tooltip, isPaused, newPausedValue }) => {
- beforeEach(() => {
- createComponent({
- props: {
- runner: {
- paused: isPaused,
+ runnerState | paused | expectedIcon | expectedContent | expectedTooltip
+ ${'paused'} | ${true} | ${'play'} | ${I18N_RESUME} | ${I18N_RESUME_TOOLTIP}
+ ${'active'} | ${false} | ${'pause'} | ${I18N_PAUSE} | ${I18N_PAUSE_TOOLTIP}
+ `(
+ 'When the runner is $runnerState',
+ ({ paused, expectedIcon, expectedContent, expectedTooltip }) => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ runner: { paused },
},
- },
- });
- });
-
- it(`Displays a ${icon} button`, () => {
- expect(findBtn().props('loading')).toBe(false);
- expect(findBtn().props('icon')).toBe(icon);
- });
-
- it('Displays button content', () => {
- expect(findBtn().text()).toBe(content);
- expect(getTooltip()).toBe(tooltip);
- });
-
- it('Does not display redundant text for screen readers', () => {
- expect(findBtn().attributes('aria-label')).toBe(undefined);
- });
-
- describe(`Before the ${icon} button is clicked`, () => {
- it('The mutation has not been called', () => {
- expect(runnerTogglePausedHandler).not.toHaveBeenCalled();
+ });
});
- });
-
- describe(`Immediately after the ${icon} button is clicked`, () => {
- const setup = async () => {
- findBtn().vm.$emit('click');
- await nextTick();
- };
- it('The button has a loading state', async () => {
- await setup();
-
- expect(findBtn().props('loading')).toBe(true);
+ it(`Displays a ${expectedIcon} button`, () => {
+ expect(findBtn().props('loading')).toBe(false);
+ expect(findBtn().props('icon')).toBe(expectedIcon);
});
- it('The stale tooltip is removed', async () => {
- await setup();
-
- expect(getTooltip()).toBe('');
+ it('Displays button content', () => {
+ expect(findBtn().text()).toBe(expectedContent);
+ expect(getTooltip()).toBe(expectedTooltip);
});
- });
- describe(`After clicking on the ${icon} button`, () => {
- beforeEach(async () => {
- await clickAndWait();
+ it('Does not display redundant text for screen readers', () => {
+ expect(findBtn().attributes('aria-label')).toBe(undefined);
});
+ },
+ );
+ });
- it(`The mutation to that sets "paused" to ${newPausedValue} is called`, () => {
- expect(runnerTogglePausedHandler).toHaveBeenCalledTimes(1);
- expect(runnerTogglePausedHandler).toHaveBeenCalledWith({
- input: {
- id: mockRunner.id,
- paused: newPausedValue,
+ describe('Compact button', () => {
+ describe.each`
+ runnerState | paused | expectedIcon | expectedContent | expectedTooltip
+ ${'paused'} | ${true} | ${'play'} | ${I18N_RESUME} | ${I18N_RESUME_TOOLTIP}
+ ${'active'} | ${false} | ${'pause'} | ${I18N_PAUSE} | ${I18N_PAUSE_TOOLTIP}
+ `(
+ 'When the runner is $runnerState',
+ ({ paused, expectedIcon, expectedContent, expectedTooltip }) => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ runner: { paused },
+ compact: true,
},
+ mountFn: mountExtended,
});
});
- it('The button does not have a loading state', () => {
+ it(`Displays a ${expectedIcon} button`, () => {
expect(findBtn().props('loading')).toBe(false);
+ expect(findBtn().props('icon')).toBe(expectedIcon);
});
- it('The button emits toggledPaused', () => {
- expect(wrapper.emitted('toggledPaused')).toHaveLength(1);
- });
- });
-
- describe('When update fails', () => {
- describe('On a network error', () => {
- const mockErrorMsg = 'Update error!';
-
- beforeEach(async () => {
- runnerTogglePausedHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
-
- await clickAndWait();
- });
-
- it('error is reported to sentry', () => {
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(mockErrorMsg),
- component: 'RunnerPauseButton',
- });
- });
+ it('Displays button content', () => {
+ expect(findBtn().text()).toBe('');
+ // Note: Use <template v-if> to ensure rendering a
+ // text-less button. Ensure we don't send even empty an
+ // content slot to prevent a distorted/rectangular button.
+ expect(wrapper.find('.gl-button-text').exists()).toBe(false);
- it('error is shown to the user', () => {
- expect(createAlert).toHaveBeenCalledTimes(1);
- });
+ expect(getTooltip()).toBe(expectedTooltip);
});
- describe('On a validation error', () => {
- const mockErrorMsg = 'Runner not found!';
- const mockErrorMsg2 = 'User not allowed!';
-
- beforeEach(async () => {
- runnerTogglePausedHandler.mockResolvedValueOnce({
- data: {
- runnerUpdate: {
- runner: {
- id: mockRunner.id,
- paused: isPaused,
- },
- errors: [mockErrorMsg, mockErrorMsg2],
- },
- },
- });
-
- await clickAndWait();
- });
-
- it('error is reported to sentry', () => {
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(`${mockErrorMsg} ${mockErrorMsg2}`),
- component: 'RunnerPauseButton',
- });
- });
-
- it('error is shown to the user', () => {
- expect(createAlert).toHaveBeenCalledTimes(1);
- });
+ it('Does not display redundant text for screen readers', () => {
+ expect(findBtn().attributes('aria-label')).toBe(expectedContent);
});
- });
- });
+ },
+ );
});
- describe('When displaying a compact button for an active runner', () => {
- beforeEach(() => {
- createComponent({
- props: {
- runner: {
- paused: false,
- },
- compact: true,
- },
- mountFn: mountExtended,
- });
- });
-
- it('Displays no text', () => {
- expect(findBtn().text()).toBe('');
+ it('Shows loading state', () => {
+ createComponent({ loading: true });
- // Note: Use <template v-if> to ensure rendering a
- // text-less button. Ensure we don't send even empty an
- // content slot to prevent a distorted/rectangular button.
- expect(wrapper.find('.gl-button-text').exists()).toBe(false);
- });
+ expect(findBtn().props('loading')).toBe(true);
+ expect(getTooltip()).toBe('');
+ });
- it('Display correctly for screen readers', () => {
- expect(findBtn().attributes('aria-label')).toBe(I18N_PAUSE);
- expect(getTooltip()).toBe(I18N_PAUSE_TOOLTIP);
- });
+ it('Triggers action', () => {
+ const mockOnClick = jest.fn();
- describe('Immediately after the button is clicked', () => {
- const setup = async () => {
- findBtn().vm.$emit('click');
- await nextTick();
- };
+ createComponent({ onClick: mockOnClick });
+ findBtn().vm.$emit('click');
- it('The button has a loading state', async () => {
- await setup();
+ expect(mockOnClick).toHaveBeenCalled();
+ });
- expect(findBtn().props('loading')).toBe(true);
- });
+ it('Emits toggledPaused when done', () => {
+ createComponent();
- it('The stale tooltip is removed', async () => {
- await setup();
+ findRunnerPauseAction().vm.$emit('done');
- expect(getTooltip()).toBe('');
- });
- });
+ expect(wrapper.emitted('toggledPaused')).toHaveLength(1);
});
});