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/pipelines/test_reports')
-rw-r--r--spec/frontend/pipelines/test_reports/empty_state_spec.js45
-rw-r--r--spec/frontend/pipelines/test_reports/mock_data.js31
-rw-r--r--spec/frontend/pipelines/test_reports/stores/actions_spec.js149
-rw-r--r--spec/frontend/pipelines/test_reports/stores/getters_spec.js171
-rw-r--r--spec/frontend/pipelines/test_reports/stores/mutations_spec.js114
-rw-r--r--spec/frontend/pipelines/test_reports/stores/utils_spec.js40
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js149
-rw-r--r--spec/frontend/pipelines/test_reports/test_reports_spec.js125
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js169
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_spec.js106
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_table_spec.js100
11 files changed, 0 insertions, 1199 deletions
diff --git a/spec/frontend/pipelines/test_reports/empty_state_spec.js b/spec/frontend/pipelines/test_reports/empty_state_spec.js
deleted file mode 100644
index ee0f8a90a11..00000000000
--- a/spec/frontend/pipelines/test_reports/empty_state_spec.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { GlEmptyState } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import EmptyState, { i18n } from '~/pipelines/components/test_reports/empty_state.vue';
-
-describe('Test report empty state', () => {
- let wrapper;
-
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
-
- const createComponent = ({ hasTestReport = true } = {}) => {
- wrapper = shallowMount(EmptyState, {
- provide: {
- emptyStateImagePath: '/image/path',
- hasTestReport,
- },
- stubs: {
- GlEmptyState,
- },
- });
- };
-
- describe('when pipeline has a test report', () => {
- it('should render empty test report message', () => {
- createComponent();
-
- expect(findEmptyState().props()).toMatchObject({
- primaryButtonText: i18n.noTestsButton,
- description: i18n.noTestsDescription,
- title: i18n.noTestsTitle,
- });
- });
- });
-
- describe('when pipeline does not have a test report', () => {
- it('should render no test report message', () => {
- createComponent({ hasTestReport: false });
-
- expect(findEmptyState().props()).toMatchObject({
- primaryButtonText: i18n.noReportsButton,
- description: i18n.noReportsDescription,
- title: i18n.noReportsTitle,
- });
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/mock_data.js b/spec/frontend/pipelines/test_reports/mock_data.js
deleted file mode 100644
index c3ca1429842..00000000000
--- a/spec/frontend/pipelines/test_reports/mock_data.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { TestStatus } from '~/pipelines/constants';
-
-export default [
- {
- classname: 'spec.test_spec',
- file: 'spec/trace_spec.rb',
- execution_time: 0,
- name: 'Test#skipped text',
- stack_trace: null,
- status: TestStatus.SKIPPED,
- system_output: null,
- },
- {
- classname: 'spec.test_spec',
- file: 'spec/trace_spec.rb',
- execution_time: 0,
- name: 'Test#error text',
- stack_trace: null,
- status: TestStatus.ERROR,
- system_output: null,
- },
- {
- classname: 'spec.test_spec',
- file: 'spec/trace_spec.rb',
- execution_time: 0,
- name: 'Test#unknown text',
- stack_trace: null,
- status: TestStatus.UNKNOWN,
- system_output: null,
- },
-];
diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
deleted file mode 100644
index e05d2151f0a..00000000000
--- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testReports from 'test_fixtures/pipelines/test_report.json';
-import { TEST_HOST } from 'helpers/test_constants';
-import testAction from 'helpers/vuex_action_helper';
-import { createAlert } from '~/alert';
-import axios from '~/lib/utils/axios_utils';
-import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
-import * as actions from '~/pipelines/stores/test_reports/actions';
-import * as types from '~/pipelines/stores/test_reports/mutation_types';
-
-jest.mock('~/alert');
-
-describe('Actions TestReports Store', () => {
- let mock;
- let state;
-
- const summary = { total_count: 1 };
-
- const suiteEndpoint = `${TEST_HOST}/tests/suite.json`;
- const summaryEndpoint = `${TEST_HOST}/test_reports/summary.json`;
- const defaultState = {
- suiteEndpoint,
- summaryEndpoint,
- testReports: {},
- selectedSuite: null,
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- state = { ...defaultState };
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('fetch report summary', () => {
- beforeEach(() => {
- mock.onGet(summaryEndpoint).replyOnce(HTTP_STATUS_OK, summary, {});
- });
-
- it('sets testReports and shows tests', () => {
- return testAction(
- actions.fetchSummary,
- null,
- state,
- [{ type: types.SET_SUMMARY, payload: summary }],
- [{ type: 'toggleLoading' }, { type: 'toggleLoading' }],
- );
- });
-
- it('should create alert on API error', async () => {
- await testAction(
- actions.fetchSummary,
- null,
- { summaryEndpoint: null },
- [],
- [{ type: 'toggleLoading' }, { type: 'toggleLoading' }],
- );
- expect(createAlert).toHaveBeenCalled();
- });
- });
-
- describe('fetch test suite', () => {
- beforeEach(() => {
- const buildIds = [1];
- testReports.test_suites[0].build_ids = buildIds;
- mock
- .onGet(suiteEndpoint, { params: { build_ids: buildIds } })
- .replyOnce(HTTP_STATUS_OK, testReports.test_suites[0], {});
- });
-
- it('sets test suite and shows tests', () => {
- const suite = testReports.test_suites[0];
- const index = 0;
-
- return testAction(
- actions.fetchTestSuite,
- index,
- { ...state, testReports },
- [{ type: types.SET_SUITE, payload: { suite, index } }],
- [{ type: 'toggleLoading' }, { type: 'toggleLoading' }],
- );
- });
-
- it('should call SET_SUITE_ERROR on error', () => {
- const index = 0;
-
- return testAction(
- actions.fetchTestSuite,
- index,
- { ...state, testReports, suiteEndpoint: null },
- [{ type: types.SET_SUITE_ERROR, payload: expect.any(Error) }],
- [{ type: 'toggleLoading' }, { type: 'toggleLoading' }],
- );
- });
-
- describe('when we already have the suite data', () => {
- it('should not fetch suite', () => {
- const index = 0;
- testReports.test_suites[0].hasFullSuite = true;
-
- return testAction(actions.fetchTestSuite, index, { ...state, testReports }, [], []);
- });
- });
- });
-
- describe('set selected suite index', () => {
- it('sets selectedSuiteIndex', () => {
- const selectedSuiteIndex = 0;
-
- return testAction(
- actions.setSelectedSuiteIndex,
- selectedSuiteIndex,
- { ...state, hasFullReport: true },
- [{ type: types.SET_SELECTED_SUITE_INDEX, payload: selectedSuiteIndex }],
- [],
- );
- });
- });
-
- describe('remove selected suite index', () => {
- it('sets selectedSuiteIndex to null', () => {
- return testAction(
- actions.removeSelectedSuiteIndex,
- {},
- state,
- [{ type: types.SET_SELECTED_SUITE_INDEX, payload: null }],
- [],
- );
- });
- });
-
- describe('toggles loading', () => {
- it('sets isLoading to true', () => {
- return testAction(actions.toggleLoading, {}, state, [{ type: types.TOGGLE_LOADING }], []);
- });
-
- it('toggles isLoading to false', () => {
- return testAction(
- actions.toggleLoading,
- {},
- { ...state, isLoading: true },
- [{ type: types.TOGGLE_LOADING }],
- [],
- );
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/stores/getters_spec.js b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
deleted file mode 100644
index 70e3a01dbf1..00000000000
--- a/spec/frontend/pipelines/test_reports/stores/getters_spec.js
+++ /dev/null
@@ -1,171 +0,0 @@
-import testReports from 'test_fixtures/pipelines/test_report.json';
-import * as getters from '~/pipelines/stores/test_reports/getters';
-import {
- iconForTestStatus,
- formatFilePath,
- formattedTime,
-} from '~/pipelines/stores/test_reports/utils';
-
-describe('Getters TestReports Store', () => {
- let state;
-
- const defaultState = {
- blobPath: '/test/blob/path',
- testReports,
- selectedSuiteIndex: 0,
- pageInfo: {
- page: 1,
- perPage: 2,
- },
- };
-
- const emptyState = {
- blobPath: '',
- testReports: {},
- selectedSuite: null,
- pageInfo: {
- page: 1,
- perPage: 2,
- },
- };
-
- beforeEach(() => {
- state = {
- testReports,
- };
- });
-
- const setupState = (testState = defaultState) => {
- state = testState;
- };
-
- describe('getTestSuites', () => {
- it('should return the test suites', () => {
- setupState();
-
- const suites = getters.getTestSuites(state);
- const expected = testReports.test_suites.map((x) => ({
- ...x,
- formattedTime: formattedTime(x.total_time),
- }));
-
- expect(suites).toEqual(expected);
- });
-
- it('should return an empty array when testReports is empty', () => {
- setupState(emptyState);
-
- expect(getters.getTestSuites(state)).toEqual([]);
- });
- });
-
- describe('getSelectedSuite', () => {
- it('should return the selected suite', () => {
- setupState();
-
- const selectedSuite = getters.getSelectedSuite(state);
- const expected = testReports.test_suites[state.selectedSuiteIndex];
-
- expect(selectedSuite).toEqual(expected);
- });
- });
-
- describe('getSuiteTests', () => {
- it('should return the current page of test cases inside the suite', () => {
- setupState();
-
- const cases = getters.getSuiteTests(state);
- const expected = testReports.test_suites[0].test_cases
- .map((x) => ({
- ...x,
- filePath: `${state.blobPath}/${formatFilePath(x.file)}`,
- formattedTime: formattedTime(x.execution_time),
- icon: iconForTestStatus(x.status),
- }))
- .slice(0, state.pageInfo.perPage);
-
- expect(cases).toEqual(expected);
- });
-
- it('should return an empty array when testReports is empty', () => {
- setupState(emptyState);
-
- expect(getters.getSuiteTests(state)).toEqual([]);
- });
-
- describe('when a test case classname property is null', () => {
- it('should return an empty string value for the classname property', () => {
- const testCases = testReports.test_suites[0].test_cases;
- setupState({
- ...defaultState,
- testReports: {
- ...testReports,
- test_suites: [
- {
- test_cases: testCases.map((testCase) => ({
- ...testCase,
- classname: null,
- })),
- },
- ],
- },
- });
-
- const expected = testCases
- .map((x) => ({
- ...x,
- classname: '',
- filePath: `${state.blobPath}/${formatFilePath(x.file)}`,
- formattedTime: formattedTime(x.execution_time),
- icon: iconForTestStatus(x.status),
- }))
- .slice(0, state.pageInfo.perPage);
-
- expect(getters.getSuiteTests(state)).toEqual(expected);
- });
- });
-
- describe('when a test case name property is null', () => {
- it('should return an empty string value for the name property', () => {
- const testCases = testReports.test_suites[0].test_cases;
- setupState({
- ...defaultState,
- testReports: {
- ...testReports,
- test_suites: [
- {
- test_cases: testCases.map((testCase) => ({
- ...testCase,
- name: null,
- })),
- },
- ],
- },
- });
-
- const expected = testCases
- .map((x) => ({
- ...x,
- name: '',
- filePath: `${state.blobPath}/${formatFilePath(x.file)}`,
- formattedTime: formattedTime(x.execution_time),
- icon: iconForTestStatus(x.status),
- }))
- .slice(0, state.pageInfo.perPage);
-
- expect(getters.getSuiteTests(state)).toEqual(expected);
- });
- });
- });
-
- describe('getSuiteTestCount', () => {
- it('should return the total number of test cases', () => {
- setupState();
-
- const testCount = getters.getSuiteTestCount(state);
- const expected = testReports.test_suites[0].test_cases.length;
-
- expect(testCount).toEqual(expected);
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js b/spec/frontend/pipelines/test_reports/stores/mutations_spec.js
deleted file mode 100644
index 685ac6ea3e5..00000000000
--- a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import testReports from 'test_fixtures/pipelines/test_report.json';
-import * as types from '~/pipelines/stores/test_reports/mutation_types';
-import mutations from '~/pipelines/stores/test_reports/mutations';
-import { createAlert } from '~/alert';
-
-jest.mock('~/alert');
-
-describe('Mutations TestReports Store', () => {
- let mockState;
-
- const defaultState = {
- endpoint: '',
- testReports: {},
- selectedSuite: null,
- isLoading: false,
- pageInfo: {
- page: 1,
- perPage: 2,
- },
- };
-
- beforeEach(() => {
- mockState = { ...defaultState };
- });
-
- describe('set page', () => {
- it('should set the current page to display', () => {
- const pageToDisplay = 3;
- mutations[types.SET_PAGE](mockState, pageToDisplay);
-
- expect(mockState.pageInfo.page).toEqual(pageToDisplay);
- });
- });
-
- describe('set suite', () => {
- it('should set the suite at the given index', () => {
- mockState.testReports = testReports;
- const suite = { name: 'test_suite' };
- const index = 0;
- const expectedState = { ...mockState };
- expectedState.testReports.test_suites[index] = { suite, hasFullSuite: true };
- mutations[types.SET_SUITE](mockState, { suite, index });
-
- expect(mockState.testReports.test_suites[index]).toEqual(
- expectedState.testReports.test_suites[index],
- );
- });
- });
-
- describe('set suite error', () => {
- it('should set the error message in state if provided', () => {
- const message = 'Test report artifacts not found';
-
- mutations[types.SET_SUITE_ERROR](mockState, {
- response: { data: { errors: message } },
- });
-
- expect(mockState.errorMessage).toBe(message);
- });
-
- it('should show an alert otherwise', () => {
- mutations[types.SET_SUITE_ERROR](mockState, {});
-
- expect(createAlert).toHaveBeenCalled();
- });
- });
-
- describe('set selected suite index', () => {
- it('should set selectedSuiteIndex', () => {
- const selectedSuiteIndex = 0;
- mutations[types.SET_SELECTED_SUITE_INDEX](mockState, selectedSuiteIndex);
-
- expect(mockState.selectedSuiteIndex).toEqual(selectedSuiteIndex);
- });
- });
-
- describe('set summary', () => {
- it('should set summary', () => {
- const summary = {
- total: { time: 0, count: 10, success: 1, failed: 2, skipped: 3, error: 4 },
- };
- const expectedSummary = {
- ...summary,
- total_time: 0,
- total_count: 10,
- success_count: 1,
- failed_count: 2,
- skipped_count: 3,
- error_count: 4,
- };
- mutations[types.SET_SUMMARY](mockState, summary);
-
- expect(mockState.testReports).toEqual(expectedSummary);
- });
- });
-
- describe('toggle loading', () => {
- it('should set to true', () => {
- const expectedState = { ...mockState, isLoading: true };
- mutations[types.TOGGLE_LOADING](mockState);
-
- expect(mockState.isLoading).toEqual(expectedState.isLoading);
- });
-
- it('should toggle back to false', () => {
- const expectedState = { ...mockState, isLoading: false };
- mockState.isLoading = true;
-
- mutations[types.TOGGLE_LOADING](mockState);
-
- expect(mockState.isLoading).toEqual(expectedState.isLoading);
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/stores/utils_spec.js b/spec/frontend/pipelines/test_reports/stores/utils_spec.js
deleted file mode 100644
index 703fe69026c..00000000000
--- a/spec/frontend/pipelines/test_reports/stores/utils_spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import { formatFilePath, formattedTime } from '~/pipelines/stores/test_reports/utils';
-
-describe('Test reports utils', () => {
- describe('formatFilePath', () => {
- it.each`
- file | expected
- ${'./test.js'} | ${'test.js'}
- ${'/test.js'} | ${'test.js'}
- ${'.//////////////test.js'} | ${'test.js'}
- ${'test.js'} | ${'test.js'}
- ${'mock/path./test.js'} | ${'mock/path./test.js'}
- ${'./mock/path./test.js'} | ${'mock/path./test.js'}
- `('should format $file to be $expected', ({ file, expected }) => {
- expect(formatFilePath(file)).toBe(expected);
- });
- });
-
- describe('formattedTime', () => {
- describe('when time is smaller than a second', () => {
- it('should return time in milliseconds fixed to 2 decimals', () => {
- const result = formattedTime(0.4815162342);
- expect(result).toBe('481.52ms');
- });
- });
-
- describe('when time is equal to a second', () => {
- it('should return time in seconds fixed to 2 decimals', () => {
- const result = formattedTime(1);
- expect(result).toBe('1.00s');
- });
- });
-
- describe('when time is greater than a second', () => {
- it('should return time in seconds fixed to 2 decimals', () => {
- const result = formattedTime(4.815162342);
- expect(result).toBe('4.82s');
- });
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
deleted file mode 100644
index f8663408817..00000000000
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import { GlModal, GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
-import CodeBlock from '~/vue_shared/components/code_block.vue';
-import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
-
-describe('Test case details', () => {
- let wrapper;
- const defaultTestCase = {
- classname: 'spec.test_spec',
- name: 'Test#something cool',
- file: '~/index.js',
- filePath: '/src/javascripts/index.js',
- formattedTime: '10.04ms',
- recent_failures: {
- count: 2,
- base_branch: 'main',
- },
- system_output: 'Line 42 is broken',
- };
-
- const findCopyFileBtn = () => wrapper.findComponent(ModalCopyButton);
- const findModal = () => wrapper.findComponent(GlModal);
- const findName = () => wrapper.findByTestId('test-case-name');
- const findFile = () => wrapper.findByTestId('test-case-file');
- const findFileLink = () => wrapper.findComponent(GlLink);
- const findDuration = () => wrapper.findByTestId('test-case-duration');
- const findRecentFailures = () => wrapper.findByTestId('test-case-recent-failures');
- const findAttachmentUrl = () => wrapper.findByTestId('test-case-attachment-url');
- const findSystemOutput = () => wrapper.findByTestId('test-case-trace');
-
- const createComponent = (testCase = {}) => {
- wrapper = extendedWrapper(
- shallowMount(TestCaseDetails, {
- propsData: {
- modalId: 'my-modal',
- testCase: {
- ...defaultTestCase,
- ...testCase,
- },
- },
- stubs: { CodeBlock, GlModal },
- }),
- );
- };
-
- describe('required details', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders the test case classname as modal title', () => {
- expect(findModal().props('title')).toBe(defaultTestCase.classname);
- });
-
- it('renders the test case name', () => {
- expect(findName().text()).toBe(defaultTestCase.name);
- });
-
- it('renders the test case file', () => {
- expect(findFile().text()).toBe(defaultTestCase.file);
- expect(findFileLink().attributes('href')).toBe(defaultTestCase.filePath);
- });
-
- it('renders copy button for test case file', () => {
- expect(findCopyFileBtn().attributes('text')).toBe(defaultTestCase.file);
- });
-
- it('renders the test case duration', () => {
- expect(findDuration().text()).toBe(defaultTestCase.formattedTime);
- });
- });
-
- describe('when test case has execution time instead of formatted time', () => {
- beforeEach(() => {
- createComponent({ ...defaultTestCase, formattedTime: null, execution_time: 17 });
- });
-
- it('renders the test case duration', () => {
- expect(findDuration().text()).toBe('17 s');
- });
- });
-
- describe('when test case has recent failures', () => {
- describe('has only 1 recent failure', () => {
- it('renders the recent failure', () => {
- createComponent({ recent_failures: { ...defaultTestCase.recent_failures, count: 1 } });
-
- expect(findRecentFailures().text()).toContain(
- `Failed 1 time in ${defaultTestCase.recent_failures.base_branch} in the last 14 days`,
- );
- });
- });
-
- describe('has more than 1 recent failure', () => {
- it('renders the recent failures', () => {
- createComponent();
-
- expect(findRecentFailures().text()).toContain(
- `Failed ${defaultTestCase.recent_failures.count} times in ${defaultTestCase.recent_failures.base_branch} in the last 14 days`,
- );
- });
- });
- });
-
- describe('when test case does not have recent failures', () => {
- it('does not render the recent failures', () => {
- createComponent({ recent_failures: null });
-
- expect(findRecentFailures().exists()).toBe(false);
- });
- });
-
- describe('when test case has attachment URL', () => {
- it('renders the attachment URL as a link', () => {
- const expectedUrl = '/my/path.jpg';
- createComponent({ attachment_url: expectedUrl });
- const attachmentUrl = findAttachmentUrl();
-
- expect(attachmentUrl.exists()).toBe(true);
- expect(attachmentUrl.attributes('href')).toBe(expectedUrl);
- });
- });
-
- describe('when test case does not have attachment URL', () => {
- it('does not render the attachment URL', () => {
- createComponent({ attachment_url: null });
-
- expect(findAttachmentUrl().exists()).toBe(false);
- });
- });
-
- describe('when test case has system output', () => {
- it('renders the test case system output', () => {
- createComponent();
-
- expect(findSystemOutput().text()).toContain(defaultTestCase.system_output);
- });
- });
-
- describe('when test case does not have system output', () => {
- it('does not render the test case system output', () => {
- createComponent({ system_output: null });
-
- expect(findSystemOutput().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js
deleted file mode 100644
index de16f496eff..00000000000
--- a/spec/frontend/pipelines/test_reports/test_reports_spec.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
-// eslint-disable-next-line no-restricted-imports
-import Vuex from 'vuex';
-import testReports from 'test_fixtures/pipelines/test_report.json';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import EmptyState from '~/pipelines/components/test_reports/empty_state.vue';
-import TestReports from '~/pipelines/components/test_reports/test_reports.vue';
-import TestSummary from '~/pipelines/components/test_reports/test_summary.vue';
-import TestSummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
-import * as getters from '~/pipelines/stores/test_reports/getters';
-
-Vue.use(Vuex);
-
-describe('Test reports app', () => {
- let wrapper;
- let store;
-
- const loadingSpinner = () => wrapper.findComponent(GlLoadingIcon);
- const testsDetail = () => wrapper.findByTestId('tests-detail');
- const emptyState = () => wrapper.findComponent(EmptyState);
- const testSummary = () => wrapper.findComponent(TestSummary);
- const testSummaryTable = () => wrapper.findComponent(TestSummaryTable);
-
- const actionSpies = {
- fetchTestSuite: jest.fn(),
- fetchSummary: jest.fn(),
- setSelectedSuiteIndex: jest.fn(),
- removeSelectedSuiteIndex: jest.fn(),
- };
-
- const createComponent = ({ state = {} } = {}) => {
- store = new Vuex.Store({
- modules: {
- testReports: {
- namespaced: true,
- state: {
- isLoading: false,
- selectedSuiteIndex: null,
- testReports,
- ...state,
- },
- actions: actionSpies,
- getters,
- },
- },
- });
-
- jest.spyOn(store, 'registerModule').mockReturnValue(null);
-
- wrapper = extendedWrapper(
- shallowMount(TestReports, {
- provide: {
- blobPath: '/blob/path',
- summaryEndpoint: '/summary.json',
- suiteEndpoint: '/suite.json',
- },
- store,
- }),
- );
- };
-
- describe('when component is created', () => {
- it('should call fetchSummary when pipeline has test report', () => {
- createComponent();
-
- expect(actionSpies.fetchSummary).toHaveBeenCalled();
- });
- });
-
- describe('when loading', () => {
- beforeEach(() => createComponent({ state: { isLoading: true } }));
-
- it('shows the loading spinner', () => {
- expect(emptyState().exists()).toBe(false);
- expect(testsDetail().exists()).toBe(false);
- expect(loadingSpinner().exists()).toBe(true);
- });
- });
-
- describe('when the api returns no data', () => {
- it('displays empty state component', () => {
- createComponent({ state: { testReports: {} } });
-
- expect(emptyState().exists()).toBe(true);
- });
- });
-
- describe('when the api returns data', () => {
- beforeEach(() => createComponent());
-
- it('sets testReports and shows tests', () => {
- expect(wrapper.vm.testReports).toEqual(expect.any(Object));
- expect(wrapper.vm.showTests).toBe(true);
- });
-
- it('shows tests details', () => {
- expect(testsDetail().exists()).toBe(true);
- });
- });
-
- describe('when a suite is clicked', () => {
- beforeEach(() => {
- createComponent({ state: { hasFullReport: true } });
- testSummaryTable().vm.$emit('row-click', 0);
- });
-
- it('should call setSelectedSuiteIndex and fetchTestSuite', () => {
- expect(actionSpies.setSelectedSuiteIndex).toHaveBeenCalled();
- expect(actionSpies.fetchTestSuite).toHaveBeenCalled();
- });
- });
-
- describe('when clicking back to summary', () => {
- beforeEach(() => {
- createComponent({ state: { selectedSuiteIndex: 0 } });
- testSummary().vm.$emit('on-back-click');
- });
-
- it('should call removeSelectedSuiteIndex', () => {
- expect(actionSpies.removeSelectedSuiteIndex).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
deleted file mode 100644
index 08b430fa703..00000000000
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import { GlButton, GlFriendlyWrap, GlLink, GlPagination, GlEmptyState } from '@gitlab/ui';
-import Vue from 'vue';
-// eslint-disable-next-line no-restricted-imports
-import Vuex from 'vuex';
-import testReports from 'test_fixtures/pipelines/test_report.json';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import SuiteTable, { i18n } from '~/pipelines/components/test_reports/test_suite_table.vue';
-import { TestStatus } from '~/pipelines/constants';
-import * as getters from '~/pipelines/stores/test_reports/getters';
-import { formatFilePath } from '~/pipelines/stores/test_reports/utils';
-import { ARTIFACTS_EXPIRED_ERROR_MESSAGE } from '~/pipelines/stores/test_reports/constants';
-import skippedTestCases from './mock_data';
-
-Vue.use(Vuex);
-
-describe('Test reports suite table', () => {
- let wrapper;
- let store;
-
- const {
- test_suites: [testSuite],
- } = testReports;
-
- testSuite.test_cases = [...testSuite.test_cases, ...skippedTestCases];
- const testCases = testSuite.test_cases;
- const blobPath = '/test/blob/path';
-
- const noCasesMessage = () => wrapper.findByTestId('no-test-cases');
- const artifactsExpiredMessage = () => wrapper.findByTestId('artifacts-expired');
- const artifactsExpiredEmptyState = () => wrapper.findComponent(GlEmptyState);
- const allCaseRows = () => wrapper.findAllByTestId('test-case-row');
- const findCaseRowAtIndex = (index) => wrapper.findAllByTestId('test-case-row').at(index);
- const findLinkForRow = (row) => row.findComponent(GlLink);
- const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
-
- const createComponent = ({ suite = testSuite, perPage = 20, errorMessage } = {}) => {
- store = new Vuex.Store({
- modules: {
- testReports: {
- namespaced: true,
- state: {
- blobPath,
- testReports: {
- test_suites: [suite],
- },
- selectedSuiteIndex: 0,
- pageInfo: {
- page: 1,
- perPage,
- },
- errorMessage,
- },
- getters,
- },
- },
- });
-
- wrapper = shallowMountExtended(SuiteTable, {
- provide: {
- blobPath: '/blob/path',
- summaryEndpoint: '/summary.json',
- suiteEndpoint: '/suite.json',
- },
- store,
- stubs: { GlFriendlyWrap },
- });
- };
-
- it('should render a message when there are no test cases', () => {
- createComponent({ suite: [] });
-
- expect(noCasesMessage().exists()).toBe(true);
- expect(artifactsExpiredMessage().exists()).toBe(false);
- });
-
- it('should render an empty state when artifacts have expired', () => {
- createComponent({ suite: [], errorMessage: ARTIFACTS_EXPIRED_ERROR_MESSAGE });
- const emptyState = artifactsExpiredEmptyState();
-
- expect(noCasesMessage().exists()).toBe(false);
- expect(artifactsExpiredMessage().exists()).toBe(true);
-
- expect(emptyState.exists()).toBe(true);
- expect(emptyState.props('title')).toBe(i18n.expiredArtifactsTitle);
- });
-
- describe('when a test suite is supplied', () => {
- beforeEach(() => createComponent());
-
- it('renders the correct number of rows', () => {
- expect(allCaseRows()).toHaveLength(testCases.length);
- });
-
- it.each([
- TestStatus.ERROR,
- TestStatus.FAILED,
- TestStatus.SKIPPED,
- TestStatus.SUCCESS,
- 'unknown',
- ])('renders the correct icon for test case with %s status', (status) => {
- const test = testCases.findIndex((x) => x.status === status);
- const row = findCaseRowAtIndex(test);
-
- expect(findIconForRow(row, status).exists()).toBe(true);
- });
-
- it('renders the file name for the test with a copy button', () => {
- const { file } = testCases[0];
- const relativeFile = formatFilePath(file);
- const filePath = `${blobPath}/${relativeFile}`;
- const row = findCaseRowAtIndex(0);
- const fileLink = findLinkForRow(row);
- const button = row.findComponent(GlButton);
-
- expect(fileLink.attributes('href')).toBe(filePath);
- expect(row.text()).toContain(file);
- expect(button.exists()).toBe(true);
- expect(button.attributes('data-clipboard-text')).toBe(file);
- });
- });
-
- describe('when a test suite has more test cases than the pagination size', () => {
- const perPage = 2;
-
- beforeEach(() => {
- createComponent({ testSuite, perPage });
- });
-
- it('renders one page of test cases', () => {
- expect(allCaseRows().length).toBe(perPage);
- });
-
- it('renders a pagination component', () => {
- expect(wrapper.findComponent(GlPagination).exists()).toBe(true);
- });
- });
-
- describe('when a test case classname property is null', () => {
- it('still renders all test cases', () => {
- createComponent({
- testSuite: {
- ...testSuite,
- test_cases: testSuite.test_cases.map((testCase) => ({
- ...testCase,
- classname: null,
- })),
- },
- });
-
- expect(allCaseRows()).toHaveLength(testCases.length);
- });
- });
-
- describe('when a test case name property is null', () => {
- it('still renders all test cases', () => {
- createComponent({
- testSuite: {
- ...testSuite,
- test_cases: testSuite.test_cases.map((testCase) => ({
- ...testCase,
- name: null,
- })),
- },
- });
-
- expect(allCaseRows()).toHaveLength(testCases.length);
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/test_summary_spec.js b/spec/frontend/pipelines/test_reports/test_summary_spec.js
deleted file mode 100644
index 7eed6671fb9..00000000000
--- a/spec/frontend/pipelines/test_reports/test_summary_spec.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import { mount } from '@vue/test-utils';
-import testReports from 'test_fixtures/pipelines/test_report.json';
-import Summary from '~/pipelines/components/test_reports/test_summary.vue';
-import { formattedTime } from '~/pipelines/stores/test_reports/utils';
-
-describe('Test reports summary', () => {
- let wrapper;
-
- const {
- test_suites: [testSuite],
- } = testReports;
-
- const backButton = () => wrapper.find('.js-back-button');
- const totalTests = () => wrapper.find('.js-total-tests');
- const failedTests = () => wrapper.find('.js-failed-tests');
- const erroredTests = () => wrapper.find('.js-errored-tests');
- const successRate = () => wrapper.find('.js-success-rate');
- const duration = () => wrapper.find('.js-duration');
-
- const defaultProps = {
- report: testSuite,
- showBack: false,
- };
-
- const createComponent = (props) => {
- wrapper = mount(Summary, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- };
-
- describe('should not render', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('a back button by default', () => {
- expect(backButton().exists()).toBe(false);
- });
- });
-
- describe('should render', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('a back button and emit on-back-click event', () => {
- createComponent({
- showBack: true,
- });
-
- expect(backButton().exists()).toBe(true);
- });
- });
-
- describe('when a report is supplied', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('displays the correct total', () => {
- expect(totalTests().text()).toBe('4 tests');
- });
-
- it('displays the correct failure count', () => {
- expect(failedTests().text()).toBe('2 failures');
- });
-
- it('displays the correct error count', () => {
- expect(erroredTests().text()).toBe('0 errors');
- });
-
- it('calculates and displays percentages correctly', () => {
- expect(successRate().text()).toBe('50% success rate');
- });
-
- it('displays the correctly formatted duration', () => {
- expect(duration().text()).toBe(formattedTime(testSuite.total_time));
- });
- });
-
- describe('success percentage calculation', () => {
- it.each`
- name | successCount | totalCount | skippedCount | result
- ${'displays 0 when there are no tests'} | ${0} | ${0} | ${0} | ${'0'}
- ${'displays whole number when possible'} | ${10} | ${50} | ${0} | ${'20'}
- ${'excludes skipped tests from total'} | ${10} | ${50} | ${5} | ${'22.22'}
- ${'rounds to 0.01'} | ${1} | ${16604} | ${0} | ${'0.01'}
- ${'correctly rounds to 50'} | ${8302} | ${16604} | ${0} | ${'50'}
- ${'rounds down for large close numbers'} | ${16603} | ${16604} | ${0} | ${'99.99'}
- ${'correctly displays 100'} | ${16604} | ${16604} | ${0} | ${'100'}
- `('$name', ({ successCount, totalCount, skippedCount, result }) => {
- createComponent({
- report: {
- success_count: successCount,
- skipped_count: skippedCount,
- total_count: totalCount,
- },
- });
-
- expect(successRate().text()).toBe(`${result}% success rate`);
- });
- });
-});
diff --git a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
deleted file mode 100644
index a45946d5a03..00000000000
--- a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import { mount } from '@vue/test-utils';
-import Vue from 'vue';
-// eslint-disable-next-line no-restricted-imports
-import Vuex from 'vuex';
-import testReports from 'test_fixtures/pipelines/test_report.json';
-import SummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
-import * as getters from '~/pipelines/stores/test_reports/getters';
-
-Vue.use(Vuex);
-
-describe('Test reports summary table', () => {
- let wrapper;
- let store;
-
- const allSuitesRows = () => wrapper.findAll('.js-suite-row');
- const noSuitesToShow = () => wrapper.find('.js-no-tests-suites');
-
- const defaultProps = {
- testReports,
- };
-
- const createComponent = (reports = null) => {
- store = new Vuex.Store({
- modules: {
- testReports: {
- namespaced: true,
- state: {
- testReports: reports || testReports,
- },
- getters,
- },
- },
- });
-
- wrapper = mount(SummaryTable, {
- provide: {
- blobPath: '/blob/path',
- summaryEndpoint: '/summary.json',
- suiteEndpoint: '/suite.json',
- },
- propsData: defaultProps,
- store,
- });
- };
-
- describe('when test reports are supplied', () => {
- beforeEach(() => createComponent());
- const findErrorIcon = () => wrapper.findComponent({ ref: 'suiteErrorIcon' });
-
- it('renders the correct number of rows', () => {
- expect(noSuitesToShow().exists()).toBe(false);
- expect(allSuitesRows().length).toBe(testReports.test_suites.length);
- });
-
- describe('when there is a suite error', () => {
- beforeEach(() => {
- createComponent({
- test_suites: [
- {
- ...testReports.test_suites[0],
- suite_error: 'Suite Error',
- },
- ],
- });
- });
-
- it('renders error icon', () => {
- expect(findErrorIcon().exists()).toBe(true);
- expect(findErrorIcon().attributes('title')).toEqual('Suite Error');
- });
- });
-
- describe('when there is not a suite error', () => {
- beforeEach(() => {
- createComponent({
- test_suites: [
- {
- ...testReports.test_suites[0],
- suite_error: null,
- },
- ],
- });
- });
-
- it('does not render error icon', () => {
- expect(findErrorIcon().exists()).toBe(false);
- });
- });
- });
-
- describe('when there are no test suites', () => {
- beforeEach(() => {
- createComponent({ test_suites: [] });
- });
-
- it('displays the no suites to show message', () => {
- expect(noSuitesToShow().exists()).toBe(true);
- });
- });
-});