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.js162
1 files changed, 121 insertions, 41 deletions
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index 585614a6b79..fb95be3a77c 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -1,6 +1,7 @@
-import { GlButton, GlModal } from '@gitlab/ui';
+import { GlButton, GlModal, GlDropdown } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
+import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
@@ -16,6 +17,7 @@ describe('Snippet header component', () => {
let errorMsg;
let err;
const originalRelativeUrlRoot = gon.relative_url_root;
+ const reportAbusePath = '/-/snippets/42/mark_as_spam';
const GlEmoji = { template: '<img/>' };
@@ -24,6 +26,7 @@ describe('Snippet header component', () => {
permissions = {},
mutationRes = mutationTypes.RESOLVE,
snippetProps = {},
+ provide = {},
} = {}) {
const defaultProps = Object.assign(snippet, snippetProps);
if (permissions) {
@@ -42,6 +45,10 @@ describe('Snippet header component', () => {
wrapper = mount(SnippetHeader, {
mocks: { $apollo },
+ provide: {
+ reportAbusePath,
+ ...provide,
+ },
propsData: {
snippet: {
...defaultProps,
@@ -54,9 +61,27 @@ describe('Snippet header component', () => {
});
}
- const findAuthorEmoji = () => wrapper.find(GlEmoji);
+ const findAuthorEmoji = () => wrapper.findComponent(GlEmoji);
const findAuthoredMessage = () => wrapper.find('[data-testid="authored-message"]').text();
- const buttonCount = () => wrapper.findAll(GlButton).length;
+ const findButtons = () => wrapper.findAllComponents(GlButton);
+ const findButtonsAsModel = () =>
+ findButtons().wrappers.map((x) => ({
+ text: x.text(),
+ href: x.attributes('href'),
+ category: x.props('category'),
+ variant: x.props('variant'),
+ disabled: x.props('disabled'),
+ }));
+ const findResponsiveDropdown = () => wrapper.findComponent(GlDropdown);
+ // We can't search by component here since we are full mounting and the attributes are applied to a child of the GlDropdownItem
+ const findResponsiveDropdownItems = () => findResponsiveDropdown().findAll('[role="menuitem"]');
+ const findResponsiveDropdownItemsAsModel = () =>
+ findResponsiveDropdownItems().wrappers.map((x) => ({
+ disabled: x.attributes('disabled'),
+ href: x.attributes('href'),
+ title: x.attributes('title'),
+ text: x.text(),
+ }));
beforeEach(() => {
gon.relative_url_root = '/foo/';
@@ -141,42 +166,108 @@ describe('Snippet header component', () => {
expect(text).toBe('Authored 1 month ago');
});
- it('renders action buttons based on permissions', () => {
- createComponent({
- permissions: {
- adminSnippet: false,
- updateSnippet: false,
+ it('renders a action buttons', () => {
+ createComponent();
+
+ expect(findButtonsAsModel()).toEqual([
+ {
+ category: 'primary',
+ disabled: false,
+ href: `${snippet.webUrl}/edit`,
+ text: 'Edit',
+ variant: 'default',
},
- });
- expect(buttonCount()).toEqual(0);
+ {
+ category: 'secondary',
+ disabled: false,
+ text: 'Delete',
+ variant: 'danger',
+ },
+ {
+ category: 'primary',
+ disabled: false,
+ href: reportAbusePath,
+ text: 'Submit as spam',
+ variant: 'default',
+ },
+ ]);
+ });
- createComponent({
- permissions: {
- adminSnippet: true,
- updateSnippet: false,
+ it('renders responsive dropdown for action buttons', () => {
+ createComponent();
+
+ expect(findResponsiveDropdownItemsAsModel()).toEqual([
+ {
+ href: `${snippet.webUrl}/edit`,
+ text: 'Edit',
},
- });
- expect(buttonCount()).toEqual(1);
+ {
+ text: 'Delete',
+ },
+ {
+ href: reportAbusePath,
+ text: 'Submit as spam',
+ title: 'Submit as spam',
+ },
+ ]);
+ });
+ it.each`
+ permissions | buttons
+ ${{ adminSnippet: false, updateSnippet: false }} | ${['Submit as spam']}
+ ${{ adminSnippet: true, updateSnippet: false }} | ${['Delete', 'Submit as spam']}
+ ${{ adminSnippet: false, updateSnippet: true }} | ${['Edit', 'Submit as spam']}
+ `('with permissions ($permissions), renders buttons ($buttons)', ({ permissions, buttons }) => {
createComponent({
permissions: {
- adminSnippet: true,
- updateSnippet: true,
+ ...permissions,
},
});
- expect(buttonCount()).toEqual(2);
- createComponent({
- permissions: {
- adminSnippet: true,
- updateSnippet: true,
- },
+ expect(findButtonsAsModel().map((x) => x.text)).toEqual(buttons);
+ });
+
+ it('with canCreateSnippet permission, renders create button', async () => {
+ createComponent();
+
+ // TODO: we should avoid `wrapper.setData` since they
+ // are component internals. Let's use the apollo mock helpers
+ // in a follow-up.
+ wrapper.setData({ canCreateSnippet: true });
+ await wrapper.vm.$nextTick();
+
+ expect(findButtonsAsModel()).toEqual(
+ expect.arrayContaining([
+ {
+ category: 'secondary',
+ disabled: false,
+ href: `/foo/-/snippets/new`,
+ text: 'New snippet',
+ variant: 'success',
+ },
+ ]),
+ );
+ });
+
+ describe('with guest user', () => {
+ beforeEach(() => {
+ createComponent({
+ permissions: {
+ adminSnippet: false,
+ updateSnippet: false,
+ },
+ provide: {
+ reportAbusePath: null,
+ },
+ });
});
- wrapper.setData({
- canCreateSnippet: true,
+
+ it('does not show any action buttons', () => {
+ expect(findButtons()).toHaveLength(0);
});
- return wrapper.vm.$nextTick().then(() => {
- expect(buttonCount()).toEqual(3);
+
+ it('does not show responsive action dropdown', () => {
+ expect(findResponsiveDropdown().exists()).toBe(false);
});
});
@@ -200,19 +291,6 @@ describe('Snippet header component', () => {
});
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();
@@ -231,6 +309,8 @@ describe('Snippet header component', () => {
});
describe('in case of successful mutation, closes modal and redirects to correct listing', () => {
+ useMockLocationHelper();
+
const createDeleteSnippet = (snippetProps = {}) => {
createComponent({
snippetProps,