Commit e66a0e30 authored by Paul Slaughter's avatar Paul Slaughter Committed by Alex Kalderimis

WebIDE show fork button when cannot push code

- Uses the same BE helpers that are used in the
project homepage.
- Uses a ViewModel approach, such that a getter
returns an easily consumable model so that the
cannot_push_code_alert component is trivial.
parent d3635ba2
<script>
import { GlAlert, GlButton } from '@gitlab/ui';
export default {
components: {
GlAlert,
GlButton,
},
props: {
message: {
type: String,
required: true,
},
action: {
type: Object,
required: false,
default: null,
},
},
computed: {
hasAction() {
return Boolean(this.action?.href);
},
actionButtonMethod() {
return this.action?.isForm ? 'post' : null;
},
},
};
</script>
<template>
<gl-alert :dismissible="false">
{{ message }}
<template v-if="hasAction" #actions>
<gl-button variant="confirm" :href="action.href" :data-method="actionButtonMethod">
{{ action.text }}
</gl-button>
</template>
</gl-alert>
</template>
<script>
import { GlAlert, GlButton, GlLoadingIcon } from '@gitlab/ui';
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { __ } from '~/locale';
import {
......@@ -14,6 +14,7 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { modalTypes } from '../constants';
import eventHub from '../eventhub';
import { measurePerformance } from '../utils';
import CannotPushCodeAlert from './cannot_push_code_alert.vue';
import IdeSidebar from './ide_side_bar.vue';
import RepoEditor from './repo_editor.vue';
......@@ -29,7 +30,6 @@ export default {
components: {
IdeSidebar,
RepoEditor,
GlAlert,
GlButton,
GlLoadingIcon,
ErrorMessage: () => import(/* webpackChunkName: 'ide_runtime' */ './error_message.vue'),
......@@ -41,6 +41,7 @@ export default {
import(/* webpackChunkName: 'ide_runtime' */ '~/vue_shared/components/file_finder/index.vue'),
RightPane: () => import(/* webpackChunkName: 'ide_runtime' */ './panes/right.vue'),
NewModal: () => import(/* webpackChunkName: 'ide_runtime' */ './new_dropdown/modal.vue'),
CannotPushCodeAlert,
},
mixins: [glFeatureFlagsMixin()],
data() {
......@@ -120,9 +121,11 @@ export default {
class="ide position-relative d-flex flex-column align-items-stretch"
:class="{ [`theme-${themeName}`]: themeName }"
>
<gl-alert v-if="!canPushCodeStatus.isAllowed" :dismissible="false">{{
canPushCodeStatus.message
}}</gl-alert>
<cannot-push-code-alert
v-if="!canPushCodeStatus.isAllowed"
:message="canPushCodeStatus.message"
:action="canPushCodeStatus.action"
/>
<error-message v-if="errorMessage" :message="errorMessage" />
<div class="ide-view flex-grow d-flex">
<template v-if="loadDeferred">
......
......@@ -54,6 +54,7 @@ export function initIde(el, options = {}) {
});
this.setLinks({
webIDEHelpPagePath: el.dataset.webIdeHelpPagePath,
forkInfo: el.dataset.forkInfo ? JSON.parse(el.dataset.forkInfo) : null,
});
this.setInitialData({
clientsidePreviewEnabled: parseBoolean(el.dataset.clientsidePreviewEnabled),
......
import { s__ } from '~/locale';
export const MSG_CANNOT_PUSH_CODE = s__(
export const MSG_CANNOT_PUSH_CODE_SHOULD_FORK = s__(
'WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request.',
);
export const MSG_CANNOT_PUSH_CODE_SHORT = s__(
export const MSG_CANNOT_PUSH_CODE_GO_TO_FORK = s__(
'WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request.',
);
export const MSG_CANNOT_PUSH_CODE = s__(
'WebIDE|You need permission to edit files directly in this project.',
);
......@@ -15,3 +19,7 @@ export const MSG_CANNOT_PUSH_UNSIGNED = s__(
export const MSG_CANNOT_PUSH_UNSIGNED_SHORT = s__(
'WebIDE|This project does not accept unsigned commits.',
);
export const MSG_FORK = s__('WebIDE|Fork project');
export const MSG_GO_TO_FORK = s__('WebIDE|Go to fork');
......@@ -11,12 +11,42 @@ import {
} from '../constants';
import {
MSG_CANNOT_PUSH_CODE,
MSG_CANNOT_PUSH_CODE_SHORT,
MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
MSG_CANNOT_PUSH_UNSIGNED,
MSG_CANNOT_PUSH_UNSIGNED_SHORT,
MSG_FORK,
MSG_GO_TO_FORK,
} from '../messages';
import { getChangesCountForFiles, filePathMatches } from './utils';
const getCannotPushCodeViewModel = (state) => {
const { ide_path: idePath, fork_path: forkPath } = state.links.forkInfo || {};
if (idePath) {
return {
message: MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
action: {
href: idePath,
text: MSG_GO_TO_FORK,
},
};
} else if (forkPath) {
return {
message: MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
action: {
href: forkPath,
isForm: true,
text: MSG_FORK,
},
};
}
return {
message: MSG_CANNOT_PUSH_CODE,
};
};
export const activeFile = (state) => state.openFiles.find((file) => file.active) || null;
export const addedFiles = (state) => state.changedFiles.filter((f) => f.tempFile);
......@@ -188,8 +218,8 @@ export const canPushCodeStatus = (state, getters) => {
if (!canPushCode) {
return {
isAllowed: false,
message: MSG_CANNOT_PUSH_CODE,
messageShort: MSG_CANNOT_PUSH_CODE_SHORT,
messageShort: MSG_CANNOT_PUSH_CODE,
...getCannotPushCodeViewModel(state),
};
}
......
......@@ -27,9 +27,20 @@ class IdeController < ApplicationController
@branch = params[:branch]
@path = params[:path]
@merge_request = params[:merge_request_id]
@fork_info = fork_info(project, @branch)
end
def fork_info(project, branch)
return if can?(current_user, :push_code, project)
existing_fork = current_user.fork_of(project)
unless can?(current_user, :push_code, project)
@forked_project = ForkProjectsFinder.new(project, current_user: current_user).execute.first
if existing_fork
path = helpers.ide_edit_path(existing_fork, branch, '')
{ ide_path: path }
elsif can?(current_user, :fork_project, project)
path = helpers.ide_fork_and_edit_path(project, branch, '', with_notice: false)
{ fork_path: path }
end
end
......
......@@ -41,20 +41,20 @@ module BlobHelper
result
end
def ide_fork_and_edit_path(project = @project, ref = @ref, path = @path, options = {})
fork_path_for_current_user(project, ide_edit_path(project, ref, path))
def ide_fork_and_edit_path(project = @project, ref = @ref, path = @path, with_notice: true)
fork_path_for_current_user(project, ide_edit_path(project, ref, path), with_notice: with_notice)
end
def fork_and_edit_path(project = @project, ref = @ref, path = @path, options = {})
fork_path_for_current_user(project, edit_blob_path(project, ref, path, options))
end
def fork_path_for_current_user(project, path)
def fork_path_for_current_user(project, path, with_notice: true)
return unless current_user
project_forks_path(project,
namespace_key: current_user.namespace&.id,
continue: edit_blob_fork_params(path))
continue: edit_blob_fork_params(path, with_notice: with_notice))
end
def encode_ide_path(path)
......@@ -330,12 +330,12 @@ module BlobHelper
blob if blob&.readable_text?
end
def edit_blob_fork_params(path)
def edit_blob_fork_params(path, with_notice: true)
{
to: path,
notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now
}
notice: (edit_in_new_fork_notice if with_notice),
notice_now: (edit_in_new_fork_notice_now if with_notice)
}.compact
end
def edit_modify_file_fork_params(action)
......
......@@ -16,7 +16,7 @@ module IdeHelper
'branch-name' => @branch,
'file-path' => @path,
'merge-request' => @merge_request,
'forked-project' => convert_to_project_entity_json(@forked_project),
'fork-info' => @fork_info&.to_json,
'project' => convert_to_project_entity_json(@project)
}
end
......
---
title: WebIDE show fork button when cannot push code
merge_request: 56608
author:
type: changed
......@@ -33912,6 +33912,12 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
msgid "WebIDE|Fork project"
msgstr ""
msgid "WebIDE|Go to fork"
msgstr ""
msgid "WebIDE|Merge request"
msgstr ""
......@@ -33927,6 +33933,9 @@ msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Fork this project to make your changes and submit a merge request."
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project. Go to your fork to make changes and submit a merge request."
msgstr ""
msgid "Webhook"
msgstr ""
......
import { GlButton, GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { stubComponent } from 'helpers/stub_component';
import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
const TEST_MESSAGE = 'Hello test message!';
const TEST_HREF = '/test/path/to/fork';
const TEST_BUTTON_TEXT = 'Fork text';
describe('ide/components/cannot_push_code_alert', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
});
const createComponent = (props = {}) => {
wrapper = shallowMount(CannotPushCodeAlert, {
propsData: {
message: TEST_MESSAGE,
...props,
},
stubs: {
GlAlert: {
...stubComponent(GlAlert),
template: `<div><slot></slot><slot name="actions"></slot></div>`,
},
},
});
};
const findAlert = () => wrapper.findComponent(GlAlert);
const findButtonData = () => {
const button = findAlert().findComponent(GlButton);
if (!button.exists()) {
return null;
}
return {
href: button.attributes('href'),
method: button.attributes('data-method'),
text: button.text(),
};
};
describe('without actions', () => {
beforeEach(() => {
createComponent();
});
it('shows alert with message', () => {
expect(findAlert().props()).toMatchObject({ dismissible: false });
expect(findAlert().text()).toBe(TEST_MESSAGE);
});
});
describe.each`
action | buttonData
${{}} | ${null}
${{ href: TEST_HREF, text: TEST_BUTTON_TEXT }} | ${{ href: TEST_HREF, text: TEST_BUTTON_TEXT }}
${{ href: TEST_HREF, text: TEST_BUTTON_TEXT, isForm: true }} | ${{ href: TEST_HREF, text: TEST_BUTTON_TEXT, method: 'post' }}
`('with action=$action', ({ action, buttonData }) => {
beforeEach(() => {
createComponent({ action });
});
it(`show button=${JSON.stringify(buttonData)}`, () => {
expect(findButtonData()).toEqual(buttonData);
});
});
});
......@@ -14,7 +14,7 @@ import {
createBranchChangedCommitError,
branchAlreadyExistsCommitError,
} from '~/ide/lib/errors';
import { MSG_CANNOT_PUSH_CODE_SHORT } from '~/ide/messages';
import { MSG_CANNOT_PUSH_CODE } from '~/ide/messages';
import { createStore } from '~/ide/stores';
import { COMMIT_TO_NEW_BRANCH } from '~/ide/stores/modules/commit/constants';
......@@ -85,8 +85,8 @@ describe('IDE commit form', () => {
${'when there are no changes'} | ${[]} | ${{ pushCode: true }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${''}
${'when there are changes'} | ${['test']} | ${{ pushCode: true }} | ${goToEditView} | ${findBeginCommitButtonData} | ${false} | ${''}
${'when there are changes'} | ${['test']} | ${{ pushCode: true }} | ${goToCommitView} | ${findCommitButtonData} | ${false} | ${''}
${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE_SHORT}
${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToCommitView} | ${findCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE_SHORT}
${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToEditView} | ${findBeginCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE}
${'when user cannot push'} | ${['test']} | ${{ pushCode: false }} | ${goToCommitView} | ${findCommitButtonData} | ${true} | ${MSG_CANNOT_PUSH_CODE}
`('$desc', ({ stagedFiles, userPermissions, viewFn, buttonFn, disabled, tooltip }) => {
beforeEach(async () => {
store.state.stagedFiles = stagedFiles;
......
import { GlAlert } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
import ErrorMessage from '~/ide/components/error_message.vue';
import Ide from '~/ide/components/ide.vue';
import { MSG_CANNOT_PUSH_CODE } from '~/ide/messages';
import { MSG_CANNOT_PUSH_CODE_GO_TO_FORK, MSG_GO_TO_FORK } from '~/ide/messages';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
import { projectData } from '../mock_data';
......@@ -12,14 +12,15 @@ import { projectData } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
const TEST_FORK_IDE_PATH = '/test/ide/path';
describe('WebIDE', () => {
const emptyProjData = { ...projectData, empty_repo: true, branches: {} };
let store;
let wrapper;
const createComponent = ({ projData = emptyProjData, state = {} } = {}) => {
const store = createStore();
store.state.currentProjectId = 'abcproject';
store.state.currentBranchId = 'master';
store.state.projects.abcproject = projData && { ...projData };
......@@ -37,7 +38,11 @@ describe('WebIDE', () => {
});
};
const findAlert = () => wrapper.find(GlAlert);
const findAlert = () => wrapper.findComponent(CannotPushCodeAlert);
beforeEach(() => {
store = createStore();
});
afterEach(() => {
wrapper.destroy();
......@@ -148,6 +153,12 @@ describe('WebIDE', () => {
});
it('when user cannot push code, shows alert', () => {
store.state.links = {
forkInfo: {
ide_path: TEST_FORK_IDE_PATH,
},
};
createComponent({
projData: {
userPermissions: {
......@@ -157,9 +168,12 @@ describe('WebIDE', () => {
});
expect(findAlert().props()).toMatchObject({
dismissible: false,
message: MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
action: {
href: TEST_FORK_IDE_PATH,
text: MSG_GO_TO_FORK,
},
});
expect(findAlert().text()).toBe(MSG_CANNOT_PUSH_CODE);
});
it.each`
......
......@@ -6,15 +6,20 @@ import {
} from '~/ide/constants';
import {
MSG_CANNOT_PUSH_CODE,
MSG_CANNOT_PUSH_CODE_SHORT,
MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
MSG_CANNOT_PUSH_UNSIGNED,
MSG_CANNOT_PUSH_UNSIGNED_SHORT,
MSG_FORK,
MSG_GO_TO_FORK,
} from '~/ide/messages';
import { createStore } from '~/ide/stores';
import * as getters from '~/ide/stores/getters';
import { file } from '../helpers';
const TEST_PROJECT_ID = 'test_project';
const TEST_IDE_PATH = '/test/ide/path';
const TEST_FORK_PATH = '/test/fork/path';
describe('IDE store getters', () => {
let localState;
......@@ -433,27 +438,84 @@ describe('IDE store getters', () => {
});
describe('canPushCodeStatus', () => {
it.each`
pushCode | rejectUnsignedCommits | expected
${true} | ${false} | ${{ isAllowed: true, message: '', messageShort: '' }}
${false} | ${false} | ${{ isAllowed: false, message: MSG_CANNOT_PUSH_CODE, messageShort: MSG_CANNOT_PUSH_CODE_SHORT }}
${false} | ${true} | ${{ isAllowed: false, message: MSG_CANNOT_PUSH_UNSIGNED, messageShort: MSG_CANNOT_PUSH_UNSIGNED_SHORT }}
`(
'with pushCode="$pushCode" and rejectUnsignedCommits="$rejectUnsignedCommits"',
({ pushCode, rejectUnsignedCommits, expected }) => {
localState.projects[TEST_PROJECT_ID] = {
pushRules: {
[PUSH_RULE_REJECT_UNSIGNED_COMMITS]: rejectUnsignedCommits,
it.each([
[
'when can push code, and can push unsigned commits',
{
input: { pushCode: true, rejectUnsignedCommits: false },
output: { isAllowed: true, message: '', messageShort: '' },
},
],
[
'when cannot push code, and can push unsigned commits',
{
input: { pushCode: false, rejectUnsignedCommits: false },
output: {
isAllowed: false,
message: MSG_CANNOT_PUSH_CODE,
messageShort: MSG_CANNOT_PUSH_CODE,
},
},
],
[
'when cannot push code, and has ide_path in forkInfo',
{
input: {
pushCode: false,
rejectUnsignedCommits: false,
forkInfo: { ide_path: TEST_IDE_PATH },
},
userPermissions: {
[PERMISSION_PUSH_CODE]: pushCode,
output: {
isAllowed: false,
message: MSG_CANNOT_PUSH_CODE_GO_TO_FORK,
messageShort: MSG_CANNOT_PUSH_CODE,
action: { href: TEST_IDE_PATH, text: MSG_GO_TO_FORK },
},
};
localState.currentProjectId = TEST_PROJECT_ID;
},
],
[
'when cannot push code, and has fork_path in forkInfo',
{
input: {
pushCode: false,
rejectUnsignedCommits: false,
forkInfo: { fork_path: TEST_FORK_PATH },
},
output: {
isAllowed: false,
message: MSG_CANNOT_PUSH_CODE_SHOULD_FORK,
messageShort: MSG_CANNOT_PUSH_CODE,
action: { href: TEST_FORK_PATH, text: MSG_FORK, isForm: true },
},
},
],
[
'when can push code, but cannot push unsigned commits',
{
input: { pushCode: true, rejectUnsignedCommits: true },
output: {
isAllowed: false,
message: MSG_CANNOT_PUSH_UNSIGNED,
messageShort: MSG_CANNOT_PUSH_UNSIGNED_SHORT,
},
},
],
])('%s', (testName, { input, output }) => {
const { forkInfo, rejectUnsignedCommits, pushCode } = input;
expect(localStore.getters.canPushCodeStatus).toEqual(expected);
},
);
localState.links = { forkInfo };
localState.projects[TEST_PROJECT_ID] = {
pushRules: {
[PUSH_RULE_REJECT_UNSIGNED_COMMITS]: rejectUnsignedCommits,
},
userPermissions: {
[PERMISSION_PUSH_CODE]: pushCode,
},
};
localState.currentProjectId = TEST_PROJECT_ID;
expect(localStore.getters.canPushCodeStatus).toEqual(output);
});
});
describe('canPushCode', () => {
......
......@@ -489,9 +489,18 @@ RSpec.describe BlobHelper do
expect(uri.path).to eq("/#{project.namespace.path}/#{project.path}/-/forks")
expect(params).to include("continue[to]=/-/ide/project/#{project.namespace.path}/#{project.path}/edit/master")
expect(params).to include("continue[notice]=#{edit_in_new_fork_notice}")
expect(params).to include("continue[notice_now]=#{edit_in_new_fork_notice_now}")
expect(params).to include("namespace_key=#{current_user.namespace.id}")
end
it 'does not include notice params with_notice: false' do
uri = URI(helper.ide_fork_and_edit_path(project, "master", "", with_notice: false))
expect(uri.path).to eq("/#{project.namespace.path}/#{project.path}/-/forks")
expect(CGI.unescape(uri.query)).to eq("continue[to]=/-/ide/project/#{project.namespace.path}/#{project.path}/edit/master&namespace_key=#{current_user.namespace.id}")
end
context 'when user is not logged in' do
let(:current_user) { nil }
......
......@@ -17,7 +17,7 @@ RSpec.describe IdeHelper do
'branch-name' => nil,
'file-path' => nil,
'merge-request' => nil,
'forked-project' => nil,
'fork-info' => nil,
'project' => nil
)
end
......@@ -25,10 +25,12 @@ RSpec.describe IdeHelper do
context 'when instance vars are set' do
it 'returns instance data in the hash' do
fork_info = { ide_path: '/test/ide/path' }
self.instance_variable_set(:@branch, 'master')
self.instance_variable_set(:@path, 'foo/bar')
self.instance_variable_set(:@merge_request, '1')
self.instance_variable_set(:@forked_project, project)
self.instance_variable_set(:@fork_info, fork_info)
self.instance_variable_set(:@project, project)
serialized_project = API::Entities::Project.represent(project).to_json
......@@ -38,7 +40,7 @@ RSpec.describe IdeHelper do
'branch-name' => 'master',
'file-path' => 'foo/bar',
'merge-request' => '1',
'forked-project' => serialized_project,
'fork-info' => fork_info.to_json,
'project' => serialized_project
)
end
......
......@@ -8,6 +8,7 @@ RSpec.describe IdeController do
let_it_be(:other_user) { create(:user) }
let(:user) { creator }
let(:branch) { '' }
before do
sign_in(user)
......@@ -28,24 +29,33 @@ RSpec.describe IdeController do
let(:user) { other_user }
context 'when user does not have fork' do
it 'does not instantiate forked_project instance var and return 200' do
it 'instantiates fork_info instance var with fork_path and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to eq({ fork_path: controller.helpers.ide_fork_and_edit_path(project, branch, '', with_notice: false) })
end
it 'has nil fork_info if user cannot fork' do
project.project_feature.update!(forking_access_level: ProjectFeature::DISABLED)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:fork_info)).to be_nil
end
end
context 'when user has have fork' do
let!(:fork) { fork_project(project, user, repository: true) }
context 'when user has fork' do
let!(:fork) { fork_project(project, user, repository: true, namespace: user.namespace) }
it 'instantiates forked_project instance var and return 200' do
it 'instantiates fork_info instance var with ide_path and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
expect(assigns(:forked_project)).to eq fork
expect(assigns(:fork_info)).to eq({ ide_path: controller.helpers.ide_edit_path(fork, branch, '') })
end
end
end
......@@ -61,7 +71,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
end
......@@ -76,7 +86,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
end
......@@ -91,7 +101,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
......@@ -108,55 +118,58 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
context "/-/ide/project/:project/#{action}/:branch" do
let(:route) { "/-/ide/project/#{project.full_path}/#{action}/master" }
let(:branch) { 'master' }
let(:route) { "/-/ide/project/#{project.full_path}/#{action}/#{branch}" }
it 'instantiates project and branch instance vars and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
expect(assigns(:branch)).to eq 'master'
expect(assigns(:branch)).to eq branch
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
context "/-/ide/project/:project/#{action}/:branch/-" do
let(:route) { "/-/ide/project/#{project.full_path}/#{action}/branch/slash/-" }
let(:branch) { 'branch/slash' }
let(:route) { "/-/ide/project/#{project.full_path}/#{action}/#{branch}/-" }
it 'instantiates project and branch instance vars and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
expect(assigns(:branch)).to eq 'branch/slash'
expect(assigns(:branch)).to eq branch
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to be_nil
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
context "/-/ide/project/:project/#{action}/:branch/-/:path" do
let(:route) { "/-/ide/project/#{project.full_path}/#{action}/master/-/foo/.bar" }
let(:branch) { 'master' }
let(:route) { "/-/ide/project/#{project.full_path}/#{action}/#{branch}/-/foo/.bar" }
it 'instantiates project, branch, and path instance vars and return 200' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:project)).to eq project
expect(assigns(:branch)).to eq 'master'
expect(assigns(:branch)).to eq branch
expect(assigns(:path)).to eq 'foo/.bar'
expect(assigns(:merge_request)).to be_nil
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
......@@ -179,7 +192,7 @@ RSpec.describe IdeController do
expect(assigns(:branch)).to be_nil
expect(assigns(:path)).to be_nil
expect(assigns(:merge_request)).to eq merge_request.id.to_s
expect(assigns(:forked_project)).to be_nil
expect(assigns(:fork_info)).to be_nil
end
it_behaves_like 'user cannot push code'
......
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