diff --git a/app/views/projects/merge_requests/_code_dropdown.html.haml b/app/views/projects/merge_requests/_code_dropdown.html.haml index df7baaf7102203b1fb3aad4fa52423776bb4b721..e734d011c37dc4e8eb428b49309b3fd577703b22 100644 --- a/app/views/projects/merge_requests/_code_dropdown.html.haml +++ b/app/views/projects/merge_requests/_code_dropdown.html.haml @@ -24,6 +24,7 @@ = link_to "#{Gitlab::CurrentSettings.gitpod_url}##{merge_request_url(@merge_request)}", target: '_blank', class: 'dropdown-item' do .gl-dropdown-item-text-wrapper = _('Open in Gitpod') + = render_if_exists 'projects/merge_requests/code_dropdown_open_in_workspace' %li.gl-dropdown-divider %hr.dropdown-divider %li.gl-dropdown-section-header diff --git a/ee/app/helpers/remote_development/merge_requests_helper.rb b/ee/app/helpers/remote_development/merge_requests_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..ec543aa194130855f87fbebc2fcca30490d8a1e4 --- /dev/null +++ b/ee/app/helpers/remote_development/merge_requests_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module RemoteDevelopment + module MergeRequestsHelper + extend ActiveSupport::Concern + + included do + # Creates URL to open workspace for a specific project and ref + # @param [String] project_path Path of the project of the to-be created workspace + # @param [String] ref Ref of the project that needs to be opened in the workspace + def workspace_path_with_params(project_path:, ref:) + raise unless project_path && ref + + # noinspection RubyResolve -- RubyMine can't find the helper function + "#{new_remote_development_workspace_path}?project=#{CGI.escape(project_path)}&gitRef=#{ref}" + end + end + end +end diff --git a/ee/app/views/projects/merge_requests/_code_dropdown_open_in_workspace.html.haml b/ee/app/views/projects/merge_requests/_code_dropdown_open_in_workspace.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..7b3ce3a71d0ac966a010950179b89c32b60b98ac --- /dev/null +++ b/ee/app/views/projects/merge_requests/_code_dropdown_open_in_workspace.html.haml @@ -0,0 +1,6 @@ +- return unless ::License.feature_available?(:remote_development) + +%li.gl-dropdown-item + = link_to workspace_path_with_params(project_path: @merge_request.source_project.full_path, ref: @merge_request.source_branch), target: '_blank', class: 'dropdown-item', data: { testid: 'open-in-workspace-button' } do + .gl-dropdown-item-text-wrapper + = _('Open in Workspace') diff --git a/ee/spec/features/remote_development/open_in_workspace_spec.rb b/ee/spec/features/remote_development/open_in_workspace_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..37deed1921a046e2489638a41147d572b6b4af5f --- /dev/null +++ b/ee/spec/features/remote_development/open_in_workspace_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Open in Workspace button', :js, feature_category: :workspaces do + let_it_be(:project) { create(:project, :public) } + let(:user) { project.creator } + let(:merge_request) { create(:merge_request, source_project: project) } + + before do + stub_licensed_features(remote_development: true) + sign_in(user) + end + + context 'when the user is on the Merge Request page' do + before do + visit(merge_request_path(merge_request)) + end + + it 'they should be able to click on Open in Workspace' do + within '.merge-request' do + click_button 'Code' + end + + new_tab = window_opened_by do + click_link 'Open in Workspace' + end + + switch_to_window new_tab + + wait_for_requests + + expect(page).to have_selector('.page-title.gl-text-size-h-display', text: 'New workspace') + end + end +end diff --git a/ee/spec/helpers/remote_development/merge_requests_helper_spec.rb b/ee/spec/helpers/remote_development/merge_requests_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f74e54315d9e8b61dfbcaac5295be79eabbc9bea --- /dev/null +++ b/ee/spec/helpers/remote_development/merge_requests_helper_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe RemoteDevelopment::MergeRequestsHelper, feature_category: :workspaces do + let(:project_path) { 'group/project' } + let(:ref) { 'main' } + + describe '#new_workspace_path' do + context 'when project_path and ref are provided' do + it 'returns the correct path with escaped parameters' do + # noinspection SpellCheckingInspection + expected_path = "/-/remote_development/workspaces/new?project=group%2Fproject&gitRef=main" + + expect(helper.workspace_path_with_params(project_path: project_path, ref: ref)).to eq(expected_path) + end + end + + describe 'parameter validation' do + using RSpec::Parameterized::TableSyntax + + where(:case_name, :project_path, :ref) do + 'when project_path is nil' | nil | 'main' + 'when ref is nil' | 'a/b' | nil + 'when both are nil' | nil | nil + end + + with_them do + it 'raises RuntimeError' do + expect do + helper.workspace_path_with_params(project_path: project_path, ref: ref) + end.to raise_error(RuntimeError) + end + end + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 1732abfe58b7c939f747531aca206162e96c1345..179fcc1695864bfaa0f00e0425fb39b4803f65d8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -42214,6 +42214,9 @@ msgstr "" msgid "Open in Web IDE" msgstr "" +msgid "Open in Workspace" +msgstr "" + msgid "Open in file view" msgstr ""