diff --git a/app/assets/javascripts/repository/components/header_area/blob_button_group.vue b/app/assets/javascripts/repository/components/header_area/blob_button_group.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c233bd2823da68a981d6d6695e2205df62578206
--- /dev/null
+++ b/app/assets/javascripts/repository/components/header_area/blob_button_group.vue
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/repository/components/header_area/blob_controls.vue b/app/assets/javascripts/repository/components/header_area/blob_controls.vue
index 8948029cfb570066382e507f5cf4b3f76002f4ac..6d83dd15d72bb45708e433a8d505823b6de6143a 100644
--- a/app/assets/javascripts/repository/components/header_area/blob_controls.vue
+++ b/app/assets/javascripts/repository/components/header_area/blob_controls.vue
@@ -1,5 +1,6 @@
-
+
-
+
diff --git a/app/assets/javascripts/repository/components/header_area/blob_overflow_menu.vue b/app/assets/javascripts/repository/components/header_area/blob_overflow_menu.vue
index 6c95b78315bb47de2ca564644d65420550da2d3f..fa6954d011d94e80a40fde56f89de565332097a9 100644
--- a/app/assets/javascripts/repository/components/header_area/blob_overflow_menu.vue
+++ b/app/assets/javascripts/repository/components/header_area/blob_overflow_menu.vue
@@ -1,9 +1,11 @@
-
-
-
-
-
-
+
+
+
+
diff --git a/app/assets/javascripts/repository/queries/blob_controls.query.graphql b/app/assets/javascripts/repository/queries/blob_controls.query.graphql
index 71470717d1a4c433928fed2a7c3d811c34b0a745..9c50ba6236b9df9f62b71e6c69b93214d2da9ec1 100644
--- a/app/assets/javascripts/repository/queries/blob_controls.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_controls.query.graphql
@@ -1,9 +1,14 @@
query getBlobControls($projectPath: ID!, $filePath: String!, $ref: String!, $refType: RefType) {
project(fullPath: $projectPath) {
+ __typename
id
repository {
+ __typename
+ empty
blobs(paths: [$filePath], ref: $ref, refType: $refType) {
+ __typename
nodes {
+ __typename
id
name
blamePath
@@ -15,13 +20,21 @@ query getBlobControls($projectPath: ID!, $filePath: String!, $ref: String!, $ref
path
rawPath
rawTextBlob
+ archived
+ replacePath
+ webPath
+ canCurrentUserPushToBranch
+ canModifyBlob
+ canModifyBlobWithWebIde
simpleViewer {
+ __typename
fileType
tooLarge
type
renderError
}
richViewer {
+ __typename
fileType
tooLarge
type
diff --git a/ee/app/assets/javascripts/repository/components/header_area/lock_file_dropdown_item.vue b/ee/app/assets/javascripts/repository/components/header_area/lock_file_dropdown_item.vue
index ebc8fe7dfaba0d1643bb52dfbb0507453b0b83ef..ca284ea0632bc12c503b3a3f16077044a9c36902 100644
--- a/ee/app/assets/javascripts/repository/components/header_area/lock_file_dropdown_item.vue
+++ b/ee/app/assets/javascripts/repository/components/header_area/lock_file_dropdown_item.vue
@@ -2,7 +2,6 @@
import { GlDisclosureDropdownItem, GlModal } from '@gitlab/ui';
import { createAlert } from '~/alert';
import { sprintf, __ } from '~/locale';
-import projectInfoQuery from 'ee_else_ce/repository/queries/project_info.query.graphql';
import lockPathMutation from '~/repository/mutations/lock_path.mutation.graphql';
import { DEFAULT_BLOB_INFO } from '~/repository/constants';
@@ -12,7 +11,6 @@ export default {
unlock: __('Unlock'),
modalTitle: __('Lock file?'),
actionCancel: __('Cancel'),
- fetchError: __('An error occurred while fetching lock information, please try again.'),
mutationError: __('An error occurred while editing lock information, please try again.'),
},
components: {
@@ -32,23 +30,20 @@ export default {
type: String,
required: true,
},
- },
- apollo: {
- // eslint-disable-next-line @gitlab/vue-no-undef-apollo-properties
- projectInfo: {
- query: projectInfoQuery,
- variables() {
- return {
- projectPath: this.projectPath,
- };
- },
- update({ project }) {
- this.pathLocks = project?.pathLocks || DEFAULT_BLOB_INFO.pathLocks;
- this.userPermissions = project?.userPermissions;
- },
- error() {
- createAlert({ message: this.$options.i18n.fetchError });
- },
+ pathLocks: {
+ type: Object,
+ required: false,
+ default: () => DEFAULT_BLOB_INFO.pathLocks,
+ },
+ userPermissions: {
+ type: Object,
+ required: false,
+ default: () => DEFAULT_BLOB_INFO.userPermissions,
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
},
},
data() {
@@ -56,14 +51,9 @@ export default {
isUpdating: false,
isModalVisible: false,
locked: false,
- pathLocks: DEFAULT_BLOB_INFO.pathLocks,
- userPermissions: DEFAULT_BLOB_INFO.userPermissions,
};
},
computed: {
- isLoading() {
- return this.$apollo?.queries.projectInfo.loading;
- },
lockButtonTitle() {
return this.isLocked ? this.$options.i18n.unlock : this.$options.i18n.lock;
},
@@ -112,8 +102,11 @@ export default {
},
},
watch: {
- isLocked(val) {
- this.locked = val;
+ isLocked: {
+ immediate: true,
+ handler(val) {
+ this.locked = val;
+ },
},
},
methods: {
diff --git a/ee/spec/frontend/repository/components/header_area/lock_file_dropdown_item_spec.js b/ee/spec/frontend/repository/components/header_area/lock_file_dropdown_item_spec.js
index 73db421a766cd5a77ea4095c4d7b83151b8152d6..434b60e83ab762387e3769c3fa6d210a59705a02 100644
--- a/ee/spec/frontend/repository/components/header_area/lock_file_dropdown_item_spec.js
+++ b/ee/spec/frontend/repository/components/header_area/lock_file_dropdown_item_spec.js
@@ -5,7 +5,6 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import lockPathMutation from '~/repository/mutations/lock_path.mutation.graphql';
-import projectInfoQuery from 'ee_component/repository/queries/project_info.query.graphql';
import { projectMock, userPermissionsMock } from 'ee_jest/repository/mock_data';
import LockFileDropdownItem from 'ee_component/repository/components/header_area/lock_file_dropdown_item.vue';
import { createAlert } from '~/alert';
@@ -17,22 +16,11 @@ describe('LockFileDropdownItem component', () => {
let wrapper;
let fakeApollo;
- const projectInfoQueryMockResolver = jest
- .fn()
- .mockResolvedValue({ data: { project: projectMock } });
- const projectInfoQueryErrorResolver = jest.fn().mockRejectedValue(new Error('Request failed'));
+ const lockPathMutationResolver = jest.fn();
- const lochPathMutationResolver = jest.fn();
-
- const createComponent = ({
- mutationResolver = lochPathMutationResolver,
- projectInfoResolver = projectInfoQueryMockResolver,
- } = {}) => {
+ const createComponent = ({ props = {}, mutationResolver = lockPathMutationResolver } = {}) => {
window.gon = { current_username: projectMock.pathLocks.nodes[0].user.username };
- fakeApollo = createMockApollo([
- [projectInfoQuery, projectInfoResolver],
- [lockPathMutation, mutationResolver],
- ]);
+ fakeApollo = createMockApollo([[lockPathMutation, mutationResolver]]);
wrapper = shallowMount(LockFileDropdownItem, {
apolloProvider: fakeApollo,
@@ -40,6 +28,10 @@ describe('LockFileDropdownItem component', () => {
name: 'locked_file.js',
path: 'some/path/locked_file.js',
projectPath: 'some/project/path',
+ isLoading: false,
+ userPermissions: userPermissionsMock,
+ pathLocks: projectMock.pathLocks,
+ ...props,
},
});
};
@@ -60,19 +52,13 @@ describe('LockFileDropdownItem component', () => {
});
it('renders disabled the lock dropdown item if user can not lock a file', async () => {
- const projectWithNoPushPermission = {
- data: {
- project: {
- ...projectMock,
- userPermissions: {
- ...userPermissionsMock,
- pushCode: false,
- },
+ createComponent({
+ props: {
+ userPermissions: {
+ ...userPermissionsMock,
+ pushCode: false,
},
},
- };
- createComponent({
- projectInfoResolver: jest.fn().mockResolvedValue(projectWithNoPushPermission),
});
await waitForPromises();
@@ -82,12 +68,11 @@ describe('LockFileDropdownItem component', () => {
});
it('renders disabled until query fetches projects info', async () => {
- const projectInfoQueryLoading = jest.fn().mockResolvedValue(new Promise(() => {}));
createComponent({
- projectInfoResolver: projectInfoQueryLoading,
+ props: { isLoading: true },
});
await waitForPromises();
- expect(projectInfoQueryLoading).toHaveBeenCalled();
+
expect(findLockFileDropdownItem().props('item')).toMatchObject({
extraAttrs: { disabled: true },
});
@@ -110,17 +95,8 @@ describe('LockFileDropdownItem component', () => {
});
it('renders the Lock dropdown item label, when file is not locked', async () => {
- const projectWithNoLocks = {
- data: {
- project: {
- ...projectMock,
- pathLocks: { __typename: 'PathLockConnection', nodes: [] },
- },
- },
- };
-
createComponent({
- projectInfoResolver: jest.fn().mockResolvedValue(projectWithNoLocks),
+ props: { pathLocks: { __typename: 'PathLockConnection', nodes: [] } },
});
await waitForPromises();
@@ -137,15 +113,6 @@ describe('LockFileDropdownItem component', () => {
});
});
- it('creates an alert with the correct message, when projectInfo query fails', async () => {
- createComponent({ projectInfoResolver: projectInfoQueryErrorResolver });
- await waitForPromises();
-
- expect(createAlert).toHaveBeenCalledWith({
- message: 'An error occurred while fetching lock information, please try again.',
- });
- });
-
describe('Modal', () => {
it('displays a confirm modal when the lock dropdown item is clicked', () => {
findLockFileDropdownItem().vm.$emit('action');
@@ -195,7 +162,7 @@ describe('LockFileDropdownItem component', () => {
findLockFileDropdownItem().vm.$emit('action');
clickSubmit();
- expect(lochPathMutationResolver).toHaveBeenCalledWith({
+ expect(lockPathMutationResolver).toHaveBeenCalledWith({
filePath: 'some/path/locked_file.js',
lock: false,
projectPath: 'some/project/path',
@@ -205,7 +172,7 @@ describe('LockFileDropdownItem component', () => {
it('does not execute a lock mutation if lock not confirmed', () => {
findLockFileDropdownItem().vm.$emit('action');
- expect(lochPathMutationResolver).not.toHaveBeenCalled();
+ expect(lockPathMutationResolver).not.toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/repository/components/header_area/blob_button_group_spec.js b/spec/frontend/repository/components/header_area/blob_button_group_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..374b55f0b536706f3926fc1e7c031b0099eb7100
--- /dev/null
+++ b/spec/frontend/repository/components/header_area/blob_button_group_spec.js
@@ -0,0 +1,193 @@
+import { GlDisclosureDropdownItem } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { projectMock } from 'ee_else_ce_jest/repository/mock_data';
+import projectInfoQuery from 'ee_else_ce/repository/queries/project_info.query.graphql';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { stubComponent } from 'helpers/stub_component';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import BlobButtonGroup from '~/repository/components/header_area/blob_button_group.vue';
+import CommitChangesModal from '~/repository/components/commit_changes_modal.vue';
+import UploadBlobModal from '~/repository/components/upload_blob_modal.vue';
+import { createAlert } from '~/alert';
+
+Vue.use(VueApollo);
+jest.mock('~/alert');
+jest.mock('~/lib/utils/common_utils', () => ({
+ isLoggedIn: jest.fn().mockReturnValue(true),
+}));
+
+const DEFAULT_PROPS = {
+ name: 'some name',
+ path: 'some/path',
+ replacePath: 'some/replace/path',
+ deletePath: 'some/delete/path',
+ canPushToBranch: true,
+ isEmptyRepository: false,
+ projectPath: 'some/project/path',
+ isUsingLfs: true,
+};
+
+const DEFAULT_INJECT = {
+ targetBranch: 'master',
+ originalBranch: 'master',
+ canModifyBlob: true,
+ canModifyBlobWithWebIde: true,
+};
+
+describe('BlobButtonGroup component', () => {
+ let wrapper;
+ let fakeApollo;
+
+ let showUploadBlobModalMock;
+ let showDeleteBlobModalMock;
+
+ const projectInfoQueryMockResolver = jest
+ .fn()
+ .mockResolvedValue({ data: { project: projectMock } });
+ const projectInfoQueryErrorResolver = jest.fn().mockRejectedValue(new Error('Request failed'));
+
+ const createComponent = async ({
+ props = {},
+ projectInfoResolver = projectInfoQueryMockResolver,
+ inject = {},
+ } = {}) => {
+ showUploadBlobModalMock = jest.fn();
+ showDeleteBlobModalMock = jest.fn();
+
+ const UploadBlobModalStub = stubComponent(UploadBlobModal, {
+ methods: {
+ show: showUploadBlobModalMock,
+ },
+ });
+ const DeleteBlobModalStub = stubComponent(CommitChangesModal, {
+ methods: {
+ show: showDeleteBlobModalMock,
+ },
+ });
+
+ fakeApollo = createMockApollo([[projectInfoQuery, projectInfoResolver]]);
+
+ wrapper = mountExtended(BlobButtonGroup, {
+ apolloProvider: fakeApollo,
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...props,
+ },
+ provide: {
+ ...DEFAULT_INJECT,
+ ...inject,
+ },
+ stubs: {
+ UploadBlobModal: UploadBlobModalStub,
+ CommitChangesModal: DeleteBlobModalStub,
+ },
+ });
+ await waitForPromises();
+ };
+
+ const findDropdownItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem);
+ const findDropdownItemWithText = (text) =>
+ findDropdownItems().wrappers.find((x) => x.props('item').text === text);
+ const findDeleteItem = () => findDropdownItemWithText('Delete');
+ const findReplaceItem = () => findDropdownItemWithText('Replace');
+ const findDeleteBlobModal = () => wrapper.findComponent(CommitChangesModal);
+ const findUploadBlobModal = () => wrapper.findComponent(UploadBlobModal);
+
+ beforeEach(async () => {
+ await createComponent();
+ });
+
+ afterEach(() => {
+ fakeApollo = null;
+ });
+
+ it('renders component', () => {
+ expect(wrapper.props()).toMatchObject({
+ name: 'some name',
+ path: 'some/path',
+ });
+ });
+
+ it('creates an alert with the correct message, when projectInfo query fails', async () => {
+ await createComponent({ projectInfoResolver: projectInfoQueryErrorResolver });
+
+ expect(createAlert).toHaveBeenCalledWith({
+ message: 'An error occurred while fetching lock information, please try again.',
+ });
+ });
+
+ describe('dropdown items', () => {
+ it('renders both the replace and delete item', () => {
+ expect(wrapper.findAllComponents(GlDisclosureDropdownItem)).toHaveLength(2);
+ expect(findReplaceItem().exists()).toBe(true);
+ expect(findDeleteItem().exists()).toBe(true);
+ });
+
+ it('triggers the UploadBlobModal from the replace item', () => {
+ findReplaceItem().vm.$emit('action');
+
+ expect(showUploadBlobModalMock).toHaveBeenCalled();
+ });
+
+ it('triggers the CommitChangesModal from the delete item', () => {
+ findDeleteItem().vm.$emit('action');
+
+ expect(showDeleteBlobModalMock).toHaveBeenCalled();
+ });
+
+ describe('when user cannot modify blob', () => {
+ beforeEach(async () => {
+ await createComponent({
+ props: { isUsingLfs: false },
+ inject: { canModifyBlob: false, canModifyBlobWithWebIde: false },
+ });
+ });
+
+ it('does not trigger the UploadBlobModal from the replace item', () => {
+ findReplaceItem().vm.$emit('action');
+
+ expect(findReplaceItem().props('item')).toMatchObject({
+ extraAttrs: { disabled: true },
+ });
+
+ expect(showUploadBlobModalMock).not.toHaveBeenCalled();
+ expect(wrapper.emitted().fork).toHaveLength(1);
+ });
+
+ it('does not trigger the DeleteBlobModal from the delete item', () => {
+ findDeleteItem().vm.$emit('action');
+
+ expect(findDeleteItem().props('item')).toMatchObject({
+ extraAttrs: { disabled: true },
+ });
+
+ expect(showDeleteBlobModalMock).not.toHaveBeenCalled();
+ expect(wrapper.emitted().fork).toHaveLength(1);
+ });
+ });
+ });
+
+ it('renders UploadBlobModal', () => {
+ expect(findUploadBlobModal().props()).toMatchObject({
+ commitMessage: 'Replace some name',
+ targetBranch: 'master',
+ originalBranch: 'master',
+ canPushCode: true,
+ path: 'some/path',
+ replacePath: 'some/replace/path',
+ });
+ });
+
+ it('renders CommitChangesModal for delete', () => {
+ expect(findDeleteBlobModal().props()).toMatchObject({
+ commitMessage: 'Delete some name',
+ targetBranch: 'master',
+ originalBranch: 'master',
+ canPushCode: true,
+ emptyRepo: false,
+ isUsingLfs: true,
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/header_area/blob_controls_spec.js b/spec/frontend/repository/components/header_area/blob_controls_spec.js
index 95b9f9f1f2038a7beef8c331bdc085fb950dba47..ad98ce073cbb6847794c1f7da1e4243c42f8d2a1 100644
--- a/spec/frontend/repository/components/header_area/blob_controls_spec.js
+++ b/spec/frontend/repository/components/header_area/blob_controls_spec.js
@@ -38,9 +38,13 @@ const createComponent = async (
mockResolver = jest.fn().mockResolvedValue({
data: {
project: {
+ __typename: 'Project',
id: '1234',
repository: {
+ __typename: 'Repository',
+ empty: blobControlsDataMock.repository.empty,
blobs: {
+ __typename: 'RepositoryBlobConnection',
nodes: [{ ...blobControlsDataMock.repository.blobs.nodes[0], ...blobInfoOverrides }],
},
},
@@ -55,6 +59,8 @@ const createComponent = async (
apolloProvider: createMockApollo([[blobControlsQuery, mockResolver]]),
provide: {
glFeatures,
+ canModifyBlob: true,
+ canModifyBlobWithWebIde: true,
},
propsData: {
projectPath,
@@ -112,7 +118,7 @@ describe('Blob controls component', () => {
});
it('does not render blame button when blobInfo.externalStorage is "lfs"', async () => {
- await createComponent({}, { externalStorage: 'lfs' });
+ await createComponent({}, { storedExternally: true, externalStorage: 'lfs' });
expect(findBlameButton().exists()).toBe(false);
});
@@ -169,18 +175,26 @@ describe('Blob controls component', () => {
environmentPath: '',
isEmpty: false,
overrideCopy: true,
+ archived: false,
+ replacePath: 'some/replace/file.js',
+ webPath: 'some/file.js',
+ canCurrentUserPushToBranch: true,
simpleViewer: {
+ __typename: 'BlobViewer',
renderError: null,
tooLarge: false,
type: 'simple',
fileType: 'rich',
},
richViewer: {
+ __typename: 'BlobViewer',
renderError: 'too big file',
tooLarge: false,
type: 'rich',
fileType: 'rich',
},
+ isEmptyRepository: false,
+ isUsingLfs: false,
});
});
diff --git a/spec/frontend/repository/components/header_area/blob_overflow_menu_spec.js b/spec/frontend/repository/components/header_area/blob_overflow_menu_spec.js
index e9aaccf36f61d8593027f81a93bb00f382b1c3b8..6a36820bd735cf26fc8ac30cff3ca511dfef7000 100644
--- a/spec/frontend/repository/components/header_area/blob_overflow_menu_spec.js
+++ b/spec/frontend/repository/components/header_area/blob_overflow_menu_spec.js
@@ -1,10 +1,16 @@
import { GlDisclosureDropdown } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { isLoggedIn } from '~/lib/utils/common_utils';
import BlobOverflowMenu from '~/repository/components/header_area/blob_overflow_menu.vue';
import BlobDefaultActionsGroup from '~/repository/components/header_area/blob_default_actions_group.vue';
+import BlobButtonGroup from '~/repository/components/header_area/blob_button_group.vue';
import createRouter from '~/repository/router';
import { blobControlsDataMock, refMock } from '../../mock_data';
+jest.mock('~/lib/utils/common_utils', () => ({
+ isLoggedIn: jest.fn().mockReturnValue(true),
+}));
+
describe('Blob Overflow Menu', () => {
let wrapper;
@@ -17,6 +23,8 @@ describe('Blob Overflow Menu', () => {
wrapper = shallowMountExtended(BlobOverflowMenu, {
router,
provide: {
+ canModifyBlob: true,
+ canModifyBlobWithWebIde: true,
...provided,
},
propsData: {
@@ -27,6 +35,11 @@ describe('Blob Overflow Menu', () => {
simpleViewer: blobControlsDataMock.repository.blobs.nodes[0].simpleViewer,
name: blobControlsDataMock.repository.blobs.nodes[0].name,
isBinary: blobControlsDataMock.repository.blobs.nodes[0].binary,
+ archived: blobControlsDataMock.repository.blobs.nodes[0].archived,
+ replacePath: blobControlsDataMock.repository.blobs.nodes[0].replacePath,
+ webPath: blobControlsDataMock.repository.blobs.nodes[0].webPath,
+ canCurrentUserPushToBranch:
+ blobControlsDataMock.repository.blobs.nodes[0].canCurrentUserPushToBranch,
...propsData,
},
stub: {
@@ -35,18 +48,14 @@ describe('Blob Overflow Menu', () => {
});
}
- const findDefaultBlobActions = () => wrapper.findByTestId('default-actions-container');
const findBlobDefaultActionsGroup = () => wrapper.findComponent(BlobDefaultActionsGroup);
+ const findBlobButtonGroup = () => wrapper.findComponent(BlobButtonGroup);
beforeEach(() => {
createComponent();
});
describe('Default blob actions', () => {
- it('renders component', () => {
- expect(findDefaultBlobActions().exists()).toBe(true);
- });
-
it('renders BlobDefaultActionsGroup component', () => {
expect(findBlobDefaultActionsGroup().exists()).toBe(true);
});
@@ -71,4 +80,25 @@ describe('Blob Overflow Menu', () => {
});
});
});
+
+ describe('Blob Button Group', () => {
+ it('renders component', () => {
+ expect(findBlobButtonGroup().exists()).toBe(true);
+ });
+
+ it('does not render when blob is archived', () => {
+ createComponent({
+ archived: true,
+ });
+
+ expect(findBlobButtonGroup().exists()).toBe(false);
+ });
+
+ it('does not render when user is not logged in', () => {
+ isLoggedIn.mockImplementationOnce(() => false);
+ createComponent();
+
+ expect(findBlobButtonGroup().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js
index 422fabdc82495a8b88c747a5f01f060a92a512bc..7c2682cc9f396e1016e72e058655a212e57901b7 100644
--- a/spec/frontend/repository/mock_data.js
+++ b/spec/frontend/repository/mock_data.js
@@ -89,11 +89,16 @@ export const refWithSpecialCharMock = 'feat/selected-#-ref-#';
export const encodedRefWithSpecialCharMock = 'feat/selected-%23-ref-%23';
export const blobControlsDataMock = {
+ __typename: 'Project',
id: '1234',
repository: {
+ __typename: 'Repository',
+ empty: false,
blobs: {
+ __typename: 'RepositoryBlobConnection',
nodes: [
{
+ __typename: 'RepositoryBlob',
id: '5678',
name: 'file.js',
blamePath: 'blame/file.js',
@@ -105,7 +110,14 @@ export const blobControlsDataMock = {
environmentExternalUrlForRouteMap: '',
rawPath: 'https://testing.com/flightjs/flight/snippets/51/raw',
rawTextBlob: 'Example raw text content',
+ archived: false,
+ replacePath: 'some/replace/file.js',
+ webPath: 'some/file.js',
+ canCurrentUserPushToBranch: true,
+ canModifyBlob: true,
+ canModifyBlobWithWebIde: true,
simpleViewer: {
+ __typename: 'BlobViewer',
collapsed: false,
loadingPartialName: 'loading',
renderError: null,
@@ -114,6 +126,7 @@ export const blobControlsDataMock = {
fileType: 'rich',
},
richViewer: {
+ __typename: 'BlobViewer',
collapsed: false,
loadingPartialName: 'loading',
renderError: 'too big file',