Commit a230569e authored by Natalia Tepluhina's avatar Natalia Tepluhina Committed by Vitaly Slobodin

Fixed test cases count

Applied a fix to test cases count
Fixed a query shape

Fixed a loading state test

Made test passing

Removed unnnecessary $apollo properties

Added changelog entry
parent a0d465de
...@@ -13,7 +13,6 @@ import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/auth ...@@ -13,7 +13,6 @@ import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/auth
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import projectTestCases from '../queries/project_test_cases.query.graphql'; import projectTestCases from '../queries/project_test_cases.query.graphql';
import projectTestCasesCount from '../queries/project_test_cases_count.query.graphql';
import { TestCaseTabs, AvailableSortOptions, DEFAULT_PAGE_SIZE } from '../constants'; import { TestCaseTabs, AvailableSortOptions, DEFAULT_PAGE_SIZE } from '../constants';
import TestCaseListEmptyState from './test_case_list_empty_state.vue'; import TestCaseListEmptyState from './test_case_list_empty_state.vue';
...@@ -47,7 +46,7 @@ export default { ...@@ -47,7 +46,7 @@ export default {
}, },
}, },
apollo: { apollo: {
testCases: { project: {
query: projectTestCases, query: projectTestCases,
variables() { variables() {
const queryVariables = { const queryVariables = {
...@@ -78,14 +77,6 @@ export default { ...@@ -78,14 +77,6 @@ export default {
return queryVariables; return queryVariables;
}, },
update(data) {
const testCasesRoot = data.project?.issues;
return {
list: testCasesRoot?.nodes || [],
pageInfo: testCasesRoot?.pageInfo || {},
};
},
error(error) { error(error) {
createFlash({ createFlash({
message: s__('TestCases|Something went wrong while fetching test cases list.'), message: s__('TestCases|Something went wrong while fetching test cases list.'),
...@@ -94,31 +85,6 @@ export default { ...@@ -94,31 +85,6 @@ export default {
}); });
}, },
}, },
testCasesCount: {
query: projectTestCasesCount,
variables() {
return {
projectPath: this.projectFullPath,
types: ['TEST_CASE'],
};
},
update(data) {
const { opened, closed, all } = data.project?.issueStatusCounts;
return {
opened,
closed,
all,
};
},
error(error) {
createFlash({
message: s__('TestCases|Something went wrong while fetching count of test cases.'),
captureError: true,
error,
});
},
},
}, },
data() { data() {
return { return {
...@@ -128,23 +94,32 @@ export default { ...@@ -128,23 +94,32 @@ export default {
nextPageCursor: this.next, nextPageCursor: this.next,
filterParams: this.initialFilterParams, filterParams: this.initialFilterParams,
sortedBy: this.initialSortBy, sortedBy: this.initialSortBy,
testCases: { project: {
list: [], issueStatusCounts: {},
pageInfo: {}, issues: {},
},
testCasesCount: {
opened: 0,
closed: 0,
all: 0,
}, },
}; };
}, },
computed: { computed: {
testCases() {
return {
list: this.project?.issues?.nodes || [],
pageInfo: this.project?.issues?.pageInfo || {},
};
},
testCasesCount() {
const { opened = 0, closed = 0, all = 0 } = this.project?.issueStatusCounts || {};
return {
opened,
closed,
all,
};
},
testCaseListLoading() { testCaseListLoading() {
return this.$apollo.queries.testCases.loading; return this.$apollo.queries.project.loading;
}, },
testCaseListEmpty() { testCaseListEmpty() {
return !this.$apollo.queries.testCases.loading && !this.testCases.list.length; return !this.$apollo.queries.project.loading && !this.testCases.list.length;
}, },
showPaginationControls() { showPaginationControls() {
const { hasPreviousPage, hasNextPage } = this.testCases.pageInfo; const { hasPreviousPage, hasNextPage } = this.testCases.pageInfo;
......
...@@ -17,6 +17,16 @@ query projectIssues( ...@@ -17,6 +17,16 @@ query projectIssues(
) { ) {
project(fullPath: $projectPath) { project(fullPath: $projectPath) {
name name
issueStatusCounts(
types: $types
authorUsername: $authorUsername
labelName: $labelName
search: $search
) {
opened
closed
all
}
issues( issues(
types: $types types: $types
state: $state state: $state
......
query projectIssueCounts($projectPath: ID!, $types: [IssueType!]) {
project(fullPath: $projectPath) {
issueStatusCounts(types: $types) {
opened
closed
all
}
}
}
---
title: Resolve Filter count does not get reflected in Test Cases
merge_request: 52889
author:
type: fixed
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import TestCaseListRoot from 'ee/test_case_list/components/test_case_list_root.vue'; import TestCaseListRoot from 'ee/test_case_list/components/test_case_list_root.vue';
import { TestCaseTabs, AvailableSortOptions } from 'ee/test_case_list/constants';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import { mockIssuable } from 'jest/issuable_list/mock_data'; import { mockIssuable } from 'jest/issuable_list/mock_data';
...@@ -31,94 +31,62 @@ const mockPageInfo = { ...@@ -31,94 +31,62 @@ const mockPageInfo = {
endCursor: 'eyJpZCI6IjIxIiwiY3JlYXRlZF9hdCI6IjIwMjAtMDMtMzEgMTM6MzE6MTUgVVRDIn0', endCursor: 'eyJpZCI6IjIxIiwiY3JlYXRlZF9hdCI6IjIwMjAtMDMtMzEgMTM6MzE6MTUgVVRDIn0',
}; };
const createComponent = ({
provide = mockProvide,
initialFilterParams = {},
testCasesLoading = false,
testCasesList = [],
} = {}) =>
shallowMount(TestCaseListRoot, {
propsData: {
initialFilterParams,
},
provide,
mocks: {
$apollo: {
queries: {
testCases: {
loading: testCasesLoading,
list: testCasesList,
pageInfo: mockPageInfo,
},
testCasesCount: {
loading: testCasesLoading,
opened: 5,
closed: 0,
all: 5,
},
},
},
},
});
describe('TestCaseListRoot', () => { describe('TestCaseListRoot', () => {
let wrapper; let wrapper;
beforeEach(() => { const getIssuableList = () => wrapper.find(IssuableList);
wrapper = createComponent();
}); const createComponent = ({
provide = mockProvide,
initialFilterParams = {},
testCasesLoading = false,
data = {},
} = {}) => {
wrapper = shallowMount(TestCaseListRoot, {
propsData: {
initialFilterParams,
},
data() {
return data;
},
provide,
mocks: {
$apollo: {
queries: {
project: {
loading: testCasesLoading,
},
},
},
},
});
};
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
describe('computed', () => { describe('passes a correct loading state to Issuables List', () => {
describe('testCaseListLoading', () => { it.each`
it.each` testCasesLoading | returnValue
testCasesLoading | returnValue ${true} | ${true}
${true} | ${true} ${false} | ${false}
${false} | ${false} `(
`( 'passes $returnValue to Issuables List prop when query loading is $testCasesLoading',
'returns $returnValue when testCases query loading is $loadingValue', ({ testCasesLoading, returnValue }) => {
({ testCasesLoading, returnValue }) => { createComponent({
const wrapperTemp = createComponent({ provide: mockProvide,
provide: mockProvide, initialFilterParams: {},
initialFilterParams: {}, testCasesList: [],
testCasesList: [], testCasesLoading,
testCasesLoading, });
});
expect(wrapperTemp.vm.testCaseListLoading).toBe(returnValue);
wrapperTemp.destroy();
},
);
});
describe('testCaseListEmpty', () => {
it.each`
testCasesLoading | testCasesList | testCaseListDescription | returnValue
${true} | ${[]} | ${'empty'} | ${false}
${true} | ${[mockIssuable]} | ${'not empty'} | ${false}
${false} | ${[]} | ${'not empty'} | ${true}
${false} | ${[mockIssuable]} | ${'empty'} | ${true}
`(
'returns $returnValue when testCases query loading is $testCasesLoading and testCases array is $testCaseListDescription',
({ testCasesLoading, testCasesList, returnValue }) => {
const wrapperTemp = createComponent({
provide: mockProvide,
initialFilterParams: {},
testCasesLoading,
testCasesList,
});
expect(wrapperTemp.vm.testCaseListEmpty).toBe(returnValue);
wrapperTemp.destroy(); expect(getIssuableList().props('issuablesLoading')).toBe(returnValue);
}, },
); );
}); });
describe('computed', () => {
describe('showPaginationControls', () => { describe('showPaginationControls', () => {
it.each` it.each`
hasPreviousPage | hasNextPage | returnValue hasPreviousPage | hasNextPage | returnValue
...@@ -131,18 +99,20 @@ describe('TestCaseListRoot', () => { ...@@ -131,18 +99,20 @@ describe('TestCaseListRoot', () => {
`( `(
'returns $returnValue when hasPreviousPage is $hasPreviousPage and hasNextPage is $hasNextPage within `testCases.pageInfo`', 'returns $returnValue when hasPreviousPage is $hasPreviousPage and hasNextPage is $hasNextPage within `testCases.pageInfo`',
async ({ hasPreviousPage, hasNextPage, returnValue }) => { async ({ hasPreviousPage, hasNextPage, returnValue }) => {
wrapper.setData({ createComponent({
testCases: { data: {
pageInfo: { project: {
hasPreviousPage, issues: {
hasNextPage, pageInfo: {
hasPreviousPage,
hasNextPage,
},
},
}, },
}, },
}); });
await wrapper.vm.$nextTick(); expect(getIssuableList().props('showPaginationControls')).toBe(returnValue);
expect(wrapper.vm.showPaginationControls).toBe(returnValue);
}, },
); );
...@@ -153,38 +123,44 @@ describe('TestCaseListRoot', () => { ...@@ -153,38 +123,44 @@ describe('TestCaseListRoot', () => {
`( `(
'returns $returnValue when testCases array is $testCaseListDescription', 'returns $returnValue when testCases array is $testCaseListDescription',
async ({ testCasesList, returnValue }) => { async ({ testCasesList, returnValue }) => {
wrapper.setData({ createComponent({
testCases: { data: {
list: testCasesList, project: {
issues: {
nodes: testCasesList,
},
},
}, },
}); });
await wrapper.vm.$nextTick(); expect(getIssuableList().props('showPaginationControls')).toBe(returnValue);
expect(wrapper.vm.showPaginationControls).toBe(returnValue);
}, },
); );
}); });
describe('previousPage', () => { describe('previousPage', () => {
it('returns number representing previous page based on currentPage value', () => { it('returns number representing previous page based on currentPage value', () => {
wrapper.setData({ createComponent({
currentPage: 3, data: {
currentPage: 3,
},
}); });
return wrapper.vm.$nextTick(() => { expect(getIssuableList().props('previousPage')).toBe(2);
expect(wrapper.vm.previousPage).toBe(2);
});
}); });
}); });
describe('nextPage', () => { describe('nextPage', () => {
beforeEach(() => { beforeEach(() => {
wrapper.setData({ createComponent({
testCasesCount: { data: {
opened: 5, project: {
closed: 0, issueStatusCounts: {
all: 5, opened: 5,
closed: 0,
all: 5,
},
},
}, },
}); });
}); });
...@@ -194,9 +170,9 @@ describe('TestCaseListRoot', () => { ...@@ -194,9 +170,9 @@ describe('TestCaseListRoot', () => {
currentPage: 1, currentPage: 1,
}); });
await wrapper.vm.$nextTick(); await nextTick;
expect(wrapper.vm.nextPage).toBe(2); expect(getIssuableList().props('nextPage')).toBe(2);
}); });
it('returns `null` when currentPage is already last page', async () => { it('returns `null` when currentPage is already last page', async () => {
...@@ -204,9 +180,9 @@ describe('TestCaseListRoot', () => { ...@@ -204,9 +180,9 @@ describe('TestCaseListRoot', () => {
currentPage: 3, currentPage: 3,
}); });
await wrapper.vm.$nextTick(); await nextTick;
expect(wrapper.vm.nextPage).toBeNull(); expect(getIssuableList().props('nextPage')).toBeNull();
}); });
}); });
}); });
...@@ -214,20 +190,20 @@ describe('TestCaseListRoot', () => { ...@@ -214,20 +190,20 @@ describe('TestCaseListRoot', () => {
describe('methods', () => { describe('methods', () => {
describe('updateUrl', () => { describe('updateUrl', () => {
it('updates window URL based on presence of props for filtered search and sort criteria', async () => { it('updates window URL based on presence of props for filtered search and sort criteria', async () => {
wrapper.setData({ createComponent({
currentState: 'opened', data: {
currentPage: 2, currentState: 'opened',
nextPageCursor: 'abc123', currentPage: 2,
sortedBy: 'updated_asc', nextPageCursor: 'abc123',
filterParams: { sortedBy: 'updated_asc',
authorUsernames: 'root', filterParams: {
search: 'foo', authorUsernames: 'root',
labelName: ['bug'], search: 'foo',
labelName: ['bug'],
},
}, },
}); });
await wrapper.vm.$nextTick();
wrapper.vm.updateUrl(); wrapper.vm.updateUrl();
expect(global.window.location.href).toBe( expect(global.window.location.href).toBe(
...@@ -238,49 +214,22 @@ describe('TestCaseListRoot', () => { ...@@ -238,49 +214,22 @@ describe('TestCaseListRoot', () => {
}); });
describe('template', () => { describe('template', () => {
const getIssuableList = () => wrapper.find(IssuableList);
it('renders issuable-list component', () => {
expect(getIssuableList().exists()).toBe(true);
expect(getIssuableList().props()).toMatchObject({
namespace: mockProvide.projectFullPath,
tabs: TestCaseTabs,
tabCounts: {
opened: 0,
closed: 0,
all: 0,
},
currentTab: 'opened',
searchInputPlaceholder: 'Search test cases',
searchTokens: expect.any(Array),
sortOptions: AvailableSortOptions,
initialSortBy: 'created_desc',
issuables: [],
issuablesLoading: false,
showPaginationControls: wrapper.vm.showPaginationControls,
defaultPageSize: 2, // mocked value in tests
currentPage: 1,
previousPage: 0,
nextPage: null,
recentSearchesStorageKey: 'test_cases',
issuableSymbol: '#',
});
});
describe('issuable-list events', () => { describe('issuable-list events', () => {
beforeEach(() => { beforeEach(() => {
createComponent();
jest.spyOn(wrapper.vm, 'updateUrl').mockImplementation(jest.fn); jest.spyOn(wrapper.vm, 'updateUrl').mockImplementation(jest.fn);
}); });
it('click-tab event changes currentState value and calls updateUrl', () => { it('click-tab event changes currentState value and calls updateUrl', async () => {
getIssuableList().vm.$emit('click-tab', 'closed'); getIssuableList().vm.$emit('click-tab', 'closed');
expect(wrapper.vm.currentState).toBe('closed'); await nextTick;
expect(getIssuableList().props('currentTab')).toBe('closed');
expect(wrapper.vm.updateUrl).toHaveBeenCalled(); expect(wrapper.vm.updateUrl).toHaveBeenCalled();
}); });
it('page-change event changes prevPageCursor and nextPageCursor values based on based on currentPage and calls updateUrl', () => { it('page-change event changes prevPageCursor and nextPageCursor values based on based on currentPage and calls updateUrl', async () => {
wrapper.setData({ await wrapper.setData({
testCases: { testCases: {
pageInfo: mockPageInfo, pageInfo: mockPageInfo,
}, },
...@@ -293,7 +242,7 @@ describe('TestCaseListRoot', () => { ...@@ -293,7 +242,7 @@ describe('TestCaseListRoot', () => {
expect(wrapper.vm.updateUrl).toHaveBeenCalled(); expect(wrapper.vm.updateUrl).toHaveBeenCalled();
}); });
it('filter event changes filterParams value and calls updateUrl', () => { it('filter event changes filterParams value and calls updateUrl', async () => {
getIssuableList().vm.$emit('filter', [ getIssuableList().vm.$emit('filter', [
{ {
type: 'author_username', type: 'author_username',
...@@ -315,18 +264,22 @@ describe('TestCaseListRoot', () => { ...@@ -315,18 +264,22 @@ describe('TestCaseListRoot', () => {
}, },
]); ]);
expect(wrapper.vm.filterParams).toEqual({ await nextTick;
authorUsername: 'root',
labelName: ['bug'], expect(getIssuableList().props('initialFilterValue')).toEqual([
search: 'foo', { type: 'author_username', value: { data: 'root' } },
}); { type: 'label_name', value: { data: 'bug' } },
'foo',
]);
expect(wrapper.vm.updateUrl).toHaveBeenCalled(); expect(wrapper.vm.updateUrl).toHaveBeenCalled();
}); });
it('sort event changes sortedBy value and calls updateUrl', () => { it('sort event changes sortedBy value and calls updateUrl', async () => {
getIssuableList().vm.$emit('sort', 'updated_desc'); getIssuableList().vm.$emit('sort', 'updated_desc');
expect(wrapper.vm.sortedBy).toEqual('updated_desc'); await nextTick;
expect(getIssuableList().props('initialSortBy')).toBe('updated_desc');
expect(wrapper.vm.updateUrl).toHaveBeenCalled(); expect(wrapper.vm.updateUrl).toHaveBeenCalled();
}); });
}); });
......
...@@ -28475,9 +28475,6 @@ msgstr "" ...@@ -28475,9 +28475,6 @@ msgstr ""
msgid "TestCases|Something went wrong while creating a test case." msgid "TestCases|Something went wrong while creating a test case."
msgstr "" msgstr ""
msgid "TestCases|Something went wrong while fetching count of test cases."
msgstr ""
msgid "TestCases|Something went wrong while fetching test case." msgid "TestCases|Something went wrong while fetching test case."
msgstr "" msgstr ""
......
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