summaryrefslogtreecommitdiff
path: root/spec/frontend/repository
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/repository')
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js69
-rw-r--r--spec/frontend/repository/components/blob_header_edit_spec.js82
-rw-r--r--spec/frontend/repository/components/blob_replace_spec.js67
-rw-r--r--spec/frontend/repository/components/table/row_spec.js22
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js5
-rw-r--r--spec/frontend/repository/components/upload_blob_modal_spec.js80
-rw-r--r--spec/frontend/repository/log_tree_spec.js15
7 files changed, 331 insertions, 9 deletions
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index f03df8cf2ac..495039b4ccb 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -5,6 +5,7 @@ import BlobContent from '~/blob/components/blob_content.vue';
import BlobHeader from '~/blob/components/blob_header.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';
let wrapper;
const simpleMockData = {
@@ -75,10 +76,11 @@ const factory = createFactory(shallowMount);
const fullFactory = createFactory(mount);
describe('Blob content viewer component', () => {
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findBlobHeader = () => wrapper.find(BlobHeader);
- const findBlobHeaderEdit = () => wrapper.find(BlobHeaderEdit);
- const findBlobContent = () => wrapper.find(BlobContent);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findBlobHeader = () => wrapper.findComponent(BlobHeader);
+ const findBlobHeaderEdit = () => wrapper.findComponent(BlobHeaderEdit);
+ const findBlobContent = () => wrapper.findComponent(BlobContent);
+ const findBlobReplace = () => wrapper.findComponent(BlobReplace);
afterEach(() => {
wrapper.destroy();
@@ -162,15 +164,23 @@ describe('Blob content viewer component', () => {
});
describe('BlobHeader action slot', () => {
- it('renders BlobHeaderEdit button in simple viewer', async () => {
+ const { ideEditPath, editBlobPath } = simpleMockData;
+
+ it('renders BlobHeaderEdit buttons in simple viewer', async () => {
fullFactory({
mockData: { blobInfo: simpleMockData },
stubs: {
BlobContent: true,
+ BlobReplace: true,
},
});
+
await nextTick();
- expect(findBlobHeaderEdit().props('editPath')).toEqual('some_file.js/edit');
+
+ expect(findBlobHeaderEdit().props()).toMatchObject({
+ editPath: editBlobPath,
+ webIdePath: ideEditPath,
+ });
});
it('renders BlobHeaderEdit button in rich viewer', async () => {
@@ -178,10 +188,55 @@ describe('Blob content viewer component', () => {
mockData: { blobInfo: richMockData },
stubs: {
BlobContent: true,
+ BlobReplace: true,
},
});
+
await nextTick();
- expect(findBlobHeaderEdit().props('editPath')).toEqual('some_file.js/edit');
+
+ expect(findBlobHeaderEdit().props()).toMatchObject({
+ editPath: editBlobPath,
+ webIdePath: ideEditPath,
+ });
+ });
+
+ describe('BlobReplace', () => {
+ const { name, path } = simpleMockData;
+
+ it('renders component', async () => {
+ window.gon.current_user_id = 1;
+
+ fullFactory({
+ mockData: { blobInfo: simpleMockData },
+ stubs: {
+ BlobContent: true,
+ BlobReplace: true,
+ },
+ });
+
+ await nextTick();
+
+ expect(findBlobReplace().props()).toMatchObject({
+ name,
+ path,
+ });
+ });
+
+ it('does not render if not logged in', async () => {
+ window.gon.current_user_id = null;
+
+ fullFactory({
+ mockData: { blobInfo: simpleMockData },
+ stubs: {
+ BlobContent: true,
+ BlobReplace: true,
+ },
+ });
+
+ await nextTick();
+
+ expect(findBlobReplace().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/repository/components/blob_header_edit_spec.js b/spec/frontend/repository/components/blob_header_edit_spec.js
new file mode 100644
index 00000000000..c0eb7c523c4
--- /dev/null
+++ b/spec/frontend/repository/components/blob_header_edit_spec.js
@@ -0,0 +1,82 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import BlobHeaderEdit from '~/repository/components/blob_header_edit.vue';
+import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
+
+const DEFAULT_PROPS = {
+ editPath: 'some_file.js/edit',
+ webIdePath: 'some_file.js/ide/edit',
+};
+
+describe('BlobHeaderEdit component', () => {
+ let wrapper;
+
+ const createComponent = (consolidatedEditButton = false, props = {}) => {
+ wrapper = shallowMount(BlobHeaderEdit, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ provide: {
+ glFeatures: {
+ consolidatedEditButton,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findButtons = () => wrapper.findAll(GlButton);
+ const findEditButton = () => findButtons().at(0);
+ const findWebIdeButton = () => findButtons().at(1);
+ const findWebIdeLink = () => wrapper.find(WebIdeLink);
+
+ it('renders component', () => {
+ createComponent();
+
+ const { editPath, webIdePath } = DEFAULT_PROPS;
+
+ expect(wrapper.props()).toMatchObject({
+ editPath,
+ webIdePath,
+ });
+ });
+
+ it('renders both buttons', () => {
+ createComponent();
+
+ expect(findButtons()).toHaveLength(2);
+ });
+
+ it('renders the Edit button', () => {
+ createComponent();
+
+ expect(findEditButton().attributes('href')).toBe(DEFAULT_PROPS.editPath);
+ expect(findEditButton().text()).toBe('Edit');
+ expect(findEditButton()).not.toBeDisabled();
+ });
+
+ it('renders the Web IDE button', () => {
+ createComponent();
+
+ expect(findWebIdeButton().attributes('href')).toBe(DEFAULT_PROPS.webIdePath);
+ expect(findWebIdeButton().text()).toBe('Web IDE');
+ expect(findWebIdeButton()).not.toBeDisabled();
+ });
+
+ it('renders WebIdeLink component', () => {
+ createComponent(true);
+
+ const { editPath: editUrl, webIdePath: webIdeUrl } = DEFAULT_PROPS;
+
+ expect(findWebIdeLink().props()).toMatchObject({
+ editUrl,
+ webIdeUrl,
+ isBlob: true,
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/blob_replace_spec.js b/spec/frontend/repository/components/blob_replace_spec.js
new file mode 100644
index 00000000000..4a6f147da22
--- /dev/null
+++ b/spec/frontend/repository/components/blob_replace_spec.js
@@ -0,0 +1,67 @@
+import { shallowMount } from '@vue/test-utils';
+import BlobReplace from '~/repository/components/blob_replace.vue';
+import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
+
+const DEFAULT_PROPS = {
+ name: 'some name',
+ path: 'some/path',
+ canPushCode: true,
+ replacePath: 'some/replace/path',
+};
+
+const DEFAULT_INJECT = {
+ targetBranch: 'master',
+ originalBranch: 'master',
+};
+
+describe('BlobReplace component', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(BlobReplace, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ provide: {
+ ...DEFAULT_INJECT,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findUploadBlobModal = () => wrapper.findComponent(UploadBlobModal);
+
+ it('renders component', () => {
+ createComponent();
+
+ const { name, path } = DEFAULT_PROPS;
+
+ expect(wrapper.props()).toMatchObject({
+ name,
+ path,
+ });
+ });
+
+ it('renders UploadBlobModal', () => {
+ createComponent();
+
+ const { targetBranch, originalBranch } = DEFAULT_INJECT;
+ const { name, path, canPushCode, replacePath } = DEFAULT_PROPS;
+ const title = `Replace ${name}`;
+
+ expect(findUploadBlobModal().props()).toMatchObject({
+ modalTitle: title,
+ commitMessage: title,
+ targetBranch,
+ originalBranch,
+ canPushCode,
+ path,
+ replacePath,
+ primaryBtnText: 'Replace file',
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 6ba6f993db1..da28c9873d9 100644
--- a/spec/frontend/repository/components/table/row_spec.js
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -1,5 +1,6 @@
import { GlBadge, GlLink, GlIcon } from '@gitlab/ui';
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import TableRow from '~/repository/components/table/row.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { FILE_SYMLINK_MODE } from '~/vue_shared/constants';
@@ -18,6 +19,10 @@ function factory(propsData = {}) {
name: propsData.path,
projectPath: 'gitlab-org/gitlab-ce',
url: `https://test.com`,
+ totalEntries: 10,
+ },
+ directives: {
+ GlHoverLoad: createMockDirective(),
},
provide: {
glFeatures: { refactorBlobViewer: true },
@@ -34,6 +39,8 @@ function factory(propsData = {}) {
}
describe('Repository table row component', () => {
+ const findRouterLink = () => vm.find(RouterLinkStub);
+
afterEach(() => {
vm.destroy();
});
@@ -81,6 +88,21 @@ describe('Repository table row component', () => {
});
});
+ it('renders a gl-hover-load directive', () => {
+ factory({
+ id: '1',
+ sha: '123',
+ path: 'test',
+ type: 'blob',
+ currentPath: '/',
+ });
+
+ const hoverLoadDirective = getBinding(findRouterLink().element, 'gl-hover-load');
+
+ expect(hoverLoadDirective).not.toBeUndefined();
+ expect(hoverLoadDirective.value).toBeInstanceOf(Function);
+ });
+
it.each`
type | component | componentName
${'tree'} | ${RouterLinkStub} | ${'RouterLink'}
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index 2930e39df8a..d397bc185e2 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -1,7 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue';
-import TreeContent, { INITIAL_FETCH_COUNT } from '~/repository/components/tree_content.vue';
+import TreeContent from '~/repository/components/tree_content.vue';
+import { TREE_INITIAL_FETCH_COUNT } from '~/repository/constants';
let vm;
let $apollo;
@@ -128,7 +129,7 @@ describe('Repository table component', () => {
it('has limit of 1000 files on initial load', () => {
factory('/');
- expect(INITIAL_FETCH_COUNT * vm.vm.pageSize).toBe(1000);
+ expect(TREE_INITIAL_FETCH_COUNT * vm.vm.pageSize).toBe(1000);
});
});
});
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index ec85d5666fb..d93b1d7e5f1 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -200,4 +200,84 @@ describe('UploadBlobModal', () => {
});
},
);
+
+ describe('blob file submission type', () => {
+ const submitForm = async () => {
+ wrapper.vm.uploadFile = jest.fn();
+ wrapper.vm.replaceFile = jest.fn();
+ wrapper.vm.submitForm();
+ await wrapper.vm.$nextTick();
+ };
+
+ const submitRequest = async () => {
+ mock = new MockAdapter(axios);
+ findModal().vm.$emit('primary', mockEvent);
+ await waitForPromises();
+ };
+
+ describe('upload blob file', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('displays the default "Upload New File" modal title ', () => {
+ expect(findModal().props('title')).toBe('Upload New File');
+ });
+
+ it('display the defaul primary button text', () => {
+ expect(findModal().props('actionPrimary').text).toBe('Upload file');
+ });
+
+ it('calls the default uploadFile when the form submit', async () => {
+ await submitForm();
+
+ expect(wrapper.vm.uploadFile).toHaveBeenCalled();
+ expect(wrapper.vm.replaceFile).not.toHaveBeenCalled();
+ });
+
+ it('makes a POST request', async () => {
+ await submitRequest();
+
+ expect(mock.history.put).toHaveLength(0);
+ expect(mock.history.post).toHaveLength(1);
+ });
+ });
+
+ describe('replace blob file', () => {
+ const modalTitle = 'Replace foo.js';
+ const replacePath = 'replace-path';
+ const primaryBtnText = 'Replace file';
+
+ beforeEach(() => {
+ createComponent({
+ modalTitle,
+ replacePath,
+ primaryBtnText,
+ });
+ });
+
+ it('displays the passed modal title', () => {
+ expect(findModal().props('title')).toBe(modalTitle);
+ });
+
+ it('display the passed primary button text', () => {
+ expect(findModal().props('actionPrimary').text).toBe(primaryBtnText);
+ });
+
+ it('calls the replaceFile when the form submit', async () => {
+ await submitForm();
+
+ expect(wrapper.vm.replaceFile).toHaveBeenCalled();
+ expect(wrapper.vm.uploadFile).not.toHaveBeenCalled();
+ });
+
+ it('makes a PUT request', async () => {
+ await submitRequest();
+
+ expect(mock.history.put).toHaveLength(1);
+ expect(mock.history.post).toHaveLength(0);
+ expect(mock.history.put[0].url).toBe(replacePath);
+ });
+ });
+ });
});
diff --git a/spec/frontend/repository/log_tree_spec.js b/spec/frontend/repository/log_tree_spec.js
index a842053caad..8cabf902a4f 100644
--- a/spec/frontend/repository/log_tree_spec.js
+++ b/spec/frontend/repository/log_tree_spec.js
@@ -69,6 +69,21 @@ describe('fetchLogsTree', () => {
mock.restore();
});
+ it('persists the offset for a given page if offset is larger than maximum offset', async () => {
+ await fetchLogsTree(client, 'path', '1000', resolver, 900).then(() => {});
+
+ await fetchLogsTree(client, 'path', '1100', resolver, 1200).then(() => {
+ expect(axios.get).toHaveBeenCalledWith('/gitlab-org/gitlab-foss/-/refs/main/logs_tree/path', {
+ params: { format: 'json', offset: 975 },
+ });
+ });
+ });
+
+ it('does not call axios get if offset is larger than the maximum offset', () =>
+ fetchLogsTree(client, '', '1000', resolver, 900).then(() => {
+ expect(axios.get).not.toHaveBeenCalled();
+ }));
+
it('calls axios get', () =>
fetchLogsTree(client, '', '0', resolver).then(() => {
expect(axios.get).toHaveBeenCalledWith('/gitlab-org/gitlab-foss/-/refs/main/logs_tree/', {