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/runner/components/cells')
-rw-r--r--spec/frontend/runner/components/cells/runner_actions_cell_spec.js201
-rw-r--r--spec/frontend/runner/components/cells/runner_name_cell_spec.js42
-rw-r--r--spec/frontend/runner/components/cells/runner_type_cell_spec.js48
3 files changed, 291 insertions, 0 deletions
diff --git a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
new file mode 100644
index 00000000000..12651a82a0c
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
@@ -0,0 +1,201 @@
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import RunnerActionCell from '~/runner/components/cells/runner_actions_cell.vue';
+import deleteRunnerMutation from '~/runner/graphql/delete_runner.mutation.graphql';
+import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
+import runnerUpdateMutation from '~/runner/graphql/runner_update.mutation.graphql';
+
+const mockId = '1';
+
+const getRunnersQueryName = getRunnersQuery.definitions[0].name.value;
+
+describe('RunnerTypeCell', () => {
+ let wrapper;
+ let mutate;
+
+ const findEditBtn = () => wrapper.findByTestId('edit-runner');
+ const findToggleActiveBtn = () => wrapper.findByTestId('toggle-active-runner');
+ const findDeleteBtn = () => wrapper.findByTestId('delete-runner');
+
+ const createComponent = ({ active = true } = {}, options) => {
+ wrapper = extendedWrapper(
+ shallowMount(RunnerActionCell, {
+ propsData: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ active,
+ },
+ },
+ mocks: {
+ $apollo: {
+ mutate,
+ },
+ },
+ ...options,
+ }),
+ );
+ };
+
+ beforeEach(() => {
+ mutate = jest.fn();
+ });
+
+ afterEach(() => {
+ mutate.mockReset();
+ wrapper.destroy();
+ });
+
+ it('Displays the runner edit link with the correct href', () => {
+ createComponent();
+
+ expect(findEditBtn().attributes('href')).toBe('/admin/runners/1');
+ });
+
+ describe.each`
+ state | label | icon | isActive | newActiveValue
+ ${'active'} | ${'Pause'} | ${'pause'} | ${true} | ${false}
+ ${'paused'} | ${'Resume'} | ${'play'} | ${false} | ${true}
+ `('When the runner is $state', ({ label, icon, isActive, newActiveValue }) => {
+ beforeEach(() => {
+ mutate.mockResolvedValue({
+ data: {
+ runnerUpdate: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/1`,
+ __typename: 'CiRunner',
+ },
+ },
+ },
+ });
+
+ createComponent({ active: isActive });
+ });
+
+ it(`Displays a ${icon} button`, () => {
+ expect(findToggleActiveBtn().props('loading')).toBe(false);
+ expect(findToggleActiveBtn().props('icon')).toBe(icon);
+ expect(findToggleActiveBtn().attributes('title')).toBe(label);
+ expect(findToggleActiveBtn().attributes('aria-label')).toBe(label);
+ });
+
+ it(`After clicking the ${icon} button, the button has a loading state`, async () => {
+ await findToggleActiveBtn().vm.$emit('click');
+
+ expect(findToggleActiveBtn().props('loading')).toBe(true);
+ });
+
+ it(`After the ${icon} button is clicked, stale tooltip is removed`, async () => {
+ await findToggleActiveBtn().vm.$emit('click');
+
+ expect(findToggleActiveBtn().attributes('title')).toBe('');
+ expect(findToggleActiveBtn().attributes('aria-label')).toBe('');
+ });
+
+ describe(`When clicking on the ${icon} button`, () => {
+ beforeEach(async () => {
+ await findToggleActiveBtn().vm.$emit('click');
+ await waitForPromises();
+ });
+
+ it(`The apollo mutation to set active to ${newActiveValue} is called`, () => {
+ expect(mutate).toHaveBeenCalledTimes(1);
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: runnerUpdateMutation,
+ variables: {
+ input: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ active: newActiveValue,
+ },
+ },
+ });
+ });
+
+ it('The button does not have a loading state', () => {
+ expect(findToggleActiveBtn().props('loading')).toBe(false);
+ });
+ });
+ });
+
+ describe('When the user clicks a runner', () => {
+ beforeEach(() => {
+ createComponent();
+
+ mutate.mockResolvedValue({
+ data: {
+ runnerDelete: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/1`,
+ __typename: 'CiRunner',
+ },
+ },
+ },
+ });
+
+ jest.spyOn(window, 'confirm');
+ });
+
+ describe('When the user confirms deletion', () => {
+ beforeEach(async () => {
+ window.confirm.mockReturnValue(true);
+ await findDeleteBtn().vm.$emit('click');
+ });
+
+ it('The user sees a confirmation alert', async () => {
+ expect(window.confirm).toHaveBeenCalledTimes(1);
+ expect(window.confirm).toHaveBeenCalledWith(expect.any(String));
+ });
+
+ it('The delete mutation is called correctly', () => {
+ expect(mutate).toHaveBeenCalledTimes(1);
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: deleteRunnerMutation,
+ variables: {
+ input: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ },
+ },
+ awaitRefetchQueries: true,
+ refetchQueries: [getRunnersQueryName],
+ });
+ });
+
+ it('The delete button does not have a loading state', () => {
+ expect(findDeleteBtn().props('loading')).toBe(false);
+ expect(findDeleteBtn().attributes('title')).toBe('Remove');
+ });
+
+ it('After the delete button is clicked, loading state is shown', async () => {
+ await findDeleteBtn().vm.$emit('click');
+
+ expect(findDeleteBtn().props('loading')).toBe(true);
+ });
+
+ it('After the delete button is clicked, stale tooltip is removed', async () => {
+ await findDeleteBtn().vm.$emit('click');
+
+ expect(findDeleteBtn().attributes('title')).toBe('');
+ });
+ });
+
+ describe('When the user does not confirm deletion', () => {
+ beforeEach(async () => {
+ window.confirm.mockReturnValue(false);
+ await findDeleteBtn().vm.$emit('click');
+ });
+
+ it('The user sees a confirmation alert', () => {
+ expect(window.confirm).toHaveBeenCalledTimes(1);
+ });
+
+ it('The delete mutation is not called', () => {
+ expect(mutate).toHaveBeenCalledTimes(0);
+ });
+
+ it('The delete button does not have a loading state', () => {
+ expect(findDeleteBtn().props('loading')).toBe(false);
+ expect(findDeleteBtn().attributes('title')).toBe('Remove');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/cells/runner_name_cell_spec.js b/spec/frontend/runner/components/cells/runner_name_cell_spec.js
new file mode 100644
index 00000000000..26055fc0faf
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_name_cell_spec.js
@@ -0,0 +1,42 @@
+import { GlLink } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import RunnerNameCell from '~/runner/components/cells/runner_name_cell.vue';
+
+const mockId = '1';
+const mockShortSha = '2P6oDVDm';
+const mockDescription = 'runner-1';
+
+describe('RunnerTypeCell', () => {
+ let wrapper;
+
+ const findLink = () => wrapper.findComponent(GlLink);
+
+ const createComponent = () => {
+ wrapper = mount(RunnerNameCell, {
+ propsData: {
+ runner: {
+ id: `gid://gitlab/Ci::Runner/${mockId}`,
+ shortSha: mockShortSha,
+ description: mockDescription,
+ },
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays the runner link with id and short token', () => {
+ expect(findLink().text()).toBe(`#${mockId} (${mockShortSha})`);
+ expect(findLink().attributes('href')).toBe(`/admin/runners/${mockId}`);
+ });
+
+ it('Displays the runner description', () => {
+ expect(wrapper.text()).toContain(mockDescription);
+ });
+});
diff --git a/spec/frontend/runner/components/cells/runner_type_cell_spec.js b/spec/frontend/runner/components/cells/runner_type_cell_spec.js
new file mode 100644
index 00000000000..48958a282fc
--- /dev/null
+++ b/spec/frontend/runner/components/cells/runner_type_cell_spec.js
@@ -0,0 +1,48 @@
+import { GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import RunnerTypeCell from '~/runner/components/cells/runner_type_cell.vue';
+import { INSTANCE_TYPE } from '~/runner/constants';
+
+describe('RunnerTypeCell', () => {
+ let wrapper;
+
+ const findBadges = () => wrapper.findAllComponents(GlBadge);
+
+ const createComponent = ({ runner = {} } = {}) => {
+ wrapper = mount(RunnerTypeCell, {
+ propsData: {
+ runner: {
+ runnerType: INSTANCE_TYPE,
+ active: true,
+ locked: false,
+ ...runner,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Displays the runner type', () => {
+ createComponent();
+
+ expect(findBadges()).toHaveLength(1);
+ expect(findBadges().at(0).text()).toBe('shared');
+ });
+
+ it('Displays locked and paused states', () => {
+ createComponent({
+ runner: {
+ active: false,
+ locked: true,
+ },
+ });
+
+ expect(findBadges()).toHaveLength(3);
+ expect(findBadges().at(0).text()).toBe('shared');
+ expect(findBadges().at(1).text()).toBe('locked');
+ expect(findBadges().at(2).text()).toBe('paused');
+ });
+});