Wrap pagination events in a helper

parent aec26eeb
......@@ -112,8 +112,14 @@ export default {
};
},
computed: {
pipelineNodes() {
return this.pipelines?.nodes ?? [];
},
hasPipelines() {
return Boolean(this.pipelines?.nodes?.length);
return this.pipelineNodes.length > 0;
},
pageInfo() {
return this.pipelines?.pageInfo;
},
tableFields() {
return this.fields.map(({ key, label }) => ({
......@@ -124,6 +130,13 @@ export default {
}));
},
},
watch: {
hasPipelines(hasPipelines) {
if (this.hasError && hasPipelines) {
this.hasError = false;
}
},
},
methods: {
resetCursor() {
this.cursor = { ...defaultCursor };
......@@ -168,23 +181,24 @@ export default {
{{ title }}
<gl-badge size="sm" class="gl-tab-counter-badge">{{ itemsCount }}</gl-badge>
</template>
<template v-if="$apollo.queries.pipelines.loading">
<gl-skeleton-loader v-for="i in 20" :key="i" :width="815" :height="50">
<rect width="85" height="20" x="15" y="15" rx="4" />
<rect width="155" height="20" x="125" y="15" rx="4" />
<rect width="60" height="20" x="350" y="15" rx="4" />
<rect width="150" height="20" x="450" y="15" rx="4" />
<rect width="70" height="20" x="640" y="15" rx="4" />
<rect width="25" height="20" x="740" y="15" rx="4" />
</gl-skeleton-loader>
</template>
<template v-else-if="hasPipelines">
<template v-if="$apollo.queries.pipelines.loading || hasPipelines">
<gl-table
thead-class="gl-border-b-solid gl-border-gray-100 gl-border-1"
:fields="tableFields"
:items="pipelines.nodes"
:items="pipelineNodes"
:busy="$apollo.queries.pipelines.loading"
stacked="md"
>
<template #table-busy>
<gl-skeleton-loader v-for="i in 20" :key="i" :width="1000" :height="45">
<rect width="85" height="20" x="0" y="5" rx="4" />
<rect width="100" height="20" x="150" y="5" rx="4" />
<rect width="150" height="20" x="300" y="5" rx="4" />
<rect width="100" height="20" x="500" y="5" rx="4" />
<rect width="150" height="20" x="655" y="5" rx="4" />
<rect width="70" height="20" x="855" y="5" rx="4" />
</gl-skeleton-loader>
</template>
<template #cell(detailedStatus)="{ item }">
<div class="gl-my-3">
<ci-badge-link :status="item.detailedStatus" />
......@@ -207,7 +221,7 @@ export default {
<div class="gl-display-flex gl-justify-content-center">
<gl-keyset-pagination
data-testid="pagination"
v-bind="pipelines.pageInfo"
v-bind="pageInfo"
:prev-text="$options.i18n.previousPage"
:next-text="$options.i18n.nextPage"
@prev="prevPage"
......@@ -215,11 +229,15 @@ export default {
/>
</div>
</template>
<template v-else-if="hasError">
<gl-alert variant="danger" :dismissible="false" class="gl-my-4" data-testid="error-alert">
{{ $options.i18n.errorMessage }}
</gl-alert>
</template>
<gl-alert
v-else-if="hasError"
variant="danger"
:dismissible="false"
class="gl-my-4"
data-testid="error-alert"
>
{{ $options.i18n.errorMessage }}
</gl-alert>
<empty-state v-else :title="emptyStateTitle" :text="emptyStateText" no-primary-button />
</gl-tab>
</template>
import { GlTab, GlTable, GlSkeletonLoader, GlAlert } from '@gitlab/ui';
import { GlTab, GlTable, GlAlert } from '@gitlab/ui';
import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import allPipelinesWithPipelinesMock from 'test_fixtures/graphql/on_demand_scans/graphql/on_demand_scans.query.graphql.with_pipelines.json';
......@@ -32,7 +32,6 @@ describe('BaseTab', () => {
const findTable = () => wrapper.findComponent(GlTable);
const findEmptyState = () => wrapper.findComponent(EmptyState);
const findPagination = () => wrapper.findByTestId('pagination');
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findErrorAlert = () => wrapper.findComponent(GlAlert);
// Helpers
......@@ -40,6 +39,11 @@ describe('BaseTab', () => {
return createMockApollo([[onDemandScansQuery, requestHandler]]);
};
const navigateToPage = (direction) => {
findPagination().vm.$emit(direction);
return wrapper.vm.$nextTick();
};
const createComponent = (propsData) => {
router = createRouter();
wrapper = shallowMountExtended(BaseTab, {
......@@ -68,7 +72,7 @@ describe('BaseTab', () => {
`,
}),
GlTable: stubComponent(GlTable, {
props: ['items'],
props: ['items', 'busy'],
}),
},
});
......@@ -97,12 +101,14 @@ describe('BaseTab', () => {
});
});
it('shows a loader until the request resolves', async () => {
it('puts the table in the busy state until the request resolves', async () => {
createComponent();
expect(findSkeletonLoader().exists()).toBe(true);
expect(findTable().props('busy')).toBe(true);
await waitForPromises();
expect(findSkeletonLoader().exists()).toBe(false);
expect(findTable().props('busy')).toBe(false);
});
it('resets the route if no pipeline matches the cursor', async () => {
......@@ -138,8 +144,8 @@ describe('BaseTab', () => {
);
});
it('when navigating to another page, scrolls back to the top', () => {
findPagination().vm.$emit('next');
it('when navigating to another page, scrolls back to the top', async () => {
await navigateToPage('next');
expect(scrollToElement).toHaveBeenCalledWith(wrapper.vm.$el);
});
......@@ -148,18 +154,16 @@ describe('BaseTab', () => {
expect(Object.keys(router.currentRoute.query)).not.toContain('after');
expect(requestHandler).toHaveBeenCalledTimes(1);
findPagination().vm.$emit('next');
await wrapper.vm.$nextTick();
await navigateToPage('next');
expect(Object.keys(router.currentRoute.query)).toContain('after');
expect(requestHandler).toHaveBeenCalledTimes(2);
});
it('when navigating back to the previous page, the route is updated and pipelines are fetched', async () => {
findPagination().vm.$emit('next');
await navigateToPage('next');
await waitForPromises();
findPagination().vm.$emit('prev');
await wrapper.vm.$nextTick();
await navigateToPage('prev');
expect(Object.keys(router.currentRoute.query)).not.toContain('after');
expect(Object.keys(router.currentRoute.query)).toContain('before');
......@@ -179,14 +183,32 @@ describe('BaseTab', () => {
});
describe('when the request errors out', () => {
let respondWithError;
beforeEach(async () => {
requestHandler = jest.fn().mockRejectedValue();
respondWithError = true;
requestHandler = () => {
const response = respondWithError
? Promise.reject()
: Promise.resolve(allPipelinesWithPipelinesMock);
respondWithError = false;
return response;
};
createComponent();
await waitForPromises();
});
it('show an error alert', () => {
it('shows an error alert', () => {
expect(findErrorAlert().exists()).toBe(true);
});
it('removes the alert if the next request succeeds', async () => {
expect(findErrorAlert().exists()).toBe(true);
wrapper.vm.$apollo.queries.pipelines.refetch();
await waitForPromises();
expect(findErrorAlert().exists()).toBe(false);
});
});
});
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