summaryrefslogtreecommitdiff
path: root/spec/frontend/snippets/components/snippet_blob_view_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/snippets/components/snippet_blob_view_spec.js')
-rw-r--r--spec/frontend/snippets/components/snippet_blob_view_spec.js222
1 files changed, 132 insertions, 90 deletions
diff --git a/spec/frontend/snippets/components/snippet_blob_view_spec.js b/spec/frontend/snippets/components/snippet_blob_view_spec.js
index c7ff8c21d80..05ff64c2296 100644
--- a/spec/frontend/snippets/components/snippet_blob_view_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_view_spec.js
@@ -1,5 +1,6 @@
-import { mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMount } from '@vue/test-utils';
import {
Blob as BlobMock,
SimpleViewerMock,
@@ -7,6 +8,7 @@ import {
RichBlobContentMock,
SimpleBlobContentMock,
} from 'jest/blob/components/mock_data';
+import GetBlobContent from 'shared_queries/snippet/snippet_blob_content.query.graphql';
import BlobContent from '~/blob/components/blob_content.vue';
import BlobHeader from '~/blob/components/blob_header.vue';
import {
@@ -17,9 +19,13 @@ import {
import SnippetBlobView from '~/snippets/components/snippet_blob_view.vue';
import { VISIBILITY_LEVEL_PUBLIC_STRING } from '~/visibility_level/constants';
import { RichViewer, SimpleViewer } from '~/vue_shared/components/blob_viewers';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
describe('Blob Embeddable', () => {
let wrapper;
+ let requestHandlers;
+
const snippet = {
id: 'gid://foo.bar/snippet',
webUrl: 'https://foo.bar',
@@ -29,23 +35,47 @@ describe('Blob Embeddable', () => {
activeViewerType: SimpleViewerMock.type,
};
+ const mockDefaultHandler = ({ path, nodes } = { path: BlobMock.path }) => {
+ const renderedNodes = nodes || [
+ { __typename: 'Blob', path, richData: 'richData', plainData: 'plainData' },
+ ];
+
+ return jest.fn().mockResolvedValue({
+ data: {
+ snippets: {
+ __typename: 'Snippet',
+ id: '1',
+ nodes: [
+ {
+ __typename: 'Snippet',
+ id: '2',
+ blobs: {
+ __typename: 'Blob',
+ hasUnretrievableBlobs: false,
+ nodes: renderedNodes,
+ },
+ },
+ ],
+ },
+ },
+ });
+ };
+
+ const createMockApolloProvider = (handler) => {
+ Vue.use(VueApollo);
+
+ requestHandlers = handler;
+ return createMockApollo([[GetBlobContent, requestHandlers]]);
+ };
+
function createComponent({
snippetProps = {},
data = dataMock,
blob = BlobMock,
- contentLoading = false,
+ handler = mockDefaultHandler(),
} = {}) {
- const $apollo = {
- queries: {
- blobContent: {
- loading: contentLoading,
- refetch: jest.fn(),
- skip: true,
- },
- },
- };
-
- wrapper = mount(SnippetBlobView, {
+ wrapper = shallowMount(SnippetBlobView, {
+ apolloProvider: createMockApolloProvider(handler),
propsData: {
snippet: {
...snippet,
@@ -58,45 +88,56 @@ describe('Blob Embeddable', () => {
...data,
};
},
- mocks: { $apollo },
+ stubs: {
+ BlobHeader,
+ BlobContent,
+ },
});
}
- afterEach(() => {
- wrapper.destroy();
- });
+ const findBlobHeader = () => wrapper.findComponent(BlobHeader);
+ const findBlobContent = () => wrapper.findComponent(BlobContent);
+ const findSimpleViewer = () => wrapper.findComponent(SimpleViewer);
+ const findRichViewer = () => wrapper.findComponent(RichViewer);
describe('rendering', () => {
it('renders correct components', () => {
createComponent();
- expect(wrapper.findComponent(BlobHeader).exists()).toBe(true);
- expect(wrapper.findComponent(BlobContent).exists()).toBe(true);
+ expect(findBlobHeader().exists()).toBe(true);
+ expect(findBlobContent().exists()).toBe(true);
});
- it('sets simple viewer correctly', () => {
+ it('sets simple viewer correctly', async () => {
createComponent();
- expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+ await waitForPromises();
+
+ expect(findSimpleViewer().exists()).toBe(true);
});
- it('sets rich viewer correctly', () => {
+ it('sets rich viewer correctly', async () => {
const data = { ...dataMock, activeViewerType: RichViewerMock.type };
createComponent({
data,
});
- expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
+ await waitForPromises();
+ expect(findRichViewer().exists()).toBe(true);
});
it('correctly switches viewer type', async () => {
createComponent();
- expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+ await waitForPromises();
+
+ expect(findSimpleViewer().exists()).toBe(true);
- wrapper.vm.switchViewer(RichViewerMock.type);
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE, RichViewerMock.type);
+ await waitForPromises();
- await nextTick();
- expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
- await wrapper.vm.switchViewer(SimpleViewerMock.type);
+ expect(findRichViewer().exists()).toBe(true);
- expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE, SimpleViewerMock.type);
+ await waitForPromises();
+
+ expect(findSimpleViewer().exists()).toBe(true);
});
it('passes information about render error down to blob header', () => {
@@ -110,7 +151,7 @@ describe('Blob Embeddable', () => {
},
});
- expect(wrapper.findComponent(BlobHeader).props('hasRenderError')).toBe(true);
+ expect(findBlobHeader().props('hasRenderError')).toBe(true);
});
describe('bob content in multi-file scenario', () => {
@@ -123,47 +164,38 @@ describe('Blob Embeddable', () => {
richData: 'Another Rich Foo',
};
+ const MixedSimpleBlobContentMock = {
+ ...SimpleBlobContentMock,
+ richData: '<h1>Rich</h1>',
+ };
+
+ const MixedRichBlobContentMock = {
+ ...RichBlobContentMock,
+ plainData: 'Plain',
+ };
+
it.each`
- snippetBlobs | description | currentBlob | expectedContent
- ${[SimpleBlobContentMock]} | ${'one existing textual blob'} | ${SimpleBlobContentMock} | ${SimpleBlobContentMock.plainData}
- ${[RichBlobContentMock]} | ${'one existing rich blob'} | ${RichBlobContentMock} | ${RichBlobContentMock.richData}
- ${[SimpleBlobContentMock, RichBlobContentMock]} | ${'mixed blobs with current textual blob'} | ${SimpleBlobContentMock} | ${SimpleBlobContentMock.plainData}
- ${[SimpleBlobContentMock, RichBlobContentMock]} | ${'mixed blobs with current rich blob'} | ${RichBlobContentMock} | ${RichBlobContentMock.richData}
- ${[SimpleBlobContentMock, SimpleBlobContentMock2]} | ${'textual blobs with current textual blob'} | ${SimpleBlobContentMock} | ${SimpleBlobContentMock.plainData}
- ${[RichBlobContentMock, RichBlobContentMock2]} | ${'rich blobs with current rich blob'} | ${RichBlobContentMock} | ${RichBlobContentMock.richData}
+ snippetBlobs | description | currentBlob | expectedContent | activeViewerType
+ ${[SimpleBlobContentMock]} | ${'one existing textual blob'} | ${SimpleBlobContentMock} | ${SimpleBlobContentMock.plainData} | ${SimpleViewerMock.type}
+ ${[RichBlobContentMock]} | ${'one existing rich blob'} | ${RichBlobContentMock} | ${RichBlobContentMock.richData} | ${RichViewerMock.type}
+ ${[SimpleBlobContentMock, MixedRichBlobContentMock]} | ${'mixed blobs with current textual blob'} | ${SimpleBlobContentMock} | ${SimpleBlobContentMock.plainData} | ${SimpleViewerMock.type}
+ ${[MixedSimpleBlobContentMock, RichBlobContentMock]} | ${'mixed blobs with current rich blob'} | ${RichBlobContentMock} | ${RichBlobContentMock.richData} | ${RichViewerMock.type}
+ ${[SimpleBlobContentMock, SimpleBlobContentMock2]} | ${'textual blobs with current textual blob'} | ${SimpleBlobContentMock} | ${SimpleBlobContentMock.plainData} | ${SimpleViewerMock.type}
+ ${[RichBlobContentMock, RichBlobContentMock2]} | ${'rich blobs with current rich blob'} | ${RichBlobContentMock} | ${RichBlobContentMock.richData} | ${RichViewerMock.type}
`(
'renders correct content for $description',
- async ({ snippetBlobs, currentBlob, expectedContent }) => {
- const apolloData = {
- snippets: {
- nodes: [
- {
- blobs: {
- nodes: snippetBlobs,
- },
- },
- ],
- },
- };
+ async ({ snippetBlobs, currentBlob, expectedContent, activeViewerType }) => {
createComponent({
+ handler: mockDefaultHandler({ path: currentBlob.path, nodes: snippetBlobs }),
+ data: { activeViewerType },
blob: {
...BlobMock,
path: currentBlob.path,
},
});
+ await waitForPromises();
- // mimic apollo's update
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- blobContent: wrapper.vm.onContentUpdate(apolloData),
- });
-
- await nextTick();
-
- const findContent = () => wrapper.findComponent(BlobContent);
-
- expect(findContent().props('content')).toBe(expectedContent);
+ expect(findBlobContent().props('content')).toBe(expectedContent);
},
);
});
@@ -178,28 +210,32 @@ describe('Blob Embeddable', () => {
window.location.hash = '#LC2';
});
- it('renders simple viewer by default', () => {
+ it('renders simple viewer by default', async () => {
createComponent({
data: {},
});
+ await waitForPromises();
- expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
- expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+ expect(findBlobHeader().props('activeViewerType')).toBe(SimpleViewerMock.type);
+ expect(findSimpleViewer().exists()).toBe(true);
});
describe('switchViewer()', () => {
it('switches to the passed viewer', async () => {
createComponent();
+ await waitForPromises();
+
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE, RichViewerMock.type);
+ await waitForPromises();
- wrapper.vm.switchViewer(RichViewerMock.type);
+ expect(findBlobHeader().props('activeViewerType')).toBe(RichViewerMock.type);
+ expect(findRichViewer().exists()).toBe(true);
- await nextTick();
- expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
- expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE, SimpleViewerMock.type);
+ await waitForPromises();
- await wrapper.vm.switchViewer(SimpleViewerMock.type);
- expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
- expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+ expect(findBlobHeader().props('activeViewerType')).toBe(SimpleViewerMock.type);
+ expect(findSimpleViewer().exists()).toBe(true);
});
});
});
@@ -209,28 +245,32 @@ describe('Blob Embeddable', () => {
window.location.hash = '#last-headline';
});
- it('renders rich viewer by default', () => {
+ it('renders rich viewer by default', async () => {
createComponent({
data: {},
});
+ await waitForPromises();
- expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
- expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
+ expect(findBlobHeader().props('activeViewerType')).toBe(RichViewerMock.type);
+ expect(findRichViewer().exists()).toBe(true);
});
describe('switchViewer()', () => {
it('switches to the passed viewer', async () => {
createComponent();
+ await waitForPromises();
- wrapper.vm.switchViewer(SimpleViewerMock.type);
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE, SimpleViewerMock.type);
+ await waitForPromises();
- await nextTick();
- expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
- expect(wrapper.findComponent(SimpleViewer).exists()).toBe(true);
+ expect(findBlobHeader().props('activeViewerType')).toBe(SimpleViewerMock.type);
+ expect(findSimpleViewer().exists()).toBe(true);
- await wrapper.vm.switchViewer(RichViewerMock.type);
- expect(wrapper.vm.activeViewerType).toBe(RichViewerMock.type);
- expect(wrapper.findComponent(RichViewer).exists()).toBe(true);
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE, RichViewerMock.type);
+ await waitForPromises();
+
+ expect(findBlobHeader().props('activeViewerType')).toBe(RichViewerMock.type);
+ expect(findRichViewer().exists()).toBe(true);
});
});
});
@@ -239,19 +279,21 @@ describe('Blob Embeddable', () => {
describe('functionality', () => {
describe('render error', () => {
- const findContentEl = () => wrapper.findComponent(BlobContent);
-
it('correctly sets blob on the blob-content-error component', () => {
createComponent();
- expect(findContentEl().props('blob')).toEqual(BlobMock);
+ expect(findBlobContent().props('blob')).toEqual(BlobMock);
});
- it(`refetches blob content on ${BLOB_RENDER_EVENT_LOAD} event`, () => {
+ it(`refetches blob content on ${BLOB_RENDER_EVENT_LOAD} event`, async () => {
createComponent();
+ await waitForPromises();
+
+ expect(requestHandlers).toHaveBeenCalledTimes(1);
+
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_LOAD);
+ await waitForPromises();
- expect(wrapper.vm.$apollo.queries.blobContent.refetch).not.toHaveBeenCalled();
- findContentEl().vm.$emit(BLOB_RENDER_EVENT_LOAD);
- expect(wrapper.vm.$apollo.queries.blobContent.refetch).toHaveBeenCalledTimes(1);
+ expect(requestHandlers).toHaveBeenCalledTimes(2);
});
it(`sets '${SimpleViewerMock.type}' as active on ${BLOB_RENDER_EVENT_SHOW_SOURCE} event`, () => {
@@ -261,7 +303,7 @@ describe('Blob Embeddable', () => {
},
});
- findContentEl().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE);
+ findBlobContent().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE);
expect(wrapper.vm.activeViewerType).toEqual(SimpleViewerMock.type);
});
});