2020-05-24 23:13:21 +05:30
|
|
|
import MockAdapter from 'axios-mock-adapter';
|
|
|
|
import { mount } from '@vue/test-utils';
|
2020-11-24 15:15:51 +05:30
|
|
|
import {
|
|
|
|
GlLoadingIcon,
|
|
|
|
GlPagination,
|
|
|
|
GlDeprecatedSkeletonLoading as GlSkeletonLoading,
|
|
|
|
GlTable,
|
|
|
|
} from '@gitlab/ui';
|
2020-06-23 00:09:42 +05:30
|
|
|
import * as Sentry from '@sentry/browser';
|
2020-10-24 23:57:45 +05:30
|
|
|
import axios from '~/lib/utils/axios_utils';
|
|
|
|
import Clusters from '~/clusters_list/components/clusters.vue';
|
|
|
|
import ClusterStore from '~/clusters_list/store';
|
|
|
|
import { apiData } from '../mock_data';
|
2020-04-08 14:13:33 +05:30
|
|
|
|
|
|
|
describe('Clusters', () => {
|
2020-05-24 23:13:21 +05:30
|
|
|
let mock;
|
|
|
|
let store;
|
2020-04-08 14:13:33 +05:30
|
|
|
let wrapper;
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
const endpoint = 'some/endpoint';
|
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
const entryData = {
|
|
|
|
endpoint,
|
|
|
|
imgTagsAwsText: 'AWS Icon',
|
|
|
|
imgTagsDefaultText: 'Default Icon',
|
|
|
|
imgTagsGcpText: 'GCP Icon',
|
|
|
|
};
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
const findLoader = () => wrapper.find(GlLoadingIcon);
|
2020-05-24 23:13:21 +05:30
|
|
|
const findPaginatedButtons = () => wrapper.find(GlPagination);
|
|
|
|
const findTable = () => wrapper.find(GlTable);
|
2020-04-08 14:13:33 +05:30
|
|
|
const findStatuses = () => findTable().findAll('.js-status');
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
const mockPollingApi = (response, body, header) => {
|
|
|
|
mock.onGet(`${endpoint}?page=${header['x-page']}`).reply(response, body, header);
|
|
|
|
};
|
2020-04-08 14:13:33 +05:30
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
const mountWrapper = () => {
|
2020-06-23 00:09:42 +05:30
|
|
|
store = ClusterStore(entryData);
|
2020-05-24 23:13:21 +05:30
|
|
|
wrapper = mount(Clusters, { store });
|
|
|
|
return axios.waitForAll();
|
2020-04-08 14:13:33 +05:30
|
|
|
};
|
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
const paginationHeader = (total = apiData.clusters.length, perPage = 20, currentPage = 1) => {
|
|
|
|
return {
|
|
|
|
'x-total': total,
|
|
|
|
'x-per-page': perPage,
|
|
|
|
'x-page': currentPage,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
let captureException;
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
beforeEach(() => {
|
2020-06-23 00:09:42 +05:30
|
|
|
captureException = jest.spyOn(Sentry, 'captureException');
|
|
|
|
|
2020-05-24 23:13:21 +05:30
|
|
|
mock = new MockAdapter(axios);
|
2020-06-23 00:09:42 +05:30
|
|
|
mockPollingApi(200, apiData, paginationHeader());
|
2020-05-24 23:13:21 +05:30
|
|
|
|
|
|
|
return mountWrapper();
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
wrapper.destroy();
|
|
|
|
mock.restore();
|
2020-06-23 00:09:42 +05:30
|
|
|
captureException.mockRestore();
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('clusters table', () => {
|
2020-05-24 23:13:21 +05:30
|
|
|
describe('when data is loading', () => {
|
|
|
|
beforeEach(() => {
|
2020-07-28 23:09:34 +05:30
|
|
|
wrapper.vm.$store.state.loadingClusters = true;
|
2020-05-24 23:13:21 +05:30
|
|
|
return wrapper.vm.$nextTick();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a loader instead of the table while loading', () => {
|
|
|
|
expect(findLoader().exists()).toBe(true);
|
|
|
|
expect(findTable().exists()).toBe(false);
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
it('displays a table component', () => {
|
|
|
|
expect(findTable().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('renders the correct table headers', () => {
|
2020-05-24 23:13:21 +05:30
|
|
|
const tableHeaders = wrapper.vm.fields;
|
2020-04-08 14:13:33 +05:30
|
|
|
const headers = findTable().findAll('th');
|
|
|
|
|
|
|
|
expect(headers.length).toBe(tableHeaders.length);
|
|
|
|
|
|
|
|
tableHeaders.forEach((headerText, i) =>
|
|
|
|
expect(headers.at(i).text()).toEqual(headerText.label),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should stack on smaller devices', () => {
|
|
|
|
expect(findTable().classes()).toContain('b-table-stacked-md');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-06-23 00:09:42 +05:30
|
|
|
describe('cluster icon', () => {
|
|
|
|
it.each`
|
|
|
|
providerText | lineNumber
|
|
|
|
${'GCP Icon'} | ${0}
|
|
|
|
${'AWS Icon'} | ${1}
|
|
|
|
${'Default Icon'} | ${2}
|
|
|
|
${'Default Icon'} | ${3}
|
|
|
|
${'Default Icon'} | ${4}
|
|
|
|
${'Default Icon'} | ${5}
|
|
|
|
`('renders provider image and alt text for each cluster', ({ providerText, lineNumber }) => {
|
|
|
|
const images = findTable().findAll('.js-status img');
|
|
|
|
const image = images.at(lineNumber);
|
|
|
|
|
|
|
|
expect(image.attributes('alt')).toBe(providerText);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
describe('cluster status', () => {
|
|
|
|
it.each`
|
2020-06-23 00:09:42 +05:30
|
|
|
statusName | lineNumber | result
|
|
|
|
${'creating'} | ${0} | ${true}
|
|
|
|
${null} | ${1} | ${false}
|
|
|
|
${null} | ${2} | ${false}
|
|
|
|
${'deleting'} | ${3} | ${true}
|
|
|
|
${null} | ${4} | ${false}
|
|
|
|
${null} | ${5} | ${false}
|
|
|
|
`(
|
|
|
|
'renders $result when status=$statusName and lineNumber=$lineNumber',
|
|
|
|
({ lineNumber, result }) => {
|
|
|
|
const statuses = findStatuses();
|
|
|
|
const status = statuses.at(lineNumber);
|
|
|
|
expect(status.find(GlLoadingIcon).exists()).toBe(result);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('nodes present', () => {
|
2020-07-28 23:09:34 +05:30
|
|
|
describe('nodes while loading', () => {
|
|
|
|
it.each`
|
|
|
|
nodeSize | lineNumber
|
|
|
|
${null} | ${0}
|
|
|
|
${'1'} | ${1}
|
|
|
|
${'2'} | ${2}
|
|
|
|
${'1'} | ${3}
|
|
|
|
${'1'} | ${4}
|
|
|
|
${null} | ${5}
|
|
|
|
`('renders node size for each cluster', ({ nodeSize, lineNumber }) => {
|
|
|
|
const sizes = findTable().findAll('td:nth-child(3)');
|
|
|
|
const size = sizes.at(lineNumber);
|
|
|
|
|
|
|
|
if (nodeSize) {
|
|
|
|
expect(size.text()).toBe(nodeSize);
|
|
|
|
} else {
|
|
|
|
expect(size.find(GlSkeletonLoading).exists()).toBe(true);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('nodes finish loading', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
wrapper.vm.$store.state.loadingNodes = false;
|
|
|
|
return wrapper.vm.$nextTick();
|
|
|
|
});
|
|
|
|
|
|
|
|
it.each`
|
|
|
|
nodeSize | lineNumber
|
|
|
|
${'Unknown'} | ${0}
|
|
|
|
${'1'} | ${1}
|
|
|
|
${'2'} | ${2}
|
|
|
|
${'1'} | ${3}
|
|
|
|
${'1'} | ${4}
|
|
|
|
${'Unknown'} | ${5}
|
|
|
|
`('renders node size for each cluster', ({ nodeSize, lineNumber }) => {
|
|
|
|
const sizes = findTable().findAll('td:nth-child(3)');
|
|
|
|
const size = sizes.at(lineNumber);
|
|
|
|
|
|
|
|
expect(size.text()).toBe(nodeSize);
|
|
|
|
expect(size.find(GlSkeletonLoading).exists()).toBe(false);
|
|
|
|
});
|
2020-06-23 00:09:42 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('nodes with unknown quantity', () => {
|
|
|
|
it('notifies Sentry about all missing quantity types', () => {
|
|
|
|
expect(captureException).toHaveBeenCalledTimes(8);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('notifies Sentry about CPU missing quantity types', () => {
|
|
|
|
const missingCpuTypeError = new Error('UnknownK8sCpuQuantity:1missingCpuUnit');
|
|
|
|
|
|
|
|
expect(captureException).toHaveBeenCalledWith(missingCpuTypeError);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('notifies Sentry about Memory missing quantity types', () => {
|
|
|
|
const missingMemoryTypeError = new Error('UnknownK8sMemoryQuantity:1missingMemoryUnit');
|
|
|
|
|
|
|
|
expect(captureException).toHaveBeenCalledWith(missingMemoryTypeError);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('cluster CPU', () => {
|
|
|
|
it.each`
|
|
|
|
clusterCpu | lineNumber
|
|
|
|
${''} | ${0}
|
|
|
|
${'1.93 (87% free)'} | ${1}
|
|
|
|
${'3.87 (86% free)'} | ${2}
|
|
|
|
${'(% free)'} | ${3}
|
|
|
|
${'(% free)'} | ${4}
|
|
|
|
${''} | ${5}
|
|
|
|
`('renders total cpu for each cluster', ({ clusterCpu, lineNumber }) => {
|
|
|
|
const clusterCpus = findTable().findAll('td:nth-child(4)');
|
|
|
|
const cpuData = clusterCpus.at(lineNumber);
|
|
|
|
|
|
|
|
expect(cpuData.text()).toBe(clusterCpu);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('cluster Memory', () => {
|
|
|
|
it.each`
|
|
|
|
clusterMemory | lineNumber
|
|
|
|
${''} | ${0}
|
|
|
|
${'5.92 (78% free)'} | ${1}
|
|
|
|
${'12.86 (79% free)'} | ${2}
|
|
|
|
${'(% free)'} | ${3}
|
|
|
|
${'(% free)'} | ${4}
|
|
|
|
${''} | ${5}
|
|
|
|
`('renders total memory for each cluster', ({ clusterMemory, lineNumber }) => {
|
|
|
|
const clusterMemories = findTable().findAll('td:nth-child(5)');
|
|
|
|
const memoryData = clusterMemories.at(lineNumber);
|
|
|
|
|
|
|
|
expect(memoryData.text()).toBe(clusterMemory);
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|
|
|
|
});
|
2020-05-24 23:13:21 +05:30
|
|
|
|
|
|
|
describe('pagination', () => {
|
|
|
|
const perPage = apiData.clusters.length;
|
|
|
|
const totalFirstPage = 100;
|
|
|
|
const totalSecondPage = 500;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
2020-06-23 00:09:42 +05:30
|
|
|
mockPollingApi(200, apiData, paginationHeader(totalFirstPage, perPage, 1));
|
2020-05-24 23:13:21 +05:30
|
|
|
return mountWrapper();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should load to page 1 with header values', () => {
|
|
|
|
const buttons = findPaginatedButtons();
|
|
|
|
|
|
|
|
expect(buttons.props('perPage')).toBe(perPage);
|
|
|
|
expect(buttons.props('totalItems')).toBe(totalFirstPage);
|
|
|
|
expect(buttons.props('value')).toBe(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when updating currentPage', () => {
|
|
|
|
beforeEach(() => {
|
2020-06-23 00:09:42 +05:30
|
|
|
mockPollingApi(200, apiData, paginationHeader(totalSecondPage, perPage, 2));
|
2020-05-24 23:13:21 +05:30
|
|
|
wrapper.setData({ currentPage: 2 });
|
|
|
|
return axios.waitForAll();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should change pagination when currentPage changes', () => {
|
|
|
|
const buttons = findPaginatedButtons();
|
|
|
|
|
|
|
|
expect(buttons.props('perPage')).toBe(perPage);
|
|
|
|
expect(buttons.props('totalItems')).toBe(totalSecondPage);
|
|
|
|
expect(buttons.props('value')).toBe(2);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2020-04-08 14:13:33 +05:30
|
|
|
});
|