Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/ci/catalog/components/pages/ci_resource_details_page_spec.js')
-rw-r--r--spec/frontend/ci/catalog/components/pages/ci_resource_details_page_spec.js186
1 files changed, 186 insertions, 0 deletions
diff --git a/spec/frontend/ci/catalog/components/pages/ci_resource_details_page_spec.js b/spec/frontend/ci/catalog/components/pages/ci_resource_details_page_spec.js
new file mode 100644
index 00000000000..40f243ed891
--- /dev/null
+++ b/spec/frontend/ci/catalog/components/pages/ci_resource_details_page_spec.js
@@ -0,0 +1,186 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import VueRouter from 'vue-router';
+import { GlEmptyState } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { CI_CATALOG_RESOURCE_TYPE, cacheConfig } from '~/ci/catalog/graphql/settings';
+
+import getCiCatalogResourceSharedData from '~/ci/catalog/graphql/queries/get_ci_catalog_resource_shared_data.query.graphql';
+import getCiCatalogResourceDetails from '~/ci/catalog/graphql/queries/get_ci_catalog_resource_details.query.graphql';
+
+import CiResourceDetails from '~/ci/catalog/components/details/ci_resource_details.vue';
+import CiResourceDetailsPage from '~/ci/catalog/components/pages/ci_resource_details_page.vue';
+import CiResourceHeader from '~/ci/catalog/components/details/ci_resource_header.vue';
+import CiResourceHeaderSkeletonLoader from '~/ci/catalog/components/details/ci_resource_header_skeleton_loader.vue';
+
+import { createRouter } from '~/ci/catalog/router/index';
+import { CI_RESOURCE_DETAILS_PAGE_NAME } from '~/ci/catalog/router/constants';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { catalogSharedDataMock, catalogAdditionalDetailsMock } from '../../mock';
+
+Vue.use(VueApollo);
+Vue.use(VueRouter);
+
+let router;
+
+const defaultSharedData = { ...catalogSharedDataMock.data.ciCatalogResource };
+const defaultAdditionalData = { ...catalogAdditionalDetailsMock.data.ciCatalogResource };
+
+describe('CiResourceDetailsPage', () => {
+ let wrapper;
+ let sharedDataResponse;
+ let additionalDataResponse;
+
+ const defaultProps = {};
+
+ const defaultProvide = {
+ ciCatalogPath: '/ci/catalog/resources',
+ };
+
+ const findDetailsComponent = () => wrapper.findComponent(CiResourceDetails);
+ const findHeaderComponent = () => wrapper.findComponent(CiResourceHeader);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findHeaderSkeletonLoader = () => wrapper.findComponent(CiResourceHeaderSkeletonLoader);
+
+ const createComponent = ({ props = {} } = {}) => {
+ const handlers = [
+ [getCiCatalogResourceSharedData, sharedDataResponse],
+ [getCiCatalogResourceDetails, additionalDataResponse],
+ ];
+
+ const mockApollo = createMockApollo(handlers, undefined, cacheConfig);
+
+ wrapper = shallowMount(CiResourceDetailsPage, {
+ router,
+ apolloProvider: mockApollo,
+ provide: {
+ ...defaultProvide,
+ },
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ stubs: {
+ RouterView: true,
+ },
+ });
+ };
+
+ beforeEach(async () => {
+ sharedDataResponse = jest.fn();
+ additionalDataResponse = jest.fn();
+
+ router = createRouter();
+ await router.push({
+ name: CI_RESOURCE_DETAILS_PAGE_NAME,
+ params: { id: defaultSharedData.id },
+ });
+ });
+
+ describe('when the app is loading', () => {
+ describe('and shared data is pre-fetched', () => {
+ beforeEach(() => {
+ // By mocking a return value and not a promise, we skip the loading
+ // to simulate having the pre-fetched query
+ sharedDataResponse.mockReturnValueOnce(catalogSharedDataMock);
+ additionalDataResponse.mockResolvedValue(catalogAdditionalDetailsMock);
+ createComponent();
+ });
+
+ it('renders the header skeleton loader', () => {
+ expect(findHeaderSkeletonLoader().exists()).toBe(false);
+ });
+
+ it('passes down the loading state to the header component', () => {
+ sharedDataResponse.mockReturnValueOnce(catalogSharedDataMock);
+
+ expect(findHeaderComponent().props()).toMatchObject({
+ isLoadingDetails: true,
+ isLoadingSharedData: false,
+ });
+ });
+ });
+
+ describe('and shared data is not pre-fetched', () => {
+ beforeEach(() => {
+ sharedDataResponse.mockResolvedValue(catalogSharedDataMock);
+ additionalDataResponse.mockResolvedValue(catalogAdditionalDetailsMock);
+ createComponent();
+ });
+
+ it('does not render the header skeleton', () => {
+ expect(findHeaderSkeletonLoader().exists()).toBe(false);
+ });
+
+ it('passes all loading state to the header component as true', () => {
+ expect(findHeaderComponent().props()).toMatchObject({
+ isLoadingDetails: true,
+ isLoadingSharedData: true,
+ });
+ });
+ });
+ });
+
+ describe('and there are no resources', () => {
+ beforeEach(async () => {
+ const mockError = new Error('error');
+ sharedDataResponse.mockRejectedValue(mockError);
+ additionalDataResponse.mockRejectedValue(mockError);
+
+ createComponent();
+ await waitForPromises();
+ });
+
+ it('renders the empty state', () => {
+ expect(findDetailsComponent().exists()).toBe(false);
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findEmptyState().props('primaryButtonLink')).toBe(defaultProvide.ciCatalogPath);
+ });
+ });
+
+ describe('when data has loaded', () => {
+ beforeEach(async () => {
+ sharedDataResponse.mockResolvedValue(catalogSharedDataMock);
+ additionalDataResponse.mockResolvedValue(catalogAdditionalDetailsMock);
+ createComponent();
+
+ await waitForPromises();
+ });
+
+ it('does not render the header skeleton loader', () => {
+ expect(findHeaderSkeletonLoader().exists()).toBe(false);
+ });
+
+ describe('Catalog header', () => {
+ it('exists', () => {
+ expect(findHeaderComponent().exists()).toBe(true);
+ });
+
+ it('passes expected props', () => {
+ expect(findHeaderComponent().props()).toEqual({
+ isLoadingDetails: false,
+ isLoadingSharedData: false,
+ openIssuesCount: defaultAdditionalData.openIssuesCount,
+ openMergeRequestsCount: defaultAdditionalData.openMergeRequestsCount,
+ pipelineStatus:
+ defaultAdditionalData.versions.nodes[0].commit.pipelines.nodes[0].detailedStatus,
+ resource: defaultSharedData,
+ });
+ });
+ });
+
+ describe('Catalog details', () => {
+ it('exists', () => {
+ expect(findDetailsComponent().exists()).toBe(true);
+ });
+
+ it('passes expected props', () => {
+ expect(findDetailsComponent().props()).toEqual({
+ resourceId: convertToGraphQLId(CI_CATALOG_RESOURCE_TYPE, defaultAdditionalData.id),
+ });
+ });
+ });
+ });
+});