Commit 436f75a1 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '241534-test-report-modal' into 'master'

Move test case trace to modal

See merge request gitlab-org/gitlab!45575
parents 0aaab579 f24b5949
<script>
import { GlModal } from '@gitlab/ui';
import { __ } from '~/locale';
import CodeBlock from '~/vue_shared/components/code_block.vue';
export default {
name: 'TestCaseDetails',
components: {
CodeBlock,
GlModal,
},
props: {
modalId: {
type: String,
required: true,
},
testCase: {
type: Object,
required: true,
validator: ({ classname, formattedTime, name }) =>
Boolean(classname) && Boolean(formattedTime) && Boolean(name),
},
},
text: {
name: __('Name'),
duration: __('Execution time'),
trace: __('System output'),
},
modalCloseButton: {
text: __('Close'),
attributes: [{ variant: 'info' }],
},
};
</script>
<template>
<gl-modal
:modal-id="modalId"
:title="testCase.classname"
:action-primary="$options.modalCloseButton"
>
<div class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3">
<strong class="gl-text-right col-sm-3">{{ $options.text.name }}</strong>
<div class="col-sm-9" data-testid="test-case-name">
{{ testCase.name }}
</div>
</div>
<div class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3">
<strong class="gl-text-right col-sm-3">{{ $options.text.duration }}</strong>
<div class="col-sm-9" data-testid="test-case-duration">
{{ testCase.formattedTime }}
</div>
</div>
<div
v-if="testCase.system_output"
class="gl-display-flex gl-flex-wrap gl-mx-n4 gl-my-3"
data-testid="test-case-trace"
>
<strong class="gl-text-right col-sm-3">{{ $options.text.trace }}</strong>
<div class="col-sm-9">
<code-block :code="testCase.system_output" />
</div>
</div>
</gl-modal>
</template>
...@@ -61,7 +61,7 @@ export default { ...@@ -61,7 +61,7 @@ export default {
<div <div
v-else-if="!isLoading && showTests" v-else-if="!isLoading && showTests"
ref="container" ref="container"
class="tests-detail position-relative" class="position-relative"
data-testid="tests-detail" data-testid="tests-detail"
> >
<transition <transition
...@@ -69,13 +69,13 @@ export default { ...@@ -69,13 +69,13 @@ export default {
@before-enter="beforeEnterTransition" @before-enter="beforeEnterTransition"
@after-leave="afterLeaveTransition" @after-leave="afterLeaveTransition"
> >
<div v-if="showSuite" key="detail" class="w-100 position-absolute slide-enter-to-element"> <div v-if="showSuite" key="detail" class="w-100 slide-enter-to-element">
<test-summary :report="getSelectedSuite" show-back @on-back-click="summaryBackClick" /> <test-summary :report="getSelectedSuite" show-back @on-back-click="summaryBackClick" />
<test-suite-table /> <test-suite-table />
</div> </div>
<div v-else key="summary" class="w-100 position-absolute slide-enter-from-element"> <div v-else key="summary" class="w-100 slide-enter-from-element">
<test-summary :report="testReports" /> <test-summary :report="testReports" />
<test-summary-table @row-click="summaryTableRowClick" /> <test-summary-table @row-click="summaryTableRowClick" />
......
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import { GlTooltipDirective, GlFriendlyWrap, GlIcon, GlButton } from '@gitlab/ui'; import { GlModalDirective, GlTooltipDirective, GlFriendlyWrap, GlIcon, GlButton } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import TestCaseDetails from './test_case_details.vue';
export default { export default {
name: 'TestsSuiteTable', name: 'TestsSuiteTable',
...@@ -9,9 +10,11 @@ export default { ...@@ -9,9 +10,11 @@ export default {
GlIcon, GlIcon,
GlFriendlyWrap, GlFriendlyWrap,
GlButton, GlButton,
TestCaseDetails,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
GlModalDirective,
}, },
props: { props: {
heading: { heading: {
...@@ -43,7 +46,7 @@ export default { ...@@ -43,7 +46,7 @@ export default {
<div role="rowheader" class="table-section section-20"> <div role="rowheader" class="table-section section-20">
{{ __('Suite') }} {{ __('Suite') }}
</div> </div>
<div role="rowheader" class="table-section section-20"> <div role="rowheader" class="table-section section-40">
{{ __('Name') }} {{ __('Name') }}
</div> </div>
<div role="rowheader" class="table-section section-10"> <div role="rowheader" class="table-section section-10">
...@@ -52,12 +55,12 @@ export default { ...@@ -52,12 +55,12 @@ export default {
<div role="rowheader" class="table-section section-10 text-center"> <div role="rowheader" class="table-section section-10 text-center">
{{ __('Status') }} {{ __('Status') }}
</div> </div>
<div role="rowheader" class="table-section flex-grow-1"> <div role="rowheader" class="table-section section-10">
{{ __('Trace'), }}
</div>
<div role="rowheader" class="table-section section-10 text-right">
{{ __('Duration') }} {{ __('Duration') }}
</div> </div>
<div role="rowheader" class="table-section section-10">
{{ __('Details'), }}
</div>
</div> </div>
<div <div
...@@ -72,7 +75,7 @@ export default { ...@@ -72,7 +75,7 @@ export default {
</div> </div>
</div> </div>
<div class="table-section section-20 section-wrap"> <div class="table-section section-40 section-wrap">
<div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div> <div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div>
<div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break"> <div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break">
<gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.name" /> <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.name" />
...@@ -107,24 +110,24 @@ export default { ...@@ -107,24 +110,24 @@ export default {
</div> </div>
</div> </div>
<div class="table-section flex-grow-1">
<div role="rowheader" class="table-mobile-header">{{ __('Trace'), }}</div>
<div class="table-mobile-content">
<pre
v-if="testCase.system_output"
class="build-trace build-trace-rounded text-left"
><code class="bash p-0">{{testCase.system_output}}</code></pre>
</div>
</div>
<div class="table-section section-10 section-wrap"> <div class="table-section section-10 section-wrap">
<div role="rowheader" class="table-mobile-header"> <div role="rowheader" class="table-mobile-header">
{{ __('Duration') }} {{ __('Duration') }}
</div> </div>
<div class="table-mobile-content text-right pr-sm-1"> <div class="table-mobile-content pr-sm-1">
{{ testCase.formattedTime }} {{ testCase.formattedTime }}
</div> </div>
</div> </div>
<div class="table-section section-10 section-wrap">
<div role="rowheader" class="table-mobile-header">{{ __('Details'), }}</div>
<div class="table-mobile-content">
<gl-button v-gl-modal-directive="`test-case-details-${index}`">{{
__('View details')
}}</gl-button>
<test-case-details :modal-id="`test-case-details-${index}`" :test-case="testCase" />
</div>
</div>
</div> </div>
</div> </div>
......
---
title: Move test report system output to modal
merge_request: 45575
author:
type: changed
...@@ -10765,6 +10765,9 @@ msgstr "" ...@@ -10765,6 +10765,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits." msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "" msgstr ""
msgid "Execution time"
msgstr ""
msgid "Existing branch name, tag, or commit SHA" msgid "Existing branch name, tag, or commit SHA"
msgstr "" msgstr ""
...@@ -25705,6 +25708,9 @@ msgstr "" ...@@ -25705,6 +25708,9 @@ msgstr ""
msgid "System metrics (Kubernetes)" msgid "System metrics (Kubernetes)"
msgstr "" msgstr ""
msgid "System output"
msgstr ""
msgid "Table of Contents" msgid "Table of Contents"
msgstr "" msgstr ""
...@@ -27831,9 +27837,6 @@ msgstr "" ...@@ -27831,9 +27837,6 @@ msgstr ""
msgid "TotalRefCountIndicator|1000+" msgid "TotalRefCountIndicator|1000+"
msgstr "" msgstr ""
msgid "Trace"
msgstr ""
msgid "Tracing" msgid "Tracing"
msgstr "" msgstr ""
......
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
const localVue = createLocalVue();
describe('Test case details', () => {
let wrapper;
const defaultTestCase = {
classname: 'spec.test_spec',
name: 'Test#something cool',
formattedTime: '10.04ms',
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 findSystemOutput = () => wrapper.find('[data-testid="test-case-trace"]');
const createComponent = (testCase = {}) => {
wrapper = shallowMount(TestCaseDetails, {
localVue,
propsData: {
modalId: 'my-modal',
testCase: {
...defaultTestCase,
...testCase,
},
},
stubs: { CodeBlock, GlModal },
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('required details', () => {
beforeEach(() => {
createComponent();
});
it('renders the test case classname as modal title', () => {
expect(findModal().attributes('title')).toBe(defaultTestCase.classname);
});
it('renders the test case name', () => {
expect(findName().text()).toBe(defaultTestCase.name);
});
it('renders the test case duration', () => {
expect(findDuration().text()).toBe(defaultTestCase.formattedTime);
});
});
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);
});
});
});
import Vuex from 'vuex'; import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import { getJSONFixture } from 'helpers/fixtures'; import { getJSONFixture } from 'helpers/fixtures';
import { GlButton } from '@gitlab/ui'; import { GlButton, GlFriendlyWrap } from '@gitlab/ui';
import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue'; import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters'; import * as getters from '~/pipelines/stores/test_reports/getters';
import { TestStatus } from '~/pipelines/constants'; import { TestStatus } from '~/pipelines/constants';
...@@ -40,6 +40,7 @@ describe('Test reports suite table', () => { ...@@ -40,6 +40,7 @@ describe('Test reports suite table', () => {
wrapper = shallowMount(SuiteTable, { wrapper = shallowMount(SuiteTable, {
store, store,
localVue, localVue,
stubs: { GlFriendlyWrap },
}); });
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment