diff options
Diffstat (limited to 'spec/frontend/reports')
22 files changed, 1700 insertions, 0 deletions
diff --git a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js new file mode 100644 index 00000000000..a036588596a --- /dev/null +++ b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js @@ -0,0 +1,126 @@ +import { mount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import GroupedAccessibilityReportsApp from '~/reports/accessibility_report/grouped_accessibility_reports_app.vue'; +import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue'; +import store from '~/reports/accessibility_report/store'; +import { mockReport } from './mock_data'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('Grouped accessibility reports app', () => { + const Component = localVue.extend(GroupedAccessibilityReportsApp); + let wrapper; + let mockStore; + + const mountComponent = () => { + wrapper = mount(Component, { + store: mockStore, + localVue, + propsData: { + endpoint: 'endpoint.json', + }, + methods: { + fetchReport: () => {}, + }, + }); + }; + + const findHeader = () => wrapper.find('[data-testid="report-section-code-text"]'); + + beforeEach(() => { + mockStore = store(); + mountComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('while loading', () => { + beforeEach(() => { + mockStore.state.isLoading = true; + mountComponent(); + }); + + it('renders loading state', () => { + expect(findHeader().text()).toEqual('Accessibility scanning results are being parsed'); + }); + }); + + describe('with error', () => { + beforeEach(() => { + mockStore.state.isLoading = false; + mockStore.state.hasError = true; + mountComponent(); + }); + + it('renders error state', () => { + expect(findHeader().text()).toEqual('Accessibility scanning failed loading results'); + }); + }); + + describe('with a report', () => { + describe('with no issues', () => { + beforeEach(() => { + mockStore.state.report = { + summary: { + errored: 0, + }, + }; + }); + + it('renders no issues header', () => { + expect(findHeader().text()).toContain( + 'Accessibility scanning detected no issues for the source branch only', + ); + }); + }); + + describe('with one issue', () => { + beforeEach(() => { + mockStore.state.report = { + summary: { + errored: 1, + }, + }; + }); + + it('renders one issue header', () => { + expect(findHeader().text()).toContain( + 'Accessibility scanning detected 1 issue for the source branch only', + ); + }); + }); + + describe('with multiple issues', () => { + beforeEach(() => { + mockStore.state.report = { + summary: { + errored: 2, + }, + }; + }); + + it('renders multiple issues header', () => { + expect(findHeader().text()).toContain( + 'Accessibility scanning detected 2 issues for the source branch only', + ); + }); + }); + + describe('with issues to show', () => { + beforeEach(() => { + mockStore.state.report = mockReport; + }); + + it('renders custom accessibility issue body', () => { + const issueBody = wrapper.find(AccessibilityIssueBody); + + expect(issueBody.props('issue').code).toBe(mockReport.new_errors[0].code); + expect(issueBody.props('issue').message).toBe(mockReport.new_errors[0].message); + expect(issueBody.props('isNew')).toBe(true); + }); + }); + }); +}); diff --git a/spec/frontend/reports/accessibility_report/mock_data.js b/spec/frontend/reports/accessibility_report/mock_data.js new file mode 100644 index 00000000000..f8e832c1ce5 --- /dev/null +++ b/spec/frontend/reports/accessibility_report/mock_data.js @@ -0,0 +1,55 @@ +export const mockReport = { + status: 'failed', + summary: { + total: 2, + resolved: 0, + errored: 2, + }, + new_errors: [ + { + code: 'WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail', + type: 'error', + typeCode: 1, + message: + 'This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.84:1. Recommendation: change text colour to #767676.', + context: '<a href="/stages-devops-lifecycle/" class="main-nav-link">Product</a>', + selector: '#main-nav > div:nth-child(2) > ul > li:nth-child(1) > a', + runner: 'htmlcs', + runnerExtras: {}, + }, + ], + new_notes: [], + new_warnings: [], + resolved_errors: [ + { + code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent', + type: 'error', + typeCode: 1, + message: + 'Anchor element found with a valid href attribute, but no link content has been supplied.', + context: '<a href="/" class="navbar-brand animated"><svg height="36" viewBox="0 0 1...</a>', + selector: '#main-nav > div:nth-child(1) > a', + runner: 'htmlcs', + runnerExtras: {}, + }, + ], + resolved_notes: [], + resolved_warnings: [], + existing_errors: [ + { + code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent', + type: 'error', + typeCode: 1, + message: + 'Anchor element found with a valid href attribute, but no link content has been supplied.', + context: '<a href="/" class="navbar-brand animated"><svg height="36" viewBox="0 0 1...</a>', + selector: '#main-nav > div:nth-child(1) > a', + runner: 'htmlcs', + runnerExtras: {}, + }, + ], + existing_notes: [], + existing_warnings: [], +}; + +export default () => {}; diff --git a/spec/frontend/reports/accessibility_report/store/actions_spec.js b/spec/frontend/reports/accessibility_report/store/actions_spec.js new file mode 100644 index 00000000000..129a5bade86 --- /dev/null +++ b/spec/frontend/reports/accessibility_report/store/actions_spec.js @@ -0,0 +1,121 @@ +import axios from '~/lib/utils/axios_utils'; +import MockAdapter from 'axios-mock-adapter'; +import * as actions from '~/reports/accessibility_report/store/actions'; +import * as types from '~/reports/accessibility_report/store/mutation_types'; +import createStore from '~/reports/accessibility_report/store'; +import { TEST_HOST } from 'spec/test_constants'; +import testAction from 'helpers/vuex_action_helper'; +import { mockReport } from '../mock_data'; + +describe('Accessibility Reports actions', () => { + let localState; + let localStore; + + beforeEach(() => { + localStore = createStore(); + localState = localStore.state; + }); + + describe('setEndpoints', () => { + it('should commit SET_ENDPOINTS mutation', done => { + const endpoint = 'endpoint.json'; + + testAction( + actions.setEndpoint, + endpoint, + localState, + [{ type: types.SET_ENDPOINT, payload: endpoint }], + [], + done, + ); + }); + }); + + describe('fetchReport', () => { + let mock; + + beforeEach(() => { + localState.endpoint = `${TEST_HOST}/endpoint.json`; + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + actions.stopPolling(); + actions.clearEtagPoll(); + }); + + describe('success', () => { + it('should commit REQUEST_REPORT mutation and dispatch receiveReportSuccess', done => { + const data = { report: { summary: {} } }; + mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, data); + + testAction( + actions.fetchReport, + null, + localState, + [{ type: types.REQUEST_REPORT }], + [ + { + payload: { status: 200, data }, + type: 'receiveReportSuccess', + }, + ], + done, + ); + }); + }); + + describe('error', () => { + it('should commit REQUEST_REPORT and RECEIVE_REPORT_ERROR mutations', done => { + mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500); + + testAction( + actions.fetchReport, + null, + localState, + [{ type: types.REQUEST_REPORT }], + [{ type: 'receiveReportError' }], + done, + ); + }); + }); + }); + + describe('receiveReportSuccess', () => { + it('should commit RECEIVE_REPORT_SUCCESS mutation with 200', done => { + testAction( + actions.receiveReportSuccess, + { status: 200, data: mockReport }, + localState, + [{ type: types.RECEIVE_REPORT_SUCCESS, payload: mockReport }], + [{ type: 'stopPolling' }], + done, + ); + }); + + it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', done => { + testAction( + actions.receiveReportSuccess, + { status: 204, data: mockReport }, + localState, + [], + [], + done, + ); + }); + }); + + describe('receiveReportError', () => { + it('should commit RECEIVE_REPORT_ERROR mutation', done => { + testAction( + actions.receiveReportError, + null, + localState, + [{ type: types.RECEIVE_REPORT_ERROR }], + [{ type: 'stopPolling' }], + done, + ); + }); + }); +}); diff --git a/spec/frontend/reports/accessibility_report/store/getters_spec.js b/spec/frontend/reports/accessibility_report/store/getters_spec.js new file mode 100644 index 00000000000..d74c71cfa09 --- /dev/null +++ b/spec/frontend/reports/accessibility_report/store/getters_spec.js @@ -0,0 +1,149 @@ +import * as getters from '~/reports/accessibility_report/store/getters'; +import createStore from '~/reports/accessibility_report/store'; +import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '~/reports/constants'; + +describe('Accessibility reports store getters', () => { + let localState; + let localStore; + + beforeEach(() => { + localStore = createStore(); + localState = localStore.state; + }); + + describe('summaryStatus', () => { + describe('when summary is loading', () => { + it('returns loading status', () => { + localState.isLoading = true; + + expect(getters.summaryStatus(localState)).toEqual(LOADING); + }); + }); + + describe('when summary has error', () => { + it('returns error status', () => { + localState.hasError = true; + + expect(getters.summaryStatus(localState)).toEqual(ERROR); + }); + }); + + describe('when summary has failed status', () => { + it('returns loading status', () => { + localState.status = STATUS_FAILED; + + expect(getters.summaryStatus(localState)).toEqual(ERROR); + }); + }); + + describe('when summary has successfully loaded', () => { + it('returns loading status', () => { + expect(getters.summaryStatus(localState)).toEqual(SUCCESS); + }); + }); + }); + + describe('groupedSummaryText', () => { + describe('when state is loading', () => { + it('returns the loading summary message', () => { + localState.isLoading = true; + const result = 'Accessibility scanning results are being parsed'; + + expect(getters.groupedSummaryText(localState)).toEqual(result); + }); + }); + + describe('when state has error', () => { + it('returns the error summary message', () => { + localState.hasError = true; + const result = 'Accessibility scanning failed loading results'; + + expect(getters.groupedSummaryText(localState)).toEqual(result); + }); + }); + + describe('when state has successfully loaded', () => { + describe('when report has errors', () => { + it('returns summary message containing number of errors', () => { + localState.report = { + summary: { + errored: 2, + }, + }; + const result = 'Accessibility scanning detected 2 issues for the source branch only'; + + expect(getters.groupedSummaryText(localState)).toEqual(result); + }); + }); + + describe('when report has no errors', () => { + it('returns summary message containing no errors', () => { + localState.report = { + summary: { + errored: 0, + }, + }; + const result = 'Accessibility scanning detected no issues for the source branch only'; + + expect(getters.groupedSummaryText(localState)).toEqual(result); + }); + }); + }); + }); + + describe('shouldRenderIssuesList', () => { + describe('when has issues to render', () => { + it('returns true', () => { + localState.report = { + existing_errors: [{ name: 'Issue' }], + }; + + expect(getters.shouldRenderIssuesList(localState)).toEqual(true); + }); + }); + + describe('when does not have issues to render', () => { + it('returns false', () => { + localState.report = { + status: 'success', + summary: { errored: 0 }, + }; + + expect(getters.shouldRenderIssuesList(localState)).toEqual(false); + }); + }); + }); + + describe('unresolvedIssues', () => { + it('returns the array unresolved errors', () => { + localState.report = { + existing_errors: [1], + }; + const result = [1]; + + expect(getters.unresolvedIssues(localState)).toEqual(result); + }); + }); + + describe('resolvedIssues', () => { + it('returns array of resolved errors', () => { + localState.report = { + resolved_errors: [1], + }; + const result = [1]; + + expect(getters.resolvedIssues(localState)).toEqual(result); + }); + }); + + describe('newIssues', () => { + it('returns array of new errors', () => { + localState.report = { + new_errors: [1], + }; + const result = [1]; + + expect(getters.newIssues(localState)).toEqual(result); + }); + }); +}); diff --git a/spec/frontend/reports/accessibility_report/store/mutations_spec.js b/spec/frontend/reports/accessibility_report/store/mutations_spec.js new file mode 100644 index 00000000000..a4e9571b721 --- /dev/null +++ b/spec/frontend/reports/accessibility_report/store/mutations_spec.js @@ -0,0 +1,64 @@ +import mutations from '~/reports/accessibility_report/store/mutations'; +import createStore from '~/reports/accessibility_report/store'; + +describe('Accessibility Reports mutations', () => { + let localState; + let localStore; + + beforeEach(() => { + localStore = createStore(); + localState = localStore.state; + }); + + describe('SET_ENDPOINT', () => { + it('sets endpoint to given value', () => { + const endpoint = 'endpoint.json'; + mutations.SET_ENDPOINT(localState, endpoint); + + expect(localState.endpoint).toEqual(endpoint); + }); + }); + + describe('REQUEST_REPORT', () => { + it('sets isLoading to true', () => { + mutations.REQUEST_REPORT(localState); + + expect(localState.isLoading).toEqual(true); + }); + }); + + describe('RECEIVE_REPORT_SUCCESS', () => { + it('sets isLoading to false', () => { + mutations.RECEIVE_REPORT_SUCCESS(localState, {}); + + expect(localState.isLoading).toEqual(false); + }); + + it('sets hasError to false', () => { + mutations.RECEIVE_REPORT_SUCCESS(localState, {}); + + expect(localState.hasError).toEqual(false); + }); + + it('sets report to response report', () => { + const report = { data: 'testing' }; + mutations.RECEIVE_REPORT_SUCCESS(localState, report); + + expect(localState.report).toEqual(report); + }); + }); + + describe('RECEIVE_REPORT_ERROR', () => { + it('sets isLoading to false', () => { + mutations.RECEIVE_REPORT_ERROR(localState); + + expect(localState.isLoading).toEqual(false); + }); + + it('sets hasError to true', () => { + mutations.RECEIVE_REPORT_ERROR(localState); + + expect(localState.hasError).toEqual(true); + }); + }); +}); diff --git a/spec/frontend/reports/components/__snapshots__/grouped_issues_list_spec.js.snap b/spec/frontend/reports/components/__snapshots__/grouped_issues_list_spec.js.snap new file mode 100644 index 00000000000..c932379a253 --- /dev/null +++ b/spec/frontend/reports/components/__snapshots__/grouped_issues_list_spec.js.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Grouped Issues List renders a smart virtual list with the correct props 1`] = ` +Object { + "length": 4, + "remain": 20, + "rtag": "div", + "size": 32, + "wclass": "report-block-list", + "wtag": "ul", +} +`; + +exports[`Grouped Issues List with data renders a report item with the correct props 1`] = ` +Object { + "component": "TestIssueBody", + "isNew": false, + "issue": Object { + "name": "foo", + }, + "showReportSectionStatusIcon": false, + "status": "none", + "statusIconSize": 24, +} +`; diff --git a/spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap b/spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap new file mode 100644 index 00000000000..70e1ff01323 --- /dev/null +++ b/spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IssueStatusIcon renders "failed" state correctly 1`] = ` +<div + class="report-block-list-icon failed" +> + <icon-stub + data-qa-selector="status_failed_icon" + name="status_failed_borderless" + size="24" + /> +</div> +`; + +exports[`IssueStatusIcon renders "neutral" state correctly 1`] = ` +<div + class="report-block-list-icon neutral" +> + <icon-stub + data-qa-selector="status_neutral_icon" + name="dash" + size="24" + /> +</div> +`; + +exports[`IssueStatusIcon renders "success" state correctly 1`] = ` +<div + class="report-block-list-icon success" +> + <icon-stub + data-qa-selector="status_success_icon" + name="status_success_borderless" + size="24" + /> +</div> +`; diff --git a/spec/frontend/reports/components/grouped_issues_list_spec.js b/spec/frontend/reports/components/grouped_issues_list_spec.js new file mode 100644 index 00000000000..1f8f4a0e4c1 --- /dev/null +++ b/spec/frontend/reports/components/grouped_issues_list_spec.js @@ -0,0 +1,86 @@ +import { shallowMount } from '@vue/test-utils'; +import GroupedIssuesList from '~/reports/components/grouped_issues_list.vue'; +import ReportItem from '~/reports/components/report_item.vue'; +import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue'; + +describe('Grouped Issues List', () => { + let wrapper; + + const createComponent = ({ propsData = {}, stubs = {} } = {}) => { + wrapper = shallowMount(GroupedIssuesList, { + propsData, + stubs, + }); + }; + + const findHeading = groupName => wrapper.find(`[data-testid="${groupName}Heading"`); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('renders a smart virtual list with the correct props', () => { + createComponent({ + propsData: { + resolvedIssues: [{ name: 'foo' }], + unresolvedIssues: [{ name: 'bar' }], + }, + stubs: { + SmartVirtualList, + }, + }); + + expect(wrapper.find(SmartVirtualList).props()).toMatchSnapshot(); + }); + + describe('without data', () => { + beforeEach(createComponent); + + it.each(['unresolved', 'resolved'])('does not a render a header for %s issues', issueName => { + expect(findHeading(issueName).exists()).toBe(false); + }); + + it.each('resolved', 'unresolved')('does not render report items for %s issues', () => { + expect(wrapper.contains(ReportItem)).toBe(false); + }); + }); + + describe('with data', () => { + it.each` + givenIssues | givenHeading | groupName + ${[{ name: 'foo issue' }]} | ${'Foo Heading'} | ${'resolved'} + ${[{ name: 'bar issue' }]} | ${'Bar Heading'} | ${'unresolved'} + `('renders the heading for $groupName issues', ({ givenIssues, givenHeading, groupName }) => { + createComponent({ + propsData: { [`${groupName}Issues`]: givenIssues, [`${groupName}Heading`]: givenHeading }, + }); + + expect(findHeading(groupName).text()).toBe(givenHeading); + }); + + it.each(['resolved', 'unresolved'])('renders all %s issues', issueName => { + const issues = [{ name: 'foo' }, { name: 'bar' }]; + + createComponent({ + propsData: { [`${issueName}Issues`]: issues }, + }); + + expect(wrapper.findAll(ReportItem)).toHaveLength(issues.length); + }); + + it('renders a report item with the correct props', () => { + createComponent({ + propsData: { + resolvedIssues: [{ name: 'foo' }], + component: 'TestIssueBody', + }, + stubs: { + ReportItem, + }, + }); + + expect(wrapper.find(ReportItem).props()).toMatchSnapshot(); + }); + }); +}); diff --git a/spec/frontend/reports/components/grouped_test_reports_app_spec.js b/spec/frontend/reports/components/grouped_test_reports_app_spec.js new file mode 100644 index 00000000000..1a01db391da --- /dev/null +++ b/spec/frontend/reports/components/grouped_test_reports_app_spec.js @@ -0,0 +1,260 @@ +import Vue from 'vue'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import state from '~/reports/store/state'; +import component from '~/reports/components/grouped_test_reports_app.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; +import { failedReport } from '../mock_data/mock_data'; +import newFailedTestReports from '../mock_data/new_failures_report.json'; +import newErrorsTestReports from '../mock_data/new_errors_report.json'; +import successTestReports from '../mock_data/no_failures_report.json'; +import mixedResultsTestReports from '../mock_data/new_and_fixed_failures_report.json'; +import resolvedFailures from '../mock_data/resolved_failures.json'; + +describe('Grouped Test Reports App', () => { + let vm; + let mock; + const Component = Vue.extend(component); + + beforeEach(() => { + mock = new MockAdapter(axios); + }); + + afterEach(() => { + vm.$store.replaceState(state()); + vm.$destroy(); + mock.restore(); + }); + + describe('with success result', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, successTestReports, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders success summary text', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.gl-spinner')).toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary contained no changed test results out of 11 total tests', + ); + + expect(vm.$el.textContent).toContain( + 'rspec:pg found no changed test results out of 8 total tests', + ); + + expect(vm.$el.textContent).toContain( + 'java ant found no changed test results out of 3 total tests', + ); + done(); + }); + }); + }); + + describe('with 204 result', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(204, {}, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders success summary text', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.gl-spinner')).not.toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary results are being parsed', + ); + + done(); + }); + }); + }); + + describe('with new failed result', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, newFailedTestReports, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders failed summary text + new badge', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.gl-spinner')).toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary contained 2 failed out of 11 total tests', + ); + + expect(vm.$el.textContent).toContain('rspec:pg found 2 failed out of 8 total tests'); + + expect(vm.$el.textContent).toContain('New'); + expect(vm.$el.textContent).toContain( + 'java ant found no changed test results out of 3 total tests', + ); + done(); + }); + }); + }); + + describe('with new error result', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, newErrorsTestReports, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders error summary text + new badge', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.gl-spinner')).toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary contained 2 errors out of 11 total tests', + ); + + expect(vm.$el.textContent).toContain('karma found 2 errors out of 3 total tests'); + + expect(vm.$el.textContent).toContain('New'); + expect(vm.$el.textContent).toContain( + 'rspec:pg found no changed test results out of 8 total tests', + ); + done(); + }); + }); + }); + + describe('with mixed results', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, mixedResultsTestReports, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders summary text', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.gl-spinner')).toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary contained 2 failed and 2 fixed test results out of 11 total tests', + ); + + expect(vm.$el.textContent).toContain( + 'rspec:pg found 1 failed and 2 fixed test results out of 8 total tests', + ); + + expect(vm.$el.textContent).toContain('New'); + expect(vm.$el.textContent).toContain(' java ant found 1 failed out of 3 total tests'); + done(); + }); + }); + }); + + describe('with resolved failures and resolved errors', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, resolvedFailures, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders summary text', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.gl-spinner')).toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary contained 4 fixed test results out of 11 total tests', + ); + + expect(vm.$el.textContent).toContain( + 'rspec:pg found 4 fixed test results out of 8 total tests', + ); + done(); + }); + }); + + it('renders resolved failures', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.report-block-container').textContent).toContain( + resolvedFailures.suites[0].resolved_failures[0].name, + ); + + expect(vm.$el.querySelector('.report-block-container').textContent).toContain( + resolvedFailures.suites[0].resolved_failures[1].name, + ); + done(); + }); + }); + + it('renders resolved errors', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.report-block-container').textContent).toContain( + resolvedFailures.suites[0].resolved_errors[0].name, + ); + + expect(vm.$el.querySelector('.report-block-container').textContent).toContain( + resolvedFailures.suites[0].resolved_errors[1].name, + ); + done(); + }); + }); + }); + + describe('with a report that failed to load', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, failedReport, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders an error status for the report', done => { + setImmediate(() => { + const { name } = failedReport.suites[0]; + + expect(vm.$el.querySelector('.report-block-list-issue').textContent).toContain( + `An error occurred while loading ${name} results`, + ); + done(); + }); + }); + }); + + describe('with error', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(500, {}, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders loading summary text with loading icon', done => { + setImmediate(() => { + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary failed loading results', + ); + done(); + }); + }); + }); + + describe('while loading', () => { + beforeEach(() => { + mock.onGet('test_results.json').reply(200, {}, {}); + vm = mountComponent(Component, { + endpoint: 'test_results.json', + }); + }); + + it('renders loading summary text with loading icon', done => { + expect(vm.$el.querySelector('.gl-spinner')).not.toBeNull(); + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Test summary results are being parsed', + ); + + setImmediate(() => { + done(); + }); + }); + }); +}); diff --git a/spec/frontend/reports/components/issue_status_icon_spec.js b/spec/frontend/reports/components/issue_status_icon_spec.js new file mode 100644 index 00000000000..3a55ff0a9e3 --- /dev/null +++ b/spec/frontend/reports/components/issue_status_icon_spec.js @@ -0,0 +1,29 @@ +import { shallowMount } from '@vue/test-utils'; +import ReportItem from '~/reports/components/issue_status_icon.vue'; +import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants'; + +describe('IssueStatusIcon', () => { + let wrapper; + + const createComponent = ({ status }) => { + wrapper = shallowMount(ReportItem, { + propsData: { + status, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it.each([STATUS_SUCCESS, STATUS_NEUTRAL, STATUS_FAILED])( + 'renders "%s" state correctly', + status => { + createComponent({ status }); + + expect(wrapper.element).toMatchSnapshot(); + }, + ); +}); diff --git a/spec/frontend/reports/components/modal_open_name_spec.js b/spec/frontend/reports/components/modal_open_name_spec.js new file mode 100644 index 00000000000..d59f3571c4b --- /dev/null +++ b/spec/frontend/reports/components/modal_open_name_spec.js @@ -0,0 +1,47 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import { mountComponentWithStore } from 'helpers/vue_mount_component_helper'; +import component from '~/reports/components/modal_open_name.vue'; + +Vue.use(Vuex); + +describe('Modal open name', () => { + const Component = Vue.extend(component); + let vm; + + const store = new Vuex.Store({ + actions: { + openModal: () => {}, + }, + state: {}, + mutations: {}, + }); + + beforeEach(() => { + vm = mountComponentWithStore(Component, { + store, + props: { + issue: { + title: 'Issue', + }, + status: 'failed', + }, + }); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders the issue name', () => { + expect(vm.$el.textContent.trim()).toEqual('Issue'); + }); + + it('calls openModal actions when button is clicked', () => { + jest.spyOn(vm, 'openModal').mockImplementation(() => {}); + + vm.$el.click(); + + expect(vm.openModal).toHaveBeenCalled(); + }); +}); diff --git a/spec/frontend/reports/components/modal_spec.js b/spec/frontend/reports/components/modal_spec.js new file mode 100644 index 00000000000..ff046e64b6e --- /dev/null +++ b/spec/frontend/reports/components/modal_spec.js @@ -0,0 +1,54 @@ +import Vue from 'vue'; +import component from '~/reports/components/modal.vue'; +import state from '~/reports/store/state'; +import mountComponent from '../../helpers/vue_mount_component_helper'; +import { trimText } from '../../helpers/text_helper'; + +describe('Grouped Test Reports Modal', () => { + const Component = Vue.extend(component); + const modalDataStructure = state().modal.data; + + // populate data + modalDataStructure.execution_time.value = 0.009411; + modalDataStructure.system_output.value = 'Failure/Error: is_expected.to eq(3)\n\n'; + modalDataStructure.class.value = 'link'; + + let vm; + + beforeEach(() => { + vm = mountComponent(Component, { + title: 'Test#sum when a is 1 and b is 2 returns summary', + modalData: modalDataStructure, + }); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders code block', () => { + expect(vm.$el.querySelector('code').textContent).toEqual( + modalDataStructure.system_output.value, + ); + }); + + it('renders link', () => { + expect(vm.$el.querySelector('.js-modal-link').getAttribute('href')).toEqual( + modalDataStructure.class.value, + ); + + expect(trimText(vm.$el.querySelector('.js-modal-link').textContent)).toEqual( + modalDataStructure.class.value, + ); + }); + + it('renders seconds', () => { + expect(vm.$el.textContent).toContain(`${modalDataStructure.execution_time.value} s`); + }); + + it('render title', () => { + expect(trimText(vm.$el.querySelector('.modal-title').textContent)).toEqual( + 'Test#sum when a is 1 and b is 2 returns summary', + ); + }); +}); diff --git a/spec/frontend/reports/components/summary_row_spec.js b/spec/frontend/reports/components/summary_row_spec.js new file mode 100644 index 00000000000..cb0cc025e80 --- /dev/null +++ b/spec/frontend/reports/components/summary_row_spec.js @@ -0,0 +1,37 @@ +import Vue from 'vue'; +import mountComponent from 'helpers/vue_mount_component_helper'; +import component from '~/reports/components/summary_row.vue'; + +describe('Summary row', () => { + const Component = Vue.extend(component); + let vm; + + const props = { + summary: 'SAST detected 1 new vulnerability and 1 fixed vulnerability', + popoverOptions: { + title: 'Static Application Security Testing (SAST)', + content: '<a>Learn more about SAST</a>', + }, + statusIcon: 'warning', + }; + + beforeEach(() => { + vm = mountComponent(Component, props); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders provided summary', () => { + expect( + vm.$el.querySelector('.report-block-list-issue-description-text').textContent.trim(), + ).toEqual(props.summary); + }); + + it('renders provided icon', () => { + expect(vm.$el.querySelector('.report-block-list-icon span').classList).toContain( + 'js-ci-status-icon-warning', + ); + }); +}); diff --git a/spec/frontend/reports/components/test_issue_body_spec.js b/spec/frontend/reports/components/test_issue_body_spec.js new file mode 100644 index 00000000000..ff81020a4eb --- /dev/null +++ b/spec/frontend/reports/components/test_issue_body_spec.js @@ -0,0 +1,72 @@ +import Vue from 'vue'; +import component from '~/reports/components/test_issue_body.vue'; +import createStore from '~/reports/store'; +import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper'; +import { trimText } from '../../helpers/text_helper'; +import { issue } from '../mock_data/mock_data'; + +describe('Test Issue body', () => { + let vm; + const Component = Vue.extend(component); + const store = createStore(); + + const commonProps = { + issue, + status: 'failed', + }; + + afterEach(() => { + vm.$destroy(); + }); + + describe('on click', () => { + it('calls openModal action', () => { + vm = mountComponentWithStore(Component, { + store, + props: commonProps, + }); + + jest.spyOn(vm, 'openModal').mockImplementation(() => {}); + + vm.$el.querySelector('button').click(); + + expect(vm.openModal).toHaveBeenCalledWith({ + issue: commonProps.issue, + }); + }); + }); + + describe('is new', () => { + beforeEach(() => { + vm = mountComponentWithStore(Component, { + store, + props: { ...commonProps, isNew: true }, + }); + }); + + it('renders issue name', () => { + expect(vm.$el.textContent).toContain(commonProps.issue.name); + }); + + it('renders new badge', () => { + expect(trimText(vm.$el.querySelector('.badge').textContent)).toEqual('New'); + }); + }); + + describe('not new', () => { + beforeEach(() => { + vm = mountComponentWithStore(Component, { + store, + props: commonProps, + }); + }); + + it('renders issue name', () => { + expect(vm.$el.textContent).toContain(commonProps.issue.name); + }); + + it('does not renders new badge', () => { + expect(vm.$el.querySelector('.badge')).toEqual(null); + }); + }); +}); diff --git a/spec/frontend/reports/mock_data/mock_data.js b/spec/frontend/reports/mock_data/mock_data.js new file mode 100644 index 00000000000..3caaab2fd79 --- /dev/null +++ b/spec/frontend/reports/mock_data/mock_data.js @@ -0,0 +1,24 @@ +export const issue = { + result: 'failure', + name: 'Test#sum when a is 1 and b is 2 returns summary', + execution_time: 0.009411, + system_output: + "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in \u003ctop (required)\u003e'", +}; + +export const failedReport = { + summary: { total: 11, resolved: 0, errored: 2, failed: 0 }, + suites: [ + { + name: 'rspec:pg', + status: 'error', + summary: { total: 0, resolved: 0, errored: 0, failed: 0 }, + new_failures: [], + resolved_failures: [], + existing_failures: [], + new_errors: [], + resolved_errors: [], + existing_errors: [], + }, + ], +}; diff --git a/spec/frontend/reports/mock_data/new_and_fixed_failures_report.json b/spec/frontend/reports/mock_data/new_and_fixed_failures_report.json new file mode 100644 index 00000000000..6141e5433a6 --- /dev/null +++ b/spec/frontend/reports/mock_data/new_and_fixed_failures_report.json @@ -0,0 +1,55 @@ +{ + "status": "failed", + "summary": { "total": 11, "resolved": 2, "errored": 0, "failed": 2 }, + "suites": [ + { + "name": "rspec:pg", + "status": "failed", + "summary": { "total": 8, "resolved": 2, "errored": 0, "failed": 1 }, + "new_failures": [ + { + "status": "failed", + "name": "Test#subtract when a is 2 and b is 1 returns correct result", + "execution_time": 0.00908, + "system_output": "Failure/Error: is_expected.to eq(1)\n\n expected: 1\n got: 3\n\n (compared using ==)\n./spec/test_spec.rb:43:in `block (4 levels) in <top (required)>'" + } + ], + "resolved_failures": [ + { + "status": "success", + "name": "Test#sum when a is 1 and b is 2 returns summary", + "execution_time": 0.000318, + "system_output": null + }, + { + "status": "success", + "name": "Test#sum when a is 100 and b is 200 returns summary", + "execution_time": 0.000074, + "system_output": null + } + ], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "java ant", + "status": "failed", + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 1 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [ + { + "status": "failed", + "name": "sumTest", + "execution_time": 0.004, + "system_output": "junit.framework.AssertionFailedError: expected:<3> but was:<-1>\n\tat CalculatorTest.sumTest(Unknown Source)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" + } + ], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/frontend/reports/mock_data/new_errors_report.json b/spec/frontend/reports/mock_data/new_errors_report.json new file mode 100644 index 00000000000..cebf98fdb63 --- /dev/null +++ b/spec/frontend/reports/mock_data/new_errors_report.json @@ -0,0 +1,38 @@ +{ + "summary": { "total": 11, "resolved": 0, "errored": 2, "failed": 0 }, + "suites": [ + { + "name": "rspec:pg", + "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "karma", + "summary": { "total": 3, "resolved": 0, "errored": 2, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [ + { + "result": "error", + "name": "Test#sum when a is 1 and b is 2 returns summary", + "execution_time": 0.009411, + "system_output": "Failed: Error in render: 'TypeError: Cannot read property 'status' of undefined'" + }, + { + "result": "error", + "name": "Test#sum when a is 100 and b is 200 returns summary", + "execution_time": 0.000162, + "system_output": "Failed: Error in render: 'TypeError: Cannot read property 'length' of undefined'" + } + ], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/frontend/reports/mock_data/new_failures_report.json b/spec/frontend/reports/mock_data/new_failures_report.json new file mode 100644 index 00000000000..8b9c12c6271 --- /dev/null +++ b/spec/frontend/reports/mock_data/new_failures_report.json @@ -0,0 +1,38 @@ +{ + "summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 2 }, + "suites": [ + { + "name": "rspec:pg", + "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2 }, + "new_failures": [ + { + "result": "failure", + "name": "Test#sum when a is 1 and b is 2 returns summary", + "execution_time": 0.009411, + "system_output": "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in <top (required)>'" + }, + { + "result": "failure", + "name": "Test#sum when a is 100 and b is 200 returns summary", + "execution_time": 0.000162, + "system_output": "Failure/Error: is_expected.to eq(300)\n\n expected: 300\n got: -100\n\n (compared using ==)\n./spec/test_spec.rb:21:in `block (4 levels) in <top (required)>'" + } + ], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "java ant", + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/frontend/reports/mock_data/no_failures_report.json b/spec/frontend/reports/mock_data/no_failures_report.json new file mode 100644 index 00000000000..7da9e0c6211 --- /dev/null +++ b/spec/frontend/reports/mock_data/no_failures_report.json @@ -0,0 +1,28 @@ +{ + "status": "success", + "summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 0 }, + "suites": [ + { + "name": "rspec:pg", + "status": "success", + "summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + }, + { + "name": "java ant", + "status": "success", + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/frontend/reports/mock_data/resolved_failures.json b/spec/frontend/reports/mock_data/resolved_failures.json new file mode 100644 index 00000000000..49de6aa840b --- /dev/null +++ b/spec/frontend/reports/mock_data/resolved_failures.json @@ -0,0 +1,58 @@ +{ + "status": "success", + "summary": { "total": 11, "resolved": 4, "errored": 0, "failed": 0 }, + "suites": [ + { + "name": "rspec:pg", + "status": "success", + "summary": { "total": 8, "resolved": 4, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [ + { + "status": "success", + "name": "Test#sum when a is 1 and b is 2 returns summary", + "execution_time": 0.000411, + "system_output": null, + "stack_trace": null + }, + { + "status": "success", + "name": "Test#sum when a is 100 and b is 200 returns summary", + "execution_time": 7.6e-5, + "system_output": null, + "stack_trace": null + } + ], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [ + { + "status": "success", + "name": "Test#sum when a is 4 and b is 4 returns summary", + "execution_time": 0.00342, + "system_output": null, + "stack_trace": null + }, + { + "status": "success", + "name": "Test#sum when a is 40 and b is 400 returns summary", + "execution_time": 0.0000231, + "system_output": null, + "stack_trace": null + } + ], + "existing_errors": [] + }, + { + "name": "java ant", + "status": "success", + "summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 }, + "new_failures": [], + "resolved_failures": [], + "existing_failures": [], + "new_errors": [], + "resolved_errors": [], + "existing_errors": [] + } + ] +} diff --git a/spec/frontend/reports/store/actions_spec.js b/spec/frontend/reports/store/actions_spec.js new file mode 100644 index 00000000000..3f189736922 --- /dev/null +++ b/spec/frontend/reports/store/actions_spec.js @@ -0,0 +1,171 @@ +import MockAdapter from 'axios-mock-adapter'; +import testAction from 'helpers/vuex_action_helper'; +import { TEST_HOST } from 'helpers/test_constants'; +import axios from '~/lib/utils/axios_utils'; +import { + setEndpoint, + requestReports, + fetchReports, + stopPolling, + clearEtagPoll, + receiveReportsSuccess, + receiveReportsError, + openModal, + setModalData, +} from '~/reports/store/actions'; +import state from '~/reports/store/state'; +import * as types from '~/reports/store/mutation_types'; + +describe('Reports Store Actions', () => { + let mockedState; + + beforeEach(() => { + mockedState = state(); + }); + + describe('setEndpoint', () => { + it('should commit SET_ENDPOINT mutation', done => { + testAction( + setEndpoint, + 'endpoint.json', + mockedState, + [{ type: types.SET_ENDPOINT, payload: 'endpoint.json' }], + [], + done, + ); + }); + }); + + describe('requestReports', () => { + it('should commit REQUEST_REPORTS mutation', done => { + testAction(requestReports, null, mockedState, [{ type: types.REQUEST_REPORTS }], [], done); + }); + }); + + describe('fetchReports', () => { + let mock; + + beforeEach(() => { + mockedState.endpoint = `${TEST_HOST}/endpoint.json`; + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + stopPolling(); + clearEtagPoll(); + }); + + describe('success', () => { + it('dispatches requestReports and receiveReportsSuccess ', done => { + mock + .onGet(`${TEST_HOST}/endpoint.json`) + .replyOnce(200, { summary: {}, suites: [{ name: 'rspec' }] }); + + testAction( + fetchReports, + null, + mockedState, + [], + [ + { + type: 'requestReports', + }, + { + payload: { data: { summary: {}, suites: [{ name: 'rspec' }] }, status: 200 }, + type: 'receiveReportsSuccess', + }, + ], + done, + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500); + }); + + it('dispatches requestReports and receiveReportsError ', done => { + testAction( + fetchReports, + null, + mockedState, + [], + [ + { + type: 'requestReports', + }, + { + type: 'receiveReportsError', + }, + ], + done, + ); + }); + }); + }); + + describe('receiveReportsSuccess', () => { + it('should commit RECEIVE_REPORTS_SUCCESS mutation with 200', done => { + testAction( + receiveReportsSuccess, + { data: { summary: {} }, status: 200 }, + mockedState, + [{ type: types.RECEIVE_REPORTS_SUCCESS, payload: { summary: {} } }], + [], + done, + ); + }); + + it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', done => { + testAction( + receiveReportsSuccess, + { data: { summary: {} }, status: 204 }, + mockedState, + [], + [], + done, + ); + }); + }); + + describe('receiveReportsError', () => { + it('should commit RECEIVE_REPORTS_ERROR mutation', done => { + testAction( + receiveReportsError, + null, + mockedState, + [{ type: types.RECEIVE_REPORTS_ERROR }], + [], + done, + ); + }); + }); + + describe('openModal', () => { + it('should dispatch setModalData', done => { + testAction( + openModal, + { name: 'foo' }, + mockedState, + [], + [{ type: 'setModalData', payload: { name: 'foo' } }], + done, + ); + }); + }); + + describe('setModalData', () => { + it('should commit SET_ISSUE_MODAL_DATA', done => { + testAction( + setModalData, + { name: 'foo' }, + mockedState, + [{ type: types.SET_ISSUE_MODAL_DATA, payload: { name: 'foo' } }], + [], + done, + ); + }); + }); +}); diff --git a/spec/frontend/reports/store/mutations_spec.js b/spec/frontend/reports/store/mutations_spec.js new file mode 100644 index 00000000000..9446cd454ab --- /dev/null +++ b/spec/frontend/reports/store/mutations_spec.js @@ -0,0 +1,126 @@ +import state from '~/reports/store/state'; +import mutations from '~/reports/store/mutations'; +import * as types from '~/reports/store/mutation_types'; +import { issue } from '../mock_data/mock_data'; + +describe('Reports Store Mutations', () => { + let stateCopy; + + beforeEach(() => { + stateCopy = state(); + }); + + describe('SET_ENDPOINT', () => { + it('should set endpoint', () => { + mutations[types.SET_ENDPOINT](stateCopy, 'endpoint.json'); + + expect(stateCopy.endpoint).toEqual('endpoint.json'); + }); + }); + + describe('REQUEST_REPORTS', () => { + it('should set isLoading to true', () => { + mutations[types.REQUEST_REPORTS](stateCopy); + + expect(stateCopy.isLoading).toEqual(true); + }); + }); + + describe('RECEIVE_REPORTS_SUCCESS', () => { + const mockedResponse = { + summary: { + total: 14, + resolved: 0, + failed: 7, + }, + suites: [ + { + name: 'build:linux', + summary: { + total: 2, + resolved: 0, + failed: 1, + }, + new_failures: [ + { + name: 'StringHelper#concatenate when a is git and b is lab returns summary', + execution_time: 0.0092435, + system_output: "Failure/Error: is_expected.to eq('gitlab')", + }, + ], + resolved_failures: [ + { + name: 'StringHelper#concatenate when a is git and b is lab returns summary', + execution_time: 0.009235, + system_output: "Failure/Error: is_expected.to eq('gitlab')", + }, + ], + existing_failures: [ + { + name: 'StringHelper#concatenate when a is git and b is lab returns summary', + execution_time: 1232.08, + system_output: "Failure/Error: is_expected.to eq('gitlab')", + }, + ], + }, + ], + }; + + beforeEach(() => { + mutations[types.RECEIVE_REPORTS_SUCCESS](stateCopy, mockedResponse); + }); + + it('should reset isLoading', () => { + expect(stateCopy.isLoading).toEqual(false); + }); + + it('should reset hasError', () => { + expect(stateCopy.hasError).toEqual(false); + }); + + it('should set summary counts', () => { + expect(stateCopy.summary.total).toEqual(mockedResponse.summary.total); + expect(stateCopy.summary.resolved).toEqual(mockedResponse.summary.resolved); + expect(stateCopy.summary.failed).toEqual(mockedResponse.summary.failed); + }); + + it('should set reports', () => { + expect(stateCopy.reports).toEqual(mockedResponse.suites); + }); + }); + + describe('RECEIVE_REPORTS_ERROR', () => { + beforeEach(() => { + mutations[types.RECEIVE_REPORTS_ERROR](stateCopy); + }); + + it('should reset isLoading', () => { + expect(stateCopy.isLoading).toEqual(false); + }); + + it('should set hasError to true', () => { + expect(stateCopy.hasError).toEqual(true); + }); + + it('should reset reports', () => { + expect(stateCopy.reports).toEqual([]); + }); + }); + + describe('SET_ISSUE_MODAL_DATA', () => { + beforeEach(() => { + mutations[types.SET_ISSUE_MODAL_DATA](stateCopy, { + issue, + }); + }); + + it('should set modal title', () => { + expect(stateCopy.modal.title).toEqual(issue.name); + }); + + it('should set modal data', () => { + expect(stateCopy.modal.data.execution_time.value).toEqual(issue.execution_time); + expect(stateCopy.modal.data.system_output.value).toEqual(issue.system_output); + }); + }); +}); |