summaryrefslogtreecommitdiff
path: root/spec/frontend/repository/components/blob_content_viewer_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/repository/components/blob_content_viewer_spec.js')
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js171
1 files changed, 157 insertions, 14 deletions
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index 495039b4ccb..a83d0a607f2 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -1,11 +1,23 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
+import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import BlobContent from '~/blob/components/blob_content.vue';
import BlobHeader from '~/blob/components/blob_header.vue';
+import BlobButtonGroup from '~/repository/components/blob_button_group.vue';
import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
-import BlobHeaderEdit from '~/repository/components/blob_header_edit.vue';
-import BlobReplace from '~/repository/components/blob_replace.vue';
+import BlobEdit from '~/repository/components/blob_edit.vue';
+import { loadViewer, viewerProps } from '~/repository/components/blob_viewers';
+import DownloadViewer from '~/repository/components/blob_viewers/download_viewer.vue';
+import EmptyViewer from '~/repository/components/blob_viewers/empty_viewer.vue';
+import TextViewer from '~/repository/components/blob_viewers/text_viewer.vue';
+import blobInfoQuery from '~/repository/queries/blob_info.query.graphql';
+
+jest.mock('~/repository/components/blob_viewers');
let wrapper;
const simpleMockData = {
@@ -17,6 +29,7 @@ const simpleMockData = {
fileType: 'text',
tooLarge: false,
path: 'some_file.js',
+ webPath: 'some_file.js',
editBlobPath: 'some_file.js/edit',
ideEditPath: 'some_file.js/ide/edit',
storedExternally: false,
@@ -27,7 +40,6 @@ const simpleMockData = {
canLock: true,
isLocked: false,
lockLink: 'some_file.js/lock',
- canModifyBlob: true,
forkPath: 'some_file.js/fork',
simpleViewer: {
fileType: 'text',
@@ -47,6 +59,51 @@ const richMockData = {
},
};
+const projectMockData = {
+ userPermissions: {
+ pushCode: true,
+ },
+ repository: {
+ empty: false,
+ },
+};
+
+const localVue = createLocalVue();
+const mockAxios = new MockAdapter(axios);
+
+const createComponentWithApollo = (mockData = {}) => {
+ localVue.use(VueApollo);
+
+ const defaultPushCode = projectMockData.userPermissions.pushCode;
+ const defaultEmptyRepo = projectMockData.repository.empty;
+ const { blobs, emptyRepo = defaultEmptyRepo, canPushCode = defaultPushCode } = mockData;
+
+ const mockResolver = jest.fn().mockResolvedValue({
+ data: {
+ project: {
+ userPermissions: { pushCode: canPushCode },
+ repository: {
+ empty: emptyRepo,
+ blobs: {
+ nodes: [blobs],
+ },
+ },
+ },
+ },
+ });
+
+ const fakeApollo = createMockApollo([[blobInfoQuery, mockResolver]]);
+
+ wrapper = shallowMount(BlobContentViewer, {
+ localVue,
+ apolloProvider: fakeApollo,
+ propsData: {
+ path: 'some_file.js',
+ projectPath: 'some/path',
+ },
+ });
+};
+
const createFactory = (mountFn) => (
{ props = {}, mockData = {}, stubs = {} } = {},
loading = false,
@@ -78,9 +135,9 @@ const fullFactory = createFactory(mount);
describe('Blob content viewer component', () => {
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findBlobHeader = () => wrapper.findComponent(BlobHeader);
- const findBlobHeaderEdit = () => wrapper.findComponent(BlobHeaderEdit);
+ const findBlobEdit = () => wrapper.findComponent(BlobEdit);
const findBlobContent = () => wrapper.findComponent(BlobContent);
- const findBlobReplace = () => wrapper.findComponent(BlobReplace);
+ const findBlobButtonGroup = () => wrapper.findComponent(BlobButtonGroup);
afterEach(() => {
wrapper.destroy();
@@ -163,6 +220,67 @@ describe('Blob content viewer component', () => {
});
});
+ describe('legacy viewers', () => {
+ it('does not load a legacy viewer when a rich viewer is not available', async () => {
+ createComponentWithApollo({ blobs: simpleMockData });
+ await waitForPromises();
+
+ expect(mockAxios.history.get).toHaveLength(0);
+ });
+
+ it('loads a legacy viewer when a rich viewer is available', async () => {
+ createComponentWithApollo({ blobs: richMockData });
+ await waitForPromises();
+
+ expect(mockAxios.history.get).toHaveLength(1);
+ });
+ });
+
+ describe('Blob viewer', () => {
+ afterEach(() => {
+ loadViewer.mockRestore();
+ viewerProps.mockRestore();
+ });
+
+ it('does not render a BlobContent component if a Blob viewer is available', () => {
+ loadViewer.mockReturnValueOnce(() => true);
+ factory({ mockData: { blobInfo: richMockData } });
+
+ expect(findBlobContent().exists()).toBe(false);
+ });
+
+ it.each`
+ viewer | loadViewerReturnValue | viewerPropsReturnValue
+ ${'empty'} | ${EmptyViewer} | ${{}}
+ ${'download'} | ${DownloadViewer} | ${{ filePath: '/some/file/path', fileName: 'test.js', fileSize: 100 }}
+ ${'text'} | ${TextViewer} | ${{ content: 'test', fileName: 'test.js', readOnly: true }}
+ `(
+ 'renders viewer component for $viewer files',
+ async ({ viewer, loadViewerReturnValue, viewerPropsReturnValue }) => {
+ loadViewer.mockReturnValue(loadViewerReturnValue);
+ viewerProps.mockReturnValue(viewerPropsReturnValue);
+
+ factory({
+ mockData: {
+ blobInfo: {
+ ...simpleMockData,
+ fileType: null,
+ simpleViewer: {
+ ...simpleMockData.simpleViewer,
+ fileType: viewer,
+ },
+ },
+ },
+ });
+
+ await nextTick();
+
+ expect(loadViewer).toHaveBeenCalledWith(viewer);
+ expect(wrapper.findComponent(loadViewerReturnValue).exists()).toBe(true);
+ },
+ );
+ });
+
describe('BlobHeader action slot', () => {
const { ideEditPath, editBlobPath } = simpleMockData;
@@ -177,7 +295,7 @@ describe('Blob content viewer component', () => {
await nextTick();
- expect(findBlobHeaderEdit().props()).toMatchObject({
+ expect(findBlobEdit().props()).toMatchObject({
editPath: editBlobPath,
webIdePath: ideEditPath,
});
@@ -194,31 +312,56 @@ describe('Blob content viewer component', () => {
await nextTick();
- expect(findBlobHeaderEdit().props()).toMatchObject({
+ expect(findBlobEdit().props()).toMatchObject({
editPath: editBlobPath,
webIdePath: ideEditPath,
});
});
- describe('BlobReplace', () => {
- const { name, path } = simpleMockData;
+ it('does not render BlobHeaderEdit button when viewing a binary file', async () => {
+ fullFactory({
+ mockData: { blobInfo: richMockData, isBinary: true },
+ stubs: {
+ BlobContent: true,
+ BlobReplace: true,
+ },
+ });
+
+ await nextTick();
+
+ expect(findBlobEdit().exists()).toBe(false);
+ });
+
+ describe('BlobButtonGroup', () => {
+ const { name, path, replacePath, webPath } = simpleMockData;
+ const {
+ userPermissions: { pushCode },
+ repository: { empty },
+ } = projectMockData;
it('renders component', async () => {
window.gon.current_user_id = 1;
fullFactory({
- mockData: { blobInfo: simpleMockData },
+ mockData: {
+ blobInfo: simpleMockData,
+ project: { userPermissions: { pushCode }, repository: { empty } },
+ },
stubs: {
BlobContent: true,
- BlobReplace: true,
+ BlobButtonGroup: true,
},
});
await nextTick();
- expect(findBlobReplace().props()).toMatchObject({
+ expect(findBlobButtonGroup().props()).toMatchObject({
name,
path,
+ replacePath,
+ deletePath: webPath,
+ canPushCode: pushCode,
+ emptyRepo: empty,
});
});
@@ -235,7 +378,7 @@ describe('Blob content viewer component', () => {
await nextTick();
- expect(findBlobReplace().exists()).toBe(false);
+ expect(findBlobButtonGroup().exists()).toBe(false);
});
});
});