Skip to content
Snippets Groups Projects
Commit 1ea310b5 authored by Scott Hampton's avatar Scott Hampton
Browse files

Link test report file name to file

The file name in the test report is now a link to
the actual file in the commit.
parent 1206515e
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -5,6 +5,7 @@ import {
GlTooltipDirective,
GlFriendlyWrap,
GlIcon,
GlLink,
GlButton,
GlPagination,
} from '@gitlab/ui';
Loading
Loading
@@ -16,6 +17,7 @@ export default {
components: {
GlIcon,
GlFriendlyWrap,
GlLink,
GlButton,
GlPagination,
TestCaseDetails,
Loading
Loading
@@ -97,11 +99,9 @@ export default {
<div class="table-section section-10 section-wrap">
<div role="rowheader" class="table-mobile-header">{{ __('Filename') }}</div>
<div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break">
<gl-friendly-wrap
v-if="testCase.file"
:symbols="$options.wrapSymbols"
:text="testCase.file"
/>
<gl-link v-if="testCase.file" :href="testCase.filePath" target="_blank">
<gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.file" />
</gl-link>
<gl-button
v-if="testCase.file"
v-gl-tooltip
Loading
Loading
Loading
Loading
@@ -58,8 +58,9 @@ const createLegacyPipelinesDetailApp = (mediator) => {
 
const createTestDetails = () => {
const el = document.querySelector(SELECTORS.PIPELINE_TESTS);
const { summaryEndpoint, suiteEndpoint } = el?.dataset || {};
const { blobPath, summaryEndpoint, suiteEndpoint } = el?.dataset || {};
const testReportsStore = createTestReportsStore({
blobPath,
summaryEndpoint,
suiteEndpoint,
});
Loading
Loading
Loading
Loading
@@ -17,7 +17,19 @@ export const getSuiteTests = (state) => {
const { page, perPage } = state.pageInfo;
const start = (page - 1) * perPage;
 
return testCases.map(addIconStatus).slice(start, start + perPage);
return testCases
.map((testCase) => ({
...testCase,
/**
* filePath is the file string appended onto the blob path.
* We need to make sure the file string doesn't start with `./` when appending.
* Even though we could leave the `/` at the beginning, we can't guarantee that the
* file string will have `/` at the beginning so we should just remove it and add it manually
*/
filePath: testCase.file ? `${state.blobPath}/${testCase.file.replace(/^\.?\//, '')}` : null,
}))
.map(addIconStatus)
.slice(start, start + perPage);
};
 
export const getSuiteTestCount = (state) => getSelectedSuite(state)?.test_cases?.length || 0;
export default ({ summaryEndpoint = '', suiteEndpoint = '' }) => ({
export default ({ blobPath = '', summaryEndpoint = '', suiteEndpoint = '' }) => ({
blobPath,
summaryEndpoint,
suiteEndpoint,
testReports: {},
Loading
Loading
Loading
Loading
@@ -82,5 +82,6 @@
 
#js-tab-tests.tab-pane
#js-pipeline-tests-detail{ data: { summary_endpoint: summary_project_pipeline_tests_path(@project, @pipeline, format: :json),
suite_endpoint: project_pipeline_test_path(@project, @pipeline, suite_name: 'suite', format: :json) } }
suite_endpoint: project_pipeline_test_path(@project, @pipeline, suite_name: 'suite', format: :json),
blob_path: project_blob_path(@project, @pipeline.commit) } }
= render_if_exists "projects/pipelines/tabs_content", pipeline: @pipeline, project: @project
---
title: Add link to test case file in pipeline test report
merge_request:
author:
type: added
Loading
Loading
@@ -8,6 +8,7 @@ describe('Getters TestReports Store', () => {
const testReports = getJSONFixture('pipelines/test_report.json');
 
const defaultState = {
blobPath: '/test/blob/path',
testReports,
selectedSuiteIndex: 0,
pageInfo: {
Loading
Loading
@@ -17,6 +18,7 @@ describe('Getters TestReports Store', () => {
};
 
const emptyState = {
blobPath: '',
testReports: {},
selectedSuite: null,
pageInfo: {
Loading
Loading
@@ -74,6 +76,7 @@ describe('Getters TestReports Store', () => {
const expected = testReports.test_suites[0].test_cases
.map((x) => ({
...x,
filePath: `${state.blobPath}/${x.file.replace(/^\.?\//, '')}`,
formattedTime: formattedTime(x.execution_time),
icon: iconForTestStatus(x.status),
}))
Loading
Loading
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton, GlFriendlyWrap, GlPagination } from '@gitlab/ui';
import { GlButton, GlFriendlyWrap, GlLink, GlPagination } from '@gitlab/ui';
import { getJSONFixture } from 'helpers/fixtures';
import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
Loading
Loading
@@ -17,18 +17,22 @@ describe('Test reports suite table', () => {
const {
test_suites: [testSuite],
} = getJSONFixture('pipelines/test_report.json');
console.log(JSON.stringify(testSuite.test_cases));
 
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],
},
Loading
Loading
@@ -82,9 +86,16 @@ describe('Test reports suite table', () => {
 
it('renders the file name for the test with a copy button', () => {
const { file } = testCases[0];
// remove `./` from the beginning of the file path
const relativeFile = file.replace(/^\.?\//, '');
const filePath = `${blobPath}/${relativeFile}`;
const row = findCaseRowAtIndex(0);
const fileLink = findLinkForRow(row);
const button = row.find(GlButton);
 
console.log(fileLink.attributes('href'), file);
expect(fileLink.attributes('href')).toBe(filePath);
expect(row.text()).toContain(file);
expect(button.exists()).toBe(true);
expect(button.attributes('data-clipboard-text')).toBe(file);
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment