2022-07-23 23:45:48 +05:30
|
|
|
import { GlSkeletonLoader } from '@gitlab/ui';
|
2022-04-04 11:22:00 +05:30
|
|
|
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 RunnerJobs from '~/runner/components/runner_jobs.vue';
|
|
|
|
import RunnerJobsTable from '~/runner/components/runner_jobs_table.vue';
|
|
|
|
import RunnerPagination from '~/runner/components/runner_pagination.vue';
|
|
|
|
import { captureException } from '~/runner/sentry_utils';
|
|
|
|
import { I18N_NO_JOBS_FOUND, RUNNER_DETAILS_JOBS_PAGE_SIZE } from '~/runner/constants';
|
|
|
|
|
2022-07-16 23:28:13 +05:30
|
|
|
import runnerJobsQuery from '~/runner/graphql/show/runner_jobs.query.graphql';
|
2022-04-04 11:22:00 +05:30
|
|
|
|
|
|
|
import { runnerData, runnerJobsData } from '../mock_data';
|
|
|
|
|
|
|
|
jest.mock('~/flash');
|
|
|
|
jest.mock('~/runner/sentry_utils');
|
|
|
|
|
|
|
|
const mockRunner = runnerData.data.runner;
|
|
|
|
const mockRunnerWithJobs = runnerJobsData.data.runner;
|
|
|
|
const mockJobs = mockRunnerWithJobs.jobs.nodes;
|
|
|
|
|
|
|
|
Vue.use(VueApollo);
|
|
|
|
|
|
|
|
describe('RunnerJobs', () => {
|
|
|
|
let wrapper;
|
|
|
|
let mockRunnerJobsQuery;
|
|
|
|
|
2022-07-23 23:45:48 +05:30
|
|
|
const findGlSkeletonLoading = () => wrapper.findComponent(GlSkeletonLoader);
|
2022-04-04 11:22:00 +05:30
|
|
|
const findRunnerJobsTable = () => wrapper.findComponent(RunnerJobsTable);
|
|
|
|
const findRunnerPagination = () => wrapper.findComponent(RunnerPagination);
|
|
|
|
|
|
|
|
const createComponent = ({ mountFn = shallowMountExtended } = {}) => {
|
|
|
|
wrapper = mountFn(RunnerJobs, {
|
2022-05-07 20:08:51 +05:30
|
|
|
apolloProvider: createMockApollo([[runnerJobsQuery, mockRunnerJobsQuery]]),
|
2022-04-04 11:22:00 +05:30
|
|
|
propsData: {
|
|
|
|
runner: mockRunner,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
mockRunnerJobsQuery = jest.fn();
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
mockRunnerJobsQuery.mockReset();
|
|
|
|
wrapper.destroy();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Requests runner jobs', async () => {
|
|
|
|
createComponent();
|
|
|
|
|
|
|
|
await waitForPromises();
|
|
|
|
|
|
|
|
expect(mockRunnerJobsQuery).toHaveBeenCalledTimes(1);
|
|
|
|
expect(mockRunnerJobsQuery).toHaveBeenCalledWith({
|
|
|
|
id: mockRunner.id,
|
|
|
|
first: RUNNER_DETAILS_JOBS_PAGE_SIZE,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('When there are jobs assigned', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
mockRunnerJobsQuery.mockResolvedValueOnce(runnerJobsData);
|
|
|
|
|
|
|
|
createComponent();
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Shows jobs', () => {
|
|
|
|
const jobs = findRunnerJobsTable().props('jobs');
|
|
|
|
|
|
|
|
expect(jobs).toHaveLength(mockJobs.length);
|
|
|
|
expect(jobs[0]).toMatchObject(mockJobs[0]);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('When "Next" page is clicked', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
findRunnerPagination().vm.$emit('input', { page: 2, after: 'AFTER_CURSOR' });
|
|
|
|
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('A new page is requested', () => {
|
|
|
|
expect(mockRunnerJobsQuery).toHaveBeenCalledTimes(2);
|
|
|
|
expect(mockRunnerJobsQuery).toHaveBeenLastCalledWith({
|
|
|
|
id: mockRunner.id,
|
|
|
|
first: RUNNER_DETAILS_JOBS_PAGE_SIZE,
|
|
|
|
after: 'AFTER_CURSOR',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('When loading', () => {
|
|
|
|
it('shows loading indicator and no other content', () => {
|
|
|
|
createComponent();
|
|
|
|
|
|
|
|
expect(findGlSkeletonLoading().exists()).toBe(true);
|
|
|
|
expect(findRunnerJobsTable().exists()).toBe(false);
|
|
|
|
expect(findRunnerPagination().attributes('disabled')).toBe('true');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('When there are no jobs', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
mockRunnerJobsQuery.mockResolvedValueOnce({
|
|
|
|
data: {
|
|
|
|
runner: {
|
|
|
|
id: mockRunner.id,
|
|
|
|
projectCount: 0,
|
|
|
|
jobs: {
|
|
|
|
nodes: [],
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: false,
|
|
|
|
hasPreviousPage: false,
|
|
|
|
startCursor: '',
|
|
|
|
endCursor: '',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
createComponent();
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Shows a "None" label', () => {
|
|
|
|
expect(wrapper.text()).toBe(I18N_NO_JOBS_FOUND);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('When an error occurs', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
mockRunnerJobsQuery.mockRejectedValue(new Error('Error!'));
|
|
|
|
|
|
|
|
createComponent();
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('shows an error', () => {
|
|
|
|
expect(createAlert).toHaveBeenCalled();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('reports an error', () => {
|
|
|
|
expect(captureException).toHaveBeenCalledWith({
|
|
|
|
component: 'RunnerJobs',
|
|
|
|
error: expect.any(Error),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|