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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/snippets/components/snippet_header_spec.js')
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js138
1 files changed, 76 insertions, 62 deletions
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index c930c9f635b..4bf64bfd3cd 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -1,8 +1,9 @@
-import { GlButton, GlModal, GlDropdown } from '@gitlab/ui';
+import { GlModal, GlButton, GlDropdown } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import { ApolloMutation } from 'vue-apollo';
+import VueApollo from 'vue-apollo';
import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
@@ -10,31 +11,41 @@ import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
import SnippetHeader, { i18n } from '~/snippets/components/snippet_header.vue';
import DeleteSnippetMutation from '~/snippets/mutations/delete_snippet.mutation.graphql';
import axios from '~/lib/utils/axios_utils';
-import { createAlert, VARIANT_DANGER, VARIANT_SUCCESS } from '~/flash';
+import { createAlert, VARIANT_DANGER, VARIANT_SUCCESS } from '~/alert';
+import CanCreateProjectSnippet from 'shared_queries/snippet/project_permissions.query.graphql';
+import CanCreatePersonalSnippet from 'shared_queries/snippet/user_permissions.query.graphql';
+import { getCanCreateProjectSnippetMock, getCanCreatePersonalSnippetMock } from '../mock_data';
-jest.mock('~/flash');
+const ERROR_MSG = 'Foo bar';
+const ERR = { message: ERROR_MSG };
+
+const MUTATION_TYPES = {
+ RESOLVE: jest.fn().mockResolvedValue({ data: { destroySnippet: { errors: [] } } }),
+ REJECT: jest.fn().mockRejectedValue(ERR),
+};
+
+jest.mock('~/alert');
+
+Vue.use(VueApollo);
describe('Snippet header component', () => {
let wrapper;
let snippet;
- let mutationTypes;
- let mutationVariables;
let mock;
+ let mockApollo;
- let errorMsg;
- let err;
- const originalRelativeUrlRoot = gon.relative_url_root;
const reportAbusePath = '/-/snippets/42/mark_as_spam';
const canReportSpam = true;
const GlEmoji = { template: '<img/>' };
function createComponent({
- loading = false,
permissions = {},
- mutationRes = mutationTypes.RESOLVE,
snippetProps = {},
provide = {},
+ canCreateProjectSnippetMock = jest.fn().mockResolvedValue(getCanCreateProjectSnippetMock()),
+ canCreatePersonalSnippetMock = jest.fn().mockResolvedValue(getCanCreatePersonalSnippetMock()),
+ deleteSnippetMock = MUTATION_TYPES.RESOLVE,
} = {}) {
const defaultProps = Object.assign(snippet, snippetProps);
if (permissions) {
@@ -42,17 +53,14 @@ describe('Snippet header component', () => {
...permissions,
});
}
- const $apollo = {
- queries: {
- canCreateSnippet: {
- loading,
- },
- },
- mutate: mutationRes,
- };
+
+ mockApollo = createMockApollo([
+ [CanCreateProjectSnippet, canCreateProjectSnippetMock],
+ [CanCreatePersonalSnippet, canCreatePersonalSnippetMock],
+ [DeleteSnippetMutation, deleteSnippetMock],
+ ]);
wrapper = mount(SnippetHeader, {
- mocks: { $apollo },
provide: {
reportAbusePath,
canReportSpam,
@@ -64,9 +72,9 @@ describe('Snippet header component', () => {
},
},
stubs: {
- ApolloMutation,
GlEmoji,
},
+ apolloProvider: mockApollo,
});
}
@@ -91,6 +99,7 @@ describe('Snippet header component', () => {
title: x.attributes('title'),
text: x.text(),
}));
+ const findDeleteModal = () => wrapper.findComponent(GlModal);
beforeEach(() => {
gon.relative_url_root = '/foo/';
@@ -113,28 +122,12 @@ describe('Snippet header component', () => {
createdAt: new Date(differenceInMilliseconds(32 * 24 * 3600 * 1000)).toISOString(),
};
- mutationVariables = {
- mutation: DeleteSnippetMutation,
- variables: {
- id: snippet.id,
- },
- };
-
- errorMsg = 'Foo bar';
- err = { message: errorMsg };
-
- mutationTypes = {
- RESOLVE: jest.fn(() => Promise.resolve({ data: { destroySnippet: { errors: [] } } })),
- REJECT: jest.fn(() => Promise.reject(err)),
- };
-
mock = new MockAdapter(axios);
});
afterEach(() => {
- wrapper.destroy();
+ mockApollo = null;
mock.restore();
- gon.relative_url_root = originalRelativeUrlRoot;
});
it('renders itself', () => {
@@ -238,15 +231,16 @@ describe('Snippet header component', () => {
});
it('with canCreateSnippet permission, renders create button', async () => {
- createComponent();
+ createComponent({
+ canCreateProjectSnippetMock: jest
+ .fn()
+ .mockResolvedValue(getCanCreateProjectSnippetMock(true)),
+ canCreatePersonalSnippetMock: jest
+ .fn()
+ .mockResolvedValue(getCanCreatePersonalSnippetMock(true)),
+ });
- // TODO: we should avoid `wrapper.setData` since they
- // are component internals. Let's use the apollo mock helpers
- // in a follow-up.
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ canCreateSnippet: true });
- await nextTick();
+ await waitForPromises();
expect(findButtonsAsModel()).toEqual(
expect.arrayContaining([
@@ -262,7 +256,7 @@ describe('Snippet header component', () => {
});
describe('submit snippet as spam', () => {
- beforeEach(async () => {
+ beforeEach(() => {
createComponent();
});
@@ -271,7 +265,7 @@ describe('Snippet header component', () => {
${200} | ${VARIANT_SUCCESS} | ${i18n.snippetSpamSuccess}
${500} | ${VARIANT_DANGER} | ${i18n.snippetSpamFailure}
`(
- 'renders a "$variant" flash message with "$text" message for a request with a "$request" response',
+ 'renders a "$variant" alert message with "$text" message for a request with a "$request" response',
async ({ request, variant, text }) => {
const submitAsSpamBtn = findButtons().at(2);
mock.onPost(reportAbusePath).reply(request);
@@ -329,21 +323,37 @@ describe('Snippet header component', () => {
});
describe('Delete mutation', () => {
- it('dispatches a mutation to delete the snippet with correct variables', () => {
+ const deleteSnippet = async () => {
+ // Click delete action
+ findButtons().at(1).trigger('click');
+ await nextTick();
+
+ expect(findDeleteModal().props().visible).toBe(true);
+
+ // Click delete button in delete modal
+ document.querySelector('[data-testid="delete-snippet"').click();
+ await waitForPromises();
+ };
+
+ it('dispatches a mutation to delete the snippet with correct variables', async () => {
createComponent();
- wrapper.vm.deleteSnippet();
- expect(mutationTypes.RESOLVE).toHaveBeenCalledWith(mutationVariables);
+
+ await deleteSnippet();
+
+ expect(MUTATION_TYPES.RESOLVE).toHaveBeenCalledWith({
+ id: snippet.id,
+ });
});
it('sets error message if mutation fails', async () => {
- createComponent({ mutationRes: mutationTypes.REJECT });
+ createComponent({ deleteSnippetMock: MUTATION_TYPES.REJECT });
expect(Boolean(wrapper.vm.errorMessage)).toBe(false);
- wrapper.vm.deleteSnippet();
-
- await waitForPromises();
+ await deleteSnippet();
- expect(wrapper.vm.errorMessage).toEqual(errorMsg);
+ expect(document.querySelector('[data-testid="delete-alert"').textContent.trim()).toBe(
+ ERROR_MSG,
+ );
});
describe('in case of successful mutation, closes modal and redirects to correct listing', () => {
@@ -353,15 +363,16 @@ describe('Snippet header component', () => {
createComponent({
snippetProps,
});
- wrapper.vm.closeDeleteModal = jest.fn();
- wrapper.vm.deleteSnippet();
- await nextTick();
+ await deleteSnippet();
};
it('redirects to dashboard/snippets for personal snippet', async () => {
await createDeleteSnippet();
- expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
+
+ // Check that the modal is hidden after deleting the snippet
+ expect(findDeleteModal().props().visible).toBe(false);
+
expect(window.location.pathname).toBe(`${gon.relative_url_root}dashboard/snippets`);
});
@@ -372,7 +383,10 @@ describe('Snippet header component', () => {
fullPath,
},
});
- expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
+
+ // Check that the modal is hidden after deleting the snippet
+ expect(findDeleteModal().props().visible).toBe(false);
+
expect(window.location.pathname).toBe(`${fullPath}/-/snippets`);
});
});