Commit 9e372d91 authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch '280512-paginate-test-report' into 'master'

Paginate unit test report

See merge request gitlab-org/gitlab!47953
parents 2e7f6780 f33766b1
<script> <script>
import { mapGetters } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import { GlModalDirective, GlTooltipDirective, GlFriendlyWrap, GlIcon, GlButton } from '@gitlab/ui'; import {
GlModalDirective,
GlTooltipDirective,
GlFriendlyWrap,
GlIcon,
GlButton,
GlPagination,
} from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import TestCaseDetails from './test_case_details.vue'; import TestCaseDetails from './test_case_details.vue';
...@@ -10,6 +17,7 @@ export default { ...@@ -10,6 +17,7 @@ export default {
GlIcon, GlIcon,
GlFriendlyWrap, GlFriendlyWrap,
GlButton, GlButton,
GlPagination,
TestCaseDetails, TestCaseDetails,
}, },
directives: { directives: {
...@@ -24,11 +32,15 @@ export default { ...@@ -24,11 +32,15 @@ export default {
}, },
}, },
computed: { computed: {
...mapGetters(['getSuiteTests']), ...mapState(['pageInfo']),
...mapGetters(['getSuiteTests', 'getSuiteTestCount']),
hasSuites() { hasSuites() {
return this.getSuiteTests.length > 0; return this.getSuiteTests.length > 0;
}, },
}, },
methods: {
...mapActions(['setPage']),
},
wrapSymbols: ['::', '#', '.', '_', '-', '/', '\\'], wrapSymbols: ['::', '#', '.', '_', '-', '/', '\\'],
}; };
</script> </script>
...@@ -129,6 +141,14 @@ export default { ...@@ -129,6 +141,14 @@ export default {
</div> </div>
</div> </div>
</div> </div>
<gl-pagination
v-model="pageInfo.page"
class="gl-display-flex gl-justify-content-center"
:per-page="pageInfo.perPage"
:total-items="getSuiteTestCount"
@input="setPage"
/>
</div> </div>
<div v-else> <div v-else>
......
...@@ -47,6 +47,7 @@ export const fetchTestSuite = ({ state, commit, dispatch }, index) => { ...@@ -47,6 +47,7 @@ export const fetchTestSuite = ({ state, commit, dispatch }, index) => {
}); });
}; };
export const setPage = ({ commit }, page) => commit(types.SET_PAGE, page);
export const setSelectedSuiteIndex = ({ commit }, data) => export const setSelectedSuiteIndex = ({ commit }, data) =>
commit(types.SET_SELECTED_SUITE_INDEX, data); commit(types.SET_SELECTED_SUITE_INDEX, data);
export const removeSelectedSuiteIndex = ({ commit }) => export const removeSelectedSuiteIndex = ({ commit }) =>
......
...@@ -14,5 +14,10 @@ export const getSelectedSuite = state => ...@@ -14,5 +14,10 @@ export const getSelectedSuite = state =>
export const getSuiteTests = state => { export const getSuiteTests = state => {
const { test_cases: testCases = [] } = getSelectedSuite(state); const { test_cases: testCases = [] } = getSelectedSuite(state);
return testCases.map(addIconStatus); const { page, perPage } = state.pageInfo;
const start = (page - 1) * perPage;
return testCases.map(addIconStatus).slice(start, start + perPage);
}; };
export const getSuiteTestCount = state => getSelectedSuite(state)?.test_cases?.length || 0;
export const SET_PAGE = 'SET_PAGE';
export const SET_SELECTED_SUITE_INDEX = 'SET_SELECTED_SUITE_INDEX'; export const SET_SELECTED_SUITE_INDEX = 'SET_SELECTED_SUITE_INDEX';
export const SET_SUMMARY = 'SET_SUMMARY'; export const SET_SUMMARY = 'SET_SUMMARY';
export const SET_SUITE = 'SET_SUITE'; export const SET_SUITE = 'SET_SUITE';
......
import * as types from './mutation_types'; import * as types from './mutation_types';
export default { export default {
[types.SET_PAGE](state, page) {
Object.assign(state, {
pageInfo: Object.assign(state.pageInfo, {
page,
}),
});
},
[types.SET_SUITE](state, { suite = {}, index = null }) { [types.SET_SUITE](state, { suite = {}, index = null }) {
state.testReports.test_suites[index] = { ...suite, hasFullSuite: true }; state.testReports.test_suites[index] = { ...suite, hasFullSuite: true };
}, },
......
...@@ -4,4 +4,8 @@ export default ({ summaryEndpoint = '', suiteEndpoint = '' }) => ({ ...@@ -4,4 +4,8 @@ export default ({ summaryEndpoint = '', suiteEndpoint = '' }) => ({
testReports: {}, testReports: {},
selectedSuiteIndex: null, selectedSuiteIndex: null,
isLoading: false, isLoading: false,
pageInfo: {
page: 1,
perPage: 20,
},
}); });
---
title: Paginate unit test report
merge_request: 47953
author:
type: performance
...@@ -10,11 +10,19 @@ describe('Getters TestReports Store', () => { ...@@ -10,11 +10,19 @@ describe('Getters TestReports Store', () => {
const defaultState = { const defaultState = {
testReports, testReports,
selectedSuiteIndex: 0, selectedSuiteIndex: 0,
pageInfo: {
page: 1,
perPage: 2,
},
}; };
const emptyState = { const emptyState = {
testReports: {}, testReports: {},
selectedSuite: null, selectedSuite: null,
pageInfo: {
page: 1,
perPage: 2,
},
}; };
beforeEach(() => { beforeEach(() => {
...@@ -59,15 +67,17 @@ describe('Getters TestReports Store', () => { ...@@ -59,15 +67,17 @@ describe('Getters TestReports Store', () => {
}); });
describe('getSuiteTests', () => { describe('getSuiteTests', () => {
it('should return the test cases inside the suite', () => { it('should return the current page of test cases inside the suite', () => {
setupState(); setupState();
const cases = getters.getSuiteTests(state); const cases = getters.getSuiteTests(state);
const expected = testReports.test_suites[0].test_cases.map(x => ({ const expected = testReports.test_suites[0].test_cases
...x, .map(x => ({
formattedTime: formattedTime(x.execution_time), ...x,
icon: iconForTestStatus(x.status), formattedTime: formattedTime(x.execution_time),
})); icon: iconForTestStatus(x.status),
}))
.slice(0, state.pageInfo.perPage);
expect(cases).toEqual(expected); expect(cases).toEqual(expected);
}); });
...@@ -78,4 +88,15 @@ describe('Getters TestReports Store', () => { ...@@ -78,4 +88,15 @@ describe('Getters TestReports Store', () => {
expect(getters.getSuiteTests(state)).toEqual([]); expect(getters.getSuiteTests(state)).toEqual([]);
}); });
}); });
describe('getSuiteTestCount', () => {
it('should return the total number of test cases', () => {
setupState();
const testCount = getters.getSuiteTestCount(state);
const expected = testReports.test_suites[0].test_cases.length;
expect(testCount).toEqual(expected);
});
});
}); });
...@@ -12,12 +12,25 @@ describe('Mutations TestReports Store', () => { ...@@ -12,12 +12,25 @@ describe('Mutations TestReports Store', () => {
testReports: {}, testReports: {},
selectedSuite: null, selectedSuite: null,
isLoading: false, isLoading: false,
pageInfo: {
page: 1,
perPage: 2,
},
}; };
beforeEach(() => { beforeEach(() => {
mockState = { ...defaultState }; mockState = { ...defaultState };
}); });
describe('set page', () => {
it('should set the current page to display', () => {
const pageToDisplay = 3;
mutations[types.SET_PAGE](mockState, pageToDisplay);
expect(mockState.pageInfo.page).toEqual(pageToDisplay);
});
});
describe('set suite', () => { describe('set suite', () => {
it('should set the suite at the given index', () => { it('should set the suite at the given index', () => {
mockState.testReports = testReports; mockState.testReports = testReports;
......
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, GlFriendlyWrap } from '@gitlab/ui'; import { GlButton, GlFriendlyWrap, GlPagination } 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';
...@@ -26,13 +26,17 @@ describe('Test reports suite table', () => { ...@@ -26,13 +26,17 @@ describe('Test reports suite table', () => {
const findCaseRowAtIndex = index => wrapper.findAll('.js-case-row').at(index); const findCaseRowAtIndex = index => wrapper.findAll('.js-case-row').at(index);
const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`); const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
const createComponent = (suite = testSuite) => { const createComponent = (suite = testSuite, perPage = 20) => {
store = new Vuex.Store({ store = new Vuex.Store({
state: { state: {
testReports: { testReports: {
test_suites: [suite], test_suites: [suite],
}, },
selectedSuiteIndex: 0, selectedSuiteIndex: 0,
pageInfo: {
page: 1,
perPage,
},
}, },
getters, getters,
}); });
...@@ -86,4 +90,20 @@ describe('Test reports suite table', () => { ...@@ -86,4 +90,20 @@ describe('Test reports suite table', () => {
expect(button.attributes('data-clipboard-text')).toBe(file); expect(button.attributes('data-clipboard-text')).toBe(file);
}); });
}); });
describe('when a test suite has more test cases than the pagination size', () => {
const perPage = 2;
beforeEach(() => {
createComponent(testSuite, perPage);
});
it('renders one page of test cases', () => {
expect(allCaseRows().length).toBe(perPage);
});
it('renders a pagination component', () => {
expect(wrapper.find(GlPagination).exists()).toBe(true);
});
});
}); });
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