diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
commit | 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch) | |
tree | d7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /spec/frontend/pipelines/test_reports | |
parent | 446d496a6d000c73a304be52587cd9bbc7493136 (diff) | |
download | gitlab-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')
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'; |