Commit 7736ce72 authored by Scott Hampton's avatar Scott Hampton

Handle errors when fetching projects

Add error handling to the apollo queries. Add
specs for testing that the error handling works.
parent 331f903b
<script>
import {
GlAlert,
GlButton,
GlDropdown,
GlDropdownSectionHeader,
......@@ -19,6 +20,7 @@ import getGroupProjects from '../graphql/queries/get_group_projects.query.graphq
export default {
name: 'GroupRepositoryAnalytics',
components: {
GlAlert,
GlButton,
GlDropdown,
GlDropdownSectionHeader,
......@@ -57,13 +59,17 @@ export default {
}));
},
result({ data }) {
this.projectsPageInfo = data?.group?.projects?.pageInfo;
this.projectsPageInfo = data?.group?.projects?.pageInfo || {};
},
error() {
this.hasError = true;
},
},
},
data() {
return {
groupProjects: [],
hasError: false,
projectsPageInfo: {},
projectSearchTerm: '',
selectAllProjects: true,
......@@ -135,23 +141,30 @@ export default {
clickDateRange(dateRange) {
this.selectedDateRange = dateRange;
},
dismissError() {
this.hasError = false;
},
loadMoreProjects() {
this.$apollo.queries.groupProjects.fetchMore({
variables: {
groupFullPath: this.groupFullPath,
after: this.projectsPageInfo.endCursor,
},
updateQuery(previousResult, { fetchMoreResult }) {
const results = produce(fetchMoreResult, draftData => {
// eslint-disable-next-line no-param-reassign
draftData.group.projects.nodes = [
...previousResult.group.projects.nodes,
...draftData.group.projects.nodes,
];
});
return results;
},
});
this.$apollo.queries.groupProjects
.fetchMore({
variables: {
groupFullPath: this.groupFullPath,
after: this.projectsPageInfo.endCursor,
},
updateQuery(previousResult, { fetchMoreResult }) {
const results = produce(fetchMoreResult, draftData => {
// eslint-disable-next-line no-param-reassign
draftData.group.projects.nodes = [
...previousResult.group.projects.nodes,
...draftData.group.projects.nodes,
];
});
return results;
},
})
.catch(() => {
this.hasError = true;
});
},
},
text: {
......@@ -167,6 +180,7 @@ export default {
projectDropdownHeader: __('Projects'),
projectDropdownAllProjects: __('All projects'),
projectSelectAll: __('Select all'),
queryErrorMessage: s__('RepositoriesAnalytics|There was an error fetching the projects.'),
},
dateRangeOptions: [
{ value: 7, text: __('Last week') },
......@@ -194,6 +208,13 @@ export default {
:action-primary="downloadCSVModalButton"
:action-cancel="cancelModalButton"
>
<gl-alert
v-if="hasError"
variant="danger"
data-testid="group-code-coverage-projects-error"
@dismiss="dismissError"
>{{ $options.text.queryErrorMessage }}</gl-alert
>
<div>{{ $options.text.downloadCSVModalDescription }}</div>
<div class="gl-my-4">
<label class="gl-display-block col-form-label-sm col-form-label">
......
import { shallowMount, createLocalVue } from '@vue/test-utils';
import {
GlAlert,
GlDropdown,
GlDropdownItem,
GlIntersectionObserver,
......@@ -32,6 +33,7 @@ describe('Group repository analytics app', () => {
.trigger('click');
const findIntersectionObserver = () => wrapper.find(GlIntersectionObserver);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findAlert = () => wrapper.find(GlAlert);
const injectedProperties = {
groupAnalyticsCoverageReportsPath: '/coverage.csv?ref_path=refs/heads/master',
......@@ -46,6 +48,7 @@ describe('Group repository analytics app', () => {
return {
// Ensure that isSelected is set to false for each project so that every test is reset properly
groupProjects: groupProjectsData.map(project => ({ ...project, isSelected: false })),
hasError: false,
projectsPageInfo: {
hasNextPage: false,
endCursor: null,
......@@ -88,6 +91,16 @@ describe('Group repository analytics app', () => {
openCodeCoverageModal();
});
describe('when there is an error fetching the projects', () => {
beforeEach(() => {
createComponent({ data: { hasError: true } });
});
it('displays an alert for the failed query', () => {
expect(findAlert().exists()).toBe(true);
});
});
describe('when selecting a project', () => {
// Due to the fake_date helper, we can always expect today's date to be 2020-07-06
// and the default date 30 days ago to be 2020-06-06
......@@ -164,7 +177,7 @@ describe('Group repository analytics app', () => {
beforeEach(() => {
jest
.spyOn(wrapper.vm.$apollo.queries.groupProjects, 'fetchMore')
.mockImplementation(jest.fn());
.mockImplementation(jest.fn().mockResolvedValue());
findIntersectionObserver().vm.$emit('appear');
return wrapper.vm.$nextTick();
......@@ -173,6 +186,21 @@ describe('Group repository analytics app', () => {
it('makes a query to fetch more projects', () => {
expect(wrapper.vm.$apollo.queries.groupProjects.fetchMore).toHaveBeenCalledTimes(1);
});
describe('when the fetchMore query throws an error', () => {
beforeEach(() => {
jest
.spyOn(wrapper.vm.$apollo.queries.groupProjects, 'fetchMore')
.mockImplementation(jest.fn().mockRejectedValue());
findIntersectionObserver().vm.$emit('appear');
return wrapper.vm.$nextTick();
});
it('displays an alert for the failed query', () => {
expect(findAlert().exists()).toBe(true);
});
});
});
describe('when a query is loading a new page of projects', () => {
......
......@@ -8,8 +8,6 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-09-18 11:00+1200\n"
"PO-Revision-Date: 2020-09-18 11:00+1200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
......@@ -21508,6 +21506,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
msgid "RepositoriesAnalytics|There was an error fetching the projects."
msgstr ""
msgid "Repository"
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