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/repository/components')
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js10
-rw-r--r--spec/frontend/repository/components/blob_viewers/notebook_viewer_spec.js40
-rw-r--r--spec/frontend/repository/components/blob_viewers/openapi_viewer_spec.js30
-rw-r--r--spec/frontend/repository/components/fork_info_spec.js122
-rw-r--r--spec/frontend/repository/components/new_directory_modal_spec.js8
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js23
-rw-r--r--spec/frontend/repository/components/upload_blob_modal_spec.js4
7 files changed, 224 insertions, 13 deletions
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index 6ece72c41bb..2e8860f67ef 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -25,7 +25,7 @@ import CodeIntelligence from '~/code_navigation/components/app.vue';
import * as urlUtility from '~/lib/utils/url_utility';
import { isLoggedIn, handleLocationHash } from '~/lib/utils/common_utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import httpStatusCodes from '~/lib/utils/http_status';
+import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import LineHighlighter from '~/blob/line_highlighter';
import { LEGACY_FILE_TYPES } from '~/repository/constants';
import { SIMPLE_BLOB_VIEWER, RICH_BLOB_VIEWER } from '~/blob/components/constants';
@@ -256,19 +256,19 @@ describe('Blob content viewer component', () => {
);
it('loads the LineHighlighter', async () => {
- mockAxios.onGet(legacyViewerUrl).replyOnce(httpStatusCodes.OK, 'test');
+ mockAxios.onGet(legacyViewerUrl).replyOnce(HTTP_STATUS_OK, 'test');
await createComponent({ blob: { ...simpleViewerMock, fileType, highlightJs } });
expect(LineHighlighter).toHaveBeenCalled();
});
it('does not load the LineHighlighter for RichViewers', async () => {
- mockAxios.onGet(legacyViewerUrl).replyOnce(httpStatusCodes.OK, 'test');
+ mockAxios.onGet(legacyViewerUrl).replyOnce(HTTP_STATUS_OK, 'test');
await createComponent({ blob: { ...richViewerMock, fileType, highlightJs } });
expect(LineHighlighter).not.toHaveBeenCalled();
});
it('scrolls to the hash', async () => {
- mockAxios.onGet(legacyViewerUrl).replyOnce(httpStatusCodes.OK, 'test');
+ mockAxios.onGet(legacyViewerUrl).replyOnce(HTTP_STATUS_OK, 'test');
await createComponent({ blob: { ...simpleViewerMock, fileType, highlightJs } });
expect(handleLocationHash).toHaveBeenCalled();
});
@@ -368,7 +368,7 @@ describe('Blob content viewer component', () => {
it('does not load a CodeIntelligence component when no viewers are loaded', async () => {
const url = 'some_file.js?format=json&viewer=rich';
- mockAxios.onGet(url).replyOnce(httpStatusCodes.INTERNAL_SERVER_ERROR);
+ mockAxios.onGet(url).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR);
await createComponent({ blob: { ...richViewerMock, fileType: 'unknown' } });
expect(findCodeIntelligence().exists()).toBe(false);
diff --git a/spec/frontend/repository/components/blob_viewers/notebook_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/notebook_viewer_spec.js
new file mode 100644
index 00000000000..51f3d31ec72
--- /dev/null
+++ b/spec/frontend/repository/components/blob_viewers/notebook_viewer_spec.js
@@ -0,0 +1,40 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import NotebookViewer from '~/repository/components/blob_viewers/notebook_viewer.vue';
+import notebookLoader from '~/blob/notebook';
+
+jest.mock('~/blob/notebook');
+
+describe('Notebook Viewer', () => {
+ let wrapper;
+
+ const ROOT_RELATIVE_PATH = '/some/notebook/';
+ const DEFAULT_BLOB_DATA = { rawPath: `${ROOT_RELATIVE_PATH}file.ipynb` };
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(NotebookViewer, {
+ propsData: { blob: DEFAULT_BLOB_DATA },
+ });
+ };
+
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findNotebookWrapper = () => wrapper.findByTestId('notebook');
+
+ beforeEach(() => createComponent());
+
+ it('calls the notebook loader', () => {
+ expect(notebookLoader).toHaveBeenCalledWith({
+ el: wrapper.vm.$refs.viewer,
+ relativeRawPath: ROOT_RELATIVE_PATH,
+ });
+ });
+
+ it('renders a loading icon component', () => {
+ expect(findLoadingIcon().props('size')).toBe('lg');
+ });
+
+ it('renders the notebook wrapper', () => {
+ expect(findNotebookWrapper().exists()).toBe(true);
+ expect(findNotebookWrapper().attributes('data-endpoint')).toBe(DEFAULT_BLOB_DATA.rawPath);
+ });
+});
diff --git a/spec/frontend/repository/components/blob_viewers/openapi_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/openapi_viewer_spec.js
new file mode 100644
index 00000000000..21994d04076
--- /dev/null
+++ b/spec/frontend/repository/components/blob_viewers/openapi_viewer_spec.js
@@ -0,0 +1,30 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import OpenapiViewer from '~/repository/components/blob_viewers/openapi_viewer.vue';
+import renderOpenApi from '~/blob/openapi';
+
+jest.mock('~/blob/openapi');
+
+describe('OpenAPI Viewer', () => {
+ let wrapper;
+
+ const DEFAULT_BLOB_DATA = { rawPath: 'some/openapi.yml' };
+
+ const createOpenApiViewer = () => {
+ wrapper = shallowMountExtended(OpenapiViewer, {
+ propsData: { blob: DEFAULT_BLOB_DATA },
+ });
+ };
+
+ const findOpenApiViewer = () => wrapper.findByTestId('openapi');
+
+ beforeEach(() => createOpenApiViewer());
+
+ it('calls the openapi render', () => {
+ expect(renderOpenApi).toHaveBeenCalledWith(wrapper.vm.$refs.viewer);
+ });
+
+ it('renders an openapi viewer', () => {
+ expect(findOpenApiViewer().exists()).toBe(true);
+ expect(findOpenApiViewer().attributes('data-endpoint')).toBe(DEFAULT_BLOB_DATA.rawPath);
+ });
+});
diff --git a/spec/frontend/repository/components/fork_info_spec.js b/spec/frontend/repository/components/fork_info_spec.js
new file mode 100644
index 00000000000..c23d5ae5823
--- /dev/null
+++ b/spec/frontend/repository/components/fork_info_spec.js
@@ -0,0 +1,122 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlSkeletonLoader, GlIcon, GlLink } from '@gitlab/ui';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { createAlert } from '~/flash';
+
+import ForkInfo, { i18n } from '~/repository/components/fork_info.vue';
+import forkDetailsQuery from '~/repository/queries/fork_details.query.graphql';
+import { propsForkInfo } from '../mock_data';
+
+jest.mock('~/flash');
+
+describe('ForkInfo component', () => {
+ let wrapper;
+ let mockResolver;
+ const forkInfoError = new Error('Something went wrong');
+
+ Vue.use(VueApollo);
+
+ const createCommitData = ({ ahead = 3, behind = 7 }) => {
+ return {
+ data: {
+ project: { id: '1', forkDetails: { ahead, behind, __typename: 'ForkDetails' } },
+ },
+ };
+ };
+
+ const createComponent = (props = {}, data = {}, isRequestFailed = false) => {
+ mockResolver = isRequestFailed
+ ? jest.fn().mockRejectedValue(forkInfoError)
+ : jest.fn().mockResolvedValue(createCommitData(data));
+
+ wrapper = shallowMountExtended(ForkInfo, {
+ apolloProvider: createMockApollo([[forkDetailsQuery, mockResolver]]),
+ propsData: { ...propsForkInfo, ...props },
+ });
+ return waitForPromises();
+ };
+
+ const findLink = () => wrapper.findComponent(GlLink);
+ const findSkeleton = () => wrapper.findComponent(GlSkeletonLoader);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findDivergenceMessage = () => wrapper.find('.gl-text-secondary');
+ const findInaccessibleMessage = () => wrapper.findByTestId('inaccessible-project');
+ it('displays a skeleton while loading data', async () => {
+ createComponent();
+ expect(findSkeleton().exists()).toBe(true);
+ });
+
+ it('does not display skeleton when data is loaded', async () => {
+ await createComponent();
+ expect(findSkeleton().exists()).toBe(false);
+ });
+
+ it('renders fork icon', async () => {
+ await createComponent();
+ expect(findIcon().exists()).toBe(true);
+ });
+
+ it('queries the data when sourceName is present', async () => {
+ await createComponent();
+ expect(mockResolver).toHaveBeenCalled();
+ });
+
+ it('does not query the data when sourceName is empty', async () => {
+ await createComponent({ sourceName: null });
+ expect(mockResolver).not.toHaveBeenCalled();
+ });
+
+ it('renders inaccessible message when fork source is not available', async () => {
+ await createComponent({ sourceName: '' });
+ const message = findInaccessibleMessage();
+ expect(message.exists()).toBe(true);
+ expect(message.text()).toBe(i18n.inaccessibleProject);
+ });
+
+ it('shows source project name with a link to a repo', async () => {
+ await createComponent();
+ const link = findLink();
+ expect(link.text()).toBe(propsForkInfo.sourceName);
+ expect(link.attributes('href')).toBe(propsForkInfo.sourcePath);
+ });
+
+ it('renders unknown divergence message when divergence is unknown', async () => {
+ await createComponent({}, { ahead: null, behind: null });
+ expect(findDivergenceMessage().text()).toBe(i18n.unknown);
+ });
+
+ it('shows correct divergence message when data is present', async () => {
+ await createComponent();
+ expect(findDivergenceMessage().text()).toMatchInterpolatedText(
+ '7 commits behind, 3 commits ahead of the upstream repository.',
+ );
+ });
+
+ it('renders up to date message when divergence is unknown', async () => {
+ await createComponent({}, { ahead: 0, behind: 0 });
+ expect(findDivergenceMessage().text()).toBe(i18n.upToDate);
+ });
+
+ it('renders commits ahead message', async () => {
+ await createComponent({}, { behind: 0 });
+ expect(findDivergenceMessage().text()).toBe('3 commits ahead of the upstream repository.');
+ });
+
+ it('renders commits behind message', async () => {
+ await createComponent({}, { ahead: 0 });
+
+ expect(findDivergenceMessage().text()).toBe('7 commits behind the upstream repository.');
+ });
+
+ it('renders alert with error message when request fails', async () => {
+ await createComponent({}, {}, true);
+ expect(createAlert).toHaveBeenCalledWith({
+ message: i18n.error,
+ captureError: true,
+ error: forkInfoError,
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/new_directory_modal_spec.js b/spec/frontend/repository/components/new_directory_modal_spec.js
index cf0d48280f4..4e5c9a685c4 100644
--- a/spec/frontend/repository/components/new_directory_modal_spec.js
+++ b/spec/frontend/repository/components/new_directory_modal_spec.js
@@ -5,7 +5,7 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/flash';
-import httpStatusCodes from '~/lib/utils/http_status';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
import NewDirectoryModal from '~/repository/components/new_directory_modal.vue';
@@ -149,7 +149,7 @@ describe('NewDirectoryModal', () => {
originalBranch,
createNewMr,
} = defaultFormValue;
- mock.onPost(initialProps.path).reply(httpStatusCodes.OK, {});
+ mock.onPost(initialProps.path).reply(HTTP_STATUS_OK, {});
await fillForm();
await submitForm();
@@ -161,7 +161,7 @@ describe('NewDirectoryModal', () => {
});
it('does not submit "create_merge_request" formData if createNewMr is not checked', async () => {
- mock.onPost(initialProps.path).reply(httpStatusCodes.OK, {});
+ mock.onPost(initialProps.path).reply(HTTP_STATUS_OK, {});
await fillForm({ createNewMr: false });
await submitForm();
expect(mock.history.post[0].data.get('create_merge_request')).toBeNull();
@@ -169,7 +169,7 @@ describe('NewDirectoryModal', () => {
it('redirects to the new directory', async () => {
const response = { filePath: 'new-dir-path' };
- mock.onPost(initialProps.path).reply(httpStatusCodes.OK, response);
+ mock.onPost(initialProps.path).reply(HTTP_STATUS_OK, response);
await fillForm({ dirName: 'foo', branchName: 'master', commitMessage: 'foo' });
await submitForm();
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index 6eea66f1a7d..f694c8e9166 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -5,19 +5,25 @@ import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue';
import TreeContent from 'jh_else_ce/repository/components/tree_content.vue';
import { loadCommits, isRequested, resetRequestedCommits } from '~/repository/commits_service';
+import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
+import { i18n } from '~/repository/constants';
+import { graphQLErrors } from '../mock_data';
jest.mock('~/repository/commits_service', () => ({
loadCommits: jest.fn(() => Promise.resolve()),
isRequested: jest.fn(),
resetRequestedCommits: jest.fn(),
}));
+jest.mock('~/flash');
let vm;
let $apollo;
+const mockResponse = jest.fn().mockReturnValue(Promise.resolve({ data: {} }));
-function factory(path, data = () => ({})) {
+function factory(path, appoloMockResponse = mockResponse) {
$apollo = {
- query: jest.fn().mockReturnValue(Promise.resolve({ data: data() })),
+ query: appoloMockResponse,
};
vm = shallowMount(TreeContent, {
@@ -222,4 +228,17 @@ describe('Repository table component', () => {
expect(loadCommits.mock.calls).toEqual([['', path, '', 0]]);
});
});
+
+ describe('error handling', () => {
+ const gitalyError = { graphQLErrors };
+ it.each`
+ error | message
+ ${gitalyError} | ${i18n.gitalyError}
+ ${'Error'} | ${i18n.generalError}
+ `('should show an expected error', async ({ error, message }) => {
+ factory('/', jest.fn().mockRejectedValue(error));
+ await waitForPromises();
+ expect(createAlert).toHaveBeenCalledWith({ message, captureError: true });
+ });
+ });
});
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index 8db169b02b4..9de0666f27a 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -5,7 +5,7 @@ import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/flash';
-import httpStatusCodes from '~/lib/utils/http_status';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { visitUrl } from '~/lib/utils/url_utility';
import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
@@ -158,7 +158,7 @@ describe('UploadBlobModal', () => {
describe('successful response', () => {
beforeEach(async () => {
mock = new MockAdapter(axios);
- mock.onPost(initialProps.path).reply(httpStatusCodes.OK, { filePath: 'blah' });
+ mock.onPost(initialProps.path).reply(HTTP_STATUS_OK, { filePath: 'blah' });
findModal().vm.$emit('primary', mockEvent);