Commit 047a1cfb authored by Paul Slaughter's avatar Paul Slaughter

Merge branch '35614-refactor-testreports-to-use-dynamic-fixtures' into 'master'

Resolve "Refactor TestReports to use Dynamic Fixtures"

Closes #35614

See merge request gitlab-org/gitlab!19650
parents 54514133 8f86a4f6
import { TestStatus } from '~/pipelines/constants';
import { formatTime, secondsToMilliseconds } from '~/lib/utils/datetime_utility';
function iconForTestStatus(status) {
export function iconForTestStatus(status) {
switch (status) {
case 'success':
return 'status_success_borderless';
......
# frozen_string_literal: true
require "spec_helper"
describe Projects::PipelinesController, "(JavaScript fixtures)", type: :controller do
include JavaScriptFixturesHelpers
let(:namespace) { create(:namespace, name: "frontend-fixtures") }
let(:project) { create(:project, :repository, namespace: namespace, path: "pipelines-project") }
let(:commit) { create(:commit, project: project) }
let(:user) { create(:user, developer_projects: [project], email: commit.author_email) }
let(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project, user: user) }
render_views
before do
sign_in(user)
stub_feature_flags(junit_pipeline_view: true)
end
it "pipelines/test_report.json" do
get :test_report, params: {
namespace_id: project.namespace,
project_id: project,
id: pipeline.id
}, format: :json
expect(response).to be_successful
end
end
import { formatTime } from '~/lib/utils/datetime_utility';
import { TestStatus } from '~/pipelines/constants';
export const testCases = [
{
classname: 'spec.test_spec',
execution_time: 0.000748,
name: 'Test#subtract when a is 1 and b is 2 raises an error',
stack_trace: null,
status: TestStatus.SUCCESS,
system_output: null,
},
{
classname: 'spec.test_spec',
execution_time: 0.000064,
name: 'Test#subtract when a is 2 and b is 1 returns correct result',
stack_trace: null,
status: TestStatus.SUCCESS,
system_output: null,
},
{
classname: 'spec.test_spec',
execution_time: 0.009292,
name: 'Test#sum when a is 1 and b is 2 returns summary',
stack_trace: null,
status: TestStatus.FAILED,
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)>'",
},
{
classname: 'spec.test_spec',
execution_time: 0.00018,
name: 'Test#sum when a is 100 and b is 200 returns summary',
stack_trace: null,
status: TestStatus.FAILED,
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)>'",
},
export default [
{
classname: 'spec.test_spec',
execution_time: 0,
......@@ -45,79 +10,3 @@ export const testCases = [
system_output: null,
},
];
export const testCasesFormatted = [
{
...testCases[2],
icon: 'status_failed_borderless',
formattedTime: formatTime(testCases[0].execution_time * 1000),
},
{
...testCases[3],
icon: 'status_failed_borderless',
formattedTime: formatTime(testCases[1].execution_time * 1000),
},
{
...testCases[4],
icon: 'status_skipped_borderless',
formattedTime: formatTime(testCases[2].execution_time * 1000),
},
{
...testCases[0],
icon: 'status_success_borderless',
formattedTime: formatTime(testCases[3].execution_time * 1000),
},
{
...testCases[1],
icon: 'status_success_borderless',
formattedTime: formatTime(testCases[4].execution_time * 1000),
},
];
export const testSuites = [
{
error_count: 0,
failed_count: 2,
name: 'rspec:osx',
skipped_count: 0,
success_count: 2,
test_cases: testCases,
total_count: 4,
total_time: 60,
},
{
error_count: 0,
failed_count: 10,
name: 'rspec:osx',
skipped_count: 0,
success_count: 50,
test_cases: [],
total_count: 60,
total_time: 0.010284,
},
];
export const testSuitesFormatted = testSuites.map(x => ({
...x,
formattedTime: formatTime(x.total_time * 1000),
}));
export const testReports = {
error_count: 0,
failed_count: 2,
skipped_count: 0,
success_count: 2,
test_suites: testSuites,
total_count: 4,
total_time: 0.010284,
};
export const testReportsWithNoSuites = {
error_count: 0,
failed_count: 2,
skipped_count: 0,
success_count: 2,
test_suites: [],
total_count: 4,
total_time: 0.010284,
};
......@@ -2,10 +2,10 @@ import MockAdapter from 'axios-mock-adapter';
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 { getJSONFixture } from 'helpers/fixtures';
import { TEST_HOST } from '../../../helpers/test_constants';
import testAction from '../../../helpers/vuex_action_helper';
import createFlash from '~/flash';
import { testReports } from '../mock_data';
jest.mock('~/flash.js');
......@@ -13,6 +13,8 @@ describe('Actions TestReports Store', () => {
let mock;
let state;
const testReports = getJSONFixture('pipelines/test_report.json');
const endpoint = `${TEST_HOST}/test_reports.json`;
const defaultState = {
endpoint,
......
import * as getters from '~/pipelines/stores/test_reports/getters';
import { testReports, testSuitesFormatted, testCasesFormatted } from '../mock_data';
import { iconForTestStatus } from '~/pipelines/stores/test_reports/utils';
import { getJSONFixture } from 'helpers/fixtures';
describe('Getters TestReports Store', () => {
let state;
const testReports = getJSONFixture('pipelines/test_report.json');
const defaultState = {
testReports,
selectedSuite: testReports.test_suites[0],
......@@ -28,7 +31,13 @@ describe('Getters TestReports Store', () => {
it('should return the test suites', () => {
setupState();
expect(getters.getTestSuites(state)).toEqual(testSuitesFormatted);
const suites = getters.getTestSuites(state);
const expected = testReports.test_suites.map(x => ({
...x,
formattedTime: '00:00:00',
}));
expect(suites).toEqual(expected);
});
it('should return an empty array when testReports is empty', () => {
......@@ -42,7 +51,14 @@ describe('Getters TestReports Store', () => {
it('should return the test cases inside the suite', () => {
setupState();
expect(getters.getSuiteTests(state)).toEqual(testCasesFormatted);
const cases = getters.getSuiteTests(state);
const expected = testReports.test_suites[0].test_cases.map(x => ({
...x,
formattedTime: '00:00:00',
icon: iconForTestStatus(x.status),
}));
expect(cases).toEqual(expected);
});
it('should return an empty array when testReports is empty', () => {
......
import * as types from '~/pipelines/stores/test_reports/mutation_types';
import mutations from '~/pipelines/stores/test_reports/mutations';
import { testReports, testSuites } from '../mock_data';
import { getJSONFixture } from 'helpers/fixtures';
describe('Mutations TestReports Store', () => {
let mockState;
const testReports = getJSONFixture('pipelines/test_report.json');
const defaultState = {
endpoint: '',
testReports: {},
......@@ -27,7 +29,7 @@ describe('Mutations TestReports Store', () => {
describe('set reports', () => {
it('should set testReports', () => {
const expectedState = Object.assign({}, mockState, { testReports });
const expectedState = { ...mockState, testReports };
mutations[types.SET_REPORTS](mockState, testReports);
expect(mockState.testReports).toEqual(expectedState.testReports);
......@@ -36,10 +38,10 @@ describe('Mutations TestReports Store', () => {
describe('set selected suite', () => {
it('should set selectedSuite', () => {
const expectedState = Object.assign({}, mockState, { selectedSuite: testSuites[0] });
mutations[types.SET_SELECTED_SUITE](mockState, testSuites[0]);
const selectedSuite = testReports.test_suites[0];
mutations[types.SET_SELECTED_SUITE](mockState, selectedSuite);
expect(mockState.selectedSuite).toEqual(expectedState.selectedSuite);
expect(mockState.selectedSuite).toEqual(selectedSuite);
});
});
......
import Vuex from 'vuex';
import TestReports from '~/pipelines/components/test_reports/test_reports.vue';
import { shallowMount } from '@vue/test-utils';
import { testReports } from './mock_data';
import * as actions from '~/pipelines/stores/test_reports/actions';
import { getJSONFixture } from 'helpers/fixtures';
describe('Test reports app', () => {
let wrapper;
let store;
const testReports = getJSONFixture('pipelines/test_report.json');
const loadingSpinner = () => wrapper.find('.js-loading-spinner');
const testsDetail = () => wrapper.find('.js-tests-detail');
const noTestsToShow = () => wrapper.find('.js-no-tests-to-show');
......
......@@ -3,18 +3,26 @@ 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 { shallowMount } from '@vue/test-utils';
import { testSuites, testCases } from './mock_data';
import { getJSONFixture } from 'helpers/fixtures';
import skippedTestCases from './mock_data';
describe('Test reports suite table', () => {
let wrapper;
let store;
const {
test_suites: [testSuite],
} = getJSONFixture('pipelines/test_report.json');
testSuite.test_cases = [...testSuite.test_cases, ...skippedTestCases];
const testCases = testSuite.test_cases;
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 findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
const createComponent = (suite = testSuites[0]) => {
const createComponent = (suite = testSuite) => {
store = new Vuex.Store({
state: {
selectedSuite: suite,
......
import Summary from '~/pipelines/components/test_reports/test_summary.vue';
import { mount } from '@vue/test-utils';
import { testSuites } from './mock_data';
import { getJSONFixture } from 'helpers/fixtures';
describe('Test reports summary', () => {
let wrapper;
const {
test_suites: [testSuite],
} = getJSONFixture('pipelines/test_report.json');
const backButton = () => wrapper.find('.js-back-button');
const totalTests = () => wrapper.find('.js-total-tests');
const failedTests = () => wrapper.find('.js-failed-tests');
......@@ -13,7 +17,7 @@ describe('Test reports summary', () => {
const duration = () => wrapper.find('.js-duration');
const defaultProps = {
report: testSuites[0],
report: testSuite,
showBack: false,
};
......@@ -72,7 +76,7 @@ describe('Test reports summary', () => {
});
it('displays the correctly formatted duration', () => {
expect(duration().text()).toBe('00:01:00');
expect(duration().text()).toBe('00:00:00');
});
});
});
......@@ -2,7 +2,7 @@ import Vuex from 'vuex';
import SummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue';
import * as getters from '~/pipelines/stores/test_reports/getters';
import { mount, createLocalVue } from '@vue/test-utils';
import { testReports, testReportsWithNoSuites } from './mock_data';
import { getJSONFixture } from 'helpers/fixtures';
const localVue = createLocalVue();
localVue.use(Vuex);
......@@ -11,6 +11,8 @@ describe('Test reports summary table', () => {
let wrapper;
let store;
const testReports = getJSONFixture('pipelines/test_report.json');
const allSuitesRows = () => wrapper.findAll('.js-suite-row');
const noSuitesToShow = () => wrapper.find('.js-no-tests-suites');
......@@ -44,7 +46,7 @@ describe('Test reports summary table', () => {
describe('when there are no test suites', () => {
beforeEach(() => {
createComponent({ testReportsWithNoSuites });
createComponent({ test_suites: [] });
});
it('displays the no suites to show message', () => {
......
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