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')
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap2
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap82
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_description_view_spec.js.snap2
-rw-r--r--spec/frontend/snippets/components/edit_spec.js136
-rw-r--r--spec/frontend/snippets/components/snippet_blob_view_spec.js20
-rw-r--r--spec/frontend/snippets/components/snippet_description_edit_spec.js4
6 files changed, 219 insertions, 27 deletions
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap
index 301ec5652a9..959bc24eef6 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap
@@ -12,7 +12,7 @@ exports[`Snippet Blob Edit component rendering matches the snapshot 1`] = `
class="file-holder snippet"
>
<blob-header-edit-stub
- data-qa-selector="snippet_file_name"
+ data-qa-selector="file_name_field"
value="lorem.txt"
/>
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
index 9fd4cba5b87..297ad16b681 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
@@ -4,7 +4,9 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
<div
class="form-group js-description-input"
>
- <label>
+ <label
+ for="snippet-description"
+ >
Description (optional)
</label>
@@ -21,27 +23,67 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
/>
</div>
- <markdown-field-stub
- addspacingclasses="true"
- canattachfile="true"
- class="js-expanded"
- enableautocomplete="true"
- helppagepath=""
- markdowndocspath="help/"
- markdownpreviewpath="foo/"
- note="[object Object]"
- quickactionsdocspath=""
- textareavalue=""
+ <div
+ class="js-vue-markdown-field md-area position-relative js-expanded gfm-form"
>
- <textarea
- aria-label="Description"
- class="note-textarea js-gfm-input js-autosize markdown-area"
- data-qa-selector="snippet_description_field"
- data-supports-quick-actions="false"
- dir="auto"
- placeholder="Write a comment or drag your files here…"
+ <markdown-header-stub
+ linecontent=""
/>
- </markdown-field-stub>
+
+ <div
+ class="md-write-holder"
+ >
+ <div
+ class="zen-backdrop div-dropzone-wrapper"
+ >
+ <div
+ class="div-dropzone js-invalid-dropzone"
+ >
+ <textarea
+ aria-label="Description"
+ class="note-textarea js-gfm-input js-autosize markdown-area"
+ data-qa-selector="snippet_description_field"
+ data-supports-quick-actions="false"
+ dir="auto"
+ id="snippet-description"
+ placeholder="Write a comment or drag your files here…"
+ style="overflow-x: hidden; word-wrap: break-word; overflow-y: hidden;"
+ />
+ <div
+ class="div-dropzone-hover"
+ >
+ <i
+ class="fa fa-paperclip div-dropzone-icon"
+ />
+ </div>
+ </div>
+
+ <a
+ aria-label="Leave zen mode"
+ class="zen-control zen-control-leave js-zen-leave gl-text-gray-700"
+ href="#"
+ >
+ <icon-stub
+ name="screen-normal"
+ size="16"
+ />
+ </a>
+
+ <markdown-toolbar-stub
+ canattachfile="true"
+ markdowndocspath="help/"
+ quickactionsdocspath=""
+ />
+ </div>
+ </div>
+
+ <div
+ class="js-vue-md-preview md md-preview-holder"
+ style="display: none;"
+ />
+
+ <!---->
+ </div>
</div>
</div>
`;
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_description_view_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_description_view_spec.js.snap
index 9ebc4e81baf..9fb43815cbc 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_description_view_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_description_view_spec.js.snap
@@ -3,7 +3,7 @@
exports[`Snippet Description component matches the snapshot 1`] = `
<markdown-field-view-stub
class="snippet-description"
- data-qa-selector="snippet_description_field"
+ data-qa-selector="snippet_description_content"
>
<div
class="md js-snippet-description"
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index ba62a0a92ca..83f46dd347f 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import axios from '~/lib/utils/axios_utils';
+import Flash from '~/flash';
import { GlLoadingIcon } from '@gitlab/ui';
import { joinPaths, redirectTo } from '~/lib/utils/url_utility';
@@ -10,6 +11,7 @@ import SnippetVisibilityEdit from '~/snippets/components/snippet_visibility_edit
import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
import TitleField from '~/vue_shared/components/form/title.vue';
import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import { SNIPPET_CREATE_MUTATION_ERROR, SNIPPET_UPDATE_MUTATION_ERROR } from '~/snippets/constants';
import UpdateSnippetMutation from '~/snippets/mutations/updateSnippet.mutation.graphql';
import CreateSnippetMutation from '~/snippets/mutations/createSnippet.mutation.graphql';
@@ -27,6 +29,8 @@ jest.mock('~/lib/utils/url_utility', () => ({
.mockReturnValue('contentApiURL'),
}));
+jest.mock('~/flash');
+
let flashSpy;
const contentMock = 'Foo Bar';
@@ -34,6 +38,10 @@ const rawPathMock = '/foo/bar';
const rawProjectPathMock = '/project/path';
const newlyEditedSnippetUrl = 'http://foo.bar';
const apiError = { message: 'Ufff' };
+const mutationError = 'Bummer';
+
+const attachedFilePath1 = 'foo/bar';
+const attachedFilePath2 = 'alpha/beta';
const defaultProps = {
snippetGid: 'gid://gitlab/PersonalSnippet/42',
@@ -56,10 +64,26 @@ describe('Snippet Edit app', () => {
},
});
+ const resolveMutateWithErrors = jest.fn().mockResolvedValue({
+ data: {
+ updateSnippet: {
+ errors: [mutationError],
+ snippet: {
+ webUrl: newlyEditedSnippetUrl,
+ },
+ },
+ createSnippet: {
+ errors: [mutationError],
+ snippet: null,
+ },
+ },
+ });
+
const rejectMutation = jest.fn().mockRejectedValue(apiError);
const mutationTypes = {
RESOLVE: resolveMutate,
+ RESOLVE_WITH_ERRORS: resolveMutateWithErrors,
REJECT: rejectMutation,
};
@@ -99,8 +123,9 @@ describe('Snippet Edit app', () => {
wrapper.destroy();
});
- const findSubmitButton = () => wrapper.find('[type=submit]');
+ const findSubmitButton = () => wrapper.find('[data-testid="snippet-submit-btn"]');
const findCancellButton = () => wrapper.find('[data-testid="snippet-cancel-btn"]');
+ const clickSubmitBtn = () => wrapper.find('[data-testid="snippet-edit-form"]').trigger('submit');
describe('rendering', () => {
it('renders loader while the query is in flight', () => {
@@ -268,28 +293,131 @@ describe('Snippet Edit app', () => {
},
};
- wrapper.vm.handleFormSubmit();
+ clickSubmitBtn();
+
expect(resolveMutate).toHaveBeenCalledWith(mutationPayload);
});
it('redirects to snippet view on successful mutation', () => {
createComponent();
- wrapper.vm.handleFormSubmit();
+ clickSubmitBtn();
+
return waitForPromises().then(() => {
expect(redirectTo).toHaveBeenCalledWith(newlyEditedSnippetUrl);
});
});
+ it.each`
+ newSnippet | projectPath | mutationName
+ ${true} | ${rawProjectPathMock} | ${'CreateSnippetMutation with projectPath'}
+ ${true} | ${''} | ${'CreateSnippetMutation without projectPath'}
+ ${false} | ${rawProjectPathMock} | ${'UpdateSnippetMutation with projectPath'}
+ ${false} | ${''} | ${'UpdateSnippetMutation without projectPath'}
+ `(
+ 'does not redirect to snippet view if the seemingly successful' +
+ ' $mutationName response contains errors',
+ ({ newSnippet, projectPath }) => {
+ createComponent({
+ data: {
+ newSnippet,
+ },
+ props: {
+ ...defaultProps,
+ projectPath,
+ },
+ mutationRes: mutationTypes.RESOLVE_WITH_ERRORS,
+ });
+
+ clickSubmitBtn();
+
+ return waitForPromises().then(() => {
+ expect(redirectTo).not.toHaveBeenCalled();
+ expect(flashSpy).toHaveBeenCalledWith(mutationError);
+ });
+ },
+ );
+
it('flashes an error if mutation failed', () => {
createComponent({
mutationRes: mutationTypes.REJECT,
});
- wrapper.vm.handleFormSubmit();
+
+ clickSubmitBtn();
+
return waitForPromises().then(() => {
expect(redirectTo).not.toHaveBeenCalled();
expect(flashSpy).toHaveBeenCalledWith(apiError);
});
});
+
+ it.each`
+ isNew | status | expectation
+ ${true} | ${`new`} | ${SNIPPET_CREATE_MUTATION_ERROR.replace('%{err}', '')}
+ ${false} | ${`existing`} | ${SNIPPET_UPDATE_MUTATION_ERROR.replace('%{err}', '')}
+ `(
+ `renders the correct error message if mutation fails for $status snippet`,
+ ({ isNew, expectation }) => {
+ createComponent({
+ data: {
+ newSnippet: isNew,
+ },
+ mutationRes: mutationTypes.REJECT,
+ });
+
+ clickSubmitBtn();
+
+ return waitForPromises().then(() => {
+ expect(Flash).toHaveBeenCalledWith(expect.stringContaining(expectation));
+ });
+ },
+ );
+ });
+
+ describe('correctly includes attached files into the mutation', () => {
+ const createMutationPayload = expectation => {
+ return expect.objectContaining({
+ variables: {
+ input: expect.objectContaining({ uploadedFiles: expectation }),
+ },
+ });
+ };
+
+ const updateMutationPayload = () => {
+ return expect.objectContaining({
+ variables: {
+ input: expect.not.objectContaining({ uploadedFiles: expect.anything() }),
+ },
+ });
+ };
+
+ it.each`
+ paths | expectation
+ ${[attachedFilePath1]} | ${[attachedFilePath1]}
+ ${[attachedFilePath1, attachedFilePath2]} | ${[attachedFilePath1, attachedFilePath2]}
+ ${[]} | ${[]}
+ `(`correctly sends paths for $paths.length files`, ({ paths, expectation }) => {
+ createComponent({
+ data: {
+ newSnippet: true,
+ },
+ });
+
+ const fixtures = paths.map(path => {
+ return path ? `<input name="files[]" value="${path}">` : undefined;
+ });
+ wrapper.vm.$el.innerHTML += fixtures.join('');
+
+ clickSubmitBtn();
+
+ expect(resolveMutate).toHaveBeenCalledWith(createMutationPayload(expectation));
+ });
+
+ it(`neither fails nor sends 'uploadedFiles' to update mutation`, () => {
+ createComponent();
+
+ clickSubmitBtn();
+ expect(resolveMutate).toHaveBeenCalledWith(updateMutationPayload());
+ });
});
});
});
diff --git a/spec/frontend/snippets/components/snippet_blob_view_spec.js b/spec/frontend/snippets/components/snippet_blob_view_spec.js
index d06489cffa9..e4d8ee9b7df 100644
--- a/spec/frontend/snippets/components/snippet_blob_view_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_view_spec.js
@@ -3,7 +3,11 @@ import SnippetBlobView from '~/snippets/components/snippet_blob_view.vue';
import BlobHeader from '~/blob/components/blob_header.vue';
import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
import BlobContent from '~/blob/components/blob_content.vue';
-import { BLOB_RENDER_EVENT_LOAD, BLOB_RENDER_EVENT_SHOW_SOURCE } from '~/blob/components/constants';
+import {
+ BLOB_RENDER_EVENT_LOAD,
+ BLOB_RENDER_EVENT_SHOW_SOURCE,
+ BLOB_RENDER_ERRORS,
+} from '~/blob/components/constants';
import { RichViewer, SimpleViewer } from '~/vue_shared/components/blob_viewers';
import {
SNIPPET_VISIBILITY_PRIVATE,
@@ -109,6 +113,20 @@ describe('Blob Embeddable', () => {
});
});
+ it('passes information about render error down to blob header', () => {
+ createComponent({
+ blob: {
+ ...BlobMock,
+ simpleViewer: {
+ ...SimpleViewerMock,
+ renderError: BLOB_RENDER_ERRORS.REASONS.COLLAPSED.id,
+ },
+ },
+ });
+
+ expect(wrapper.find(BlobHeader).props('hasRenderError')).toBe(true);
+ });
+
describe('URLS with hash', () => {
beforeEach(() => {
window.location.hash = '#LC2';
diff --git a/spec/frontend/snippets/components/snippet_description_edit_spec.js b/spec/frontend/snippets/components/snippet_description_edit_spec.js
index c5e667747c6..816ab4e48de 100644
--- a/spec/frontend/snippets/components/snippet_description_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_description_edit_spec.js
@@ -1,4 +1,5 @@
import SnippetDescriptionEdit from '~/snippets/components/snippet_description_edit.vue';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { shallowMount } from '@vue/test-utils';
describe('Snippet Description Edit component', () => {
@@ -15,6 +16,9 @@ describe('Snippet Description Edit component', () => {
markdownPreviewPath,
markdownDocsPath,
},
+ stubs: {
+ MarkdownField,
+ },
});
}