summaryrefslogtreecommitdiff
path: root/spec/frontend/snippets/components/snippet_blob_edit_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/snippets/components/snippet_blob_edit_spec.js')
-rw-r--r--spec/frontend/snippets/components/snippet_blob_edit_spec.js227
1 files changed, 115 insertions, 112 deletions
diff --git a/spec/frontend/snippets/components/snippet_blob_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
index 009074b4558..188f9ae5cf1 100644
--- a/spec/frontend/snippets/components/snippet_blob_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
@@ -1,165 +1,168 @@
-import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
-import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
-import BlobContentEdit from '~/blob/components/blob_edit_content.vue';
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import { TEST_HOST } from 'helpers/test_constants';
+import SnippetBlobEdit from '~/snippets/components/snippet_blob_edit.vue';
+import BlobHeaderEdit from '~/blob/components/blob_edit_header.vue';
+import BlobContentEdit from '~/blob/components/blob_edit_content.vue';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
-import waitForPromises from 'helpers/wait_for_promises';
-
-jest.mock('~/blob/utils', () => jest.fn());
-
-jest.mock('~/lib/utils/url_utility', () => ({
- getBaseURL: jest.fn().mockReturnValue('foo/'),
- joinPaths: jest
- .fn()
- .mockName('joinPaths')
- .mockReturnValue('contentApiURL'),
-}));
+import { deprecatedCreateFlash as createFlash } from '~/flash';
jest.mock('~/flash');
-let flashSpy;
+const TEST_ID = 'blob_local_7';
+const TEST_PATH = 'foo/bar/test.md';
+const TEST_RAW_PATH = '/gitlab/raw/path/to/blob/7';
+const TEST_FULL_PATH = joinPaths(TEST_HOST, TEST_RAW_PATH);
+const TEST_CONTENT = 'Lorem ipsum dolar sit amet,\nconsectetur adipiscing elit.';
+
+const TEST_BLOB = {
+ id: TEST_ID,
+ rawPath: TEST_RAW_PATH,
+ path: TEST_PATH,
+ content: '',
+ isLoaded: false,
+};
+
+const TEST_BLOB_LOADED = {
+ ...TEST_BLOB,
+ content: TEST_CONTENT,
+ isLoaded: true,
+};
describe('Snippet Blob Edit component', () => {
let wrapper;
let axiosMock;
- const contentMock = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
- const pathMock = 'lorem.txt';
- const rawPathMock = 'foo/bar';
- const blob = {
- path: pathMock,
- content: contentMock,
- rawPath: rawPathMock,
- };
- const findComponent = component => wrapper.find(component);
- function createComponent(props = {}, data = { isContentLoading: false }) {
+ const createComponent = (props = {}) => {
wrapper = shallowMount(SnippetBlobEdit, {
propsData: {
+ blob: TEST_BLOB,
...props,
},
- data() {
- return {
- ...data,
- };
- },
});
- flashSpy = jest.spyOn(wrapper.vm, 'flashAPIFailure');
- }
+ };
+
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findHeader = () => wrapper.find(BlobHeaderEdit);
+ const findContent = () => wrapper.find(BlobContentEdit);
+ const getLastUpdatedArgs = () => {
+ const event = wrapper.emitted()['blob-updated'];
+
+ return event?.[event.length - 1][0];
+ };
beforeEach(() => {
axiosMock = new AxiosMockAdapter(axios);
- createComponent();
+ axiosMock.onGet(TEST_FULL_PATH).reply(200, TEST_CONTENT);
});
afterEach(() => {
- axiosMock.restore();
wrapper.destroy();
+ wrapper = null;
+ axiosMock.restore();
});
- describe('rendering', () => {
- it('matches the snapshot', () => {
- createComponent({ blob });
- expect(wrapper.element).toMatchSnapshot();
+ describe('with not loaded blob', () => {
+ beforeEach(async () => {
+ createComponent();
});
- it('renders required components', () => {
- expect(findComponent(BlobHeaderEdit).exists()).toBe(true);
- expect(findComponent(BlobContentEdit).exists()).toBe(true);
+ it('shows blob header', () => {
+ expect(findHeader().props()).toMatchObject({
+ value: TEST_BLOB.path,
+ });
+ expect(findHeader().attributes('id')).toBe(`${TEST_ID}_file_path`);
});
- it('renders loader if existing blob is supplied but no content is fetched yet', () => {
- createComponent({ blob }, { isContentLoading: true });
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
- expect(findComponent(BlobContentEdit).exists()).toBe(false);
+ it('emits delete when deleted', () => {
+ expect(wrapper.emitted().delete).toBeUndefined();
+
+ findHeader().vm.$emit('delete');
+
+ expect(wrapper.emitted().delete).toHaveLength(1);
});
- it('does not render loader if when blob is not supplied', () => {
- createComponent();
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
- expect(findComponent(BlobContentEdit).exists()).toBe(true);
+ it('emits update when path changes', () => {
+ const newPath = 'new/path.md';
+
+ findHeader().vm.$emit('input', newPath);
+
+ expect(getLastUpdatedArgs()).toEqual({ path: newPath });
});
- });
- describe('functionality', () => {
- it('does not fail without blob', () => {
- const spy = jest.spyOn(global.console, 'error');
- createComponent({ blob: undefined });
+ it('emits update when content is loaded', async () => {
+ await waitForPromises();
- expect(spy).not.toHaveBeenCalled();
- expect(findComponent(BlobContentEdit).exists()).toBe(true);
+ expect(getLastUpdatedArgs()).toEqual({ content: TEST_CONTENT });
});
+ });
- it.each`
- emitter | prop
- ${BlobHeaderEdit} | ${'filePath'}
- ${BlobContentEdit} | ${'content'}
- `('emits "blob-updated" event when the $prop gets changed', ({ emitter, prop }) => {
- expect(wrapper.emitted('blob-updated')).toBeUndefined();
- const newValue = 'foo.bar';
- findComponent(emitter).vm.$emit('input', newValue);
-
- return nextTick().then(() => {
- expect(wrapper.emitted('blob-updated')[0]).toEqual([
- expect.objectContaining({
- [prop]: newValue,
- }),
- ]);
- });
+ describe('with error', () => {
+ beforeEach(() => {
+ axiosMock.reset();
+ axiosMock.onGet(TEST_FULL_PATH).replyOnce(500);
+ createComponent();
});
- describe('fetching blob content', () => {
- const bootstrapForExistingSnippet = resp => {
- createComponent({
- blob: {
- ...blob,
- content: '',
- },
- });
+ it('should call flash', async () => {
+ await waitForPromises();
- if (resp === 500) {
- axiosMock.onGet('contentApiURL').reply(500);
- } else {
- axiosMock.onGet('contentApiURL').reply(200, contentMock);
- }
- };
+ expect(createFlash).toHaveBeenCalledWith(
+ "Can't fetch content for the blob: Error: Request failed with status code 500",
+ );
+ });
+ });
- const bootstrapForNewSnippet = () => {
- createComponent();
- };
+ describe('with loaded blob', () => {
+ beforeEach(() => {
+ createComponent({ blob: TEST_BLOB_LOADED });
+ });
- it('fetches blob content with the additional query', () => {
- bootstrapForExistingSnippet();
+ it('matches snapshot', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
- return waitForPromises().then(() => {
- expect(joinPaths).toHaveBeenCalledWith('foo/', rawPathMock);
- expect(findComponent(BlobHeaderEdit).props('value')).toBe(pathMock);
- expect(findComponent(BlobContentEdit).props('value')).toBe(contentMock);
- });
- });
+ it('does not make API request', () => {
+ expect(axiosMock.history.get).toHaveLength(0);
+ });
+ });
- it('flashes the error message if fetching content fails', () => {
- bootstrapForExistingSnippet(500);
+ describe.each`
+ props | showLoading | showContent
+ ${{ blob: TEST_BLOB, canDelete: true, showDelete: true }} | ${true} | ${false}
+ ${{ blob: TEST_BLOB, canDelete: false, showDelete: false }} | ${true} | ${false}
+ ${{ blob: TEST_BLOB_LOADED }} | ${false} | ${true}
+ `('with $props', ({ props, showLoading, showContent }) => {
+ beforeEach(() => {
+ createComponent(props);
+ });
- return waitForPromises().then(() => {
- expect(flashSpy).toHaveBeenCalled();
- expect(findComponent(BlobContentEdit).props('value')).toBe('');
- });
+ it('shows blob header', () => {
+ const { canDelete = true, showDelete = false } = props;
+
+ expect(findHeader().props()).toMatchObject({
+ canDelete,
+ showDelete,
});
+ });
- it('does not fetch content for new snippet', () => {
- bootstrapForNewSnippet();
+ it(`handles loading icon (show=${showLoading})`, () => {
+ expect(findLoadingIcon().exists()).toBe(showLoading);
+ });
- return waitForPromises().then(() => {
- // we keep using waitForPromises to make sure we do not run failed test
- expect(findComponent(BlobHeaderEdit).props('value')).toBe('');
- expect(findComponent(BlobContentEdit).props('value')).toBe('');
- expect(joinPaths).not.toHaveBeenCalled();
+ it(`handles content (show=${showContent})`, () => {
+ expect(findContent().exists()).toBe(showContent);
+
+ if (showContent) {
+ expect(findContent().props()).toEqual({
+ value: TEST_BLOB_LOADED.content,
+ fileGlobalId: TEST_BLOB_LOADED.id,
+ fileName: TEST_BLOB_LOADED.path,
});
- });
+ }
});
});
});