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')
-rw-r--r--spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js82
-rw-r--r--spec/frontend/ci/runner/components/runner_form_fields_spec.js10
-rw-r--r--spec/frontend/ci/runner/components/runner_list_empty_state_spec.js197
3 files changed, 154 insertions, 135 deletions
diff --git a/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
index cc4a022c2df..89ce3a2e18c 100644
--- a/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
@@ -1,5 +1,6 @@
+import Vue from 'vue';
import { GlAlert, GlButton, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
@@ -53,9 +54,6 @@ jest.mock('~/lib/utils/url_utility', () => ({
redirectTo: jest.fn(),
}));
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
const defaultProvide = {
ciConfigPath: mockCiConfigPath,
defaultBranch: mockDefaultBranch,
@@ -74,24 +72,10 @@ describe('Pipeline editor app component', () => {
let mockLatestCommitShaQuery;
let mockPipelineQuery;
- const createComponent = ({
- blobLoading = false,
- options = {},
- provide = {},
- stubs = {},
- } = {}) => {
+ const createComponent = ({ options = {}, provide = {}, stubs = {} } = {}) => {
wrapper = shallowMount(PipelineEditorApp, {
provide: { ...defaultProvide, ...provide },
stubs,
- mocks: {
- $apollo: {
- queries: {
- initialCiFileContent: {
- loading: blobLoading,
- },
- },
- },
- },
...options,
});
};
@@ -101,6 +85,8 @@ describe('Pipeline editor app component', () => {
stubs = {},
withUndefinedBranch = false,
} = {}) => {
+ Vue.use(VueApollo);
+
const handlers = [
[getBlobContent, mockBlobContentData],
[getCiConfigData, mockCiConfigData],
@@ -137,7 +123,6 @@ describe('Pipeline editor app component', () => {
});
const options = {
- localVue,
mocks: {},
apolloProvider: mockApollo,
};
@@ -164,7 +149,7 @@ describe('Pipeline editor app component', () => {
describe('loading state', () => {
it('displays a loading icon if the blob query is loading', () => {
- createComponent({ blobLoading: true });
+ createComponentWithApollo();
expect(findLoadingIcon().exists()).toBe(true);
expect(findEditorHome().exists()).toBe(false);
@@ -246,10 +231,6 @@ describe('Pipeline editor app component', () => {
describe('when file exists', () => {
beforeEach(async () => {
await createComponentWithApollo();
-
- jest
- .spyOn(wrapper.vm.$apollo.queries.commitSha, 'startPolling')
- .mockImplementation(jest.fn());
});
it('shows pipeline editor home component', () => {
@@ -268,8 +249,8 @@ describe('Pipeline editor app component', () => {
});
});
- it('does not poll for the commit sha', () => {
- expect(wrapper.vm.$apollo.queries.commitSha.startPolling).toHaveBeenCalledTimes(0);
+ it('calls once and does not start poll for the commit sha', () => {
+ expect(mockLatestCommitShaQuery).toHaveBeenCalledTimes(1);
});
});
@@ -281,10 +262,6 @@ describe('Pipeline editor app component', () => {
PipelineEditorEmptyState,
},
});
-
- jest
- .spyOn(wrapper.vm.$apollo.queries.commitSha, 'startPolling')
- .mockImplementation(jest.fn());
});
it('shows an empty state and does not show editor home component', () => {
@@ -293,8 +270,8 @@ describe('Pipeline editor app component', () => {
expect(findEditorHome().exists()).toBe(false);
});
- it('does not poll for the commit sha', () => {
- expect(wrapper.vm.$apollo.queries.commitSha.startPolling).toHaveBeenCalledTimes(0);
+ it('calls once and does not start poll for the commit sha', () => {
+ expect(mockLatestCommitShaQuery).toHaveBeenCalledTimes(1);
});
describe('because of a fetching error', () => {
@@ -381,38 +358,27 @@ describe('Pipeline editor app component', () => {
});
it('polls for commit sha while pipeline data is not yet available for current branch', async () => {
- jest
- .spyOn(wrapper.vm.$apollo.queries.commitSha, 'startPolling')
- .mockImplementation(jest.fn());
-
- // simulate a commit to the current branch
findEditorHome().vm.$emit('updateCommitSha');
await waitForPromises();
- expect(wrapper.vm.$apollo.queries.commitSha.startPolling).toHaveBeenCalledTimes(1);
+ expect(mockLatestCommitShaQuery).toHaveBeenCalledTimes(2);
});
it('stops polling for commit sha when pipeline data is available for newly committed branch', async () => {
- jest
- .spyOn(wrapper.vm.$apollo.queries.commitSha, 'stopPolling')
- .mockImplementation(jest.fn());
-
mockLatestCommitShaQuery.mockResolvedValue(mockCommitShaResults);
- await wrapper.vm.$apollo.queries.commitSha.refetch();
+ await waitForPromises();
+
+ await findEditorHome().vm.$emit('updateCommitSha');
- expect(wrapper.vm.$apollo.queries.commitSha.stopPolling).toHaveBeenCalledTimes(1);
+ expect(mockLatestCommitShaQuery).toHaveBeenCalledTimes(2);
});
it('stops polling for commit sha when pipeline data is available for current branch', async () => {
- jest
- .spyOn(wrapper.vm.$apollo.queries.commitSha, 'stopPolling')
- .mockImplementation(jest.fn());
-
mockLatestCommitShaQuery.mockResolvedValue(mockNewCommitShaResults);
findEditorHome().vm.$emit('updateCommitSha');
await waitForPromises();
- expect(wrapper.vm.$apollo.queries.commitSha.stopPolling).toHaveBeenCalledTimes(1);
+ expect(mockLatestCommitShaQuery).toHaveBeenCalledTimes(2);
});
});
@@ -497,15 +463,12 @@ describe('Pipeline editor app component', () => {
it('refetches blob content', async () => {
await createComponentWithApollo();
- jest
- .spyOn(wrapper.vm.$apollo.queries.initialCiFileContent, 'refetch')
- .mockImplementation(jest.fn());
- expect(wrapper.vm.$apollo.queries.initialCiFileContent.refetch).toHaveBeenCalledTimes(0);
+ expect(mockBlobContentData).toHaveBeenCalledTimes(1);
- await wrapper.vm.refetchContent();
+ findEditorHome().vm.$emit('refetchContent');
- expect(wrapper.vm.$apollo.queries.initialCiFileContent.refetch).toHaveBeenCalledTimes(1);
+ expect(mockBlobContentData).toHaveBeenCalledTimes(2);
});
it('hides start screen when refetch fetches CI file', async () => {
@@ -516,7 +479,8 @@ describe('Pipeline editor app component', () => {
expect(findEditorHome().exists()).toBe(false);
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
- await wrapper.vm.$apollo.queries.initialCiFileContent.refetch();
+ findEmptyState().vm.$emit('refetchContent');
+ await waitForPromises();
expect(findEmptyState().exists()).toBe(false);
expect(findEditorHome().exists()).toBe(true);
@@ -573,10 +537,6 @@ describe('Pipeline editor app component', () => {
mockGetTemplate.mockResolvedValue(mockCiTemplateQueryResponse);
await createComponentWithApollo();
-
- jest
- .spyOn(wrapper.vm.$apollo.queries.commitSha, 'startPolling')
- .mockImplementation(jest.fn());
});
it('skips empty state and shows editor home component', () => {
diff --git a/spec/frontend/ci/runner/components/runner_form_fields_spec.js b/spec/frontend/ci/runner/components/runner_form_fields_spec.js
index 98f170d8f18..93be4d9d35e 100644
--- a/spec/frontend/ci/runner/components/runner_form_fields_spec.js
+++ b/spec/frontend/ci/runner/components/runner_form_fields_spec.js
@@ -21,6 +21,7 @@ describe('RunnerFormFields', () => {
const findInput = (name) => wrapper.find(`input[name="${name}"]`);
const expectRendersFields = () => {
+ expect(wrapper.text()).toContain(s__('Runners|Tags'));
expect(wrapper.text()).toContain(s__('Runners|Details'));
expect(wrapper.text()).toContain(s__('Runners|Configuration'));
@@ -42,10 +43,11 @@ describe('RunnerFormFields', () => {
});
it('renders a loading frame', () => {
+ expect(wrapper.text()).toContain(s__('Runners|Tags'));
expect(wrapper.text()).toContain(s__('Runners|Details'));
expect(wrapper.text()).toContain(s__('Runners|Configuration'));
- expect(wrapper.findAllComponents(GlSkeletonLoader)).toHaveLength(2);
+ expect(wrapper.findAllComponents(GlSkeletonLoader)).toHaveLength(3);
expect(wrapper.findAll('input')).toHaveLength(0);
});
@@ -101,23 +103,23 @@ describe('RunnerFormFields', () => {
it('checks checkbox fields', async () => {
createComponent({
value: {
+ runUntagged: false,
paused: false,
accessLevel: ACCESS_LEVEL_NOT_PROTECTED,
- runUntagged: false,
},
});
+ findInput('run-untagged').setChecked(true);
findInput('paused').setChecked(true);
findInput('protected').setChecked(true);
- findInput('run-untagged').setChecked(true);
await nextTick();
expect(wrapper.emitted('input').at(-1)).toEqual([
{
+ runUntagged: true,
paused: true,
accessLevel: ACCESS_LEVEL_REF_PROTECTED,
- runUntagged: true,
},
]);
});
diff --git a/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js b/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js
index 9d521b0b8ca..22797433b58 100644
--- a/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js
+++ b/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js
@@ -1,27 +1,46 @@
import EMPTY_STATE_SVG_URL from '@gitlab/svgs/dist/illustrations/empty-state/empty-pipeline-md.svg?url';
import FILTERED_SVG_URL from '@gitlab/svgs/dist/illustrations/empty-state/empty-search-md.svg?url';
import { GlEmptyState, GlLink, 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 RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue';
-
-import { mockRegistrationToken, newRunnerPath } from 'jest/ci/runner/mock_data';
+import {
+ I18N_GET_STARTED,
+ I18N_RUNNERS_ARE_AGENTS,
+ I18N_CREATE_RUNNER_LINK,
+ I18N_STILL_USING_REGISTRATION_TOKENS,
+ I18N_CONTACT_ADMIN_TO_REGISTER,
+ I18N_FOLLOW_REGISTRATION_INSTRUCTIONS,
+ I18N_NO_RESULTS,
+ I18N_EDIT_YOUR_SEARCH,
+} from '~/ci/runner/constants';
+
+import {
+ mockRegistrationToken,
+ newRunnerPath as mockNewRunnerPath,
+} from 'jest/ci/runner/mock_data';
import RunnerListEmptyState from '~/ci/runner/components/runner_list_empty_state.vue';
describe('RunnerListEmptyState', () => {
let wrapper;
+ let glFeatures;
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findLinks = () => wrapper.findAllComponents(GlLink);
const findLink = () => wrapper.findComponent(GlLink);
const findRunnerInstructionsModal = () => wrapper.findComponent(RunnerInstructionsModal);
- const createComponent = ({ props, mountFn = shallowMountExtended, ...options } = {}) => {
+ const expectTitleToBe = (title) => {
+ expect(findEmptyState().find('h1').text()).toBe(title);
+ };
+ const expectDescriptionToBe = (sentences) => {
+ expect(findEmptyState().find('p').text()).toMatchInterpolatedText(sentences.join(' '));
+ };
+
+ const createComponent = ({ props, mountFn = shallowMountExtended } = {}) => {
wrapper = mountFn(RunnerListEmptyState, {
propsData: {
- registrationToken: mockRegistrationToken,
- newRunnerPath,
...props,
},
directives: {
@@ -30,109 +49,146 @@ describe('RunnerListEmptyState', () => {
stubs: {
GlEmptyState,
GlSprintf,
- GlLink,
},
- ...options,
+ provide: { glFeatures },
});
};
- describe('when search is not filtered', () => {
- const title = s__('Runners|Get started with runners');
+ beforeEach(() => {
+ glFeatures = null;
+ });
- describe('when there is a registration token', () => {
+ describe('when search is not filtered', () => {
+ describe.each([
+ { createRunnerWorkflowForAdmin: true },
+ { createRunnerWorkflowForNamespace: true },
+ ])('when createRunnerWorkflow is enabled by %o', (currentGlFeatures) => {
beforeEach(() => {
- createComponent();
- });
-
- it('renders an illustration', () => {
- expect(findEmptyState().props('svgPath')).toBe(EMPTY_STATE_SVG_URL);
- });
-
- it('displays "no results" text with instructions', () => {
- const desc = s__(
- 'Runners|Runners are the agents that run your CI/CD jobs. Follow the %{linkStart}installation and registration instructions%{linkEnd} to set up a runner.',
- );
-
- expect(findEmptyState().text()).toMatchInterpolatedText(`${title} ${desc}`);
+ glFeatures = currentGlFeatures;
});
- describe.each([
- { createRunnerWorkflowForAdmin: true },
- { createRunnerWorkflowForNamespace: true },
- ])('when %o', (glFeatures) => {
- describe('when newRunnerPath is defined', () => {
+ describe.each`
+ newRunnerPath | registrationToken | expectedMessages
+ ${mockNewRunnerPath} | ${mockRegistrationToken} | ${[I18N_CREATE_RUNNER_LINK, I18N_STILL_USING_REGISTRATION_TOKENS]}
+ ${mockNewRunnerPath} | ${null} | ${[I18N_CREATE_RUNNER_LINK]}
+ ${null} | ${mockRegistrationToken} | ${[I18N_STILL_USING_REGISTRATION_TOKENS]}
+ ${null} | ${null} | ${[I18N_CONTACT_ADMIN_TO_REGISTER]}
+ `(
+ 'when newRunnerPath is $newRunnerPath and registrationToken is $registrationToken',
+ ({ newRunnerPath, registrationToken, expectedMessages }) => {
beforeEach(() => {
createComponent({
- provide: {
- glFeatures,
+ props: {
+ newRunnerPath,
+ registrationToken,
},
});
});
- it('shows a link to the new runner page', () => {
- expect(findLink().attributes('href')).toBe(newRunnerPath);
+ it('shows title', () => {
+ expectTitleToBe(I18N_GET_STARTED);
});
- });
- describe('when newRunnerPath not defined', () => {
- beforeEach(() => {
- createComponent({
- props: {
- newRunnerPath: null,
- },
- provide: {
- glFeatures,
- },
- });
+ it('renders an illustration', () => {
+ expect(findEmptyState().props('svgPath')).toBe(EMPTY_STATE_SVG_URL);
});
- it('opens a runner registration instructions modal with a link', () => {
- const { value } = getBinding(findLink().element, 'gl-modal');
+ it(`shows description: "${expectedMessages.join(' ')}"`, () => {
+ expectDescriptionToBe([I18N_RUNNERS_ARE_AGENTS, ...expectedMessages]);
+ });
+ },
+ );
- expect(findRunnerInstructionsModal().props('modalId')).toEqual(value);
+ describe('with newRunnerPath and registration token', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ registrationToken: mockRegistrationToken,
+ newRunnerPath: mockNewRunnerPath,
+ },
});
});
+
+ it('shows links to the new runner page and registration instructions', () => {
+ expect(findLinks().at(0).attributes('href')).toBe(mockNewRunnerPath);
+
+ const { value } = getBinding(findLinks().at(1).element, 'gl-modal');
+ expect(findRunnerInstructionsModal().props('modalId')).toEqual(value);
+ });
});
- describe.each([
- { createRunnerWorkflowForAdmin: false },
- { createRunnerWorkflowForNamespace: false },
- ])('when %o', (glFeatures) => {
+ describe('with newRunnerPath and no registration token', () => {
beforeEach(() => {
createComponent({
- provide: {
- glFeatures,
+ props: {
+ registrationToken: mockRegistrationToken,
+ newRunnerPath: null,
},
});
});
it('opens a runner registration instructions modal with a link', () => {
const { value } = getBinding(findLink().element, 'gl-modal');
-
expect(findRunnerInstructionsModal().props('modalId')).toEqual(value);
});
});
- });
- describe('when there is no registration token', () => {
- beforeEach(() => {
- createComponent({ props: { registrationToken: null } });
- });
+ describe('with no newRunnerPath nor registration token', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ registrationToken: null,
+ newRunnerPath: null,
+ },
+ });
+ });
- it('renders an illustration', () => {
- expect(findEmptyState().props('svgPath')).toBe(EMPTY_STATE_SVG_URL);
+ it('has no link', () => {
+ expect(findLink().exists()).toBe(false);
+ });
});
+ });
+
+ describe('when createRunnerWorkflow is disabled', () => {
+ describe('when there is a registration token', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ registrationToken: mockRegistrationToken,
+ },
+ });
+ });
+
+ it('renders an illustration', () => {
+ expect(findEmptyState().props('svgPath')).toBe(EMPTY_STATE_SVG_URL);
+ });
+
+ it('opens a runner registration instructions modal with a link', () => {
+ const { value } = getBinding(findLink().element, 'gl-modal');
+ expect(findRunnerInstructionsModal().props('modalId')).toEqual(value);
+ });
- it('displays "no results" text', () => {
- const desc = s__(
- 'Runners|Runners are the agents that run your CI/CD jobs. To register new runners, please contact your administrator.',
- );
+ it('displays text with registration instructions', () => {
+ expectTitleToBe(I18N_GET_STARTED);
- expect(findEmptyState().text()).toMatchInterpolatedText(`${title} ${desc}`);
+ expectDescriptionToBe([I18N_RUNNERS_ARE_AGENTS, I18N_FOLLOW_REGISTRATION_INSTRUCTIONS]);
+ });
});
- it('has no registration instructions link', () => {
- expect(findLink().exists()).toBe(false);
+ describe('when there is no registration token', () => {
+ beforeEach(() => {
+ createComponent({ props: { registrationToken: null } });
+ });
+
+ it('displays "contact admin" text', () => {
+ expectTitleToBe(I18N_GET_STARTED);
+
+ expectDescriptionToBe([I18N_RUNNERS_ARE_AGENTS, I18N_CONTACT_ADMIN_TO_REGISTER]);
+ });
+
+ it('has no registration instructions link', () => {
+ expect(findLink().exists()).toBe(false);
+ });
});
});
});
@@ -147,8 +203,9 @@ describe('RunnerListEmptyState', () => {
});
it('displays "no filtered results" text', () => {
- expect(findEmptyState().text()).toContain(s__('Runners|No results found'));
- expect(findEmptyState().text()).toContain(s__('Runners|Edit your search and try again'));
+ expectTitleToBe(I18N_NO_RESULTS);
+
+ expectDescriptionToBe([I18N_EDIT_YOUR_SEARCH]);
});
});
});