summaryrefslogtreecommitdiff
path: root/spec/frontend/pipelines/test_reports
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 10:34:06 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 10:34:06 +0000
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /spec/frontend/pipelines/test_reports
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
downloadgitlab-ce-859a6fb938bb9ee2a317c46dfa4fcc1af49608f0.tar.gz
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'spec/frontend/pipelines/test_reports')
-rw-r--r--spec/frontend/pipelines/test_reports/stores/actions_spec.js7
-rw-r--r--spec/frontend/pipelines/test_reports/stores/getters_spec.js73
-rw-r--r--spec/frontend/pipelines/test_reports/stores/utils_spec.js16
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js37
-rw-r--r--spec/frontend/pipelines/test_reports/test_reports_spec.js2
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js44
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_table_spec.js2
7 files changed, 168 insertions, 13 deletions
diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
index f7ff36c0a46..6258b08dfbb 100644
--- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js
@@ -2,10 +2,10 @@ import MockAdapter from 'axios-mock-adapter';
import { getJSONFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/pipelines/stores/test_reports/actions';
import * as types from '~/pipelines/stores/test_reports/mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash.js');
@@ -16,7 +16,7 @@ describe('Actions TestReports Store', () => {
const testReports = getJSONFixture('pipelines/test_report.json');
const summary = { total_count: 1 };
- const suiteEndpoint = `${TEST_HOST}/tests/:suite_name.json`;
+ const suiteEndpoint = `${TEST_HOST}/tests/suite.json`;
const summaryEndpoint = `${TEST_HOST}/test_reports/summary.json`;
const defaultState = {
suiteEndpoint,
@@ -69,9 +69,8 @@ describe('Actions TestReports Store', () => {
beforeEach(() => {
const buildIds = [1];
testReports.test_suites[0].build_ids = buildIds;
- const endpoint = suiteEndpoint.replace(':suite_name', testReports.test_suites[0].name);
mock
- .onGet(endpoint, { params: { build_ids: buildIds } })
+ .onGet(suiteEndpoint, { params: { build_ids: buildIds } })
.replyOnce(200, testReports.test_suites[0], {});
});
diff --git a/spec/frontend/pipelines/test_reports/stores/getters_spec.js b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
index 7382a6beefa..f8298fdaba5 100644
--- a/spec/frontend/pipelines/test_reports/stores/getters_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
@@ -1,6 +1,10 @@
import { getJSONFixture } from 'helpers/fixtures';
import * as getters from '~/pipelines/stores/test_reports/getters';
-import { iconForTestStatus, formattedTime } from '~/pipelines/stores/test_reports/utils';
+import {
+ iconForTestStatus,
+ formatFilePath,
+ formattedTime,
+} from '~/pipelines/stores/test_reports/utils';
describe('Getters TestReports Store', () => {
let state;
@@ -8,6 +12,7 @@ describe('Getters TestReports Store', () => {
const testReports = getJSONFixture('pipelines/test_report.json');
const defaultState = {
+ blobPath: '/test/blob/path',
testReports,
selectedSuiteIndex: 0,
pageInfo: {
@@ -17,6 +22,7 @@ describe('Getters TestReports Store', () => {
};
const emptyState = {
+ blobPath: '',
testReports: {},
selectedSuite: null,
pageInfo: {
@@ -74,6 +80,7 @@ describe('Getters TestReports Store', () => {
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),
}))
@@ -87,6 +94,70 @@ describe('Getters TestReports Store', () => {
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', () => {
diff --git a/spec/frontend/pipelines/test_reports/stores/utils_spec.js b/spec/frontend/pipelines/test_reports/stores/utils_spec.js
index 7e632d099fc..703fe69026c 100644
--- a/spec/frontend/pipelines/test_reports/stores/utils_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/utils_spec.js
@@ -1,6 +1,20 @@
-import { formattedTime } from '~/pipelines/stores/test_reports/utils';
+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', () => {
diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
index bfb8b43778d..e866586a2c3 100644
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -1,5 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
@@ -11,12 +11,17 @@ describe('Test case details', () => {
classname: 'spec.test_spec',
name: 'Test#something cool',
formattedTime: '10.04ms',
+ recent_failures: {
+ count: 2,
+ base_branch: 'master',
+ },
system_output: 'Line 42 is broken',
};
const findModal = () => wrapper.find(GlModal);
const findName = () => wrapper.find('[data-testid="test-case-name"]');
const findDuration = () => wrapper.find('[data-testid="test-case-duration"]');
+ const findRecentFailures = () => wrapper.find('[data-testid="test-case-recent-failures"]');
const findSystemOutput = () => wrapper.find('[data-testid="test-case-trace"]');
const createComponent = (testCase = {}) => {
@@ -56,6 +61,36 @@ describe('Test case details', () => {
});
});
+ 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 system output', () => {
it('renders the test case system output', () => {
createComponent();
diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js
index c8ab18b9086..da5763ddf8e 100644
--- a/spec/frontend/pipelines/test_reports/test_reports_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_reports_spec.js
@@ -1,6 +1,6 @@
-import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
import TestReports from '~/pipelines/components/test_reports/test_reports.vue';
import TestSummary from '~/pipelines/components/test_reports/test_summary.vue';
diff --git a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
index b8fd056610b..a87145cc557 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -1,10 +1,11 @@
-import Vuex from 'vuex';
+import { GlButton, GlFriendlyWrap, GlLink, GlPagination } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
-import { GlButton, GlFriendlyWrap, GlPagination } from '@gitlab/ui';
import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue';
-import * as getters from '~/pipelines/stores/test_reports/getters';
import { TestStatus } from '~/pipelines/constants';
+import * as getters from '~/pipelines/stores/test_reports/getters';
+import { formatFilePath } from '~/pipelines/stores/test_reports/utils';
import skippedTestCases from './mock_data';
const localVue = createLocalVue();
@@ -20,15 +21,18 @@ describe('Test reports suite table', () => {
testSuite.test_cases = [...testSuite.test_cases, ...skippedTestCases];
const testCases = testSuite.test_cases;
+ const blobPath = '/test/blob/path';
const noCasesMessage = () => wrapper.find('.js-no-test-cases');
const allCaseRows = () => wrapper.findAll('.js-case-row');
const findCaseRowAtIndex = (index) => wrapper.findAll('.js-case-row').at(index);
+ const findLinkForRow = (row) => row.find(GlLink);
const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
const createComponent = (suite = testSuite, perPage = 20) => {
store = new Vuex.Store({
state: {
+ blobPath,
testReports: {
test_suites: [suite],
},
@@ -64,7 +68,7 @@ describe('Test reports suite table', () => {
beforeEach(() => createComponent());
it('renders the correct number of rows', () => {
- expect(allCaseRows().length).toBe(testCases.length);
+ expect(allCaseRows()).toHaveLength(testCases.length);
});
it.each([
@@ -82,9 +86,13 @@ describe('Test reports suite table', () => {
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.find(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);
@@ -106,4 +114,32 @@ describe('Test reports suite table', () => {
expect(wrapper.find(GlPagination).exists()).toBe(true);
});
});
+
+ describe('when a test case classname property is null', () => {
+ it('still renders all test cases', () => {
+ createComponent({
+ ...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,
+ 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_table_spec.js b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
index b585536ae09..892a3742fea 100644
--- a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js
@@ -1,5 +1,5 @@
-import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { getJSONFixture } from 'helpers/fixtures';
import SummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';