206 lines
5.2 KiB
JavaScript
206 lines
5.2 KiB
JavaScript
import SnippetHeader from '~/snippets/components/snippet_header.vue';
|
|
import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql';
|
|
import { ApolloMutation } from 'vue-apollo';
|
|
import { GlButton, GlModal } from '@gitlab/ui';
|
|
import { shallowMount } from '@vue/test-utils';
|
|
|
|
describe('Snippet header component', () => {
|
|
let wrapper;
|
|
const snippet = {
|
|
id: 'gid://gitlab/PersonalSnippet/50',
|
|
title: 'The property of Thor',
|
|
visibilityLevel: 'private',
|
|
webUrl: 'http://personal.dev.null/42',
|
|
userPermissions: {
|
|
adminSnippet: true,
|
|
updateSnippet: true,
|
|
reportSnippet: false,
|
|
},
|
|
project: null,
|
|
author: {
|
|
name: 'Thor Odinson',
|
|
},
|
|
blob: {
|
|
binary: false,
|
|
},
|
|
};
|
|
const mutationVariables = {
|
|
mutation: DeleteSnippetMutation,
|
|
variables: {
|
|
id: snippet.id,
|
|
},
|
|
};
|
|
const errorMsg = 'Foo bar';
|
|
const err = { message: errorMsg };
|
|
|
|
const resolveMutate = jest.fn(() =>
|
|
Promise.resolve({ data: { destroySnippet: { errors: [] } } }),
|
|
);
|
|
const rejectMutation = jest.fn(() => Promise.reject(err));
|
|
|
|
const mutationTypes = {
|
|
RESOLVE: resolveMutate,
|
|
REJECT: rejectMutation,
|
|
};
|
|
|
|
function createComponent({
|
|
loading = false,
|
|
permissions = {},
|
|
mutationRes = mutationTypes.RESOLVE,
|
|
snippetProps = {},
|
|
} = {}) {
|
|
// const defaultProps = Object.assign({}, snippet, snippetProps);
|
|
const defaultProps = Object.assign(snippet, snippetProps);
|
|
if (permissions) {
|
|
Object.assign(defaultProps.userPermissions, {
|
|
...permissions,
|
|
});
|
|
}
|
|
const $apollo = {
|
|
queries: {
|
|
canCreateSnippet: {
|
|
loading,
|
|
},
|
|
},
|
|
mutate: mutationRes,
|
|
};
|
|
|
|
wrapper = shallowMount(SnippetHeader, {
|
|
mocks: { $apollo },
|
|
propsData: {
|
|
snippet: {
|
|
...defaultProps,
|
|
},
|
|
},
|
|
stubs: {
|
|
ApolloMutation,
|
|
},
|
|
});
|
|
}
|
|
|
|
afterEach(() => {
|
|
wrapper.destroy();
|
|
});
|
|
|
|
it('renders itself', () => {
|
|
createComponent();
|
|
expect(wrapper.find('.detail-page-header').exists()).toBe(true);
|
|
});
|
|
|
|
it('renders action buttons based on permissions', () => {
|
|
createComponent({
|
|
permissions: {
|
|
adminSnippet: false,
|
|
updateSnippet: false,
|
|
},
|
|
});
|
|
expect(wrapper.findAll(GlButton).length).toEqual(0);
|
|
|
|
createComponent({
|
|
permissions: {
|
|
adminSnippet: true,
|
|
updateSnippet: false,
|
|
},
|
|
});
|
|
expect(wrapper.findAll(GlButton).length).toEqual(1);
|
|
|
|
createComponent({
|
|
permissions: {
|
|
adminSnippet: true,
|
|
updateSnippet: true,
|
|
},
|
|
});
|
|
expect(wrapper.findAll(GlButton).length).toEqual(2);
|
|
|
|
createComponent({
|
|
permissions: {
|
|
adminSnippet: true,
|
|
updateSnippet: true,
|
|
},
|
|
});
|
|
wrapper.setData({
|
|
canCreateSnippet: true,
|
|
});
|
|
return wrapper.vm.$nextTick().then(() => {
|
|
expect(wrapper.findAll(GlButton).length).toEqual(3);
|
|
});
|
|
});
|
|
|
|
it('renders modal for deletion of a snippet', () => {
|
|
createComponent();
|
|
expect(wrapper.find(GlModal).exists()).toBe(true);
|
|
});
|
|
|
|
it('renders Edit button as disabled for binary snippets', () => {
|
|
createComponent({
|
|
snippetProps: {
|
|
blob: {
|
|
binary: true,
|
|
},
|
|
},
|
|
});
|
|
expect(wrapper.find('[href*="edit"]').props('disabled')).toBe(true);
|
|
});
|
|
|
|
describe('Delete mutation', () => {
|
|
const { location } = window;
|
|
|
|
beforeEach(() => {
|
|
delete window.location;
|
|
window.location = {
|
|
pathname: '',
|
|
};
|
|
});
|
|
|
|
afterEach(() => {
|
|
window.location = location;
|
|
});
|
|
|
|
it('dispatches a mutation to delete the snippet with correct variables', () => {
|
|
createComponent();
|
|
wrapper.vm.deleteSnippet();
|
|
expect(mutationTypes.RESOLVE).toHaveBeenCalledWith(mutationVariables);
|
|
});
|
|
|
|
it('sets error message if mutation fails', () => {
|
|
createComponent({ mutationRes: mutationTypes.REJECT });
|
|
expect(Boolean(wrapper.vm.errorMessage)).toBe(false);
|
|
|
|
wrapper.vm.deleteSnippet();
|
|
return wrapper.vm.$nextTick().then(() => {
|
|
expect(wrapper.vm.errorMessage).toEqual(errorMsg);
|
|
});
|
|
});
|
|
|
|
describe('in case of successful mutation, closes modal and redirects to correct listing', () => {
|
|
const createDeleteSnippet = (snippetProps = {}) => {
|
|
createComponent({
|
|
snippetProps,
|
|
});
|
|
wrapper.vm.closeDeleteModal = jest.fn();
|
|
|
|
wrapper.vm.deleteSnippet();
|
|
return wrapper.vm.$nextTick();
|
|
};
|
|
|
|
it('redirects to dashboard/snippets for personal snippet', () => {
|
|
return createDeleteSnippet().then(() => {
|
|
expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
|
|
expect(window.location.pathname).toBe('dashboard/snippets');
|
|
});
|
|
});
|
|
|
|
it('redirects to project snippets for project snippet', () => {
|
|
const fullPath = 'foo/bar';
|
|
return createDeleteSnippet({
|
|
project: {
|
|
fullPath,
|
|
},
|
|
}).then(() => {
|
|
expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
|
|
expect(window.location.pathname).toBe(`${fullPath}/snippets`);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|