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/runner_projects_spec.js')
-rw-r--r--spec/frontend/runner/components/runner_projects_spec.js193
1 files changed, 193 insertions, 0 deletions
diff --git a/spec/frontend/runner/components/runner_projects_spec.js b/spec/frontend/runner/components/runner_projects_spec.js
new file mode 100644
index 00000000000..68a2130d6d9
--- /dev/null
+++ b/spec/frontend/runner/components/runner_projects_spec.js
@@ -0,0 +1,193 @@
+import { GlSkeletonLoading } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
+import { sprintf } from '~/locale';
+import {
+ I18N_ASSIGNED_PROJECTS,
+ I18N_NONE,
+ RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+} from '~/runner/constants';
+import RunnerProjects from '~/runner/components/runner_projects.vue';
+import RunnerAssignedItem from '~/runner/components/runner_assigned_item.vue';
+import RunnerPagination from '~/runner/components/runner_pagination.vue';
+import { captureException } from '~/runner/sentry_utils';
+
+import getRunnerProjectsQuery from '~/runner/graphql/get_runner_projects.query.graphql';
+
+import { runnerData, runnerProjectsData } from '../mock_data';
+
+jest.mock('~/flash');
+jest.mock('~/runner/sentry_utils');
+
+const mockRunner = runnerData.data.runner;
+const mockRunnerWithProjects = runnerProjectsData.data.runner;
+const mockProjects = mockRunnerWithProjects.projects.nodes;
+
+Vue.use(VueApollo);
+
+describe('RunnerProjects', () => {
+ let wrapper;
+ let mockRunnerProjectsQuery;
+
+ const findHeading = () => wrapper.find('h3');
+ const findGlSkeletonLoading = () => wrapper.findComponent(GlSkeletonLoading);
+ const findRunnerAssignedItems = () => wrapper.findAllComponents(RunnerAssignedItem);
+ const findRunnerPagination = () => wrapper.findComponent(RunnerPagination);
+
+ const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
+ wrapper = mountFn(RunnerProjects, {
+ apolloProvider: createMockApollo([[getRunnerProjectsQuery, mockRunnerProjectsQuery]]),
+ propsData: {
+ runner: mockRunner,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mockRunnerProjectsQuery = jest.fn();
+ });
+
+ afterEach(() => {
+ mockRunnerProjectsQuery.mockReset();
+ wrapper.destroy();
+ });
+
+ it('Requests runner projects', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(1);
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledWith({
+ id: mockRunner.id,
+ first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+ });
+ });
+
+ describe('When there are projects assigned', () => {
+ beforeEach(async () => {
+ mockRunnerProjectsQuery.mockResolvedValueOnce(runnerProjectsData);
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('Shows a heading', async () => {
+ const expected = sprintf(I18N_ASSIGNED_PROJECTS, { projectCount: mockProjects.length });
+
+ expect(findHeading().text()).toBe(expected);
+ });
+
+ it('Shows projects', () => {
+ expect(findRunnerAssignedItems().length).toBe(mockProjects.length);
+ });
+
+ it('Shows a project', () => {
+ const item = findRunnerAssignedItems().at(0);
+ const { webUrl, name, nameWithNamespace, avatarUrl } = mockProjects[0];
+
+ expect(item.props()).toMatchObject({
+ href: webUrl,
+ name,
+ fullName: nameWithNamespace,
+ avatarUrl,
+ });
+ });
+
+ describe('When "Next" page is clicked', () => {
+ beforeEach(async () => {
+ findRunnerPagination().vm.$emit('input', { page: 3, after: 'AFTER_CURSOR' });
+
+ await waitForPromises();
+ });
+
+ it('A new page is requested', () => {
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(2);
+ expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({
+ id: mockRunner.id,
+ first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+ after: 'AFTER_CURSOR',
+ });
+ });
+
+ it('When "Prev" page is clicked, the previous page is requested', async () => {
+ findRunnerPagination().vm.$emit('input', { page: 2, before: 'BEFORE_CURSOR' });
+
+ await waitForPromises();
+
+ expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(3);
+ expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({
+ id: mockRunner.id,
+ last: RUNNER_DETAILS_PROJECTS_PAGE_SIZE,
+ before: 'BEFORE_CURSOR',
+ });
+ });
+ });
+ });
+
+ describe('When loading', () => {
+ it('shows loading indicator and no other content', () => {
+ createComponent();
+
+ expect(findGlSkeletonLoading().exists()).toBe(true);
+
+ expect(wrapper.findByText(I18N_NONE).exists()).toBe(false);
+ expect(findRunnerAssignedItems().length).toBe(0);
+
+ expect(findRunnerPagination().attributes('disabled')).toBe('true');
+ });
+ });
+
+ describe('When there are no projects', () => {
+ beforeEach(async () => {
+ mockRunnerProjectsQuery.mockResolvedValueOnce({
+ data: {
+ runner: {
+ id: mockRunner.id,
+ projectCount: 0,
+ projects: {
+ nodes: [],
+ pageInfo: {
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+ },
+ },
+ },
+ },
+ });
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('Shows a "None" label', () => {
+ expect(wrapper.findByText(I18N_NONE).exists()).toBe(true);
+ });
+ });
+
+ describe('When an error occurs', () => {
+ beforeEach(async () => {
+ mockRunnerProjectsQuery.mockRejectedValue(new Error('Error!'));
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('shows an error', () => {
+ expect(createAlert).toHaveBeenCalled();
+ });
+
+ it('reports an error', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ component: 'RunnerProjects',
+ error: expect.any(Error),
+ });
+ });
+ });
+});