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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-03 12:10:48 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-03 12:10:48 +0300
commitf6a4346585dcc6cc564cb4974a0ea49d2ac0531d (patch)
tree9e9109c2442dbac93c7a38d60c093b56be9e0fa4 /spec/frontend/packages_and_registries
parentbdfa808bfa4983d67a1ff54e4a3b7070be4d13eb (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/packages_and_registries')
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_versions_list_spec.js165
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js47
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/details_spec.js50
3 files changed, 186 insertions, 76 deletions
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_versions_list_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_versions_list_spec.js
index fc7f5c80d45..a700f42d367 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_versions_list_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_versions_list_spec.js
@@ -1,5 +1,11 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlAlert } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
import { stubComponent } from 'helpers/stub_component';
+import waitForPromises from 'helpers/wait_for_promises';
import DeleteModal from '~/packages_and_registries/package_registry/components/delete_modal.vue';
import DeletePackageModal from '~/packages_and_registries/shared/components/delete_package_modal.vue';
import PackageVersionsList from '~/packages_and_registries/package_registry/components/details/package_versions_list.vue';
@@ -14,24 +20,26 @@ import {
DELETE_PACKAGE_VERSIONS_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_VERSION_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_VERSIONS_TRACKING_ACTION,
+ GRAPHQL_PAGE_SIZE,
} from '~/packages_and_registries/package_registry/constants';
-import { packageData } from '../../mock_data';
+import getPackageVersionsQuery from '~/packages_and_registries/package_registry/graphql//queries/get_package_versions.query.graphql';
+import {
+ emptyPackageVersionsQuery,
+ packageVersionsQuery,
+ packageVersions,
+ pagination,
+} from '../../mock_data';
+
+Vue.use(VueApollo);
describe('PackageVersionsList', () => {
let wrapper;
+ let apolloProvider;
const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>empty message</div>' };
- const packageList = [
- packageData({
- name: 'version 1',
- }),
- packageData({
- id: 'gid://gitlab/Packages::Package/112',
- name: 'version 2',
- }),
- ];
const uiElements = {
+ findAlert: () => wrapper.findComponent(GlAlert),
findLoader: () => wrapper.findComponent(PackagesListLoader),
findRegistryList: () => wrapper.findComponent(RegistryList),
findEmptySlot: () => wrapper.findComponent(EmptySlotStub),
@@ -40,12 +48,20 @@ describe('PackageVersionsList', () => {
findDeletePackagesModal: () => wrapper.findComponent(DeleteModal),
findPackageListDeleteModal: () => wrapper.findComponent(DeletePackageModal),
};
- const mountComponent = (props) => {
+
+ const mountComponent = ({
+ props = {},
+ resolver = jest.fn().mockResolvedValue(packageVersionsQuery()),
+ } = {}) => {
+ const requestHandlers = [[getPackageVersionsQuery, resolver]];
+ apolloProvider = createMockApollo(requestHandlers);
+
wrapper = shallowMountExtended(PackageVersionsList, {
+ apolloProvider,
propsData: {
- versions: packageList,
- pageInfo: {},
- isLoading: false,
+ packageId: packageVersionsQuery().data.package.id,
+ isMutationLoading: false,
+ count: packageVersions().length,
...props,
},
stubs: {
@@ -62,9 +78,13 @@ describe('PackageVersionsList', () => {
});
};
+ beforeEach(() => {
+ jest.spyOn(Sentry, 'captureException').mockImplementation();
+ });
+
describe('when list is loading', () => {
beforeEach(() => {
- mountComponent({ isLoading: true, versions: [] });
+ mountComponent({ props: { isMutationLoading: true } });
});
it('displays loader', () => {
expect(uiElements.findLoader().exists()).toBe(true);
@@ -81,11 +101,24 @@ describe('PackageVersionsList', () => {
it('does not display registry list', () => {
expect(uiElements.findRegistryList().exists()).toBe(false);
});
+
+ it('does not display alert', () => {
+ expect(uiElements.findAlert().exists()).toBe(false);
+ });
});
describe('when list is loaded and has no data', () => {
- beforeEach(() => {
- mountComponent({ isLoading: false, versions: [] });
+ const resolver = jest.fn().mockResolvedValue(emptyPackageVersionsQuery);
+ beforeEach(async () => {
+ mountComponent({
+ props: { isMutationLoading: false, count: 0 },
+ resolver,
+ });
+ await waitForPromises();
+ });
+
+ it('skips graphql query', () => {
+ expect(resolver).not.toHaveBeenCalled();
});
it('displays empty slot message', () => {
@@ -103,11 +136,44 @@ describe('PackageVersionsList', () => {
it('does not display registry list', () => {
expect(uiElements.findRegistryList().exists()).toBe(false);
});
+
+ it('does not display alert', () => {
+ expect(uiElements.findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('if load fails, alert', () => {
+ beforeEach(async () => {
+ mountComponent({ resolver: jest.fn().mockRejectedValue() });
+
+ await waitForPromises();
+ });
+
+ it('is displayed', () => {
+ expect(uiElements.findAlert().exists()).toBe(true);
+ });
+
+ it('shows error message', () => {
+ expect(uiElements.findAlert().text()).toMatchInterpolatedText('Failed to load version data');
+ });
+
+ it('is not dismissible', () => {
+ expect(uiElements.findAlert().props('dismissible')).toBe(false);
+ });
+
+ it('is of variant danger', () => {
+ expect(uiElements.findAlert().attributes('variant')).toBe('danger');
+ });
+
+ it('error is logged in sentry', () => {
+ expect(Sentry.captureException).toHaveBeenCalled();
+ });
});
describe('when list is loaded with data', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mountComponent();
+ await waitForPromises();
});
it('displays package registry list', () => {
@@ -116,7 +182,7 @@ describe('PackageVersionsList', () => {
it('binds the right props', () => {
expect(uiElements.findRegistryList().props()).toMatchObject({
- items: packageList,
+ items: packageVersions(),
pagination: {},
isLoading: false,
hiddenDelete: true,
@@ -125,16 +191,16 @@ describe('PackageVersionsList', () => {
it('displays package version rows', () => {
expect(uiElements.findAllListRow().exists()).toEqual(true);
- expect(uiElements.findAllListRow()).toHaveLength(packageList.length);
+ expect(uiElements.findAllListRow()).toHaveLength(packageVersions().length);
});
it('binds the correct props', () => {
expect(uiElements.findAllListRow().at(0).props()).toMatchObject({
- packageEntity: expect.objectContaining(packageList[0]),
+ packageEntity: expect.objectContaining(packageVersions()[0]),
});
expect(uiElements.findAllListRow().at(1).props()).toMatchObject({
- packageEntity: expect.objectContaining(packageList[1]),
+ packageEntity: expect.objectContaining(packageVersions()[1]),
});
});
@@ -148,40 +214,52 @@ describe('PackageVersionsList', () => {
});
describe('when user interacts with pagination', () => {
- beforeEach(() => {
- mountComponent({ pageInfo: { hasNextPage: true } });
+ const resolver = jest.fn().mockResolvedValue(packageVersionsQuery());
+
+ beforeEach(async () => {
+ mountComponent({ resolver });
+ await waitForPromises();
});
- it('emits prev-page event when registry list emits prev event', () => {
- uiElements.findRegistryList().vm.$emit('prev-page');
+ it('when list emits next-page fetches the next set of records', async () => {
+ uiElements.findRegistryList().vm.$emit('next-page');
+ await waitForPromises();
- expect(wrapper.emitted('prev-page')).toHaveLength(1);
+ expect(resolver).toHaveBeenLastCalledWith(
+ expect.objectContaining({ after: pagination().endCursor, first: GRAPHQL_PAGE_SIZE }),
+ );
});
- it('emits next-page when registry list emits next event', () => {
- uiElements.findRegistryList().vm.$emit('next-page');
+ it('when list emits prev-page fetches the prev set of records', async () => {
+ uiElements.findRegistryList().vm.$emit('prev-page');
+ await waitForPromises();
- expect(wrapper.emitted('next-page')).toHaveLength(1);
+ expect(resolver).toHaveBeenLastCalledWith(
+ expect.objectContaining({ before: pagination().startCursor, last: GRAPHQL_PAGE_SIZE }),
+ );
});
});
describe.each`
description | finderFunction | deletePayload
- ${'when the user can destroy the package'} | ${uiElements.findListRow} | ${packageList[0]}
- ${'when the user can bulk destroy packages and deletes only one package'} | ${uiElements.findRegistryList} | ${[packageList[0]]}
+ ${'when the user can destroy the package'} | ${uiElements.findListRow} | ${packageVersions()[0]}
+ ${'when the user can bulk destroy packages and deletes only one package'} | ${uiElements.findRegistryList} | ${[packageVersions()[0]]}
`('$description', ({ finderFunction, deletePayload }) => {
let eventSpy;
const category = 'UI::NpmPackages';
const { findPackageListDeleteModal } = uiElements;
- beforeEach(() => {
+ beforeEach(async () => {
eventSpy = jest.spyOn(Tracking, 'event');
- mountComponent({ canDestroy: true });
+ mountComponent({ props: { canDestroy: true } });
+ await waitForPromises();
finderFunction().vm.$emit('delete', deletePayload);
});
it('passes itemToBeDeleted to the modal', () => {
- expect(findPackageListDeleteModal().props('itemToBeDeleted')).toStrictEqual(packageList[0]);
+ expect(findPackageListDeleteModal().props('itemToBeDeleted')).toStrictEqual(
+ packageVersions()[0],
+ );
});
it('requesting delete tracks the right action', () => {
@@ -198,7 +276,7 @@ describe('PackageVersionsList', () => {
});
it('emits delete when modal confirms', () => {
- expect(wrapper.emitted('delete')[0][0]).toEqual([packageList[0]]);
+ expect(wrapper.emitted('delete')[0][0]).toEqual([packageVersions()[0]]);
});
it('tracks the right action', () => {
@@ -231,14 +309,15 @@ describe('PackageVersionsList', () => {
let eventSpy;
const { findDeletePackagesModal, findRegistryList } = uiElements;
- beforeEach(() => {
+ beforeEach(async () => {
eventSpy = jest.spyOn(Tracking, 'event');
- mountComponent({ canDestroy: true });
+ mountComponent({ props: { canDestroy: true } });
+ await waitForPromises();
});
it('binds the right props', () => {
expect(uiElements.findRegistryList().props()).toMatchObject({
- items: packageList,
+ items: packageVersions(),
pagination: {},
isLoading: false,
hiddenDelete: false,
@@ -248,11 +327,13 @@ describe('PackageVersionsList', () => {
describe('upon deletion', () => {
beforeEach(() => {
- findRegistryList().vm.$emit('delete', packageList);
+ findRegistryList().vm.$emit('delete', packageVersions());
});
it('passes itemsToBeDeleted to the modal', () => {
- expect(findDeletePackagesModal().props('itemsToBeDeleted')).toStrictEqual(packageList);
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toStrictEqual(
+ packageVersions(),
+ );
expect(wrapper.emitted('delete')).toBeUndefined();
});
@@ -270,7 +351,7 @@ describe('PackageVersionsList', () => {
});
it('emits delete event', () => {
- expect(wrapper.emitted('delete')[0]).toEqual([packageList]);
+ expect(wrapper.emitted('delete')[0]).toEqual([packageVersions()]);
});
it('tracks the right action', () => {
diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js
index 19c098e1f82..d568cfe6221 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -109,6 +109,7 @@ export const packageVersions = () => [
id: 'gid://gitlab/Packages::Package/243',
name: '@gitlab-org/package-15',
status: 'DEFAULT',
+ packageType: 'NPM',
canDestroy: true,
tags: { nodes: packageTags() },
version: '1.0.1',
@@ -120,6 +121,7 @@ export const packageVersions = () => [
id: 'gid://gitlab/Packages::Package/244',
name: '@gitlab-org/package-15',
status: 'DEFAULT',
+ packageType: 'NPM',
canDestroy: true,
tags: { nodes: packageTags() },
version: '1.0.2',
@@ -130,7 +132,7 @@ export const packageVersions = () => [
export const packageData = (extend) => ({
__typename: 'Package',
- id: 'gid://gitlab/Packages::Package/111',
+ id: 'gid://gitlab/Packages::Package/1',
canDestroy: true,
name: '@gitlab-org/package-15',
packageType: 'NPM',
@@ -244,14 +246,6 @@ export const packageDetailsQuery = (extendPackage) => ({
},
versions: {
count: packageVersions().length,
- nodes: packageVersions(),
- pageInfo: {
- hasNextPage: true,
- hasPreviousPage: false,
- endCursor: 'endCursor',
- startCursor: 'startCursor',
- },
- __typename: 'PackageConnection',
},
dependencyLinks: {
nodes: dependencyLinks(),
@@ -298,6 +292,41 @@ export const packageMetadataQuery = (packageType) => {
};
};
+export const packageVersionsQuery = (versions = packageVersions()) => ({
+ data: {
+ package: {
+ id: 'gid://gitlab/Packages::Package/111',
+ versions: {
+ count: versions.length,
+ nodes: versions,
+ pageInfo: pagination(),
+ __typename: 'PackageConnection',
+ },
+ __typename: 'PackageDetailsType',
+ },
+ },
+});
+
+export const emptyPackageVersionsQuery = {
+ data: {
+ package: {
+ id: 'gid://gitlab/Packages::Package/111',
+ versions: {
+ count: 0,
+ nodes: [],
+ pageInfo: {
+ hasNextPage: false,
+ hasPreviousPage: false,
+ endCursor: 'endCursor',
+ startCursor: 'startCursor',
+ },
+ __typename: 'PackageConnection',
+ },
+ __typename: 'PackageDetailsType',
+ },
+ },
+};
+
export const packagesDestroyMutation = () => ({
data: {
destroyPackages: {
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
index 544591ff2ab..ecc82b73fed 100644
--- a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
@@ -33,6 +33,7 @@ import {
import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql';
import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql';
+import getPackageVersionsQuery from '~/packages_and_registries/package_registry/graphql//queries/get_package_versions.query.graphql';
import {
packageDetailsQuery,
packageData,
@@ -42,12 +43,13 @@ import {
packageFiles,
packageDestroyFilesMutation,
packageDestroyFilesMutationError,
- pagination,
} from '../mock_data';
jest.mock('~/alert');
useMockLocationHelper();
+Vue.use(VueApollo);
+
describe('PackagesApp', () => {
let wrapper;
let apolloProvider;
@@ -57,7 +59,7 @@ describe('PackagesApp', () => {
};
const provide = {
- packageId: '111',
+ packageId: '1',
emptyListIllustration: 'svgPath',
projectListUrl: 'projectListUrl',
groupListUrl: 'groupListUrl',
@@ -73,8 +75,6 @@ describe('PackagesApp', () => {
filesDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFilesMutation()),
routeId = '1',
} = {}) {
- Vue.use(VueApollo);
-
const requestHandlers = [
[getPackageDetails, resolver],
[destroyPackageFilesMutation, filesDeleteMutationResolver],
@@ -475,6 +475,8 @@ describe('PackagesApp', () => {
await doDeleteFiles();
+ expect(resolver).toHaveBeenCalledTimes(2);
+
expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
@@ -565,8 +567,6 @@ describe('PackagesApp', () => {
packageDetailsQuery({
versions: {
count: 0,
- nodes: [],
- pageInfo: pagination({ hasNextPage: false, hasPreviousPage: false }),
},
}),
),
@@ -582,55 +582,55 @@ describe('PackagesApp', () => {
});
it('binds the correct props', async () => {
- const versionNodes = packageVersions();
createComponent();
await waitForPromises();
expect(findVersionsList().props()).toMatchObject({
canDestroy: true,
- versions: expect.arrayContaining(versionNodes),
+ count: packageVersions().length,
+ isMutationLoading: false,
+ packageId: 'gid://gitlab/Packages::Package/1',
});
});
describe('delete packages', () => {
- it('exists and has the correct props', async () => {
+ beforeEach(async () => {
createComponent();
-
await waitForPromises();
-
- expect(findDeletePackages().props()).toMatchObject({
- refetchQueries: [{ query: getPackageDetails, variables: {} }],
- showSuccessAlert: true,
- });
});
- it('deletePackages is bound to package-versions-list delete event', async () => {
- createComponent();
-
- await waitForPromises();
+ it('exists and has the correct props', () => {
+ expect(findDeletePackages().props('showSuccessAlert')).toBe(true);
+ expect(findDeletePackages().props('refetchQueries')).toEqual([
+ {
+ query: getPackageVersionsQuery,
+ variables: {
+ first: 20,
+ id: 'gid://gitlab/Packages::Package/1',
+ },
+ },
+ ]);
+ });
+ it('deletePackages is bound to package-versions-list delete event', () => {
findVersionsList().vm.$emit('delete', [{ id: 1 }]);
expect(findDeletePackages().emitted('start')).toEqual([[]]);
});
it('start and end event set loading correctly', async () => {
- createComponent();
-
- await waitForPromises();
-
findDeletePackages().vm.$emit('start');
await nextTick();
- expect(findVersionsList().props('isLoading')).toBe(true);
+ expect(findVersionsList().props('isMutationLoading')).toBe(true);
findDeletePackages().vm.$emit('end');
await nextTick();
- expect(findVersionsList().props('isLoading')).toBe(false);
+ expect(findVersionsList().props('isMutationLoading')).toBe(false);
});
});
});