165 lines
5 KiB
JavaScript
165 lines
5 KiB
JavaScript
import { GlLink, GlTable, GlSkeletonLoader } from '@gitlab/ui';
|
|
import { mount, shallowMount } from '@vue/test-utils';
|
|
import { cloneDeep } from 'lodash';
|
|
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
|
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
|
import RunnerList from '~/runner/components/runner_list.vue';
|
|
import { runnersData } from '../mock_data';
|
|
|
|
const mockRunners = runnersData.data.runners.nodes;
|
|
const mockActiveRunnersCount = mockRunners.length;
|
|
|
|
describe('RunnerList', () => {
|
|
let wrapper;
|
|
|
|
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
|
|
const findTable = () => wrapper.findComponent(GlTable);
|
|
const findHeaders = () => wrapper.findAll('th');
|
|
const findRows = () => wrapper.findAll('[data-testid^="runner-row-"]');
|
|
const findCell = ({ row = 0, fieldKey }) =>
|
|
extendedWrapper(findRows().at(row).find(`[data-testid="td-${fieldKey}"]`));
|
|
|
|
const createComponent = ({ props = {} } = {}, mountFn = shallowMount) => {
|
|
wrapper = extendedWrapper(
|
|
mountFn(RunnerList, {
|
|
propsData: {
|
|
runners: mockRunners,
|
|
activeRunnersCount: mockActiveRunnersCount,
|
|
...props,
|
|
},
|
|
}),
|
|
);
|
|
};
|
|
|
|
beforeEach(() => {
|
|
createComponent({}, mount);
|
|
});
|
|
|
|
afterEach(() => {
|
|
wrapper.destroy();
|
|
});
|
|
|
|
it('Displays headers', () => {
|
|
const headerLabels = findHeaders().wrappers.map((w) => w.text());
|
|
|
|
expect(headerLabels).toEqual([
|
|
'Type/State',
|
|
'Runner',
|
|
'Version',
|
|
'IP Address',
|
|
'Projects',
|
|
'Jobs',
|
|
'Tags',
|
|
'Last contact',
|
|
'', // actions has no label
|
|
]);
|
|
});
|
|
|
|
it('Displays a list of runners', () => {
|
|
expect(findRows()).toHaveLength(4);
|
|
|
|
expect(findSkeletonLoader().exists()).toBe(false);
|
|
});
|
|
|
|
it('Displays details of a runner', () => {
|
|
const { id, description, version, ipAddress, shortSha } = mockRunners[0];
|
|
|
|
// Badges
|
|
expect(findCell({ fieldKey: 'type' }).text()).toMatchInterpolatedText('specific paused');
|
|
|
|
// Runner identifier
|
|
expect(findCell({ fieldKey: 'name' }).text()).toContain(
|
|
`#${getIdFromGraphQLId(id)} (${shortSha})`,
|
|
);
|
|
expect(findCell({ fieldKey: 'name' }).text()).toContain(description);
|
|
|
|
// Other fields
|
|
expect(findCell({ fieldKey: 'version' }).text()).toBe(version);
|
|
expect(findCell({ fieldKey: 'ipAddress' }).text()).toBe(ipAddress);
|
|
expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('1');
|
|
expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('0');
|
|
expect(findCell({ fieldKey: 'tagList' }).text()).toBe('');
|
|
expect(findCell({ fieldKey: 'contactedAt' }).text()).toEqual(expect.any(String));
|
|
|
|
// Actions
|
|
const actions = findCell({ fieldKey: 'actions' });
|
|
|
|
expect(actions.findByTestId('edit-runner').exists()).toBe(true);
|
|
expect(actions.findByTestId('toggle-active-runner').exists()).toBe(true);
|
|
});
|
|
|
|
describe('Table data formatting', () => {
|
|
let mockRunnersCopy;
|
|
|
|
beforeEach(() => {
|
|
mockRunnersCopy = cloneDeep(mockRunners);
|
|
});
|
|
|
|
it('Formats null project counts', () => {
|
|
mockRunnersCopy[0].projectCount = null;
|
|
|
|
createComponent({ props: { runners: mockRunnersCopy } }, mount);
|
|
|
|
expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('n/a');
|
|
});
|
|
|
|
it('Formats 0 project counts', () => {
|
|
mockRunnersCopy[0].projectCount = 0;
|
|
|
|
createComponent({ props: { runners: mockRunnersCopy } }, mount);
|
|
|
|
expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('0');
|
|
});
|
|
|
|
it('Formats big project counts', () => {
|
|
mockRunnersCopy[0].projectCount = 1000;
|
|
|
|
createComponent({ props: { runners: mockRunnersCopy } }, mount);
|
|
|
|
expect(findCell({ fieldKey: 'projectCount' }).text()).toBe('1,000');
|
|
});
|
|
|
|
it('Formats job counts', () => {
|
|
mockRunnersCopy[0].jobCount = 1000;
|
|
|
|
createComponent({ props: { runners: mockRunnersCopy } }, mount);
|
|
|
|
expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000');
|
|
});
|
|
|
|
it('Formats big job counts with a plus symbol', () => {
|
|
mockRunnersCopy[0].jobCount = 1001;
|
|
|
|
createComponent({ props: { runners: mockRunnersCopy } }, mount);
|
|
|
|
expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000+');
|
|
});
|
|
});
|
|
|
|
it('Links to the runner page', () => {
|
|
const { id } = mockRunners[0];
|
|
|
|
expect(findCell({ fieldKey: 'name' }).find(GlLink).attributes('href')).toBe(
|
|
`/admin/runners/${getIdFromGraphQLId(id)}`,
|
|
);
|
|
});
|
|
|
|
describe('When data is loading', () => {
|
|
it('shows a busy state', () => {
|
|
createComponent({ props: { runners: [], loading: true } });
|
|
expect(findTable().attributes('busy')).toBeTruthy();
|
|
});
|
|
|
|
it('when there are no runners, shows an skeleton loader', () => {
|
|
createComponent({ props: { runners: [], loading: true } }, mount);
|
|
|
|
expect(findSkeletonLoader().exists()).toBe(true);
|
|
});
|
|
|
|
it('when there are runners, shows a busy indicator skeleton loader', () => {
|
|
createComponent({ props: { loading: true } }, mount);
|
|
|
|
expect(findSkeletonLoader().exists()).toBe(false);
|
|
});
|
|
});
|
|
});
|