summaryrefslogtreecommitdiff
path: root/spec/frontend/packages_and_registries
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/packages_and_registries')
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/delete_modal_spec.js (renamed from spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js)24
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js48
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js45
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js313
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js22
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js11
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js4
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js124
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js77
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/stubs.js2
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/utils_spec.js19
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/app_spec.js84
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js35
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js55
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/mock_data.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/details/details_header_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_row_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_header_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/pages/list_spec.js8
-rw-r--r--spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/file_sha_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js10
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js10
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js35
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js8
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js9
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/delete_modal_spec.js92
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap3
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap199
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap14
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/additional_metadata_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/dependency_row_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/file_sha_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/installation_title_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/metadata/composer_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/metadata/conan_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/metadata/maven_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/metadata/nuget_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/metadata/pypi_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js10
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_versions_list_spec.js236
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js17
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js34
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/functional/delete_packages_spec.js8
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap12
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js18
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js53
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js83
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/details_spec.js218
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/list_spec.js98
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/exceptions_input_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js10
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/packages_forwarding_settings_spec.js23
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js3
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_spec.js1
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js7
-rw-r--r--spec/frontend/packages_and_registries/shared/components/__snapshots__/registry_breadcrumb_spec.js.snap29
-rw-r--r--spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/shared/components/delete_package_modal_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/shared/components/package_icon_and_name_spec.js32
-rw-r--r--spec/frontend/packages_and_registries/shared/components/package_path_spec.js11
-rw-r--r--spec/frontend/packages_and_registries/shared/components/package_tags_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/shared/components/packages_list_loader_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/shared/components/publish_method_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/shared/components/registry_breadcrumb_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/shared/components/registry_list_spec.js23
-rw-r--r--spec/frontend/packages_and_registries/shared/components/settings_block_spec.js4
114 files changed, 1301 insertions, 1202 deletions
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js
index ff11c8843bb..8ba7e40d728 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js
@@ -27,11 +27,6 @@ describe('delete_button', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('tooltip', () => {
it('the title is controlled by tooltipTitle prop', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js
index 620c96e8c9e..5a7cbdcff5b 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js
@@ -46,11 +46,6 @@ describe('Delete Image', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('executes apollo mutate on doDelete', () => {
const mutate = jest.fn().mockResolvedValue({});
mountComponent({ mutate });
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_modal_spec.js
index 16c9485e69e..1eaabf1ad09 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_modal_spec.js
@@ -1,14 +1,14 @@
import { GlSprintf, GlFormInput } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import component from '~/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue';
+import component from '~/packages_and_registries/container_registry/explorer/components/delete_modal.vue';
import {
REMOVE_TAG_CONFIRMATION_TEXT,
REMOVE_TAGS_CONFIRMATION_TEXT,
DELETE_IMAGE_CONFIRMATION_TITLE,
DELETE_IMAGE_CONFIRMATION_TEXT,
} from '~/packages_and_registries/container_registry/explorer/constants';
-import { GlModal } from '../../stubs';
+import { GlModal } from '../stubs';
describe('Delete Modal', () => {
let wrapper;
@@ -30,15 +30,10 @@ describe('Delete Modal', () => {
const expectPrimaryActionStatus = (disabled = true) =>
expect(findModal().props('actionPrimary')).toMatchObject(
expect.objectContaining({
- attributes: [{ variant: 'danger' }, { disabled }],
+ attributes: { variant: 'danger', disabled },
}),
);
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('contains a GlModal', () => {
mountComponent();
expect(findModal().exists()).toBe(true);
@@ -80,7 +75,7 @@ describe('Delete Modal', () => {
});
describe('delete button', () => {
- const itemsToBeDeleted = [{ project: { path: 'foo' } }];
+ let itemsToBeDeleted = [{ project: { path: 'foo' } }];
it('is disabled by default', () => {
mountComponent({ deleteImage: true });
@@ -107,6 +102,17 @@ describe('Delete Modal', () => {
expectPrimaryActionStatus(false);
});
+
+ it('if the user types the image name when available', async () => {
+ itemsToBeDeleted = [{ name: 'foo' }];
+ mountComponent({ deleteImage: true, itemsToBeDeleted });
+
+ findInputComponent().vm.$emit('input', 'foo');
+
+ await nextTick();
+
+ expectPrimaryActionStatus(false);
+ });
});
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js
index d45b993b5a2..9d187439ca3 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js
@@ -19,11 +19,6 @@ describe('Delete alert', () => {
wrapper = shallowMount(component, { stubs: { GlSprintf }, propsData });
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('when deleteAlertType is null', () => {
it('does not show the alert', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
index b37edac83f7..01089422376 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
@@ -1,10 +1,10 @@
import { GlDropdownItem, GlIcon, GlDropdown } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import Vue, { nextTick } from 'vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import waitForPromises from 'helpers/wait_for_promises';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue';
@@ -22,37 +22,27 @@ import {
} from '~/packages_and_registries/container_registry/explorer/constants';
import getContainerRepositoryMetadata from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_metadata.query.graphql';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-import { imageTagsCountMock } from '../../mock_data';
+import { containerRepositoryMock, imageTagsCountMock } from '../../mock_data';
describe('Details Header', () => {
let wrapper;
let apolloProvider;
const defaultImage = {
- name: 'foo',
- updatedAt: '2020-11-03T13:29:21Z',
- canDelete: true,
- project: {
- visibility: 'public',
- path: 'path',
- containerExpirationPolicy: {
- enabled: false,
- },
- },
+ ...containerRepositoryMock,
};
// set the date to Dec 4, 2020
useFakeDate(2020, 11, 4);
- const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
- const findLastUpdatedAndVisibility = () => findByTestId('updated-and-visibility');
- const findTitle = () => findByTestId('title');
- const findTagsCount = () => findByTestId('tags-count');
- const findCleanup = () => findByTestId('cleanup');
+ const findCreatedAndVisibility = () => wrapper.findByTestId('created-and-visibility');
+ const findTitle = () => wrapper.findByTestId('title');
+ const findTagsCount = () => wrapper.findByTestId('tags-count');
+ const findCleanup = () => wrapper.findByTestId('cleanup');
const findDeleteButton = () => wrapper.findComponent(GlDropdownItem);
const findInfoIcon = () => wrapper.findComponent(GlIcon);
const findMenu = () => wrapper.findComponent(GlDropdown);
- const findSize = () => findByTestId('image-size');
+ const findSize = () => wrapper.findByTestId('image-size');
const waitForMetadataItems = async () => {
// Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
@@ -69,11 +59,11 @@ describe('Details Header', () => {
const requestHandlers = [[getContainerRepositoryMetadata, resolver]];
apolloProvider = createMockApollo(requestHandlers);
- wrapper = shallowMount(component, {
+ wrapper = shallowMountExtended(component, {
apolloProvider,
propsData,
directives: {
- GlTooltip: createMockDirective(),
+ GlTooltip: createMockDirective('gl-tooltip'),
},
stubs: {
TitleArea,
@@ -85,9 +75,7 @@ describe('Details Header', () => {
afterEach(() => {
// if we want to mix createMockApollo and manual mocks we need to reset everything
- wrapper.destroy();
apolloProvider = undefined;
- wrapper = null;
});
describe('image name', () => {
@@ -99,7 +87,7 @@ describe('Details Header', () => {
});
it('root image shows project path name', () => {
- expect(findTitle().text()).toBe('path');
+ expect(findTitle().text()).toBe('gitlab-test');
});
it('has an icon', () => {
@@ -121,7 +109,7 @@ describe('Details Header', () => {
});
it('shows image.name', () => {
- expect(findTitle().text()).toContain('foo');
+ expect(findTitle().text()).toContain('rails-12009');
});
it('has no icon', () => {
@@ -249,7 +237,7 @@ describe('Details Header', () => {
expect(findCleanup().props('icon')).toBe('expire');
});
- it('when the expiration policy is disabled', async () => {
+ it('when cleanup is not scheduled', async () => {
mountComponent();
await waitForMetadataItems();
@@ -289,12 +277,12 @@ describe('Details Header', () => {
);
});
- describe('visibility and updated at', () => {
- it('has last updated text', async () => {
+ describe('visibility and created at', () => {
+ it('has created text', async () => {
mountComponent();
await waitForMetadataItems();
- expect(findLastUpdatedAndVisibility().props('text')).toBe('Last updated 1 month ago');
+ expect(findCreatedAndVisibility().props('text')).toBe('Created Nov 3, 2020 13:29');
});
describe('visibility icon', () => {
@@ -302,7 +290,7 @@ describe('Details Header', () => {
mountComponent();
await waitForMetadataItems();
- expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye');
+ expect(findCreatedAndVisibility().props('icon')).toBe('eye');
});
it('shows an eye slashed when the project is not public', async () => {
mountComponent({
@@ -310,7 +298,7 @@ describe('Details Header', () => {
});
await waitForMetadataItems();
- expect(findLastUpdatedAndVisibility().props('icon')).toBe('eye-slash');
+ expect(findCreatedAndVisibility().props('icon')).toBe('eye-slash');
});
});
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js
index ce5ecfe4608..d6c1b2c3f51 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js
@@ -23,11 +23,6 @@ describe('Partial Cleanup alert', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it(`gl-alert has the correct properties`, () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js
index d83a5099bcd..3e1fd14475d 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js
@@ -27,11 +27,6 @@ describe('Status Alert', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it.each`
status | title | variant | message | link
${DELETE_SCHEDULED} | ${SCHEDULED_FOR_DELETION_STATUS_TITLE} | ${'info'} | ${SCHEDULED_FOR_DELETION_STATUS_MESSAGE} | ${PACKAGE_DELETE_HELP_PAGE_PATH}
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
index fa0d76762df..f74dfcb029d 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
@@ -50,16 +50,11 @@ describe('tags list row', () => {
},
propsData,
directives: {
- GlTooltip: createMockDirective(),
+ GlTooltip: createMockDirective('gl-tooltip'),
},
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('checkbox', () => {
it('exists', () => {
mountComponent();
@@ -158,7 +153,7 @@ describe('tags list row', () => {
it('is disabled when the component is disabled', () => {
mountComponent({ ...defaultProps, disabled: true });
- expect(findClipboardButton().attributes('disabled')).toBe('true');
+ expect(findClipboardButton().attributes('disabled')).toBeDefined();
});
});
@@ -283,26 +278,30 @@ describe('tags list row', () => {
textSrOnly: true,
category: 'tertiary',
right: true,
+ disabled: false,
});
});
- it.each`
- canDelete | digest | disabled | buttonDisabled
- ${true} | ${null} | ${true} | ${true}
- ${false} | ${'foo'} | ${true} | ${true}
- ${false} | ${null} | ${true} | ${true}
- ${true} | ${'foo'} | ${true} | ${true}
- ${true} | ${'foo'} | ${false} | ${false}
- `(
- 'is $visible that is visible when canDelete is $canDelete and digest is $digest and disabled is $disabled',
- ({ canDelete, digest, disabled, buttonDisabled }) => {
- mountComponent({ ...defaultProps, tag: { ...tag, canDelete, digest }, disabled });
+ it('has the correct classes', () => {
+ mountComponent();
- expect(findAdditionalActionsMenu().props('disabled')).toBe(buttonDisabled);
- expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(buttonDisabled);
- expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(buttonDisabled);
- },
- );
+ expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(false);
+ expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(false);
+ });
+
+ it('is not rendered when tag.canDelete is false', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, canDelete: false } });
+
+ expect(findAdditionalActionsMenu().exists()).toBe(false);
+ });
+
+ it('is hidden when disabled prop is set to true', () => {
+ mountComponent({ ...defaultProps, disabled: true });
+
+ expect(findAdditionalActionsMenu().props('disabled')).toBe(true);
+ expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(true);
+ expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(true);
+ });
describe('delete button', () => {
it('exists and has the correct attrs', () => {
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
index 1017ff06a25..0cbb9eab018 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
@@ -4,13 +4,15 @@ import { GlEmptyState } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-
+import Tracking from '~/tracking';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
+import deleteContainerRepositoryTagsMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
+
import {
GRAPHQL_PAGE_SIZE,
NO_TAGS_TITLE,
@@ -19,7 +21,13 @@ import {
NO_TAGS_MATCHING_FILTERS_DESCRIPTION,
} from '~/packages_and_registries/container_registry/explorer/constants/index';
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
-import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data';
+import {
+ graphQLDeleteImageRepositoryTagsMock,
+ tagsMock,
+ imageTagsMock,
+ tagsPageInfo,
+} from '../../mock_data';
+import { DeleteModal } from '../../stubs';
describe('Tags List', () => {
let wrapper;
@@ -31,6 +39,7 @@ describe('Tags List', () => {
noContainersImage: 'noContainersImage',
};
+ const findDeleteModal = () => wrapper.findComponent(DeleteModal);
const findPersistedSearch = () => wrapper.findComponent(PersistedSearch);
const findTagsListRow = () => wrapper.findAllComponents(TagsListRow);
const findRegistryList = () => wrapper.findComponent(RegistryList);
@@ -42,20 +51,23 @@ describe('Tags List', () => {
};
const waitForApolloRequestRender = async () => {
+ fireFirstSortUpdate();
await waitForPromises();
- await nextTick();
};
- const mountComponent = ({ propsData = { isMobile: false, id: 1 } } = {}) => {
+ const mountComponent = ({ propsData = { isMobile: false, id: 1 }, mutationResolver } = {}) => {
Vue.use(VueApollo);
- const requestHandlers = [[getContainerRepositoryTagsQuery, resolver]];
+ const requestHandlers = [
+ [getContainerRepositoryTagsQuery, resolver],
+ [deleteContainerRepositoryTagsMutation, mutationResolver],
+ ];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMount(component, {
apolloProvider,
propsData,
- stubs: { RegistryList },
+ stubs: { RegistryList, DeleteModal },
provide() {
return {
config: defaultConfig,
@@ -66,17 +78,13 @@ describe('Tags List', () => {
beforeEach(() => {
resolver = jest.fn().mockResolvedValue(imageTagsMock());
- });
-
- afterEach(() => {
- wrapper.destroy();
+ jest.spyOn(Tracking, 'event');
});
describe('registry list', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mountComponent();
- fireFirstSortUpdate();
- return waitForApolloRequestRender();
+ await waitForApolloRequestRender();
});
it('has a persisted search', () => {
@@ -98,6 +106,7 @@ describe('Tags List', () => {
pagination: tagsPageInfo,
items: tags,
idProperty: 'name',
+ hiddenDelete: false,
});
});
@@ -129,11 +138,46 @@ describe('Tags List', () => {
});
});
- it('emits a delete event when list emits delete', () => {
- const eventPayload = 'foo';
- findRegistryList().vm.$emit('delete', eventPayload);
+ describe('delete event', () => {
+ describe('single item', () => {
+ beforeEach(() => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+ });
+
+ it('opens the modal', () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
+
+ it('sets modal props', () => {
+ expect(findDeleteModal().props('itemsToBeDeleted')).toMatchObject([tags[0]]);
+ });
+
+ it('tracks a single delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'registry_tag_delete',
+ });
+ });
+ });
- expect(wrapper.emitted('delete')).toEqual([[eventPayload]]);
+ describe('multiple items', () => {
+ beforeEach(() => {
+ findRegistryList().vm.$emit('delete', tags);
+ });
+
+ it('opens the modal', () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
+
+ it('sets modal props', () => {
+ expect(findDeleteModal().props('itemsToBeDeleted')).toMatchObject(tags);
+ });
+
+ it('tracks multiple delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'bulk_registry_tag_delete',
+ });
+ });
+ });
});
});
});
@@ -141,7 +185,6 @@ describe('Tags List', () => {
describe('list rows', () => {
it('one row exist for each tag', async () => {
mountComponent();
- fireFirstSortUpdate();
await waitForApolloRequestRender();
@@ -150,7 +193,6 @@ describe('Tags List', () => {
it('the correct props are bound to it', async () => {
mountComponent({ propsData: { disabled: true, id: 1 } });
- fireFirstSortUpdate();
await waitForApolloRequestRender();
@@ -165,7 +207,6 @@ describe('Tags List', () => {
describe('events', () => {
it('select event update the selected items', async () => {
mountComponent();
- fireFirstSortUpdate();
await waitForApolloRequestRender();
findTagsListRow().at(0).vm.$emit('select');
@@ -175,23 +216,63 @@ describe('Tags List', () => {
expect(findTagsListRow().at(0).attributes('selected')).toBe('true');
});
- it('delete event emit a delete event', async () => {
- mountComponent();
- fireFirstSortUpdate();
- await waitForApolloRequestRender();
+ describe('delete event', () => {
+ let mutationResolver;
- findTagsListRow().at(0).vm.$emit('delete');
- expect(wrapper.emitted('delete')[0][0][0].name).toBe(tags[0].name);
+ beforeEach(async () => {
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
+ resolver = jest.fn().mockResolvedValue(imageTagsMock());
+ mountComponent({ mutationResolver });
+
+ await waitForApolloRequestRender();
+ findTagsListRow().at(0).vm.$emit('delete');
+ });
+
+ it('opens the modal', () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
+
+ it('tracks a single delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'registry_tag_delete',
+ });
+ });
+
+ it('confirmDelete event calls apollo mutation with the right parameters and refetches the tags list query', async () => {
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: [tags[0].name] }),
+ );
+
+ await waitForPromises();
+
+ expect(resolver).toHaveBeenLastCalledWith({
+ first: GRAPHQL_PAGE_SIZE,
+ name: '',
+ sort: 'NAME_ASC',
+ id: '1',
+ });
+ });
});
});
});
+ describe('when user does not have permission to delete list rows', () => {
+ it('sets registry list hiddenDelete prop to true', async () => {
+ resolver = jest.fn().mockResolvedValue(imageTagsMock({ canDelete: false }));
+ mountComponent();
+ await waitForApolloRequestRender();
+
+ expect(findRegistryList().props('hiddenDelete')).toBe(true);
+ });
+ });
+
describe('when the list of tags is empty', () => {
- beforeEach(() => {
- resolver = jest.fn().mockResolvedValue(imageTagsMock([]));
+ beforeEach(async () => {
+ resolver = jest.fn().mockResolvedValue(imageTagsMock({ nodes: [] }));
mountComponent();
- fireFirstSortUpdate();
- return waitForApolloRequestRender();
+ await waitForApolloRequestRender();
});
it('does not show the loader', () => {
@@ -217,7 +298,7 @@ describe('Tags List', () => {
filters: [{ type: FILTERED_SEARCH_TERM, value: { data: 'foo' } }],
});
- await waitForApolloRequestRender();
+ await waitForPromises();
expect(findEmptyState().props()).toMatchObject({
svgPath: defaultConfig.noContainersImage,
@@ -228,6 +309,175 @@ describe('Tags List', () => {
});
});
+ describe('modal', () => {
+ it('exists', async () => {
+ mountComponent();
+ await waitForApolloRequestRender();
+
+ expect(findDeleteModal().exists()).toBe(true);
+ });
+
+ describe('cancel event', () => {
+ it('tracks cancel_delete', async () => {
+ mountComponent();
+ await waitForApolloRequestRender();
+
+ findDeleteModal().vm.$emit('cancel');
+
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'cancel_delete', {
+ label: 'registry_tag_delete',
+ });
+ });
+ });
+
+ describe('confirmDelete event', () => {
+ let mutationResolver;
+
+ describe('when mutation', () => {
+ beforeEach(() => {
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
+ mountComponent({ mutationResolver });
+
+ return waitForApolloRequestRender();
+ });
+
+ it('is started renders loader', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+ await nextTick();
+
+ expect(findTagsLoader().exists()).toBe(true);
+ expect(findTagsListRow().exists()).toBe(false);
+ });
+
+ it('ends, loader is hidden', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+ await waitForPromises();
+
+ expect(findTagsLoader().exists()).toBe(false);
+ expect(findTagsListRow().exists()).toBe(true);
+ });
+ });
+
+ describe.each([
+ {
+ description: 'rejection',
+ mutationMock: jest.fn().mockRejectedValue(),
+ },
+ {
+ description: 'error',
+ mutationMock: jest.fn().mockResolvedValue({
+ data: {
+ destroyContainerRepositoryTags: {
+ errors: [new Error()],
+ },
+ },
+ }),
+ },
+ ])('when mutation fails with $description', ({ mutationMock }) => {
+ beforeEach(() => {
+ mutationResolver = mutationMock;
+ mountComponent({ mutationResolver });
+
+ return waitForApolloRequestRender();
+ });
+
+ it('when one item is selected to be deleted calls apollo mutation with the right parameters and emits delete event with right arguments', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ resolver.mockClear();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: [tags[0].name] }),
+ );
+
+ expect(resolver).not.toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('danger_tag');
+ });
+
+ it('when more than one item is selected to be deleted calls apollo mutation with the right parameters and emits delete event with right arguments', async () => {
+ findRegistryList().vm.$emit('delete', tagsMock);
+ resolver.mockClear();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
+ );
+
+ expect(resolver).not.toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('danger_tags');
+ });
+ });
+
+ describe('when mutation is successful', () => {
+ beforeEach(() => {
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
+ mountComponent({ mutationResolver });
+
+ return waitForApolloRequestRender();
+ });
+
+ it('and one item is selected to be deleted calls apollo mutation with the right parameters and refetches the tags list query', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: [tags[0].name] }),
+ );
+
+ expect(resolver).toHaveBeenLastCalledWith({
+ first: GRAPHQL_PAGE_SIZE,
+ name: '',
+ sort: 'NAME_ASC',
+ id: '1',
+ });
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('success_tag');
+ });
+
+ it('and more than one item is selected to be deleted calls apollo mutation with the right parameters and refetches the tags list query', async () => {
+ findRegistryList().vm.$emit('delete', tagsMock);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
+ );
+
+ expect(resolver).toHaveBeenLastCalledWith({
+ first: GRAPHQL_PAGE_SIZE,
+ name: '',
+ sort: 'NAME_ASC',
+ id: '1',
+ });
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('success_tags');
+ });
+ });
+ });
+ });
+
describe('loading state', () => {
it.each`
isImageLoading | queryExecuting | loadingVisible
@@ -239,7 +489,6 @@ describe('Tags List', () => {
'when the isImageLoading is $isImageLoading, and is $queryExecuting that the query is still executing is $loadingVisible that the loader is shown',
async ({ isImageLoading, queryExecuting, loadingVisible }) => {
mountComponent({ propsData: { isImageLoading, isMobile: false, id: 1 } });
- fireFirstSortUpdate();
if (!queryExecuting) {
await waitForApolloRequestRender();
}
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
index 88e79c513bc..8896185ce67 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
@@ -20,11 +20,6 @@ describe('TagsLoader component', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('produces the correct amount of loaders', () => {
mountComponent();
expect(findGlSkeletonLoaders().length).toBe(1);
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
index 535faebdd4e..0d1d2c53cab 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
@@ -36,10 +36,6 @@ describe('cleanup_status', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
it.each`
status | visible | text
${UNFINISHED_STATUS} | ${true} | ${CLEANUP_STATUS_UNFINISHED}
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
index d2086943e4f..900ea61e4ea 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
@@ -26,10 +26,6 @@ describe('Registry Group Empty state', () => {
});
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('to match the default snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
index 75068591007..5d8df45415e 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
@@ -1,4 +1,4 @@
-import { GlIcon, GlSprintf, GlSkeletonLoader, GlButton } from '@gitlab/ui';
+import { GlSprintf, GlSkeletonLoader, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { createMockDirective } from 'helpers/vue_mock_directive';
import { mockTracking } from 'helpers/tracking_helper';
@@ -49,16 +49,11 @@ describe('Image List Row', () => {
config: {},
},
directives: {
- GlTooltip: createMockDirective(),
+ GlTooltip: createMockDirective('gl-tooltip'),
},
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('image title and path', () => {
it('renders shortened name of image and contains a link to the details page', () => {
mountComponent();
@@ -150,7 +145,7 @@ describe('Image List Row', () => {
});
it('the clipboard button is disabled', () => {
- expect(findClipboardButton().attributes('disabled')).toBe('true');
+ expect(findClipboardButton().attributes('disabled')).toBeDefined();
});
});
});
@@ -206,13 +201,6 @@ describe('Image List Row', () => {
expect(findTagsCount().exists()).toBe(true);
});
- it('contains a tag icon', () => {
- mountComponent();
- const icon = findTagsCount().findComponent(GlIcon);
- expect(icon.exists()).toBe(true);
- expect(icon.props('name')).toBe('tag');
- });
-
describe('loading state', () => {
it('shows a loader when metadataLoading is true', () => {
mountComponent({ metadataLoading: true });
@@ -231,12 +219,12 @@ describe('Image List Row', () => {
it('with one tag in the image', () => {
mountComponent({ item: { ...item, tagsCount: 1 } });
- expect(findTagsCount().text()).toMatchInterpolatedText('1 Tag');
+ expect(findTagsCount().text()).toMatchInterpolatedText('1 tag');
});
it('with more than one tag in the image', () => {
mountComponent({ item: { ...item, tagsCount: 3 } });
- expect(findTagsCount().text()).toMatchInterpolatedText('3 Tags');
+ expect(findTagsCount().text()).toMatchInterpolatedText('3 tags');
});
});
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js
index 042b8383571..6c771887b88 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js
@@ -21,11 +21,6 @@ describe('Image List', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('list', () => {
it('contains one list element for each image', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
index 8cfa8128021..e4d13143484 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
@@ -34,10 +34,6 @@ describe('Registry Project Empty state', () => {
});
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('to match the default snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
index bcc8e41fce8..b7f3698e155 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
@@ -35,11 +35,6 @@ describe('registry_header', () => {
await nextTick();
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('header', () => {
it('has a title', () => {
mountComponent({ metadataLoading: true });
@@ -86,7 +81,7 @@ describe('registry_header', () => {
});
});
- describe('expiration policy', () => {
+ describe('cleanup policy', () => {
it('when is disabled', async () => {
await mountComponent({
expirationPolicy: { enabled: false },
@@ -116,11 +111,11 @@ describe('registry_header', () => {
const cleanupLink = findSetupCleanUpLink();
expect(text.exists()).toBe(true);
- expect(text.props('text')).toBe('Expiration policy will run in ');
+ expect(text.props('text')).toBe('Cleanup will run in ');
expect(cleanupLink.exists()).toBe(true);
expect(cleanupLink.text()).toBe(SET_UP_CLEANUP);
});
- it('when the expiration policy is completely disabled', async () => {
+ it('when the cleanup policy is not scheduled', async () => {
await mountComponent({
expirationPolicy: { enabled: true },
expirationPolicyHelpPagePath: 'foo',
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
index e5b99f15e8c..8ca74f5077e 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
@@ -127,7 +127,6 @@ export const containerRepositoryMock = {
location: 'host.docker.internal:5000/gitlab-org/gitlab-test/rails-12009',
canDelete: true,
createdAt: '2020-11-03T13:29:21Z',
- updatedAt: '2020-11-03T13:29:21Z',
expirationPolicyStartedAt: null,
expirationPolicyCleanupStatus: 'UNSCHEDULED',
project: {
@@ -177,11 +176,12 @@ export const tagsMock = [
},
];
-export const imageTagsMock = (nodes = tagsMock) => ({
+export const imageTagsMock = ({ nodes = tagsMock, canDelete = true } = {}) => ({
data: {
containerRepository: {
id: containerRepositoryMock.id,
tagsCount: nodes.length,
+ canDelete,
tags: {
nodes,
pageInfo: { ...tagsPageInfo },
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
index 26f0e506829..7fed81acead 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
@@ -22,22 +22,15 @@ import {
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
} from '~/packages_and_registries/container_registry/explorer/constants';
-import deleteContainerRepositoryTagsMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
import getContainerRepositoryDetailsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
-import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
-import getContainerRepositoriesDetails from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql';
import component from '~/packages_and_registries/container_registry/explorer/pages/details.vue';
import Tracking from '~/tracking';
import {
graphQLImageDetailsMock,
- graphQLDeleteImageRepositoryTagsMock,
- graphQLProjectImageRepositoriesDetailsMock,
containerRepositoryMock,
graphQLEmptyImageDetailsMock,
- tagsMock,
- imageTagsMock,
} from '../mock_data';
import { DeleteModal } from '../stubs';
@@ -69,13 +62,6 @@ describe('Details Page', () => {
isGroupPage: false,
};
- const cleanTags = tagsMock.map((t) => {
- const result = { ...t };
- // eslint-disable-next-line no-underscore-dangle
- delete result.__typename;
- return result;
- });
-
const waitForApolloRequestRender = async () => {
await waitForPromises();
await nextTick();
@@ -83,20 +69,12 @@ describe('Details Page', () => {
const mountComponent = ({
resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock()),
- mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock),
- tagsResolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock(imageTagsMock())),
- detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock),
options,
config = defaultConfig,
} = {}) => {
Vue.use(VueApollo);
- const requestHandlers = [
- [getContainerRepositoryDetailsQuery, resolver],
- [deleteContainerRepositoryTagsMutation, mutationResolver],
- [getContainerRepositoryTagsQuery, tagsResolver],
- [getContainerRepositoriesDetails, detailsResolver],
- ];
+ const requestHandlers = [[getContainerRepositoryDetailsQuery, resolver]];
apolloProvider = createMockApollo(requestHandlers);
@@ -127,11 +105,6 @@ describe('Details Page', () => {
jest.spyOn(Tracking, 'event');
});
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('when isLoading is true', () => {
it('shows the loader', () => {
mountComponent();
@@ -189,50 +162,6 @@ describe('Details Page', () => {
isMobile: false,
});
});
-
- describe('deleteEvent', () => {
- describe('single item', () => {
- let tagToBeDeleted;
- beforeEach(async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- [tagToBeDeleted] = cleanTags;
- findTagsList().vm.$emit('delete', [tagToBeDeleted]);
- });
-
- it('open the modal', async () => {
- expect(DeleteModal.methods.show).toHaveBeenCalled();
- });
-
- it('tracks a single delete event', () => {
- expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
- label: 'registry_tag_delete',
- });
- });
- });
-
- describe('multiple items', () => {
- beforeEach(async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- findTagsList().vm.$emit('delete', cleanTags);
- });
-
- it('open the modal', () => {
- expect(DeleteModal.methods.show).toHaveBeenCalled();
- });
-
- it('tracks a single delete event', () => {
- expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
- label: 'bulk_registry_tag_delete',
- });
- });
- });
- });
});
describe('modal', () => {
@@ -253,61 +182,24 @@ describe('Details Page', () => {
findDeleteModal().vm.$emit('cancel');
expect(Tracking.event).toHaveBeenCalledWith(undefined, 'cancel_delete', {
- label: 'registry_tag_delete',
+ label: 'registry_image_delete',
});
});
});
- describe('confirmDelete event', () => {
- let mutationResolver;
- let tagsResolver;
- let detailsResolver;
-
+ describe('tags list delete event', () => {
beforeEach(() => {
- mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
- tagsResolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock(imageTagsMock()));
- detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
- mountComponent({ mutationResolver, tagsResolver, detailsResolver });
+ mountComponent();
return waitForApolloRequestRender();
});
- describe('when one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters and refetches the tags list query', async () => {
- findTagsList().vm.$emit('delete', [cleanTags[0]]);
-
- await nextTick();
-
- findDeleteModal().vm.$emit('confirmDelete');
-
- expect(mutationResolver).toHaveBeenCalledWith(
- expect.objectContaining({ tagNames: [cleanTags[0].name] }),
- );
-
- await waitForPromises();
+ it('sets delete alert modal deleteAlertType value', async () => {
+ findTagsList().vm.$emit('delete', 'success_tag');
- expect(tagsResolver).toHaveBeenCalled();
- expect(detailsResolver).toHaveBeenCalled();
- });
- });
-
- describe('when more than one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters and refetches the tags list query', async () => {
- findTagsList().vm.$emit('delete', tagsMock);
-
- await nextTick();
-
- findDeleteModal().vm.$emit('confirmDelete');
-
- expect(mutationResolver).toHaveBeenCalledWith(
- expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
- );
-
- await waitForPromises();
+ await nextTick();
- expect(tagsResolver).toHaveBeenCalled();
- expect(detailsResolver).toHaveBeenCalled();
- });
+ expect(findDeleteAlert().props('deleteAlertType')).toBe('success_tag');
});
});
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
index 1e514d85e82..1823bbfe533 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
@@ -1,8 +1,8 @@
-import { GlSkeletonLoader, GlSprintf, GlAlert } from '@gitlab/ui';
+import { GlSkeletonLoader, GlSprintf, GlAlert, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
-
import VueApollo from 'vue-apollo';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import getContainerRepositoriesQuery from 'shared_queries/container_registry/get_container_repositories.query.graphql';
@@ -16,6 +16,7 @@ import {
DELETE_IMAGE_SUCCESS_MESSAGE,
DELETE_IMAGE_ERROR_MESSAGE,
SORT_FIELDS,
+ SETTINGS_TEXT,
} from '~/packages_and_registries/container_registry/explorer/constants';
import deleteContainerRepositoryMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository.mutation.graphql';
import getContainerRepositoriesDetails from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql';
@@ -36,18 +37,19 @@ import {
graphQLProjectImageRepositoriesDetailsMock,
dockerCommands,
} from '../mock_data';
-import { GlModal, GlEmptyState } from '../stubs';
+import { GlEmptyState, DeleteModal } from '../stubs';
describe('List Page', () => {
let wrapper;
let apolloProvider;
- const findDeleteModal = () => wrapper.findComponent(GlModal);
+ const findDeleteModal = () => wrapper.findComponent(DeleteModal);
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findCliCommands = () => wrapper.findComponent(CliCommands);
+ const findSettingsLink = () => wrapper.findComponent(GlButton);
const findProjectEmptyState = () => wrapper.findComponent(ProjectEmptyState);
const findGroupEmptyState = () => wrapper.findComponent(GroupEmptyState);
const findRegistryHeader = () => wrapper.findComponent(RegistryHeader);
@@ -89,7 +91,7 @@ describe('List Page', () => {
wrapper = shallowMount(component, {
apolloProvider,
stubs: {
- GlModal,
+ DeleteModal,
GlEmptyState,
GlSprintf,
RegistryHeader,
@@ -110,13 +112,12 @@ describe('List Page', () => {
...dockerCommands,
};
},
+ directives: {
+ GlTooltip: createMockDirective('gl-tooltip'),
+ },
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
it('contains registry header', async () => {
mountComponent();
fireFirstSortUpdate();
@@ -126,6 +127,42 @@ describe('List Page', () => {
expect(findRegistryHeader().props()).toMatchObject({
imagesCount: 2,
metadataLoading: false,
+ helpPagePath: '',
+ hideExpirationPolicyData: false,
+ showCleanupPolicyLink: false,
+ expirationPolicy: {},
+ cleanupPoliciesSettingsPath: '',
+ });
+ });
+
+ describe('link to settings', () => {
+ beforeEach(() => {
+ const config = {
+ showContainerRegistrySettings: true,
+ cleanupPoliciesSettingsPath: 'bar',
+ };
+ mountComponent({ config });
+ });
+
+ it('is rendered', () => {
+ expect(findSettingsLink().exists()).toBe(true);
+ });
+
+ it('has the right icon', () => {
+ expect(findSettingsLink().props('icon')).toBe('settings');
+ });
+
+ it('has the right attributes', () => {
+ expect(findSettingsLink().attributes()).toMatchObject({
+ 'aria-label': SETTINGS_TEXT,
+ href: 'bar',
+ });
+ });
+
+ it('sets tooltip with right label', () => {
+ const tooltip = getBinding(findSettingsLink().element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(SETTINGS_TEXT);
});
});
@@ -239,6 +276,14 @@ describe('List Page', () => {
expect(findCliCommands().exists()).toBe(false);
});
+
+ it('link to settings is not visible', async () => {
+ mountComponent({ resolver, config });
+
+ await waitForApolloRequestRender();
+
+ expect(findSettingsLink().exists()).toBe(false);
+ });
});
});
@@ -310,7 +355,7 @@ describe('List Page', () => {
await selectImageForDeletion();
- findDeleteModal().vm.$emit('primary');
+ findDeleteModal().vm.$emit('confirmDelete');
expect(mutationResolver).toHaveBeenCalledWith({ id: deletedContainerRepository.id });
});
@@ -468,11 +513,15 @@ describe('List Page', () => {
expect(findDeleteModal().exists()).toBe(true);
});
- it('contains a description with the path of the item to delete', async () => {
- await waitForPromises();
- findImageList().vm.$emit('delete', { path: 'foo' });
+ it('contains the deleted image as props', async () => {
await waitForPromises();
- expect(findDeleteModal().html()).toContain('foo');
+ findImageList().vm.$emit('delete', deletedContainerRepository);
+ await nextTick();
+
+ expect(findDeleteModal().props()).toEqual({
+ itemsToBeDeleted: [deletedContainerRepository],
+ deleteImage: true,
+ });
});
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js b/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js
index 7d281a53a59..0d80028adf6 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js
@@ -6,7 +6,7 @@ import {
} from '@gitlab/ui';
import { RouterLinkStub } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
-import RealDeleteModal from '~/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue';
+import RealDeleteModal from '~/packages_and_registries/container_registry/explorer/components/delete_modal.vue';
import RealListItem from '~/vue_shared/components/registry/list_item.vue';
export const GlModal = stubComponent(RealGlModal, {
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/utils_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/utils_spec.js
index 5063759a620..d7a9c200c7b 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/utils_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/utils_spec.js
@@ -1,6 +1,23 @@
-import { timeTilRun } from '~/packages_and_registries/container_registry/explorer/utils';
+import {
+ getImageName,
+ timeTilRun,
+} from '~/packages_and_registries/container_registry/explorer/utils';
describe('Container registry utilities', () => {
+ describe('getImageName', () => {
+ it('returns name when present', () => {
+ const result = getImageName({ name: 'foo' });
+
+ expect(result).toBe('foo');
+ });
+
+ it('returns project path when name is empty', () => {
+ const result = getImageName({ name: '', project: { path: 'foo' } });
+
+ expect(result).toBe('foo');
+ });
+ });
+
describe('timeTilRun', () => {
beforeEach(() => {
jest.spyOn(Date, 'now').mockImplementation(() => new Date('2063-04-04T00:42:00Z').getTime());
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
index 601f8abd34d..1928dbf72b6 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
@@ -5,7 +5,6 @@ import {
GlFormInputGroup,
GlFormGroup,
GlModal,
- GlSkeletonLoader,
GlSprintf,
GlEmptyState,
} from '@gitlab/ui';
@@ -13,6 +12,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import MockAdapter from 'axios-mock-adapter';
import createMockApollo from 'helpers/mock_apollo_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/dependency_proxy/constants';
@@ -31,11 +31,6 @@ import { proxyDetailsQuery, proxyData, pagination, proxyManifests } from './mock
const dummyApiVersion = 'v3000';
const dummyGrouptId = 1;
const dummyUrlRoot = '/gitlab';
-const dummyGon = {
- api_version: dummyApiVersion,
- relative_url_root: dummyUrlRoot,
-};
-let originalGon;
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${dummyGrouptId}/dependency_proxy/cache`;
Vue.use(VueApollo);
@@ -51,6 +46,7 @@ describe('DependencyProxyApp', () => {
groupId: dummyGrouptId,
noManifestsIllustration: 'noManifestsIllustration',
canClearCache: true,
+ settingsPath: 'path',
};
function createComponent({ provide = provideDefaults } = {}) {
@@ -71,56 +67,46 @@ describe('DependencyProxyApp', () => {
GlSprintf,
TitleArea,
},
+ directives: {
+ GlTooltip: createMockDirective('gl-tooltip'),
+ },
});
}
const findClipBoardButton = () => wrapper.findComponent(ClipboardButton);
const findFormGroup = () => wrapper.findComponent(GlFormGroup);
const findFormInputGroup = () => wrapper.findComponent(GlFormInputGroup);
- const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
- const findMainArea = () => wrapper.findByTestId('main-area');
const findProxyCountText = () => wrapper.findByTestId('proxy-count');
const findManifestList = () => wrapper.findComponent(ManifestsList);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findClearCacheDropdownList = () => wrapper.findComponent(GlDropdown);
const findClearCacheModal = () => wrapper.findComponent(GlModal);
const findClearCacheAlert = () => wrapper.findComponent(GlAlert);
+ const findSettingsLink = () => wrapper.findByTestId('settings-link');
beforeEach(() => {
resolver = jest.fn().mockResolvedValue(proxyDetailsQuery());
- originalGon = window.gon;
- window.gon = { ...dummyGon };
+ window.gon = {
+ api_version: dummyApiVersion,
+ relative_url_root: dummyUrlRoot,
+ };
mock = new MockAdapter(axios);
mock.onDelete(expectedUrl).reply(HTTP_STATUS_ACCEPTED, {});
});
afterEach(() => {
- wrapper.destroy();
- window.gon = originalGon;
mock.restore();
});
describe('when the dependency proxy is available', () => {
describe('when is loading', () => {
- it('renders the skeleton loader', () => {
- createComponent();
-
- expect(findSkeletonLoader().exists()).toBe(true);
- });
-
it('does not render a form group with label', () => {
createComponent();
expect(findFormGroup().exists()).toBe(false);
});
-
- it('does not show the main section', () => {
- createComponent();
-
- expect(findMainArea().exists()).toBe(false);
- });
});
describe('when the app is loaded', () => {
@@ -130,10 +116,6 @@ describe('DependencyProxyApp', () => {
return waitForPromises();
});
- it('renders the main area', () => {
- expect(findMainArea().exists()).toBe(true);
- });
-
it('renders a form group with a label', () => {
expect(findFormGroup().attributes('label')).toBe(
DependencyProxyApp.i18n.proxyImagePrefix,
@@ -157,6 +139,29 @@ describe('DependencyProxyApp', () => {
expect(findProxyCountText().text()).toBe('Contains 2 blobs of images (1024 Bytes)');
});
+ describe('link to settings', () => {
+ it('is rendered', () => {
+ expect(findSettingsLink().exists()).toBe(true);
+ });
+
+ it('has the right icon', () => {
+ expect(findSettingsLink().props('icon')).toBe('settings');
+ });
+
+ it('has the right attributes', () => {
+ expect(findSettingsLink().attributes()).toMatchObject({
+ 'aria-label': DependencyProxyApp.i18n.settingsText,
+ href: 'path',
+ });
+ });
+
+ it('sets tooltip with right label', () => {
+ const tooltip = getBinding(findSettingsLink().element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(DependencyProxyApp.i18n.settingsText);
+ });
+ });
+
describe('manifest lists', () => {
describe('when there are no manifests', () => {
beforeEach(() => {
@@ -189,6 +194,7 @@ describe('DependencyProxyApp', () => {
it('shows list', () => {
expect(findManifestList().props()).toMatchObject({
+ dependencyProxyImagePrefix: proxyData().dependencyProxyImagePrefix,
manifests: proxyManifests(),
pagination: pagination(),
});
@@ -218,13 +224,6 @@ describe('DependencyProxyApp', () => {
});
describe('triggering page event on list', () => {
- it('re-renders the skeleton loader', async () => {
- findManifestList().vm.$emit('next-page');
- await nextTick();
-
- expect(findSkeletonLoader().exists()).toBe(true);
- });
-
it('renders form group with label', async () => {
findManifestList().vm.$emit('next-page');
await nextTick();
@@ -233,13 +232,6 @@ describe('DependencyProxyApp', () => {
expect.stringMatching(DependencyProxyApp.i18n.proxyImagePrefix),
);
});
-
- it('does not show the main section', async () => {
- findManifestList().vm.$emit('next-page');
- await nextTick();
-
- expect(findMainArea().exists()).toBe(false);
- });
});
it('shows the clear cache dropdown list', () => {
@@ -274,9 +266,7 @@ describe('DependencyProxyApp', () => {
beforeEach(() => {
createComponent({
provide: {
- groupPath: 'gitlab-org',
- groupId: dummyGrouptId,
- noManifestsIllustration: 'noManifestsIllustration',
+ ...provideDefaults,
canClearCache: false,
},
});
@@ -285,6 +275,10 @@ describe('DependencyProxyApp', () => {
it('does not show the clear cache dropdown list', () => {
expect(findClearCacheDropdownList().exists()).toBe(false);
});
+
+ it('does not show link to settings', () => {
+ expect(findSettingsLink().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
index 2f415bfd6f9..4149f728cd8 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
@@ -1,9 +1,9 @@
-import { GlKeysetPagination } from '@gitlab/ui';
+import { GlKeysetPagination, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ManifestRow from '~/packages_and_registries/dependency_proxy/components/manifest_row.vue';
-
import Component from '~/packages_and_registries/dependency_proxy/components/manifests_list.vue';
import {
+ proxyData,
proxyManifests,
pagination,
} from 'jest/packages_and_registries/dependency_proxy/mock_data';
@@ -12,8 +12,10 @@ describe('Manifests List', () => {
let wrapper;
const defaultProps = {
+ dependencyProxyImagePrefix: proxyData().dependencyProxyImagePrefix,
manifests: proxyManifests(),
pagination: pagination(),
+ loading: false,
};
const createComponent = (propsData = defaultProps) => {
@@ -24,10 +26,8 @@ describe('Manifests List', () => {
const findRows = () => wrapper.findAllComponents(ManifestRow);
const findPagination = () => wrapper.findComponent(GlKeysetPagination);
-
- afterEach(() => {
- wrapper.destroy();
- });
+ const findMainArea = () => wrapper.findByTestId('main-area');
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
it('has the correct title', () => {
createComponent();
@@ -44,8 +44,27 @@ describe('Manifests List', () => {
it('binds a manifest to each row', () => {
createComponent();
- expect(findRows().at(0).props()).toMatchObject({
- manifest: defaultProps.manifests[0],
+ expect(findRows().at(0).props('manifest')).toBe(defaultProps.manifests[0]);
+ });
+
+ it('binds a dependencyProxyImagePrefix to each row', () => {
+ createComponent();
+
+ expect(findRows().at(0).props('dependencyProxyImagePrefix')).toBe(
+ proxyData().dependencyProxyImagePrefix,
+ );
+ });
+
+ describe('loading', () => {
+ it.each`
+ loading | expectLoader | expectContent
+ ${false} | ${false} | ${true}
+ ${true} | ${true} | ${false}
+ `('when loading is $loading', ({ loading, expectLoader, expectContent }) => {
+ createComponent({ ...defaultProps, loading });
+
+ expect(findSkeletonLoader().exists()).toBe(expectLoader);
+ expect(findMainArea().exists()).toBe(expectContent);
});
});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js
index be3236d1f9c..5f47a1b8098 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_row_spec.js
@@ -1,15 +1,17 @@
import { GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import Component from '~/packages_and_registries/dependency_proxy/components/manifest_row.vue';
import { MANIFEST_PENDING_DESTRUCTION_STATUS } from '~/packages_and_registries/dependency_proxy/constants';
-import { proxyManifests } from 'jest/packages_and_registries/dependency_proxy/mock_data';
+import { proxyData, proxyManifests } from 'jest/packages_and_registries/dependency_proxy/mock_data';
describe('Manifest Row', () => {
let wrapper;
const defaultProps = {
+ dependencyProxyImagePrefix: proxyData().dependencyProxyImagePrefix,
manifest: proxyManifests()[0],
};
@@ -24,15 +26,13 @@ describe('Manifest Row', () => {
});
};
+ const findClipboardButton = () => wrapper.findComponent(ClipboardButton);
const findListItem = () => wrapper.findComponent(ListItem);
const findCachedMessages = () => wrapper.findByTestId('cached-message');
+ const findDigest = () => wrapper.findByTestId('manifest-row-short-digest');
const findTimeAgoTooltip = () => wrapper.findComponent(TimeagoTooltip);
const findStatus = () => wrapper.findByTestId('status');
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('With a manifest on the DEFAULT status', () => {
beforeEach(() => {
createComponent();
@@ -42,12 +42,18 @@ describe('Manifest Row', () => {
expect(findListItem().exists()).toBe(true);
});
- it('displays the name', () => {
- expect(wrapper.text()).toContain('alpine');
+ it('displays the name with tag & digest', () => {
+ expect(wrapper.text()).toContain('alpine:latest');
+ expect(findDigest().text()).toMatchInterpolatedText('Digest: 995efde');
});
- it('displays the version', () => {
- expect(wrapper.text()).toContain('latest');
+ it('displays the name & digest for manifests that contain digest in image name', () => {
+ createComponent({
+ ...defaultProps,
+ manifest: proxyManifests()[1],
+ });
+ expect(wrapper.text()).toContain('alpine');
+ expect(findDigest().text()).toMatchInterpolatedText('Digest: e95efde');
});
it('displays the cached time', () => {
@@ -86,4 +92,35 @@ describe('Manifest Row', () => {
expect(findStatus().text()).toBe('Scheduled for deletion');
});
});
+
+ describe('clipboard button', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('exists', () => {
+ expect(findClipboardButton().exists()).toBe(true);
+ });
+
+ it('passes the correct title prop', () => {
+ expect(findClipboardButton().attributes('title')).toBe(Component.i18n.copyImagePathTitle);
+ });
+
+ it('has the correct copy text when image name contains tag name', () => {
+ expect(findClipboardButton().attributes('text')).toBe(
+ 'gdk.test:3000/private-group/dependency_proxy/containers/alpine:latest',
+ );
+ });
+
+ it('has the correct copy text when image name contains digest', () => {
+ createComponent({
+ ...defaultProps,
+ manifest: proxyManifests()[1],
+ });
+
+ expect(findClipboardButton().attributes('text')).toBe(
+ 'gdk.test:3000/private-group/dependency_proxy/containers/alpine@sha256:e95efde2e81b21d1ea7066aa77a59298a62a9e9fbb4b77f36c189774ec9b1089',
+ );
+ });
+ });
});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js b/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
index 37c8eb669ba..4d0be0a0c09 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
@@ -11,13 +11,15 @@ export const proxyManifests = () => [
{
id: 'proxy-1',
createdAt: '2021-09-22T09:45:28Z',
+ digest: 'sha256:995efde2e81b21d1ea7066aa77a59298a62a9e9fbb4b77f36c189774ec9b1089',
imageName: 'alpine:latest',
status: 'DEFAULT',
},
{
id: 'proxy-2',
createdAt: '2021-09-21T09:45:28Z',
- imageName: 'alpine:stable',
+ digest: 'sha256:e95efde2e81b21d1ea7066aa77a59298a62a9e9fbb4b77f36c189774ec9b1089',
+ imageName: 'alpine:sha256:e95efde2e81b21d1ea7066aa77a59298a62a9e9fbb4b77f36c189774ec9b1089',
status: 'DEFAULT',
},
];
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js
index a2e5cbdce8b..1e9b9b1ce47 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_row_spec.js
@@ -63,10 +63,6 @@ describe('Harbor artifact list row', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('list item', () => {
beforeEach(() => {
mountComponent({
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_spec.js
index b9d6dc2679e..786a4715731 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/details/artifacts_list_spec.js
@@ -26,10 +26,6 @@ describe('Harbor artifacts list', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('when isLoading is true', () => {
beforeEach(() => {
mountComponent({
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/details/details_header_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/details/details_header_spec.js
index e8cc2b2e22d..d8fb91c085c 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/details/details_header_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/details/details_header_spec.js
@@ -20,10 +20,6 @@ describe('Harbor Details Header', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('artifact name', () => {
describe('missing image name', () => {
beforeEach(() => {
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js
index 7a6169d300c..9a7ad759dba 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js
@@ -29,10 +29,6 @@ describe('harbor_list_header', () => {
await nextTick();
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('header', () => {
it('has a title', () => {
mountComponent({ metadataLoading: true });
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_row_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_row_spec.js
index b62d4e8836b..1e031e0557a 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_row_spec.js
@@ -28,10 +28,6 @@ describe('Harbor List Row', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('image title and path', () => {
it('contains a link to the details page', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js
index e7e74a0da58..a1803ecf7fb 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_spec.js
@@ -20,10 +20,6 @@ describe('Harbor List', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('list', () => {
it('contains one list element for each image', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_header_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_header_spec.js
index 5e299a269e3..9370ff1fdd4 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_header_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_header_spec.js
@@ -26,10 +26,6 @@ describe('Harbor Tags Header', () => {
totalPages: 1,
};
- afterEach(() => {
- wrapper.destroy();
- });
-
beforeEach(() => {
mountComponent({
propsData: { artifactDetail: mockArtifactDetail, pageInfo: mockPageInfo, tagsLoading: false },
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js
index 849215e286b..0b2ce01ebf6 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_row_spec.js
@@ -37,10 +37,6 @@ describe('Harbor tag list row', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('list item', () => {
beforeEach(() => {
mountComponent({
diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js
index 4c6b2b6daaa..e2a2a584b7d 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/components/tags/tags_list_spec.js
@@ -24,10 +24,6 @@ describe('Harbor Tags List', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('when isLoading is true', () => {
beforeEach(() => {
mountComponent({
diff --git a/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js
index 69765d31674..90c3d9082f7 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/pages/details_spec.js
@@ -74,10 +74,6 @@ describe('Harbor Details Page', () => {
});
});
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('when isLoading is true', () => {
it('shows the loader', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/harbor_registry/pages/list_spec.js b/spec/frontend/packages_and_registries/harbor_registry/pages/list_spec.js
index 97d30e6fe99..1bc2657822e 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/pages/list_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/pages/list_spec.js
@@ -60,10 +60,6 @@ describe('Harbor List Page', () => {
});
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('contains harbor registry header', async () => {
mountComponent();
fireFirstSortUpdate();
@@ -78,7 +74,7 @@ describe('Harbor List Page', () => {
});
describe('isLoading is true', () => {
- it('shows the skeleton loader', async () => {
+ it('shows the skeleton loader', () => {
mountComponent();
fireFirstSortUpdate();
@@ -97,7 +93,7 @@ describe('Harbor List Page', () => {
expect(findCliCommands().exists()).toBe(false);
});
- it('title has the metadataLoading props set to true', async () => {
+ it('title has the metadataLoading props set to true', () => {
mountComponent();
fireFirstSortUpdate();
diff --git a/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js b/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js
index 10901c6ec1e..6002faa1fa3 100644
--- a/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js
+++ b/spec/frontend/packages_and_registries/harbor_registry/pages/tags_spec.js
@@ -60,10 +60,6 @@ describe('Harbor Tags page', () => {
});
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('contains tags header', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
index e74375b7705..f8130287c12 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
@@ -86,10 +86,6 @@ describe('PackagesApp', () => {
const findTerraformInstallation = () => wrapper.findComponent(TerraformInstallation);
const findPackageFiles = () => wrapper.findComponent(PackageFiles);
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders the app and displays the package title', async () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
index b504f7489ab..148e87699f1 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
@@ -39,10 +39,6 @@ describe('PackageTitle', () => {
const pipelineProject = () => wrapper.find('[data-testid="pipeline-project"]');
const packageRef = () => wrapper.find('[data-testid="package-ref"]');
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('module title', () => {
it('is correctly bound', async () => {
await createComponent();
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/file_sha_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/file_sha_spec.js
index d7caa8ca2d8..7352afff051 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/file_sha_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/file_sha_spec.js
@@ -23,10 +23,6 @@ describe('FileSha', () => {
});
}
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js
index b76d7c2b57b..c3e0818fc11 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js
@@ -37,11 +37,6 @@ describe('Package Files', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('rows', () => {
it('renders a single file for an npm package', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js
index 0cbe2755f7e..a650aba464e 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js
@@ -30,11 +30,6 @@ describe('Package History', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findHistoryElement = (testId) => wrapper.find(`[data-testid="${testId}"]`);
const findElementLink = (container) => container.findComponent(GlLink);
const findElementTimeAgo = (container) => container.findComponent(TimeAgoTooltip);
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
index 78c1b840dbc..94797f01d16 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
@@ -30,10 +30,6 @@ describe('TerraformInstallation', () => {
createComponent();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders all the messages', () => {
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js
index bb970336b94..ea4d268d84e 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js
@@ -1,6 +1,6 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/flash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/alert';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages_and_registries/infrastructure_registry/details/constants';
import {
fetchPackageVersions,
@@ -15,7 +15,7 @@ import {
} from '~/packages_and_registries/shared/constants';
import { npmPackage as packageEntity } from '../../mock_data';
-jest.mock('~/flash.js');
+jest.mock('~/alert');
jest.mock('~/api.js');
describe('Actions Package details store', () => {
@@ -53,7 +53,7 @@ describe('Actions Package details store', () => {
expect(Api.projectPackage).toHaveBeenCalledWith(packageEntity.project_id, packageEntity.id);
});
- it('should create flash on API error', async () => {
+ it('should create alert on API error', async () => {
Api.projectPackage = jest.fn().mockRejectedValue();
await testAction(
@@ -83,7 +83,7 @@ describe('Actions Package details store', () => {
packageEntity.id,
);
});
- it('should create flash on API error', async () => {
+ it('should create alert on API error', async () => {
Api.deleteProjectPackage = jest.fn().mockRejectedValue();
await testAction(deletePackage, undefined, { packageEntity }, [], []);
@@ -118,7 +118,7 @@ describe('Actions Package details store', () => {
});
});
- it('should create flash on API error', async () => {
+ it('should create alert on API error', async () => {
Api.deleteProjectPackageFile = jest.fn().mockRejectedValue();
await testAction(deletePackageFile, fileId, { packageEntity }, [], []);
expect(createAlert).toHaveBeenCalledWith({
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
index 801cde8582e..d0841c6110f 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
@@ -49,9 +49,7 @@ exports[`packages_list_app renders 1`] = `
Learn how to
<b-link-stub
class="gl-link"
- event="click"
href="helpUrl"
- routertag="a"
target="_blank"
>
publish and share your packages
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js
index a086c20a5e7..a89247c0a97 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js
@@ -55,11 +55,6 @@ describe('Infrastructure Search', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('has a registry search component', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
index aca6b0942cc..12859b1d77c 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
@@ -22,11 +22,6 @@ describe('Infrastructure Title', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('title area', () => {
beforeEach(() => {
mountComponent();
@@ -37,7 +32,7 @@ describe('Infrastructure Title', () => {
});
it('has the correct title', () => {
- expect(findTitleArea().props('title')).toBe('Infrastructure Registry');
+ expect(findTitleArea().props('title')).toBe('Terraform Module Registry');
});
describe('with no modules', () => {
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
index d237023d0cd..47d36d11e35 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { createAlert, VARIANT_INFO } from '~/flash';
+import { createAlert, VARIANT_INFO } from '~/alert';
import * as commonUtils from '~/lib/utils/common_utils';
import PackageListApp from '~/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages_and_registries/infrastructure_registry/list/constants';
@@ -14,7 +14,7 @@ import InfrastructureSearch from '~/packages_and_registries/infrastructure_regis
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
jest.mock('~/lib/utils/common_utils');
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(Vuex);
@@ -72,10 +72,6 @@ describe('packages_list_app', () => {
mountComponent();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders', () => {
createStore({ packageCount: 1 });
mountComponent();
@@ -217,7 +213,7 @@ describe('packages_list_app', () => {
setWindowLocation(originalLocation);
});
- it(`creates a flash if the query string contains ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
+ it(`creates an alert if the query string contains ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
mountComponent();
expect(createAlert).toHaveBeenCalledWith({
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
index 0164d92ce34..51445942eaa 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
@@ -4,13 +4,13 @@ import Vue from 'vue';
import { last } from 'lodash';
import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import PackagesList from '~/packages_and_registries/infrastructure_registry/list/components/packages_list.vue';
import PackagesListRow from '~/packages_and_registries/infrastructure_registry/shared/package_list_row.vue';
import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
import DeletePackageModal from '~/packages_and_registries/shared/components/delete_package_modal.vue';
import { TRACKING_ACTIONS } from '~/packages_and_registries/shared/constants';
import { TRACK_CATEGORY } from '~/packages_and_registries/infrastructure_registry/shared/constants';
-import Tracking from '~/tracking';
import { packageList } from '../../mock_data';
Vue.use(Vuex);
@@ -72,11 +72,6 @@ describe('packages_list', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('when is loading', () => {
beforeEach(() => {
mountComponent({
@@ -179,23 +174,23 @@ describe('packages_list', () => {
});
describe('tracking', () => {
- let eventSpy;
+ let trackingSpy = null;
beforeEach(() => {
mountComponent();
- eventSpy = jest.spyOn(Tracking, 'event');
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ itemToBeDeleted: { package_type: 'conan' } });
- });
-
- it('deleteItemConfirmation calls event', () => {
- wrapper.vm.deleteItemConfirmation();
- expect(eventSpy).toHaveBeenCalledWith(
- TRACK_CATEGORY,
- TRACKING_ACTIONS.DELETE_PACKAGE,
- expect.any(Object),
- );
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('deleteItemConfirmation calls event', async () => {
+ await findPackageListDeleteModal().vm.$emit('ok');
+
+ expect(trackingSpy).toHaveBeenCalledWith(TRACK_CATEGORY, TRACKING_ACTIONS.DELETE_PACKAGE, {
+ category: TRACK_CATEGORY,
+ });
});
});
});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js
index 2c185e040f4..4f051264172 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js
@@ -2,14 +2,14 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { HTTP_STATUS_BAD_REQUEST, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { MISSING_DELETE_PATH_ERROR } from '~/packages_and_registries/infrastructure_registry/list/constants';
import * as actions from '~/packages_and_registries/infrastructure_registry/list/stores/actions';
import * as types from '~/packages_and_registries/infrastructure_registry/list/stores/mutation_types';
import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages_and_registries/shared/constants';
-jest.mock('~/flash.js');
+jest.mock('~/alert');
jest.mock('~/api.js');
describe('Actions Package list store', () => {
@@ -96,7 +96,7 @@ describe('Actions Package list store', () => {
});
});
- it('should create flash on API error', async () => {
+ it('should create alert on API error', async () => {
Api.projectPackages = jest.fn().mockRejectedValue();
await testAction(
actions.requestPackagesList,
@@ -198,7 +198,7 @@ describe('Actions Package list store', () => {
);
});
- it('should stop the loading and call create flash on api error', async () => {
+ it('should stop the loading and call create alert on api error', async () => {
mock.onDelete(payload._links.delete_api_path).replyOnce(HTTP_STATUS_BAD_REQUEST);
await testAction(
actions.requestDeletePackage,
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
index 721bdd34a4f..d00d7180f75 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
@@ -49,16 +49,11 @@ describe('packages_list_row', () => {
disableDelete,
},
directives: {
- GlTooltip: createMockDirective(),
+ GlTooltip: createMockDirective('gl-tooltip'),
},
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('renders', () => {
mountComponent();
expect(wrapper.element).toMatchSnapshot();
@@ -143,7 +138,7 @@ describe('packages_list_row', () => {
});
it('details link is disabled', () => {
- expect(findPackageLink().attributes('disabled')).toBe('true');
+ expect(findPackageLink().attributes('disabled')).toBeDefined();
});
it('has a warning icon', () => {
diff --git a/spec/frontend/packages_and_registries/package_registry/components/delete_modal_spec.js b/spec/frontend/packages_and_registries/package_registry/components/delete_modal_spec.js
index 9c1ebf5a2eb..4ab81182c9a 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/delete_modal_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/delete_modal_spec.js
@@ -1,7 +1,14 @@
-import { GlModal as RealGlModal } from '@gitlab/ui';
+import { GlModal as RealGlModal, GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import DeleteModal from '~/packages_and_registries/package_registry/components/delete_modal.vue';
+import {
+ DELETE_PACKAGE_MODAL_PRIMARY_ACTION,
+ DELETE_PACKAGE_WITH_REQUEST_FORWARDING_PRIMARY_ACTION,
+ DELETE_PACKAGES_REQUEST_FORWARDING_MODAL_CONTENT,
+ DELETE_PACKAGES_WITH_REQUEST_FORWARDING_PRIMARY_ACTION,
+ REQUEST_FORWARDING_HELP_PAGE_PATH,
+} from '~/packages_and_registries/package_registry/constants';
const GlModal = stubComponent(RealGlModal, {
methods: {
@@ -14,22 +21,30 @@ describe('DeleteModal', () => {
const defaultItemsToBeDeleted = [
{
- name: 'package 01',
+ name: 'package-1',
+ version: '1.0.0',
},
{
- name: 'package 02',
+ name: 'package-2',
+ version: '1.0.0',
},
];
const findModal = () => wrapper.findComponent(GlModal);
+ const findLink = () => wrapper.findComponent(GlLink);
- const mountComponent = ({ itemsToBeDeleted = defaultItemsToBeDeleted } = {}) => {
+ const mountComponent = ({
+ itemsToBeDeleted = defaultItemsToBeDeleted,
+ showRequestForwardingContent = false,
+ } = {}) => {
wrapper = shallowMountExtended(DeleteModal, {
propsData: {
itemsToBeDeleted,
+ showRequestForwardingContent,
},
stubs: {
GlModal,
+ GlSprintf,
},
});
};
@@ -45,16 +60,81 @@ describe('DeleteModal', () => {
it('passes actionPrimary prop', () => {
expect(findModal().props('actionPrimary')).toStrictEqual({
text: 'Permanently delete',
- attributes: [{ variant: 'danger' }, { category: 'primary' }],
+ attributes: { variant: 'danger', category: 'primary' },
});
});
it('renders description', () => {
- expect(findModal().text()).toContain(
+ expect(findModal().text()).toMatchInterpolatedText(
'You are about to delete 2 packages. This operation is irreversible.',
);
});
+ it('with only one item to be deleted renders correct description', () => {
+ mountComponent({ itemsToBeDeleted: [defaultItemsToBeDeleted[0]] });
+
+ expect(findModal().text()).toMatchInterpolatedText(
+ 'You are about to delete version 1.0.0 of package-1. Are you sure?',
+ );
+ });
+
+ it('sets the right action primary text', () => {
+ expect(findModal().props('actionPrimary')).toMatchObject({
+ text: DELETE_PACKAGE_MODAL_PRIMARY_ACTION,
+ });
+ });
+
+ describe('when showRequestForwardingContent is set', () => {
+ it('renders correct description', () => {
+ mountComponent({ showRequestForwardingContent: true });
+
+ expect(findModal().text()).toMatchInterpolatedText(
+ DELETE_PACKAGES_REQUEST_FORWARDING_MODAL_CONTENT,
+ );
+ });
+
+ it('contains link to help page', () => {
+ mountComponent({ showRequestForwardingContent: true });
+
+ expect(findLink().exists()).toBe(true);
+ expect(findLink().attributes('href')).toBe(REQUEST_FORWARDING_HELP_PAGE_PATH);
+ });
+
+ it('sets the right action primary text', () => {
+ mountComponent({ showRequestForwardingContent: true });
+
+ expect(findModal().props('actionPrimary')).toMatchObject({
+ text: DELETE_PACKAGES_WITH_REQUEST_FORWARDING_PRIMARY_ACTION,
+ });
+ });
+
+ describe('and only one item to be deleted', () => {
+ beforeEach(() => {
+ mountComponent({
+ showRequestForwardingContent: true,
+ itemsToBeDeleted: [defaultItemsToBeDeleted[0]],
+ });
+ });
+
+ it('renders correct description', () => {
+ expect(findModal().text()).toMatchInterpolatedText(
+ 'Deleting this package while request forwarding is enabled for the project can pose a security risk. Do you want to delete package-1 version 1.0.0 anyway? What are the risks?',
+ );
+ });
+
+ it('contains link to help page', () => {
+ expect(findLink().exists()).toBe(true);
+ expect(findLink().attributes('href')).toBe(REQUEST_FORWARDING_HELP_PAGE_PATH);
+ });
+
+ it('sets the right action primary text', () => {
+ expect(findModal().props('actionPrimary')).toMatchObject({
+ text: DELETE_PACKAGE_WITH_REQUEST_FORWARDING_PRIMARY_ACTION,
+ });
+ });
+ });
+ });
+
it('emits confirm when primary event is emitted', () => {
expect(wrapper.emitted('confirm')).toBeUndefined();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap
index 67f1906f6fd..9b429c39faa 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap
@@ -89,8 +89,9 @@ exports[`MavenInstallation maven renders all the messages 1`] = `
/>
<code-instruction-stub
+ class="gl-w-20 gl-mt-5"
copytext="Copy Maven command"
- instruction="mvn dependency:get -Dartifact=appGroup:appName:appVersion"
+ instruction="mvn install"
label="Maven Command"
trackingaction="copy_maven_command"
trackinglabel="code_instruction"
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
deleted file mode 100644
index 047fa04947c..00000000000
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap
+++ /dev/null
@@ -1,199 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PackageTitle renders with tags 1`] = `
-<div
- class="gl-display-flex gl-flex-direction-column"
- data-qa-selector="package_title"
->
- <div
- class="gl-display-flex gl-justify-content-space-between gl-py-3"
- >
- <div
- class="gl-flex-direction-column gl-flex-grow-1"
- >
- <div
- class="gl-display-flex"
- >
- <!---->
-
- <div
- class="gl-display-flex gl-flex-direction-column"
- >
- <h2
- class="gl-font-size-h1 gl-mt-3 gl-mb-0"
- data-testid="title"
- >
- @gitlab-org/package-15
- </h2>
-
- <div
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-3"
- >
- <div
- class="gl-display-flex gl-gap-3"
- data-testid="sub-header"
- >
- v
- 1.0.0
- published
- <time-ago-tooltip-stub
- cssclass=""
- time="2020-08-17T14:23:32Z"
- tooltipplacement="top"
- />
-
- <package-tags-stub
- hidelabel="true"
- tagdisplaylimit="2"
- tags="[object Object],[object Object],[object Object]"
- />
- </div>
- </div>
- </div>
- </div>
-
- <div
- class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <metadata-item-stub
- data-testid="package-type"
- icon="package"
- link=""
- size="s"
- text="npm"
- texttooltip=""
- />
- </div>
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <metadata-item-stub
- data-testid="package-size"
- icon="disk"
- link=""
- size="s"
- text="800.00 KiB"
- texttooltip=""
- />
- </div>
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <metadata-item-stub
- data-testid="package-last-downloaded-at"
- icon="download"
- link=""
- size="m"
- text="Last downloaded Aug 17, 2021"
- texttooltip=""
- />
- </div>
- </div>
- </div>
-
- <!---->
- </div>
-
- <p />
-</div>
-`;
-
-exports[`PackageTitle renders without tags 1`] = `
-<div
- class="gl-display-flex gl-flex-direction-column"
- data-qa-selector="package_title"
->
- <div
- class="gl-display-flex gl-justify-content-space-between gl-py-3"
- >
- <div
- class="gl-flex-direction-column gl-flex-grow-1"
- >
- <div
- class="gl-display-flex"
- >
- <!---->
-
- <div
- class="gl-display-flex gl-flex-direction-column"
- >
- <h2
- class="gl-font-size-h1 gl-mt-3 gl-mb-0"
- data-testid="title"
- >
- @gitlab-org/package-15
- </h2>
-
- <div
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-3"
- >
- <div
- class="gl-display-flex gl-gap-3"
- data-testid="sub-header"
- >
- v
- 1.0.0
- published
- <time-ago-tooltip-stub
- cssclass=""
- time="2020-08-17T14:23:32Z"
- tooltipplacement="top"
- />
-
- <!---->
- </div>
- </div>
- </div>
- </div>
-
- <div
- class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <metadata-item-stub
- data-testid="package-type"
- icon="package"
- link=""
- size="s"
- text="npm"
- texttooltip=""
- />
- </div>
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <metadata-item-stub
- data-testid="package-size"
- icon="disk"
- link=""
- size="s"
- text="800.00 KiB"
- texttooltip=""
- />
- </div>
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <metadata-item-stub
- data-testid="package-last-downloaded-at"
- icon="download"
- link=""
- size="m"
- text="Last downloaded Aug 17, 2021"
- texttooltip=""
- />
- </div>
- </div>
- </div>
-
- <!---->
- </div>
-
- <p />
-</div>
-`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
index b2375da7b11..b4ea6543446 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
@@ -20,7 +20,7 @@ exports[`PypiInstallation renders all the messages 1`] = `
<!---->
<button
aria-expanded="false"
- aria-haspopup="true"
+ aria-haspopup="menu"
class="btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle"
id="__BVID__27__BV_toggle_"
type="button"
@@ -42,7 +42,7 @@ exports[`PypiInstallation renders all the messages 1`] = `
role="img"
>
<use
- href="#chevron-down"
+ href="file-mock#chevron-down"
/>
</svg>
</button>
@@ -59,7 +59,6 @@ exports[`PypiInstallation renders all the messages 1`] = `
</div>
<fieldset
- aria-describedby="installation-pip-command-group__BV_description_"
class="form-group gl-form-group"
id="installation-pip-command-group"
>
@@ -75,12 +74,7 @@ exports[`PypiInstallation renders all the messages 1`] = `
<!---->
</legend>
- <div
- aria-labelledby="installation-pip-command-group__BV_label_"
- class="bv-no-focus-ring"
- role="group"
- tabindex="-1"
- >
+ <div>
<div
data-testid="pip-command"
id="installation-pip-command"
@@ -128,7 +122,7 @@ exports[`PypiInstallation renders all the messages 1`] = `
role="img"
>
<use
- href="#copy-to-clipboard"
+ href="file-mock#copy-to-clipboard"
/>
</svg>
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/additional_metadata_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/additional_metadata_spec.js
index 4f3d780b149..2e59c27cc1b 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/additional_metadata_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/additional_metadata_spec.js
@@ -65,11 +65,6 @@ describe('Package Additional metadata', () => {
jest.spyOn(Sentry, 'captureException').mockImplementation();
});
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findTitle = () => wrapper.findByTestId('title');
const findMainArea = () => wrapper.findByTestId('main');
const findComponentIs = () => wrapper.findByTestId('component-is');
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js
index 0aba8f7efc7..a6298ebdea7 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js
@@ -34,10 +34,6 @@ describe('ComposerInstallation', () => {
});
}
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('install command switch', () => {
it('has the installation title component', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js
index bf9425def9a..70534b1d0a6 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js
@@ -33,10 +33,6 @@ describe('ConanInstallation', () => {
createComponent();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders all the messages', () => {
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/dependency_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/dependency_row_spec.js
index 9aed5b90c73..19aedf120b2 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/dependency_row_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/dependency_row_spec.js
@@ -19,10 +19,6 @@ describe('DependencyRow', () => {
const dependencyVersion = () => wrapper.findByTestId('version-pattern');
const dependencyFramework = () => wrapper.findByTestId('target-framework');
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('renders', () => {
it('full dependency', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/file_sha_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/file_sha_spec.js
index feed7a7c46c..a9428773a60 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/file_sha_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/file_sha_spec.js
@@ -23,10 +23,6 @@ describe('FileSha', () => {
});
}
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/installation_title_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/installation_title_spec.js
index 5fe795f768e..a2d30be13c2 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/installation_title_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/installation_title_spec.js
@@ -20,10 +20,6 @@ describe('InstallationTitle', () => {
});
}
- afterEach(() => {
- wrapper.destroy();
- });
-
it('has a title', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js
index 8bb05b00e65..d35d95e319f 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/installations_commands_spec.js
@@ -40,10 +40,6 @@ describe('InstallationCommands', () => {
const pypiInstallation = () => wrapper.findComponent(PypiInstallation);
const composerInstallation = () => wrapper.findComponent(ComposerInstallation);
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('installation instructions', () => {
describe.each`
packageEntity | selector
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js
index fc60039db30..5ea81dccf7d 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js
@@ -35,7 +35,7 @@ describe('MavenInstallation', () => {
<artifactId>appName</artifactId>
<version>appVersion</version>
</dependency>`;
- const mavenCommandStr = 'mvn dependency:get -Dartifact=appGroup:appName:appVersion';
+ const mavenCommandStr = 'mvn install';
const mavenSetupXml = `<repositories>
<repository>
<id>gitlab-maven</id>
@@ -79,10 +79,6 @@ describe('MavenInstallation', () => {
});
}
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('install command switch', () => {
it('has the installation title component', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/composer_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/composer_spec.js
index bb6846d354f..f2f3b8507c3 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/composer_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/composer_spec.js
@@ -18,11 +18,6 @@ describe('Composer Metadata', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findComposerTargetSha = () => wrapper.findByTestId('composer-target-sha');
const findComposerTargetShaCopyButton = () => wrapper.findComponent(ClipboardButton);
const findComposerJson = () => wrapper.findByTestId('composer-json');
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/conan_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/conan_spec.js
index e7e47401aa1..2832dc3a712 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/conan_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/conan_spec.js
@@ -19,11 +19,6 @@ describe('Conan Metadata', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findConanRecipe = () => wrapper.findByTestId('conan-recipe');
beforeEach(() => {
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/maven_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/maven_spec.js
index 8680d983042..7b253a26fc7 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/maven_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/maven_spec.js
@@ -19,11 +19,6 @@ describe('Maven Metadata', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findMavenApp = () => wrapper.findByTestId('maven-app');
const findMavenGroup = () => wrapper.findByTestId('maven-group');
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/nuget_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/nuget_spec.js
index af3692023f0..9fb467f9af1 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/nuget_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/nuget_spec.js
@@ -19,11 +19,6 @@ describe('Nuget Metadata', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findNugetSource = () => wrapper.findByTestId('nuget-source');
const findNugetLicense = () => wrapper.findByTestId('nuget-license');
const findElementLink = (container) => container.findComponent(GlLink);
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/pypi_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/pypi_spec.js
index d7c6ea8379d..67f5fbc9e80 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/metadata/pypi_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/metadata/pypi_spec.js
@@ -20,11 +20,6 @@ describe('Package Additional Metadata', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findPypiRequiredPython = () => wrapper.findByTestId('pypi-required-python');
beforeEach(() => {
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js
index 8c0e2d948ca..e711f9ee45d 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js
@@ -51,10 +51,6 @@ describe('NpmInstallation', () => {
createComponent();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders all the messages', () => {
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js
index 9449c40c7c6..bcc0b78bfce 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js
@@ -36,10 +36,6 @@ describe('NugetInstallation', () => {
createComponent();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders all the messages', () => {
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
index 529a6a22ddf..1dcac017ccf 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
@@ -48,10 +48,6 @@ describe('Package Files', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('rows', () => {
it('renders a single file for an npm package', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js
index bb2fa9eb6f5..ed470f63b8a 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js
@@ -63,11 +63,6 @@ describe('Package History', () => {
jest.spyOn(Sentry, 'captureException').mockImplementation();
});
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const findPackageHistoryLoader = () => wrapper.findComponent(PackageHistoryLoader);
const findHistoryElement = (testId) => wrapper.findByTestId(testId);
const findElementLink = (container) => container.findComponent(GlLink);
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
index 1fda77f2aaa..fc0ca0e898f 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
@@ -38,7 +38,7 @@ describe('PackageTitle', () => {
},
provide,
directives: {
- GlResizeObserver: createMockDirective(),
+ GlResizeObserver: createMockDirective('gl-resize-observer'),
},
});
await nextTick();
@@ -55,21 +55,17 @@ describe('PackageTitle', () => {
const findSubHeaderText = () => wrapper.findByTestId('sub-header');
const findSubHeaderTimeAgo = () => wrapper.findComponent(TimeAgoTooltip);
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('renders', () => {
it('without tags', async () => {
await createComponent({ ...packageData(), packageFiles: { nodes: packageFiles() } });
- expect(wrapper.element).toMatchSnapshot();
+ expect(findPackageTags().exists()).toBe(false);
});
it('with tags', async () => {
await createComponent();
- expect(wrapper.element).toMatchSnapshot();
+ expect(findPackageTags().exists()).toBe(true);
});
it('with tags on mobile', async () => {
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 27c0ab96cfc..e9f2a2c5095 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 PackageVersionsList from '~/packages_and_registries/package_registry/components/details/package_versions_list.vue';
import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
@@ -7,39 +13,53 @@ import RegistryList from '~/packages_and_registries/shared/components/registry_l
import VersionRow from '~/packages_and_registries/package_registry/components/details/version_row.vue';
import Tracking from '~/tracking';
import {
+ CANCEL_DELETE_PACKAGE_VERSION_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_VERSIONS_TRACKING_ACTION,
+ DELETE_PACKAGE_VERSION_TRACKING_ACTION,
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),
- findListRow: () => wrapper.findAllComponents(VersionRow),
+ findListRow: () => wrapper.findComponent(VersionRow),
+ findAllListRow: () => wrapper.findAllComponents(VersionRow),
findDeletePackagesModal: () => wrapper.findComponent(DeleteModal),
};
- 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: {
@@ -56,9 +76,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);
@@ -75,11 +99,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', () => {
@@ -97,11 +134,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', () => {
@@ -110,7 +180,7 @@ describe('PackageVersionsList', () => {
it('binds the right props', () => {
expect(uiElements.findRegistryList().props()).toMatchObject({
- items: packageList,
+ items: packageVersions(),
pagination: {},
isLoading: false,
hiddenDelete: true,
@@ -118,17 +188,17 @@ describe('PackageVersionsList', () => {
});
it('displays package version rows', () => {
- expect(uiElements.findListRow().exists()).toEqual(true);
- expect(uiElements.findListRow()).toHaveLength(packageList.length);
+ expect(uiElements.findAllListRow().exists()).toEqual(true);
+ expect(uiElements.findAllListRow()).toHaveLength(packageVersions().length);
});
it('binds the correct props', () => {
- expect(uiElements.findListRow().at(0).props()).toMatchObject({
- packageEntity: expect.objectContaining(packageList[0]),
+ expect(uiElements.findAllListRow().at(0).props()).toMatchObject({
+ packageEntity: expect.objectContaining(packageVersions()[0]),
});
- expect(uiElements.findListRow().at(1).props()).toMatchObject({
- packageEntity: expect.objectContaining(packageList[1]),
+ expect(uiElements.findAllListRow().at(1).props()).toMatchObject({
+ packageEntity: expect.objectContaining(packageVersions()[1]),
});
});
@@ -142,20 +212,94 @@ 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('when list emits next-page fetches the next set of records', async () => {
+ uiElements.findRegistryList().vm.$emit('next-page');
+ await waitForPromises();
+
+ expect(resolver).toHaveBeenLastCalledWith(
+ expect.objectContaining({ after: pagination().endCursor, first: GRAPHQL_PAGE_SIZE }),
+ );
});
- it('emits prev-page event when registry list emits prev event', () => {
+ it('when list emits prev-page fetches the prev set of records', async () => {
uiElements.findRegistryList().vm.$emit('prev-page');
+ await waitForPromises();
- expect(wrapper.emitted('prev-page')).toHaveLength(1);
+ expect(resolver).toHaveBeenLastCalledWith(
+ expect.objectContaining({ before: pagination().startCursor, last: GRAPHQL_PAGE_SIZE }),
+ );
});
+ });
- it('emits next-page when registry list emits next event', () => {
- uiElements.findRegistryList().vm.$emit('next-page');
+ describe.each`
+ description | finderFunction | deletePayload
+ ${'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 { findDeletePackagesModal } = uiElements;
+
+ beforeEach(async () => {
+ eventSpy = jest.spyOn(Tracking, 'event');
+ mountComponent({ props: { canDestroy: true } });
+ await waitForPromises();
+ finderFunction().vm.$emit('delete', deletePayload);
+ });
+
+ it('passes itemsToBeDeleted to the modal', () => {
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toStrictEqual([
+ packageVersions()[0],
+ ]);
+ });
+
+ it('requesting delete tracks the right action', () => {
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ REQUEST_DELETE_PACKAGE_VERSION_TRACKING_ACTION,
+ expect.any(Object),
+ );
+ });
+
+ describe('when modal confirms', () => {
+ beforeEach(() => {
+ findDeletePackagesModal().vm.$emit('confirm');
+ });
+
+ it('emits delete when modal confirms', () => {
+ expect(wrapper.emitted('delete')[0][0]).toEqual([packageVersions()[0]]);
+ });
- expect(wrapper.emitted('next-page')).toHaveLength(1);
+ it('tracks the right action', () => {
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ DELETE_PACKAGE_VERSION_TRACKING_ACTION,
+ expect.any(Object),
+ );
+ });
+ });
+
+ it.each(['confirm', 'cancel'])('resets itemsToBeDeleted when modal emits %s', async (event) => {
+ await findDeletePackagesModal().vm.$emit(event);
+
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toEqual([]);
+ });
+
+ it('canceling delete tracks the right action', () => {
+ findDeletePackagesModal().vm.$emit('cancel');
+
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ CANCEL_DELETE_PACKAGE_VERSION_TRACKING_ACTION,
+ expect.any(Object),
+ );
});
});
@@ -163,14 +307,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,
@@ -180,11 +325,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();
});
@@ -202,7 +349,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', () => {
@@ -234,4 +381,15 @@ describe('PackageVersionsList', () => {
});
});
});
+
+ describe('with isRequestForwardingEnabled prop', () => {
+ const { findDeletePackagesModal } = uiElements;
+
+ it.each([true, false])('sets modal prop showRequestForwardingContent to %s', async (value) => {
+ mountComponent({ props: { isRequestForwardingEnabled: value } });
+ await waitForPromises();
+
+ expect(findDeletePackagesModal().props('showRequestForwardingContent')).toBe(value);
+ });
+ });
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
index 4a27f8011df..3f4358bb3b0 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
@@ -29,10 +29,13 @@ password = <your personal access token>`;
const findInstallationTitle = () => wrapper.findComponent(InstallationTitle);
const findSetupDocsLink = () => wrapper.findByTestId('pypi-docs-link');
- function createComponent() {
+ function createComponent(props = {}) {
wrapper = mountExtended(PypiInstallation, {
propsData: {
- packageEntity,
+ packageEntity: {
+ ...packageEntity,
+ ...props,
+ },
},
stubs: {
GlSprintf,
@@ -44,10 +47,6 @@ password = <your personal access token>`;
createComponent();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('install command switch', () => {
it('has the installation title component', () => {
expect(findInstallationTitle().exists()).toBe(true);
@@ -86,6 +85,12 @@ password = <your personal access token>`;
});
});
+ it('does not have a link to personal access token docs when package is public', () => {
+ createComponent({ publicPackage: true });
+
+ expect(findAccessTokenLink().exists()).toBe(false);
+ });
+
it('has a link to the docs', () => {
expect(findSetupDocsLink().attributes()).toMatchObject({
href: PYPI_HELP_PATH,
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js
index 67340822fa5..f7c8e909ff6 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js
@@ -1,4 +1,4 @@
-import { GlFormCheckbox, GlIcon, GlLink, GlSprintf, GlTruncate } from '@gitlab/ui';
+import { GlDropdownItem, GlFormCheckbox, GlIcon, GlLink, GlSprintf, GlTruncate } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
@@ -24,6 +24,7 @@ describe('VersionRow', () => {
const findPackageName = () => wrapper.findComponent(GlTruncate);
const findWarningIcon = () => wrapper.findComponent(GlIcon);
const findBulkDeleteAction = () => wrapper.findComponent(GlFormCheckbox);
+ const findDeleteDropdownItem = () => wrapper.findComponent(GlDropdownItem);
function createComponent({ packageEntity = packageVersion, selected = false } = {}) {
wrapper = shallowMountExtended(VersionRow, {
@@ -36,15 +37,11 @@ describe('VersionRow', () => {
GlTruncate,
},
directives: {
- GlTooltip: createMockDirective(),
+ GlTooltip: createMockDirective('gl-tooltip'),
},
});
}
- afterEach(() => {
- wrapper.destroy();
- });
-
it('has a link to the version detail', () => {
createComponent();
@@ -112,6 +109,31 @@ describe('VersionRow', () => {
});
});
+ describe('delete button', () => {
+ it('does not exist when package cannot be destroyed', () => {
+ createComponent({ packageEntity: { ...packageVersion, canDestroy: false } });
+
+ expect(findDeleteDropdownItem().exists()).toBe(false);
+ });
+
+ it('exists and has the correct props', () => {
+ createComponent();
+
+ expect(findDeleteDropdownItem().exists()).toBe(true);
+ expect(findDeleteDropdownItem().attributes()).toMatchObject({
+ variant: 'danger',
+ });
+ });
+
+ it('emits the delete event when the delete button is clicked', () => {
+ createComponent();
+
+ findDeleteDropdownItem().vm.$emit('click');
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ });
+ });
+
describe(`when the package is in ${PACKAGE_ERROR_STATUS} status`, () => {
beforeEach(() => {
createComponent({
diff --git a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_packages_spec.js b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_packages_spec.js
index 689b53fa2a4..04546c4cea4 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/functional/delete_packages_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/functional/delete_packages_spec.js
@@ -3,7 +3,7 @@ import VueApollo from 'vue-apollo';
import waitForPromises from 'helpers/wait_for_promises';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/flash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/alert';
import DeletePackages from '~/packages_and_registries/package_registry/components/functional/delete_packages.vue';
import destroyPackagesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_packages.mutation.graphql';
@@ -14,7 +14,7 @@ import {
packagesListQuery,
} from '../../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('DeletePackages', () => {
let wrapper;
@@ -67,10 +67,6 @@ describe('DeletePackages', () => {
mutationResolver = jest.fn().mockResolvedValue(packagesDestroyMutation());
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('binds deletePackages method to the default slot', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap
index ec8e77fa923..c647230bc5f 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap
@@ -66,11 +66,12 @@ exports[`packages_list_row renders 1`] = `
<!---->
- <package-icon-and-name-stub>
-
- npm
-
- </package-icon-and-name-stub>
+ <span
+ class="gl-ml-2"
+ data-testid="package-type"
+ >
+ · npm
+ </span>
<!---->
</div>
@@ -95,6 +96,7 @@ exports[`packages_list_row renders 1`] = `
Created
<timeago-tooltip-stub
cssclass=""
+ datetimeformat="DATE_WITH_TIME_FORMAT"
time="2020-08-17T14:23:32Z"
tooltipplacement="top"
/>
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
index 2a78cfb13f9..81ad47b1e13 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
@@ -1,5 +1,5 @@
import { GlFormCheckbox, GlSprintf, GlTruncate } from '@gitlab/ui';
-import Vue, { nextTick } from 'vue';
+import Vue from 'vue';
import VueRouter from 'vue-router';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
@@ -9,7 +9,6 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import PackagesListRow from '~/packages_and_registries/package_registry/components/list/package_list_row.vue';
import PackagePath from '~/packages_and_registries/shared/components/package_path.vue';
import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
-import PackageIconAndName from '~/packages_and_registries/shared/components/package_icon_and_name.vue';
import PublishMethod from '~/packages_and_registries/package_registry/components/list/publish_method.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { PACKAGE_ERROR_STATUS } from '~/packages_and_registries/package_registry/constants';
@@ -39,7 +38,7 @@ describe('packages_list_row', () => {
const findPackageTags = () => wrapper.findComponent(PackageTags);
const findPackagePath = () => wrapper.findComponent(PackagePath);
const findDeleteDropdown = () => wrapper.findByTestId('action-delete');
- const findPackageIconAndName = () => wrapper.findComponent(PackageIconAndName);
+ const findPackageType = () => wrapper.findByTestId('package-type');
const findPackageLink = () => wrapper.findByTestId('details-link');
const findWarningIcon = () => wrapper.findByTestId('warning-icon');
const findLeftSecondaryInfos = () => wrapper.findByTestId('left-secondary-infos');
@@ -67,15 +66,11 @@ describe('packages_list_row', () => {
selected,
},
directives: {
- GlTooltip: createMockDirective(),
+ GlTooltip: createMockDirective('gl-tooltip'),
},
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders', () => {
mountComponent();
expect(wrapper.element).toMatchSnapshot();
@@ -136,12 +131,11 @@ describe('packages_list_row', () => {
});
});
- it('emits the delete event when the delete button is clicked', async () => {
+ it('emits the delete event when the delete button is clicked', () => {
mountComponent({ packageEntity: packageWithoutTags });
findDeleteDropdown().vm.$emit('click');
- await nextTick();
expect(wrapper.emitted('delete')).toHaveLength(1);
});
});
@@ -237,10 +231,10 @@ describe('packages_list_row', () => {
expect(findLeftSecondaryInfos().text()).toContain('published by Administrator');
});
- it('has icon and name component', () => {
+ it('has package type with middot', () => {
mountComponent();
- expect(findPackageIconAndName().text()).toBe(packageWithoutTags.packageType.toLowerCase());
+ expect(findPackageType().text()).toBe(`· ${packageWithoutTags.packageType.toLowerCase()}`);
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
index 610640e0ca3..483b7a9383d 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
@@ -4,7 +4,6 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import PackagesListRow from '~/packages_and_registries/package_registry/components/list/package_list_row.vue';
import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
-import DeletePackageModal from '~/packages_and_registries/shared/components/delete_package_modal.vue';
import DeleteModal from '~/packages_and_registries/package_registry/components/delete_modal.vue';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import {
@@ -17,7 +16,7 @@ import {
} from '~/packages_and_registries/package_registry/constants';
import PackagesList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
import Tracking from '~/tracking';
-import { packageData } from '../../mock_data';
+import { defaultPackageGroupSettings, packageData } from '../../mock_data';
describe('packages_list', () => {
let wrapper;
@@ -39,18 +38,20 @@ describe('packages_list', () => {
list: [firstPackage, secondPackage],
isLoading: false,
pageInfo: {},
+ groupSettings: defaultPackageGroupSettings,
};
const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>bar</div>' };
const findPackagesListLoader = () => wrapper.findComponent(PackagesListLoader);
- const findPackageListDeleteModal = () => wrapper.findComponent(DeletePackageModal);
const findEmptySlot = () => wrapper.findComponent(EmptySlotStub);
const findRegistryList = () => wrapper.findComponent(RegistryList);
const findPackagesListRow = () => wrapper.findComponent(PackagesListRow);
const findErrorPackageAlert = () => wrapper.findComponent(GlAlert);
const findDeletePackagesModal = () => wrapper.findComponent(DeleteModal);
+ const showMock = jest.fn();
+
const mountComponent = (props) => {
wrapper = shallowMountExtended(PackagesList, {
propsData: {
@@ -58,10 +59,9 @@ describe('packages_list', () => {
...props,
},
stubs: {
- DeletePackageModal,
DeleteModal: stubComponent(DeleteModal, {
methods: {
- show: jest.fn(),
+ show: showMock,
},
}),
GlSprintf,
@@ -73,10 +73,6 @@ describe('packages_list', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('when is loading', () => {
beforeEach(() => {
mountComponent({ isLoading: true });
@@ -123,15 +119,20 @@ describe('packages_list', () => {
});
describe('layout', () => {
- it("doesn't contain a visible modal component", () => {
+ beforeEach(() => {
mountComponent();
+ });
- expect(findPackageListDeleteModal().props('itemToBeDeleted')).toBeNull();
+ it('modal component is not shown', () => {
+ expect(showMock).not.toHaveBeenCalled();
});
- it('does not have an error alert displayed', () => {
- mountComponent();
+ it('modal component props is empty', () => {
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toEqual([]);
+ expect(findDeletePackagesModal().props('showRequestForwardingContent')).toBe(false);
+ });
+ it('does not have an error alert displayed', () => {
expect(findErrorPackageAlert().exists()).toBe(false);
});
});
@@ -150,8 +151,8 @@ describe('packages_list', () => {
finderFunction().vm.$emit('delete', deletePayload);
});
- it('passes itemToBeDeleted to the modal', () => {
- expect(findPackageListDeleteModal().props('itemToBeDeleted')).toStrictEqual(firstPackage);
+ it('passes itemsToBeDeleted to the modal', () => {
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toStrictEqual([firstPackage]);
});
it('requesting delete tracks the right action', () => {
@@ -162,9 +163,13 @@ describe('packages_list', () => {
);
});
+ it('modal component is shown', () => {
+ expect(showMock).toHaveBeenCalledTimes(1);
+ });
+
describe('when modal confirms', () => {
beforeEach(() => {
- findPackageListDeleteModal().vm.$emit('ok');
+ findDeletePackagesModal().vm.$emit('confirm');
});
it('emits delete when modal confirms', () => {
@@ -180,14 +185,14 @@ describe('packages_list', () => {
});
});
- it.each(['ok', 'cancel'])('resets itemToBeDeleted when modal emits %s', async (event) => {
- await findPackageListDeleteModal().vm.$emit(event);
+ it.each(['confirm', 'cancel'])('resets itemsToBeDeleted when modal emits %s', async (event) => {
+ await findDeletePackagesModal().vm.$emit(event);
- expect(findPackageListDeleteModal().props('itemToBeDeleted')).toBeNull();
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toEqual([]);
});
it('canceling delete tracks the right action', () => {
- findPackageListDeleteModal().vm.$emit('cancel');
+ findDeletePackagesModal().vm.$emit('cancel');
expect(eventSpy).toHaveBeenCalledWith(
category,
@@ -241,7 +246,7 @@ describe('packages_list', () => {
it.each(['confirm', 'cancel'])('resets itemsToBeDeleted when modal emits %s', async (event) => {
await findDeletePackagesModal().vm.$emit(event);
- expect(findDeletePackagesModal().props('itemsToBeDeleted')).toHaveLength(0);
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toEqual([]);
});
it('canceling delete tracks the right action', () => {
@@ -262,7 +267,7 @@ describe('packages_list', () => {
return nextTick();
});
- it('should display an alert message', () => {
+ it('should display an alert', () => {
expect(findErrorPackageAlert().exists()).toBe(true);
expect(findErrorPackageAlert().props('title')).toBe(
'There was an error publishing a error package package',
@@ -277,7 +282,9 @@ describe('packages_list', () => {
await nextTick();
- expect(findPackageListDeleteModal().text()).toContain(errorPackage.name);
+ expect(showMock).toHaveBeenCalledTimes(1);
+
+ expect(findDeletePackagesModal().props('itemsToBeDeleted')).toStrictEqual([errorPackage]);
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
index a884959ab62..82fa5b76367 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
@@ -46,10 +46,6 @@ describe('Package Search', () => {
extractFilterAndSorting.mockReturnValue(defaultQueryParamsMock);
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('has a registry search component', async () => {
mountComponent();
@@ -58,7 +54,7 @@ describe('Package Search', () => {
expect(findRegistrySearch().exists()).toBe(true);
});
- it('registry search is mounted after mount', async () => {
+ it('registry search is mounted after mount', () => {
mountComponent();
expect(findRegistrySearch().exists()).toBe(false);
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js
index b47515e15c3..1296458155a 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_title_spec.js
@@ -20,11 +20,6 @@ describe('PackageTitle', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('title area', () => {
it('exists', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js
index fcbd7cc6a50..e9119b736c2 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/publish_method_spec.js
@@ -19,10 +19,6 @@ describe('publish_method', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders', () => {
mountComponent();
expect(wrapper.element).toMatchSnapshot();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js
index 8f3c8667c47..c98f5f32344 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/tokens/package_type_token_spec.js
@@ -19,11 +19,6 @@ describe('packages_filter', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('binds all of his attrs to filtered search token', () => {
mountComponent({ attrs: { foo: 'bar' } });
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 d897be1f344..5fb53566d4e 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -16,7 +16,7 @@ export const packagePipelines = (extend) => [
ref: 'master',
sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0',
project: {
- id: '1',
+ id: '14',
name: 'project14',
webUrl: 'http://gdk.test:3000/namespace14/project14',
__typename: 'Project',
@@ -103,12 +103,20 @@ export const linksData = {
},
};
+export const defaultPackageGroupSettings = {
+ mavenPackageRequestsForwarding: true,
+ npmPackageRequestsForwarding: true,
+ pypiPackageRequestsForwarding: true,
+ __typename: 'PackageSettings',
+};
+
export const packageVersions = () => [
{
createdAt: '2021-08-10T09:33:54Z',
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 +128,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 +139,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',
@@ -147,6 +156,7 @@ export const packageData = (extend) => ({
conanUrl: 'http://gdk.test:3000/api/v4/projects/1/packages/conan',
pypiUrl:
'http://__token__:<your_personal_token>@gdk.test:3000/api/v4/projects/1/packages/pypi/simple',
+ publicPackage: false,
pypiSetupUrl: 'http://gdk.test:3000/api/v4/projects/1/packages/pypi',
...extend,
});
@@ -209,7 +219,10 @@ export const pagination = (extend) => ({
...extend,
});
-export const packageDetailsQuery = (extendPackage) => ({
+export const packageDetailsQuery = ({
+ extendPackage = {},
+ packageSettings = defaultPackageGroupSettings,
+} = {}) => ({
data: {
package: {
...packageData(),
@@ -225,6 +238,12 @@ export const packageDetailsQuery = (extendPackage) => ({
path: 'projectPath',
name: 'gitlab-test',
fullPath: 'gitlab-test',
+ group: {
+ id: '1',
+ packageSettings,
+ __typename: 'Group',
+ },
+ __typename: 'Project',
},
tags: {
nodes: packageTags(),
@@ -243,14 +262,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(),
@@ -297,6 +308,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: {
@@ -351,7 +397,12 @@ export const packageDestroyFilesMutationError = () => ({
],
});
-export const packagesListQuery = ({ type = 'group', extend = {}, extendPagination = {} } = {}) => ({
+export const packagesListQuery = ({
+ type = 'group',
+ extend = {},
+ extendPagination = {},
+ packageSettings = defaultPackageGroupSettings,
+} = {}) => ({
data: {
[type]: {
id: '1',
@@ -378,6 +429,14 @@ export const packagesListQuery = ({ type = 'group', extend = {}, extendPaginatio
pageInfo: pagination(extendPagination),
__typename: 'PackageConnection',
},
+ ...(type === 'group' && { packageSettings }),
+ ...(type === 'project' && {
+ group: {
+ id: '1',
+ packageSettings,
+ __typename: 'Group',
+ },
+ }),
...extend,
__typename: capitalize(type),
},
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 b494965a3cb..0962b4fa757 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
@@ -1,4 +1,4 @@
-import { GlEmptyState, GlTabs, GlTab, GlSprintf } from '@gitlab/ui';
+import { GlEmptyState, GlModal, GlTabs, GlTab, GlSprintf, GlLink } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@@ -6,8 +6,8 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
-
+import { createAlert } from '~/alert';
+import { stubComponent } from 'helpers/stub_component';
import AdditionalMetadata from '~/packages_and_registries/package_registry/components/details/additional_metadata.vue';
import PackagesApp from '~/packages_and_registries/package_registry/pages/details.vue';
import DependencyRow from '~/packages_and_registries/package_registry/components/details/dependency_row.vue';
@@ -18,6 +18,7 @@ import PackageTitle from '~/packages_and_registries/package_registry/components/
import DeletePackages from '~/packages_and_registries/package_registry/components/functional/delete_packages.vue';
import PackageVersionsList from '~/packages_and_registries/package_registry/components/details/package_versions_list.vue';
import {
+ REQUEST_FORWARDING_HELP_PAGE_PATH,
FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
PACKAGE_TYPE_COMPOSER,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
@@ -33,6 +34,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 +44,14 @@ import {
packageFiles,
packageDestroyFilesMutation,
packageDestroyFilesMutationError,
- pagination,
+ defaultPackageGroupSettings,
} from '../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
useMockLocationHelper();
+Vue.use(VueApollo);
+
describe('PackagesApp', () => {
let wrapper;
let apolloProvider;
@@ -57,7 +61,7 @@ describe('PackagesApp', () => {
};
const provide = {
- packageId: '111',
+ packageId: '1',
emptyListIllustration: 'svgPath',
projectListUrl: 'projectListUrl',
groupListUrl: 'groupListUrl',
@@ -66,14 +70,13 @@ describe('PackagesApp', () => {
};
const { __typename, ...packageWithoutTypename } = packageData();
+ const showMock = jest.fn();
function createComponent({
resolver = jest.fn().mockResolvedValue(packageDetailsQuery()),
filesDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFilesMutation()),
routeId = '1',
} = {}) {
- Vue.use(VueApollo);
-
const requestHandlers = [
[getPackageDetails, resolver],
[destroyPackageFilesMutation, filesDeleteMutationResolver],
@@ -86,17 +89,11 @@ describe('PackagesApp', () => {
stubs: {
PackageTitle,
DeletePackages,
- GlModal: {
- template: `
- <div>
- <slot name="modal-title"></slot>
- <p><slot></slot></p>
- </div>
- `,
+ GlModal: stubComponent(GlModal, {
methods: {
- show: jest.fn(),
+ show: showMock,
},
- },
+ }),
GlSprintf,
GlTabs,
GlTab,
@@ -130,10 +127,7 @@ describe('PackagesApp', () => {
const findDependencyRows = () => wrapper.findAllComponents(DependencyRow);
const findDeletePackageModal = () => wrapper.findAllComponents(DeletePackages).at(1);
const findDeletePackages = () => wrapper.findComponent(DeletePackages);
-
- afterEach(() => {
- wrapper.destroy();
- });
+ const findLink = () => wrapper.findComponent(GlLink);
it('renders an empty state component', async () => {
createComponent({ resolver: jest.fn().mockResolvedValue(emptyPackageDetailsQuery) });
@@ -193,7 +187,9 @@ describe('PackagesApp', () => {
createComponent({
resolver: jest.fn().mockResolvedValue(
packageDetailsQuery({
- packageType,
+ extendPackage: {
+ packageType,
+ },
}),
),
});
@@ -248,16 +244,55 @@ describe('PackagesApp', () => {
});
});
- it('shows the delete confirmation modal when delete is clicked', async () => {
- createComponent();
+ describe('when delete button is clicked', () => {
+ describe('with request forwarding enabled', () => {
+ beforeEach(async () => {
+ const resolver = jest.fn().mockResolvedValue(
+ packageDetailsQuery({
+ packageSettings: {
+ ...defaultPackageGroupSettings,
+ npmPackageRequestsForwarding: true,
+ },
+ }),
+ );
+ createComponent({ resolver });
- await waitForPromises();
+ await waitForPromises();
- await findDeleteButton().trigger('click');
+ await findDeleteButton().trigger('click');
+ });
- expect(findDeleteModal().find('p').text()).toBe(
- 'You are about to delete version 1.0.0 of @gitlab-org/package-15. Are you sure?',
- );
+ it('shows the delete confirmation modal with request forwarding content', () => {
+ expect(findDeleteModal().text()).toBe(
+ 'Deleting this package while request forwarding is enabled for the project can pose a security risk. Do you want to delete @gitlab-org/package-15 version 1.0.0 anyway? What are the risks?',
+ );
+ });
+
+ it('contains link to help page', () => {
+ expect(findLink().exists()).toBe(true);
+ expect(findLink().attributes('href')).toBe(REQUEST_FORWARDING_HELP_PAGE_PATH);
+ });
+ });
+
+ it('shows the delete confirmation modal without request forwarding content', async () => {
+ const resolver = jest.fn().mockResolvedValue(
+ packageDetailsQuery({
+ packageSettings: {
+ ...defaultPackageGroupSettings,
+ npmPackageRequestsForwarding: false,
+ },
+ }),
+ );
+ createComponent({ resolver });
+
+ await waitForPromises();
+
+ await findDeleteButton().trigger('click');
+
+ expect(findDeleteModal().text()).toBe(
+ 'You are about to delete version 1.0.0 of @gitlab-org/package-15. Are you sure?',
+ );
+ });
});
describe('successful request', () => {
@@ -311,7 +346,9 @@ describe('PackagesApp', () => {
createComponent({
resolver: jest
.fn()
- .mockResolvedValue(packageDetailsQuery({ packageType: PACKAGE_TYPE_COMPOSER })),
+ .mockResolvedValue(
+ packageDetailsQuery({ extendPackage: { packageType: PACKAGE_TYPE_COMPOSER } }),
+ ),
});
await waitForPromises();
@@ -322,7 +359,7 @@ describe('PackagesApp', () => {
describe('deleting a file', () => {
const [fileToDelete] = packageFiles();
- const doDeleteFile = async () => {
+ const doDeleteFile = () => {
findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
findDeleteFileModal().vm.$emit('primary');
@@ -335,25 +372,33 @@ describe('PackagesApp', () => {
await waitForPromises();
- const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show');
- const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
-
findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
- expect(showDeletePackageSpy).not.toHaveBeenCalled();
- expect(showDeleteFileSpy).toHaveBeenCalled();
+ expect(showMock).toHaveBeenCalledTimes(1);
+
+ await waitForPromises();
+
+ expect(findDeleteFileModal().text()).toBe(
+ 'You are about to delete foo-1.0.1.tgz. This is a destructive action that may render your package unusable. Are you sure?',
+ );
});
it('when its the only file opens delete package confirmation modal', async () => {
const [packageFile] = packageFiles();
const resolver = jest.fn().mockResolvedValue(
packageDetailsQuery({
- packageFiles: {
- pageInfo: {
- hasNextPage: false,
+ extendPackage: {
+ packageFiles: {
+ pageInfo: {
+ hasNextPage: false,
+ },
+ nodes: [packageFile],
+ __typename: 'PackageFileConnection',
},
- nodes: [packageFile],
- __typename: 'PackageFileConnection',
+ },
+ packageSettings: {
+ ...defaultPackageGroupSettings,
+ npmPackageRequestsForwarding: false,
},
}),
);
@@ -364,17 +409,13 @@ describe('PackagesApp', () => {
await waitForPromises();
- const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show');
- const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
-
findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
- expect(showDeletePackageSpy).toHaveBeenCalled();
- expect(showDeleteFileSpy).not.toHaveBeenCalled();
+ expect(showMock).toHaveBeenCalledTimes(1);
await waitForPromises();
- expect(findDeleteModal().find('p').text()).toBe(
+ expect(findDeleteModal().text()).toBe(
'Deleting the last package asset will remove version 1.0.0 of @gitlab-org/package-15. Are you sure?',
);
});
@@ -444,7 +485,7 @@ describe('PackagesApp', () => {
});
describe('deleting multiple files', () => {
- const doDeleteFiles = async () => {
+ const doDeleteFiles = () => {
findPackageFiles().vm.$emit('delete-files', packageFiles());
findDeleteFilesModal().vm.$emit('primary');
@@ -486,6 +527,8 @@ describe('PackagesApp', () => {
await doDeleteFiles();
+ expect(resolver).toHaveBeenCalledTimes(2);
+
expect(createAlert).toHaveBeenCalledWith(
expect.objectContaining({
message: DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
@@ -532,11 +575,17 @@ describe('PackagesApp', () => {
it('opens the delete package confirmation modal', async () => {
const resolver = jest.fn().mockResolvedValue(
packageDetailsQuery({
- packageFiles: {
- pageInfo: {
- hasNextPage: false,
+ extendPackage: {
+ packageFiles: {
+ pageInfo: {
+ hasNextPage: false,
+ },
+ nodes: packageFiles(),
},
- nodes: packageFiles(),
+ },
+ packageSettings: {
+ ...defaultPackageGroupSettings,
+ npmPackageRequestsForwarding: false,
},
}),
);
@@ -546,15 +595,13 @@ describe('PackagesApp', () => {
await waitForPromises();
- const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
-
findPackageFiles().vm.$emit('delete-files', packageFiles());
- expect(showDeletePackageSpy).toHaveBeenCalled();
+ expect(showMock).toHaveBeenCalledTimes(1);
await waitForPromises();
- expect(findDeleteModal().find('p').text()).toBe(
+ expect(findDeleteModal().text()).toBe(
'Deleting all package assets will remove version 1.0.0 of @gitlab-org/package-15. Are you sure?',
);
});
@@ -576,10 +623,10 @@ describe('PackagesApp', () => {
createComponent({
resolver: jest.fn().mockResolvedValue(
packageDetailsQuery({
- versions: {
- count: 0,
- nodes: [],
- pageInfo: pagination({ hasNextPage: false, hasPreviousPage: false }),
+ extendPackage: {
+ versions: {
+ count: 0,
+ },
},
}),
),
@@ -595,61 +642,62 @@ 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',
+ isRequestForwardingEnabled: true,
});
});
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);
});
});
});
describe('dependency links', () => {
- it('does not show the dependency links for a non nuget package', async () => {
+ it('does not show the dependency links for a non nuget package', () => {
createComponent();
expect(findDependenciesCountBadge().exists()).toBe(false);
@@ -659,8 +707,10 @@ describe('PackagesApp', () => {
createComponent({
resolver: jest.fn().mockResolvedValue(
packageDetailsQuery({
- packageType: PACKAGE_TYPE_NUGET,
- dependencyLinks: { nodes: [] },
+ extendPackage: {
+ packageType: PACKAGE_TYPE_NUGET,
+ dependencyLinks: { nodes: [] },
+ },
}),
),
});
@@ -676,7 +726,9 @@ describe('PackagesApp', () => {
createComponent({
resolver: jest.fn().mockResolvedValue(
packageDetailsQuery({
- packageType: PACKAGE_TYPE_NUGET,
+ extendPackage: {
+ packageType: PACKAGE_TYPE_NUGET,
+ },
}),
),
});
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
index a2ec527ce12..2ee24200ed3 100644
--- a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
@@ -1,17 +1,18 @@
-import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlButton, GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { s__ } from '~/locale';
+import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
import ListPage from '~/packages_and_registries/package_registry/pages/list.vue';
import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
import OriginalPackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
import DeletePackages from '~/packages_and_registries/package_registry/components/functional/delete_packages.vue';
import {
- PROJECT_RESOURCE_TYPE,
- GROUP_RESOURCE_TYPE,
GRAPHQL_PAGE_SIZE,
EMPTY_LIST_HELP_URL,
PACKAGE_HELP_URL,
@@ -21,7 +22,7 @@ import getPackagesQuery from '~/packages_and_registries/package_registry/graphql
import destroyPackagesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_packages.mutation.graphql';
import { packagesListQuery, packageData, pagination } from '../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('PackagesListApp', () => {
let wrapper;
@@ -31,6 +32,7 @@ describe('PackagesListApp', () => {
emptyListIllustration: 'emptyListIllustration',
isGroupPage: true,
fullPath: 'gitlab-org',
+ settingsPath: 'settings-path',
};
const PackageList = {
@@ -50,6 +52,7 @@ describe('PackagesListApp', () => {
const findListComponent = () => wrapper.findComponent(PackageList);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findDeletePackages = () => wrapper.findComponent(DeletePackages);
+ const findSettingsLink = () => wrapper.findComponent(GlButton);
const mountComponent = ({
resolver = jest.fn().mockResolvedValue(packagesListQuery()),
@@ -72,17 +75,17 @@ describe('PackagesListApp', () => {
GlLoadingIcon,
GlSprintf,
GlLink,
+ PackageTitle,
PackageList,
DeletePackages,
},
+ directives: {
+ GlTooltip: createMockDirective('gl-tooltip'),
+ },
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
- const waitForFirstRequest = async () => {
+ const waitForFirstRequest = () => {
// emit a search update so the query is executed
findSearch().vm.$emit('update', { sort: 'NAME_DESC', filters: [] });
return waitForPromises();
@@ -108,6 +111,52 @@ describe('PackagesListApp', () => {
});
});
+ describe('link to settings', () => {
+ describe('when settings path is not provided', () => {
+ beforeEach(() => {
+ mountComponent({
+ provide: {
+ ...defaultProvide,
+ settingsPath: '',
+ },
+ });
+ });
+
+ it('is not rendered', () => {
+ expect(findSettingsLink().exists()).toBe(false);
+ });
+ });
+
+ describe('when settings path is provided', () => {
+ const label = s__('PackageRegistry|Configure in settings');
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('is rendered', () => {
+ expect(findSettingsLink().exists()).toBe(true);
+ });
+
+ it('has the right icon', () => {
+ expect(findSettingsLink().props('icon')).toBe('settings');
+ });
+
+ it('has the right attributes', () => {
+ expect(findSettingsLink().attributes()).toMatchObject({
+ 'aria-label': label,
+ href: defaultProvide.settingsPath,
+ });
+ });
+
+ it('sets tooltip with right label', () => {
+ const tooltip = getBinding(findSettingsLink().element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(label);
+ });
+ });
+ });
+
describe('search component', () => {
it('exists', () => {
mountComponent();
@@ -146,6 +195,11 @@ describe('PackagesListApp', () => {
list: expect.arrayContaining([expect.objectContaining({ id: packageData().id })]),
isLoading: false,
pageInfo: expect.objectContaining({ endCursor: pagination().endCursor }),
+ groupSettings: expect.objectContaining({
+ mavenPackageRequestsForwarding: true,
+ npmPackageRequestsForwarding: true,
+ pypiPackageRequestsForwarding: true,
+ }),
});
});
@@ -171,14 +225,14 @@ describe('PackagesListApp', () => {
});
describe.each`
- type | sortType
- ${PROJECT_RESOURCE_TYPE} | ${'sort'}
- ${GROUP_RESOURCE_TYPE} | ${'groupSort'}
+ type | sortType
+ ${WORKSPACE_PROJECT} | ${'sort'}
+ ${WORKSPACE_GROUP} | ${'groupSort'}
`('$type query', ({ type, sortType }) => {
let provide;
let resolver;
- const isGroupPage = type === GROUP_RESOURCE_TYPE;
+ const isGroupPage = type === WORKSPACE_GROUP;
beforeEach(() => {
provide = { ...defaultProvide, isGroupPage };
@@ -196,11 +250,25 @@ describe('PackagesListApp', () => {
expect.objectContaining({ isGroupPage, [sortType]: 'NAME_DESC' }),
);
});
+
+ it('list component has group settings prop set', () => {
+ expect(findListComponent().props()).toMatchObject({
+ groupSettings: expect.objectContaining({
+ mavenPackageRequestsForwarding: true,
+ npmPackageRequestsForwarding: true,
+ pypiPackageRequestsForwarding: true,
+ }),
+ });
+ });
});
- describe('empty state', () => {
+ describe.each`
+ description | resolverResponse
+ ${'empty response'} | ${packagesListQuery({ extend: { nodes: [] } })}
+ ${'error response'} | ${{ data: { group: null } }}
+ `(`$description renders empty state`, ({ resolverResponse }) => {
beforeEach(() => {
- const resolver = jest.fn().mockResolvedValue(packagesListQuery({ extend: { nodes: [] } }));
+ const resolver = jest.fn().mockResolvedValue(resolverResponse);
mountComponent({ resolver });
return waitForFirstRequest();
diff --git a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
index 796d89231f4..6dd4b9f2d20 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
@@ -28,7 +28,7 @@ import {
dependencyProxyUpdateTllPolicyMutationMock,
} from '../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses');
describe('DependencyProxySettings', () => {
@@ -82,10 +82,6 @@ describe('DependencyProxySettings', () => {
.mockResolvedValue(dependencyProxyUpdateTllPolicyMutationMock());
});
- afterEach(() => {
- wrapper.destroy();
- });
-
const findSettingsBlock = () => wrapper.findComponent(SettingsBlock);
const findEnableProxyToggle = () => wrapper.findByTestId('dependency-proxy-setting-toggle');
const findEnableTtlPoliciesToggle = () =>
diff --git a/spec/frontend/packages_and_registries/settings/group/components/exceptions_input_spec.js b/spec/frontend/packages_and_registries/settings/group/components/exceptions_input_spec.js
index 86f14961690..dd1edbaa3fd 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/exceptions_input_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/exceptions_input_spec.js
@@ -23,10 +23,6 @@ describe('Exceptions Input', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
const findInputGroup = () => wrapper.findComponent(GlFormGroup);
const findInput = () => wrapper.findComponent(GlFormInput);
@@ -102,7 +98,7 @@ describe('Exceptions Input', () => {
});
it('disables the form input', () => {
- expect(findInput().attributes('disabled')).toBe('true');
+ expect(findInput().attributes('disabled')).toBeDefined();
});
});
});
diff --git a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
index 7edc321867c..3ce8e91d43d 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
@@ -19,7 +19,7 @@ import {
dependencyProxyImageTtlPolicy,
} from '../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('Group Settings App', () => {
let wrapper;
@@ -55,10 +55,6 @@ describe('Group Settings App', () => {
show = jest.fn();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
const findAlert = () => wrapper.findComponent(GlAlert);
const findPackageSettings = () => wrapper.findComponent(PackagesSettings);
const findPackageForwardingSettings = () => wrapper.findComponent(PackagesForwardingSettings);
diff --git a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js
index 807f332f4d3..49e76cfbae0 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/package_settings_spec.js
@@ -23,7 +23,7 @@ import {
groupPackageSettingsMutationErrorMock,
} from '../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses');
describe('Packages Settings', () => {
@@ -56,10 +56,6 @@ describe('Packages Settings', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
const findSettingsBlock = () => wrapper.findComponent(SettingsBlock);
const findDescription = () => wrapper.findByTestId('description');
const findMavenSettings = () => wrapper.findByTestId('maven-settings');
@@ -181,7 +177,7 @@ describe('Packages Settings', () => {
});
});
- it('renders ExceptionsInput and assigns duplication allowness and exception props', async () => {
+ it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({ mountFn: mountExtended });
const { genericDuplicatesAllowed, genericDuplicateExceptionRegex } = packageSettings;
@@ -196,7 +192,7 @@ describe('Packages Settings', () => {
});
});
- it('on update event calls the mutation', async () => {
+ it('on update event calls the mutation', () => {
const mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock());
mountComponent({ mountFn: mountExtended, mutationResolver });
diff --git a/spec/frontend/packages_and_registries/settings/group/components/packages_forwarding_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/packages_forwarding_settings_spec.js
index a0b257a9496..8a66a685733 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/packages_forwarding_settings_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/packages_forwarding_settings_spec.js
@@ -1,12 +1,13 @@
import Vue from 'vue';
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlLink, GlSprintf } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import { s__ } from '~/locale';
import component from '~/packages_and_registries/settings/group/components/packages_forwarding_settings.vue';
import {
- PACKAGE_FORWARDING_SETTINGS_DESCRIPTION,
+ REQUEST_FORWARDING_HELP_PAGE_PATH,
PACKAGE_FORWARDING_SETTINGS_HEADER,
} from '~/packages_and_registries/settings/group/constants';
@@ -25,7 +26,7 @@ import {
mavenProps,
} from '../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses');
describe('Packages Forwarding Settings', () => {
@@ -60,6 +61,7 @@ describe('Packages Forwarding Settings', () => {
forwardSettings,
},
stubs: {
+ GlSprintf,
SettingsBlock,
},
});
@@ -72,6 +74,7 @@ describe('Packages Forwarding Settings', () => {
const findMavenForwardingSettings = () => wrapper.findByTestId('maven');
const findNpmForwardingSettings = () => wrapper.findByTestId('npm');
const findPyPiForwardingSettings = () => wrapper.findByTestId('pypi');
+ const findRequestForwardingDocsLink = () => wrapper.findComponent(GlLink);
const fillApolloCache = () => {
apolloProvider.defaultClient.cache.writeQuery({
@@ -111,8 +114,18 @@ describe('Packages Forwarding Settings', () => {
it('has the correct description text', () => {
mountComponent();
- expect(findDescription().text()).toMatchInterpolatedText(
- PACKAGE_FORWARDING_SETTINGS_DESCRIPTION,
+ expect(findDescription().text()).toBe(
+ s__(
+ 'PackageRegistry|Forward package requests to a public registry if the packages are not found in the GitLab package registry.',
+ ),
+ );
+ });
+
+ it('has the right help link', () => {
+ mountComponent();
+
+ expect(findRequestForwardingDocsLink().attributes('href')).toBe(
+ REQUEST_FORWARDING_HELP_PAGE_PATH,
);
});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
index 2bb99fb8e8f..cbe68df5343 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
@@ -61,10 +61,6 @@ describe('Cleanup image tags project settings', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('isEdited status', () => {
it.each`
description | apiResponse | workingCopy | result
@@ -130,7 +126,7 @@ describe('Cleanup image tags project settings', () => {
});
describe('an admin is visiting the page', () => {
- it('shows the admin part of the alert message', async () => {
+ it('shows the admin part of the alert', async () => {
mountComponentWithApollo({
provide: { ...defaultProvidedValues, isAdmin: true },
resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js
index cbb5aa52694..a68087f7f57 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js
@@ -46,7 +46,7 @@ describe('Container Expiration Policy Settings Form', () => {
const findOlderThanDropdown = () => wrapper.find('[data-testid="older-than-dropdown"]');
const findRemoveRegexInput = () => wrapper.find('[data-testid="remove-regex-input"]');
- const submitForm = async () => {
+ const submitForm = () => {
findForm().trigger('submit');
return waitForPromises();
};
@@ -124,10 +124,6 @@ describe('Container Expiration Policy Settings Form', () => {
jest.spyOn(Tracking, 'event');
});
- afterEach(() => {
- wrapper.destroy();
- });
-
describe.each`
model | finder | fieldName | type | defaultValue
${'enabled'} | ${findEnableToggle} | ${'Enable'} | ${'toggle'} | ${false}
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
index 43484d26d76..c9dd9ce7a45 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
@@ -63,10 +63,6 @@ describe('Container expiration policy project settings', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
it('renders the setting form', async () => {
mountComponentWithApollo({
resolver: jest.fn().mockResolvedValue(expirationPolicyPayload()),
@@ -113,7 +109,7 @@ describe('Container expiration policy project settings', () => {
});
describe('an admin is visiting the page', () => {
- it('shows the admin part of the alert message', async () => {
+ it('shows the admin part of the alert', async () => {
mountComponentWithApollo({
provide: { ...defaultProvidedValues, isAdmin: true },
resolver: jest.fn().mockResolvedValue(nullExpirationPolicyPayload()),
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
index ae41fdf65e0..058fe427106 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
@@ -32,11 +32,6 @@ describe('ExpirationDropdown', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('structure', () => {
it('has a form-select component', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
index 1cea0704154..be12d108d1e 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
@@ -38,11 +38,6 @@ describe('ExpirationInput', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('structure', () => {
it('has a label', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
index 653f2a8b40e..f950a9d5add 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
@@ -23,11 +23,6 @@ describe('ExpirationToggle', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('structure', () => {
it('has an input component', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
index 55a66cebd83..ec7b89aa927 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
@@ -23,11 +23,6 @@ describe('ExpirationToggle', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('structure', () => {
it('has a toggle component', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js
index 0fbbf4ae58f..50b72d3ad72 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js
@@ -48,7 +48,7 @@ describe('Packages Cleanup Policy Settings Form', () => {
wrapper.findByTestId('keep-n-duplicated-package-files-dropdown');
const findNextRunAt = () => wrapper.findByTestId('next-run-at');
- const submitForm = async () => {
+ const submitForm = () => {
findForm().trigger('submit');
return waitForPromises();
};
@@ -115,7 +115,6 @@ describe('Packages Cleanup Policy Settings Form', () => {
});
afterEach(() => {
- wrapper.destroy();
fakeApollo = null;
});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_spec.js
index 6dfeeca6862..94277d34f30 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_spec.js
@@ -47,7 +47,6 @@ describe('Packages cleanup policy project settings', () => {
};
afterEach(() => {
- wrapper.destroy();
fakeApollo = null;
});
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js
index 07d13839c61..12425909454 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js
@@ -20,11 +20,6 @@ describe('Registry Settings app', () => {
const findPackagesCleanupPolicy = () => wrapper.findComponent(PackagesCleanupPolicy);
const findAlert = () => wrapper.findComponent(GlAlert);
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
const defaultProvide = {
showContainerRegistrySettings: true,
showPackageRegistrySettings: true,
@@ -84,7 +79,7 @@ describe('Registry Settings app', () => {
${false} | ${true}
${false} | ${false}
`(
- 'container expiration policy $showContainerRegistrySettings and package cleanup policy is $showPackageRegistrySettings',
+ 'container cleanup policy $showContainerRegistrySettings and package cleanup policy is $showPackageRegistrySettings',
({ showContainerRegistrySettings, showPackageRegistrySettings }) => {
mountComponent({
showContainerRegistrySettings,
diff --git a/spec/frontend/packages_and_registries/shared/components/__snapshots__/registry_breadcrumb_spec.js.snap b/spec/frontend/packages_and_registries/shared/components/__snapshots__/registry_breadcrumb_spec.js.snap
index e6e89806ce0..e9ee6ebdb5c 100644
--- a/spec/frontend/packages_and_registries/shared/components/__snapshots__/registry_breadcrumb_spec.js.snap
+++ b/spec/frontend/packages_and_registries/shared/components/__snapshots__/registry_breadcrumb_spec.js.snap
@@ -5,7 +5,6 @@ exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
aria-label="Breadcrumb"
class="gl-breadcrumbs"
>
-
<ol
class="breadcrumb gl-breadcrumb-list"
>
@@ -16,29 +15,10 @@ exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
class=""
target="_self"
>
+ <!---->
<span>
</span>
-
- <span
- class="gl-breadcrumb-separator"
- data-testid="separator"
- >
- <span
- class="gl-mx-n5"
- >
- <svg
- aria-hidden="true"
- class="gl-icon s8"
- data-testid="chevron-lg-right-icon"
- role="img"
- >
- <use
- href="#chevron-lg-right"
- />
- </svg>
- </span>
- </span>
</a>
</li>
@@ -52,11 +32,10 @@ exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
href="#"
target="_self"
>
+ <!---->
<span>
</span>
-
- <!---->
</a>
</li>
@@ -70,7 +49,6 @@ exports[`Registry Breadcrumb when is rootRoute renders 1`] = `
aria-label="Breadcrumb"
class="gl-breadcrumbs"
>
-
<ol
class="breadcrumb gl-breadcrumb-list"
>
@@ -82,11 +60,10 @@ exports[`Registry Breadcrumb when is rootRoute renders 1`] = `
class=""
target="_self"
>
+ <!---->
<span>
</span>
-
- <!---->
</a>
</li>
diff --git a/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js b/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js
index 18084766db9..41482e6e681 100644
--- a/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/cli_commands_spec.js
@@ -38,11 +38,6 @@ describe('cli_commands', () => {
mountComponent();
});
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('shows the correct text on the button', () => {
expect(findDropdownButton().text()).toContain(QUICK_START);
});
diff --git a/spec/frontend/packages_and_registries/shared/components/delete_package_modal_spec.js b/spec/frontend/packages_and_registries/shared/components/delete_package_modal_spec.js
index 357dab593e8..ba5ba8f9884 100644
--- a/spec/frontend/packages_and_registries/shared/components/delete_package_modal_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/delete_package_modal_spec.js
@@ -19,11 +19,6 @@ describe('DeletePackageModal', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('when itemToBeDeleted prop is defined', () => {
beforeEach(() => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/shared/components/package_icon_and_name_spec.js b/spec/frontend/packages_and_registries/shared/components/package_icon_and_name_spec.js
deleted file mode 100644
index a0ff6ca01b5..00000000000
--- a/spec/frontend/packages_and_registries/shared/components/package_icon_and_name_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { GlIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import PackageIconAndName from '~/packages_and_registries/shared/components/package_icon_and_name.vue';
-
-describe('PackageIconAndName', () => {
- let wrapper;
-
- const findIcon = () => wrapper.findComponent(GlIcon);
-
- const mountComponent = () => {
- wrapper = shallowMount(PackageIconAndName, {
- slots: {
- default: 'test',
- },
- });
- };
-
- it('has an icon', () => {
- mountComponent();
-
- const icon = findIcon();
-
- expect(icon.exists()).toBe(true);
- expect(icon.props('name')).toBe('package');
- });
-
- it('renders the slot content', () => {
- mountComponent();
-
- expect(wrapper.text()).toBe('test');
- });
-});
diff --git a/spec/frontend/packages_and_registries/shared/components/package_path_spec.js b/spec/frontend/packages_and_registries/shared/components/package_path_spec.js
index 93425d4f399..3ffbb6f435c 100644
--- a/spec/frontend/packages_and_registries/shared/components/package_path_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/package_path_spec.js
@@ -9,7 +9,7 @@ describe('PackagePath', () => {
wrapper = shallowMount(PackagePath, {
propsData,
directives: {
- GlTooltip: createMockDirective(),
+ GlTooltip: createMockDirective('gl-tooltip'),
},
});
};
@@ -24,11 +24,6 @@ describe('PackagePath', () => {
const findItem = (name) => wrapper.find(`[data-testid="${name}"]`);
const findTooltip = (w) => getBinding(w.element, 'gl-tooltip');
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe.each`
path | rootUrl | shouldExist | shouldNotExist
${'foo/bar'} | ${'/foo/bar'} | ${[]} | ${[ROOT_CHEVRON, ELLIPSIS_ICON, ELLIPSIS_CHEVRON, LEAF_LINK]}
@@ -91,12 +86,12 @@ describe('PackagePath', () => {
});
it('root link is disabled', () => {
- expect(findItem(ROOT_LINK).attributes('disabled')).toBe('true');
+ expect(findItem(ROOT_LINK).attributes('disabled')).toBeDefined();
});
if (shouldExist.includes(LEAF_LINK)) {
it('the last link is disabled', () => {
- expect(findItem(LEAF_LINK).attributes('disabled')).toBe('true');
+ expect(findItem(LEAF_LINK).attributes('disabled')).toBeDefined();
});
}
});
diff --git a/spec/frontend/packages_and_registries/shared/components/package_tags_spec.js b/spec/frontend/packages_and_registries/shared/components/package_tags_spec.js
index 33e96c0775e..b025517ae47 100644
--- a/spec/frontend/packages_and_registries/shared/components/package_tags_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/package_tags_spec.js
@@ -20,10 +20,6 @@ describe('PackageTags', () => {
const tagBadges = () => wrapper.findAll('[data-testid="tagBadge"]');
const moreBadge = () => wrapper.find('[data-testid="moreBadge"]');
- afterEach(() => {
- if (wrapper) wrapper.destroy();
- });
-
describe('tag label', () => {
it('shows the tag label by default', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/shared/components/packages_list_loader_spec.js b/spec/frontend/packages_and_registries/shared/components/packages_list_loader_spec.js
index 0005162e0bb..e43a9f57255 100644
--- a/spec/frontend/packages_and_registries/shared/components/packages_list_loader_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/packages_list_loader_spec.js
@@ -17,11 +17,6 @@ describe('PackagesListLoader', () => {
beforeEach(createComponent);
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
describe('desktop loader', () => {
it('produces the right loader', () => {
expect(findDesktopShapes().findAll('rect[width="1000"]')).toHaveLength(20);
diff --git a/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js b/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js
index db9f96bff39..c1e86080d29 100644
--- a/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js
@@ -43,10 +43,6 @@ describe('Persisted Search', () => {
extractFilterAndSorting.mockReturnValue(defaultQueryParamsMock);
});
- afterEach(() => {
- wrapper.destroy();
- });
-
it('has a registry search component', async () => {
mountComponent();
@@ -55,7 +51,7 @@ describe('Persisted Search', () => {
expect(findRegistrySearch().exists()).toBe(true);
});
- it('registry search is mounted after mount', async () => {
+ it('registry search is mounted after mount', () => {
mountComponent();
expect(findRegistrySearch().exists()).toBe(false);
diff --git a/spec/frontend/packages_and_registries/shared/components/publish_method_spec.js b/spec/frontend/packages_and_registries/shared/components/publish_method_spec.js
index fa8f8f7641a..167599a54ea 100644
--- a/spec/frontend/packages_and_registries/shared/components/publish_method_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/publish_method_spec.js
@@ -20,11 +20,6 @@ describe('publish_method', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
it('renders', () => {
mountComponent(packageWithPipeline);
expect(wrapper.element).toMatchSnapshot();
diff --git a/spec/frontend/packages_and_registries/shared/components/registry_breadcrumb_spec.js b/spec/frontend/packages_and_registries/shared/components/registry_breadcrumb_spec.js
index 15db454ac68..c1f1a25d53b 100644
--- a/spec/frontend/packages_and_registries/shared/components/registry_breadcrumb_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/registry_breadcrumb_spec.js
@@ -31,10 +31,6 @@ describe('Registry Breadcrumb', () => {
nameGenerator.mockClear();
});
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('when is rootRoute', () => {
beforeEach(() => {
mountComponent(routes[0]);
diff --git a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
index 2e2d5e26d33..66fca2ce12e 100644
--- a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
@@ -36,10 +36,6 @@ describe('Registry List', () => {
const findScopedSlotFirstValue = (index) => findScopedSlots().at(index).find('span');
const findScopedSlotIsSelectedValue = (index) => findScopedSlots().at(index).find('p');
- afterEach(() => {
- wrapper.destroy();
- });
-
describe('header', () => {
it('renders the title passed in the prop', () => {
mountComponent();
@@ -62,7 +58,7 @@ describe('Registry List', () => {
it('sets disabled prop to true when items length is 0', () => {
mountComponent({ propsData: { ...defaultPropsData, items: [] } });
- expect(findSelectAll().attributes('disabled')).toBe('true');
+ expect(findSelectAll().attributes('disabled')).toBeDefined();
});
it('when few are selected, sets indeterminate prop to true', async () => {
@@ -111,10 +107,21 @@ describe('Registry List', () => {
expect(findDeleteSelected().text()).toBe(component.i18n.deleteSelected);
});
- it('is hidden when hiddenDelete is true', () => {
- mountComponent({ propsData: { ...defaultPropsData, hiddenDelete: true } });
+ describe('when hiddenDelete is true', () => {
+ beforeEach(() => {
+ mountComponent({ propsData: { ...defaultPropsData, hiddenDelete: true } });
+ });
- expect(findDeleteSelected().exists()).toBe(false);
+ it('is hidden', () => {
+ expect(findDeleteSelected().exists()).toBe(false);
+ });
+
+ it('populates the first slot prop correctly', () => {
+ expect(findScopedSlots().at(0).exists()).toBe(true);
+
+ // it's the first slot
+ expect(findScopedSlotFirstValue(0).text()).toBe('false');
+ });
});
it('is disabled when isLoading is true', () => {
diff --git a/spec/frontend/packages_and_registries/shared/components/settings_block_spec.js b/spec/frontend/packages_and_registries/shared/components/settings_block_spec.js
index a4c1b989dac..664a821c275 100644
--- a/spec/frontend/packages_and_registries/shared/components/settings_block_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/settings_block_spec.js
@@ -15,10 +15,6 @@ describe('SettingsBlock', () => {
});
};
- afterEach(() => {
- wrapper.destroy();
- });
-
const findDefaultSlot = () => wrapper.findByTestId('default-slot');
const findTitleSlot = () => wrapper.findByTestId('title-slot');
const findDescriptionSlot = () => wrapper.findByTestId('description-slot');