Commit 4d1eb551 authored by Denys Mishunov's avatar Denys Mishunov Committed by Frédéric Caplette

Make use of the project data served by Rails

Removed the unnecessary getProjectData service

Changelog: changed
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72218
parent d70fa1b7
......@@ -29,14 +29,20 @@ export default {
},
},
watch: {
showLoading(newVal) {
if (!newVal) {
this.$emit('tree-ready');
}
showLoading() {
this.notifyTreeReady();
},
},
mounted() {
this.notifyTreeReady();
},
methods: {
...mapActions(['toggleTreeOpen']),
notifyTreeReady() {
if (!this.showLoading) {
this.$emit('tree-ready');
}
},
clickedFile() {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FILE_CLICKED });
},
......
import Vue from 'vue';
import createFlash from '~/flash';
import IdeRouter from '~/ide/ide_router_extension';
import { joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import {
WEBIDE_MARK_FETCH_PROJECT_DATA_START,
WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
......@@ -75,49 +73,34 @@ export const createRouter = (store, defaultBranch) => {
router.beforeEach((to, from, next) => {
if (to.params.namespace && to.params.project) {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_PROJECT_DATA_START });
store
.dispatch('getProjectData', {
namespace: to.params.namespace,
projectId: to.params.project,
})
.then(() => {
const basePath = to.params.pathMatch || '';
const projectId = `${to.params.namespace}/${to.params.project}`;
const branchId = to.params.branchid;
const mergeRequestId = to.params.mrid;
const basePath = to.params.pathMatch || '';
const projectId = `${to.params.namespace}/${to.params.project}`;
const branchId = to.params.branchid;
const mergeRequestId = to.params.mrid;
if (branchId) {
performanceMarkAndMeasure({
mark: WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
measures: [
{
name: WEBIDE_MEASURE_FETCH_PROJECT_DATA,
start: WEBIDE_MARK_FETCH_PROJECT_DATA_START,
},
],
});
store.dispatch('openBranch', {
projectId,
branchId,
basePath,
});
} else if (mergeRequestId) {
store.dispatch('openMergeRequest', {
projectId,
mergeRequestId,
targetProjectId: to.query.target_project,
});
}
})
.catch((e) => {
createFlash({
message: __('Error while loading the project data. Please try again.'),
fadeTransition: false,
addBodyClass: true,
});
throw e;
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_PROJECT_DATA_START });
if (branchId) {
performanceMarkAndMeasure({
mark: WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
measures: [
{
name: WEBIDE_MEASURE_FETCH_PROJECT_DATA,
start: WEBIDE_MARK_FETCH_PROJECT_DATA_START,
},
],
});
store.dispatch('openBranch', {
projectId,
branchId,
basePath,
});
} else if (mergeRequestId) {
store.dispatch('openMergeRequest', {
projectId,
mergeRequestId,
targetProjectId: to.query.target_project,
});
}
}
next();
......
......@@ -34,11 +34,18 @@ Vue.use(PerformancePlugin, {
* @param {extendStoreCallback} options.extendStore -
* Function that receives the default store and returns an extended one.
*/
export function initIde(el, options = {}) {
export const initIde = (el, options = {}) => {
if (!el) return null;
const { rootComponent = ide, extendStore = identity } = options;
const store = createStore();
const project = JSON.parse(el.dataset.project);
store.dispatch('setProject', { project });
// fire and forget fetching non-critical project info
store.dispatch('fetchProjectPermissions');
const router = createRouter(store, el.dataset.defaultBranch || DEFAULT_BRANCH);
return new Vue({
......@@ -77,7 +84,7 @@ export function initIde(el, options = {}) {
return createElement(rootComponent);
},
});
}
};
/**
* Start the IDE.
......
import getIdeProject from 'ee_else_ce/ide/queries/get_ide_project.query.graphql';
import Api from '~/api';
import getIdeProject from 'ee_else_ce/ide/queries/get_ide_project.query.graphql';
import dismissUserCallout from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import axios from '~/lib/utils/axios_utils';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import ciConfig from '~/pipeline_editor/graphql/queries/ci_config.query.graphql';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { query, mutate } from './gql';
const fetchApiProjectData = (projectPath) => Api.project(projectPath).then(({ data }) => data);
const fetchGqlProjectData = (projectPath) =>
query({
query: getIdeProject,
variables: { projectPath },
}).then(({ data }) => ({
...data.project,
id: getIdFromGraphQLId(data.project.id),
}));
export default {
getFileData(endpoint) {
return axios.get(endpoint, {
......@@ -65,18 +54,6 @@ export default {
)
.then(({ data }) => data);
},
getProjectData(namespace, project) {
const projectPath = `${namespace}/${project}`;
return Promise.all([fetchApiProjectData(projectPath), fetchGqlProjectData(projectPath)]).then(
([apiProjectData, gqlProjectData]) => ({
data: {
...apiProjectData,
...gqlProjectData,
},
}),
);
},
getProjectMergeRequests(projectId, params = {}) {
return Api.projectMergeRequests(projectId, params);
},
......@@ -119,4 +96,13 @@ export default {
variables: { input: { featureName: name } },
}).then(({ data }) => data);
},
getProjectPermissionsData(projectPath) {
return query({
query: getIdeProject,
variables: { projectPath },
}).then(({ data }) => ({
...data.project,
id: getIdFromGraphQLId(data.project.id),
}));
},
};
import { escape } from 'lodash';
import createFlash from '~/flash';
import { __, sprintf } from '~/locale';
import { logError } from '~/lib/logger';
import api from '../../../api';
import service from '../../services';
import * as types from '../mutation_types';
export const getProjectData = ({ commit, state }, { namespace, projectId, force = false } = {}) =>
new Promise((resolve, reject) => {
if (!state.projects[`${namespace}/${projectId}`] || force) {
commit(types.TOGGLE_LOADING, { entry: state });
service
.getProjectData(namespace, projectId)
.then((res) => res.data)
.then((data) => {
commit(types.TOGGLE_LOADING, { entry: state });
commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
resolve(data);
})
.catch(() => {
createFlash({
message: __('Error loading project data. Please try again.'),
fadeTransition: false,
addBodyClass: true,
});
reject(new Error(`Project not loaded ${namespace}/${projectId}`));
});
} else {
resolve(state.projects[`${namespace}/${projectId}`]);
}
const ERROR_LOADING_PROJECT = __('Error loading project data. Please try again.');
const errorFetchingData = (e) => {
logError(ERROR_LOADING_PROJECT, e);
createFlash({
message: ERROR_LOADING_PROJECT,
fadeTransition: false,
addBodyClass: true,
});
};
export const setProject = ({ commit }, { project } = {}) => {
if (!project) {
return;
}
const projectPath = project.path_with_namespace;
commit(types.SET_PROJECT, { projectPath, project });
commit(types.SET_CURRENT_PROJECT, projectPath);
};
export const fetchProjectPermissions = ({ commit, state }) => {
const projectPath = state.currentProjectId;
if (!projectPath) {
return undefined;
}
return service
.getProjectPermissionsData(projectPath)
.then((permissions) => {
commit(types.UPDATE_PROJECT, { projectPath, props: permissions });
})
.catch(errorFetchingData);
};
export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {}) =>
service
......
......@@ -8,6 +8,7 @@ export const SET_LINKS = 'SET_LINKS';
// Project Mutation Types
export const SET_PROJECT = 'SET_PROJECT';
export const SET_CURRENT_PROJECT = 'SET_CURRENT_PROJECT';
export const UPDATE_PROJECT = 'UPDATE_PROJECT';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
// Merge request mutation types
......
import Vue from 'vue';
import * as types from '../mutation_types';
export default {
......@@ -24,4 +25,15 @@ export default {
empty_repo: value,
});
},
[types.UPDATE_PROJECT](state, { projectPath, props }) {
const project = state.projects[projectPath];
if (!project || !props) {
return;
}
Object.keys(props).forEach((key) => {
Vue.set(project, key, props[key]);
});
},
};
......@@ -29,7 +29,7 @@ module IdeHelper
def convert_to_project_entity_json(project)
return unless project
API::Entities::Project.represent(project).to_json
API::Entities::Project.represent(project, current_user: current_user).to_json
end
def enable_environments_guidance?
......
......@@ -13902,9 +13902,6 @@ msgstr ""
msgid "Error while loading the merge request. Please try again."
msgstr ""
msgid "Error while loading the project data. Please try again."
msgstr ""
msgid "Error while migrating %{upload_id}: %{error_message}"
msgstr ""
......
......@@ -38,9 +38,16 @@ describe('IDE tree list', () => {
beforeEach(() => {
bootstrapWithTree();
jest.spyOn(vm, '$emit').mockImplementation(() => {});
vm.$mount();
});
it('emits tree-ready event', () => {
expect(vm.$emit).toHaveBeenCalledTimes(1);
expect(vm.$emit).toHaveBeenCalledWith('tree-ready');
});
it('renders loading indicator', (done) => {
store.state.trees['abcproject/main'].loading = true;
......@@ -61,9 +68,15 @@ describe('IDE tree list', () => {
beforeEach(() => {
bootstrapWithTree(emptyBranchTree);
jest.spyOn(vm, '$emit').mockImplementation(() => {});
vm.$mount();
});
it('still emits tree-ready event', () => {
expect(vm.$emit).toHaveBeenCalledWith('tree-ready');
});
it('does not load files if the branch is empty', () => {
expect(vm.$el.textContent).not.toContain('fileName');
expect(vm.$el.textContent).toContain('No files');
......
......@@ -6,6 +6,7 @@ describe('IDE router', () => {
const PROJECT_NAMESPACE = 'my-group/sub-group';
const PROJECT_NAME = 'my-project';
const TEST_PATH = `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/2`;
const DEFAULT_BRANCH = 'default-main';
let store;
let router;
......@@ -13,34 +14,46 @@ describe('IDE router', () => {
beforeEach(() => {
window.history.replaceState({}, '', '/');
store = createStore();
router = createRouter(store);
router = createRouter(store, DEFAULT_BRANCH);
jest.spyOn(store, 'dispatch').mockReturnValue(new Promise(() => {}));
});
[
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob/`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/tree/`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/weird:branch/name-123/-/src/tree/`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/edit`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/merge_requests/2`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/blob/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit/blob/-/src/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/2`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit`,
`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
].forEach((route) => {
it(`finds project path when route is "${route}"`, () => {
router.push(route);
expect(store.dispatch).toHaveBeenCalledWith('getProjectData', {
namespace: PROJECT_NAMESPACE,
projectId: PROJECT_NAME,
});
it.each`
route | expectedBranchId | expectedBasePath
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob/`} | ${'main'} | ${'src/blob/'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob`} | ${'main'} | ${'src/blob'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob/-/src/blob`} | ${'blob'} | ${'src/blob'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/tree/`} | ${'main'} | ${'src/tree/'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/weird:branch/name-123/-/src/tree/`} | ${'weird:branch/name-123'} | ${'src/tree/'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/blob`} | ${'main'} | ${'src/blob'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/edit`} | ${'main'} | ${'src/edit'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/merge_requests/2`} | ${'main'} | ${'src/merge_requests/2'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/blob/-/src/blob`} | ${'blob'} | ${'src/blob'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit/blob/-/src/blob`} | ${'blob'} | ${'src/blob'}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob`} | ${'blob'} | ${''}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit`} | ${DEFAULT_BRANCH} | ${''}
${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}`} | ${DEFAULT_BRANCH} | ${''}
`('correctly opens Web IDE for $route', ({ route, expectedBranchId, expectedBasePath } = {}) => {
router.push(route);
expect(store.dispatch).toHaveBeenCalledWith('openBranch', {
projectId: `${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
branchId: expectedBranchId,
basePath: expectedBasePath,
});
});
it('correctly opens an MR', () => {
const expectedId = '2';
router.push(`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/${expectedId}`);
expect(store.dispatch).toHaveBeenCalledWith('openMergeRequest', {
projectId: `${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
mergeRequestId: expectedId,
targetProjectId: undefined,
});
expect(store.dispatch).not.toHaveBeenCalledWith('openBranch');
});
it('keeps router in sync when store changes', async () => {
......
......@@ -216,35 +216,6 @@ describe('IDE services', () => {
);
});
describe('getProjectData', () => {
it('combines gql and API requests', () => {
const gqlProjectData = {
id: 'gid://gitlab/Project/1',
userPermissions: {
bogus: true,
},
};
const expectedResponse = {
...projectData,
...gqlProjectData,
id: 1,
};
Api.project.mockReturnValue(Promise.resolve({ data: { ...projectData } }));
query.mockReturnValue(Promise.resolve({ data: { project: gqlProjectData } }));
return services.getProjectData(TEST_NAMESPACE, TEST_PROJECT).then((response) => {
expect(response).toEqual({ data: expectedResponse });
expect(Api.project).toHaveBeenCalledWith(TEST_PROJECT_ID);
expect(query).toHaveBeenCalledWith({
query: getIdeProject,
variables: {
projectPath: TEST_PROJECT_ID,
},
});
});
});
});
describe('getFiles', () => {
let mock;
let relativeUrlRoot;
......@@ -336,4 +307,38 @@ describe('IDE services', () => {
});
});
});
describe('getProjectPermissionsData', () => {
const TEST_PROJECT_PATH = 'foo/bar';
it('queries for the project permissions', () => {
const result = { data: { project: projectData } };
query.mockResolvedValue(result);
return services.getProjectPermissionsData(TEST_PROJECT_PATH).then((data) => {
expect(data).toEqual(result.data.project);
expect(query).toHaveBeenCalledWith(
expect.objectContaining({
query: getIdeProject,
variables: { projectPath: TEST_PROJECT_PATH },
}),
);
});
});
it('converts the returned GraphQL id to the regular ID number', () => {
const projectId = 2;
const gqlProjectData = {
id: `gid://gitlab/Project/${projectId}`,
userPermissions: {
bogus: true,
},
};
query.mockResolvedValue({ data: { project: gqlProjectData } });
return services.getProjectPermissionsData(TEST_PROJECT_PATH).then((data) => {
expect(data.id).toBe(projectId);
});
});
});
});
......@@ -2,9 +2,12 @@ import MockAdapter from 'axios-mock-adapter';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import testAction from 'helpers/vuex_action_helper';
import api from '~/api';
import createFlash from '~/flash';
import service from '~/ide/services';
import { createStore } from '~/ide/stores';
import {
setProject,
fetchProjectPermissions,
refreshLastCommitData,
showBranchNotFoundError,
createNewBranchFromDefault,
......@@ -13,8 +16,12 @@ import {
loadFile,
loadBranch,
} from '~/ide/stores/actions';
import { logError } from '~/lib/logger';
import axios from '~/lib/utils/axios_utils';
jest.mock('~/flash');
jest.mock('~/lib/logger');
const TEST_PROJECT_ID = 'abc/def';
describe('IDE store project actions', () => {
......@@ -34,6 +41,92 @@ describe('IDE store project actions', () => {
mock.restore();
});
describe('setProject', () => {
const project = { id: 'foo', path_with_namespace: TEST_PROJECT_ID };
const baseMutations = [
{
type: 'SET_PROJECT',
payload: {
projectPath: TEST_PROJECT_ID,
project,
},
},
{
type: 'SET_CURRENT_PROJECT',
payload: TEST_PROJECT_ID,
},
];
it.each`
desc | payload | expectedMutations
${'does not commit any action if project is not passed'} | ${undefined} | ${[]}
${'commits correct actions in the correct order by default'} | ${{ project }} | ${[...baseMutations]}
`('$desc', async ({ payload, expectedMutations } = {}) => {
await testAction({
action: setProject,
payload,
state: store.state,
expectedMutations,
expectedActions: [],
});
});
});
describe('fetchProjectPermissions', () => {
const permissionsData = {
userPermissions: {
bogus: true,
},
};
const permissionsMutations = [
{
type: 'UPDATE_PROJECT',
payload: {
projectPath: TEST_PROJECT_ID,
props: {
...permissionsData,
},
},
},
];
let spy;
beforeEach(() => {
spy = jest.spyOn(service, 'getProjectPermissionsData');
});
afterEach(() => {
createFlash.mockRestore();
});
it.each`
desc | projectPath | responseSuccess | expectedMutations
${'does not fetch permissions if project does not exist'} | ${undefined} | ${true} | ${[]}
${'fetches permission when project is specified'} | ${TEST_PROJECT_ID} | ${true} | ${[...permissionsMutations]}
${'flashes an error if the request fails'} | ${TEST_PROJECT_ID} | ${false} | ${[]}
`('$desc', async ({ projectPath, expectedMutations, responseSuccess } = {}) => {
store.state.currentProjectId = projectPath;
if (responseSuccess) {
spy.mockResolvedValue(permissionsData);
} else {
spy.mockRejectedValue();
}
await testAction({
action: fetchProjectPermissions,
state: store.state,
expectedMutations,
expectedActions: [],
});
if (!responseSuccess) {
expect(logError).toHaveBeenCalled();
expect(createFlash).toHaveBeenCalled();
}
});
});
describe('refreshLastCommitData', () => {
beforeEach(() => {
store.state.currentProjectId = 'abc/def';
......
......@@ -3,21 +3,48 @@ import state from '~/ide/stores/state';
describe('Multi-file store branch mutations', () => {
let localState;
const nonExistentProj = 'nonexistent';
const existingProj = 'abcproject';
beforeEach(() => {
localState = state();
localState.projects = { abcproject: { empty_repo: true } };
localState.projects = { [existingProj]: { empty_repo: true } };
});
describe('TOGGLE_EMPTY_STATE', () => {
it('sets empty_repo for project to passed value', () => {
mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: 'abcproject', value: false });
mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: existingProj, value: false });
expect(localState.projects.abcproject.empty_repo).toBe(false);
expect(localState.projects[existingProj].empty_repo).toBe(false);
mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: 'abcproject', value: true });
mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: existingProj, value: true });
expect(localState.projects.abcproject.empty_repo).toBe(true);
expect(localState.projects[existingProj].empty_repo).toBe(true);
});
});
describe('UPDATE_PROJECT', () => {
it.each`
desc | projectPath | props | expectedProps
${'extends existing project with the passed props'} | ${existingProj} | ${{ foo1: 'bar' }} | ${{ foo1: 'bar' }}
${'overrides existing props on the exsiting project'} | ${existingProj} | ${{ empty_repo: false }} | ${{ empty_repo: false }}
${'does nothing if the project does not exist'} | ${nonExistentProj} | ${{ foo2: 'bar' }} | ${undefined}
${'does nothing if project is not passed'} | ${undefined} | ${{ foo3: 'bar' }} | ${undefined}
${'does nothing if the props are not passed'} | ${existingProj} | ${undefined} | ${{}}
${'does nothing if the props are empty'} | ${existingProj} | ${{}} | ${{}}
`('$desc', ({ projectPath, props, expectedProps } = {}) => {
const origProject = localState.projects[projectPath];
mutations.UPDATE_PROJECT(localState, { projectPath, props });
if (!expectedProps) {
expect(localState.projects[projectPath]).toBeUndefined();
} else {
expect(localState.projects[projectPath]).toEqual({
...origProject,
...expectedProps,
});
}
});
});
});
......@@ -192,6 +192,13 @@ export const commit = async ({ newBranch = false, newMR = false, newBranchName =
switchLeftSidebarTab('Commit');
screen.getByTestId('begin-commit-button').click();
await waitForMonacoEditor();
const mrCheck = await screen.findByLabelText('Start a new merge request');
if (Boolean(mrCheck.checked) !== newMR) {
mrCheck.click();
}
if (!newBranch) {
const option = await screen.findByLabelText(/Commit to .+ branch/);
option.click();
......@@ -201,12 +208,9 @@ export const commit = async ({ newBranch = false, newMR = false, newBranchName =
const branchNameInput = await screen.findByTestId('ide-new-branch-name');
fireEvent.input(branchNameInput, { target: { value: newBranchName } });
const mrCheck = await screen.findByLabelText('Start a new merge request');
if (Boolean(mrCheck.checked) !== newMR) {
mrCheck.click();
}
}
screen.getByText('Commit').click();
await waitForMonacoEditor();
};
......@@ -4,16 +4,18 @@ import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { initIde } from '~/ide';
import extendStore from '~/ide/stores/extend';
import { getProject, getEmptyProject } from 'jest/../frontend_integration/test_helpers/fixtures';
import { IDE_DATASET } from './mock_data';
export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) => {
const projectName = isRepoEmpty ? 'lorem-ipsum-empty' : 'lorem-ipsum';
const pathSuffix = mrId ? `merge_requests/${mrId}` : `tree/master/-/${path}`;
const project = isRepoEmpty ? getEmptyProject() : getProject();
setWindowLocation(`${TEST_HOST}/-/ide/project/gitlab-test/${projectName}/${pathSuffix}`);
const el = document.createElement('div');
Object.assign(el.dataset, IDE_DATASET);
Object.assign(el.dataset, IDE_DATASET, { project: JSON.stringify(project) });
container.appendChild(el);
const vm = initIde(el, { extendStore });
......
......@@ -34,10 +34,10 @@ describe('IDE: User opens IDE', () => {
expect(await screen.findByText('No files')).toBeDefined();
});
it('shows a "New file" button', async () => {
const button = await screen.findByTitle('New file');
it('shows a "New file" button', () => {
const buttons = screen.queryAllByTitle('New file');
expect(button.tagName).toEqual('BUTTON');
expect(buttons.map((x) => x.tagName)).toContain('BUTTON');
});
});
......
......@@ -34,7 +34,7 @@ RSpec.describe IdeHelper do
self.instance_variable_set(:@fork_info, fork_info)
self.instance_variable_set(:@project, project)
serialized_project = API::Entities::Project.represent(project).to_json
serialized_project = API::Entities::Project.represent(project, current_user: project.creator).to_json
expect(helper.ide_data)
.to include(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment