Skip to content
Snippets Groups Projects
Commit b3a736ed authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 5366964a
No related branches found
No related tags found
No related merge requests found
Showing
with 862 additions and 71 deletions
Loading
Loading
@@ -74,12 +74,23 @@ module Gitlab
group_params = {
name: group_hash['name'],
path: group_hash['path'],
parent_id: parent_group&.id
parent_id: parent_group&.id,
visibility_level: sub_group_visibility_level(group_hash, parent_group)
}
 
::Groups::CreateService.new(@user, group_params).execute
end
 
def sub_group_visibility_level(group_hash, parent_group)
original_visibility_level = group_hash['visibility_level'] || Gitlab::VisibilityLevel::PRIVATE
if parent_group && parent_group.visibility_level < original_visibility_level
Gitlab::VisibilityLevel.closest_allowed_level(parent_group.visibility_level)
else
original_visibility_level
end
end
def members_mapper
@members_mapper ||= Gitlab::ImportExport::MembersMapper.new(exported_members: @group_members, user: @user, importable: @group)
end
Loading
Loading
Loading
Loading
@@ -10130,6 +10130,9 @@ msgstr ""
msgid "IDE|Successful commit"
msgstr ""
 
msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
msgstr ""
msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
msgstr ""
 
Loading
Loading
@@ -17112,9 +17115,6 @@ msgstr ""
msgid "Self monitoring project does not exist"
msgstr ""
 
msgid "Self-monitoring is not enabled on this GitLab server, contact your administrator."
msgstr ""
msgid "Self-monitoring project does not exist. Please check logs for any error messages"
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -7,6 +7,14 @@ module QA
include Page::Component::ClonePanel
include Page::Project::SubMenus::Settings
 
view 'app/assets/javascripts/repository/components/table/row.vue' do
element :file_name_link
end
view 'app/assets/javascripts/repository/components/table/index.vue' do
element :file_tree_table
end
view 'app/views/layouts/header/_new_dropdown.haml' do
element :new_menu_toggle
element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern
Loading
Loading
@@ -17,7 +25,8 @@ module QA
end
 
view 'app/views/projects/_home_panel.html.haml' do
element :project_name
element :forked_from_link
element :project_name_content
end
 
view 'app/views/projects/_files.html.haml' do
Loading
Loading
@@ -37,10 +46,6 @@ module QA
element :quick_actions
end
 
view 'app/views/projects/tree/_tree_content.html.haml' do
element :file_tree
end
view 'app/views/projects/tree/_tree_header.html.haml' do
element :add_to_tree
element :new_file_option
Loading
Loading
@@ -79,14 +84,18 @@ module QA
click_on 'Fork'
end
 
def forked_from?(parent_project_name)
has_element?(:forked_from_link, text: parent_project_name)
end
def click_file(filename)
within_element(:file_tree) do
within_element(:file_tree_table) do
click_on filename
end
end
 
def click_commit(commit_msg)
within_element(:file_tree) do
within_element(:file_tree_table) do
click_on commit_msg
end
end
Loading
Loading
@@ -96,6 +105,16 @@ module QA
click_link 'New issue'
end
 
def has_file?(name)
within_element(:file_tree_table) do
has_element?(:file_name_link, text: name)
end
end
def has_name?(name)
has_element?(:project_name_content, text: name)
end
def last_commit_content
find_element(:commit_content).text
end
Loading
Loading
@@ -113,7 +132,7 @@ module QA
end
 
def project_name
find('.qa-project-name').text
find_element(:project_name_content).text
end
 
def switch_to_branch(branch_name)
Loading
Loading
Loading
Loading
@@ -8,10 +8,12 @@ module QA
module ApiFabricator
include Capybara::DSL
 
ResourceNotFoundError = Class.new(RuntimeError)
ResourceFabricationFailedError = Class.new(RuntimeError)
ResourceURLMissingError = Class.new(RuntimeError)
ResourceNotDeletedError = Class.new(RuntimeError)
ResourceNotFoundError = Class.new(RuntimeError)
ResourceQueryError = Class.new(RuntimeError)
ResourceUpdateFailedError = Class.new(RuntimeError)
ResourceURLMissingError = Class.new(RuntimeError)
 
attr_reader :api_resource, :api_response
attr_writer :api_client
Loading
Loading
Loading
Loading
@@ -3,19 +3,24 @@
module QA
module Resource
class Fork < Base
attribute :name do
upstream.name
end
attribute :project do
Resource::Project.fabricate! do |resource|
resource.name = upstream.project.name
resource.path_with_namespace = "#{user.name}/#{upstream.project.name}"
Resource::Project.fabricate_via_api! do |resource|
resource.add_name_uuid = false
resource.name = name
resource.path_with_namespace = "#{user.username}/#{name}"
end
end
 
attribute :upstream do
Repository::ProjectPush.fabricate!
Repository::ProjectPush.fabricate!.project
end
 
attribute :user do
User.fabricate! do |resource|
User.fabricate_via_api! do |resource|
if Runtime::Env.forker?
resource.username = Runtime::Env.forker_username
resource.password = Runtime::Env.forker_password
Loading
Loading
@@ -33,7 +38,7 @@ module QA
login.sign_in_using_credentials(user: user)
end
 
upstream.project.visit!
upstream.visit!
 
Page::Project::Show.perform(&:fork_project)
 
Loading
Loading
@@ -47,6 +52,41 @@ module QA
 
populate(:project)
end
def fabricate_via_api!
populate(:upstream, :user)
Runtime::Logger.debug("Forking project #{upstream.name} to namespace #{user.username}...")
super
wait_until_forked
populate(:project)
end
def api_get_path
"/projects/#{CGI.escape(path_with_namespace)}"
end
def api_post_path
"/projects/#{upstream.id}/fork"
end
def api_post_body
{
namespace: user.username,
name: name,
path: name
}
end
def wait_until_forked
Runtime::Logger.debug("Waiting for the fork process to complete...")
forked = wait_until do
project.import_status == "finished"
end
raise "Timed out while waiting for the fork process to complete." unless forked
end
end
end
end
Loading
Loading
@@ -8,7 +8,7 @@ module QA
attr_accessor :fork_branch
 
attribute :fork do
Fork.fabricate!
Fork.fabricate_via_browser_ui!
end
 
attribute :push do
Loading
Loading
Loading
Loading
@@ -94,6 +94,10 @@ module QA
"#{api_get_path}/runners"
end
 
def api_put_path
"/projects/#{id}"
end
def api_post_path
'/projects'
end
Loading
Loading
@@ -115,6 +119,35 @@ module QA
post_body
end
 
def change_repository_storage(new_storage)
put_body = { repository_storage: new_storage }
response = put Runtime::API::Request.new(api_client, api_put_path).url, put_body
unless response.code == HTTP_STATUS_OK
raise ResourceUpdateFailedError, "Could not change repository storage to #{new_storage}. Request returned (#{response.code}): `#{response}`."
end
wait_until do
reload!
api_response[:repository_storage] == new_storage
end
end
def import_status
response = get Runtime::API::Request.new(api_client, "/projects/#{id}/import").url
unless response.code == HTTP_STATUS_OK
raise ResourceQueryError, "Could not get import status. Request returned (#{response.code}): `#{response}`."
end
result = parse_body(response)
Runtime::Logger.error("Import failed: #{result[:import_error]}") if result[:import_status] == "failed"
result[:import_status]
end
def runners(tag_list: nil)
response = get Runtime::API::Request.new(api_client, "#{api_runners_path}?tag_list=#{tag_list.compact.join(',')}").url
parse_body(response)
Loading
Loading
Loading
Loading
@@ -22,6 +22,10 @@ module QA
SUPPORTED_FEATURES
end
 
def additional_repository_storage
ENV['QA_ADDITIONAL_REPOSITORY_STORAGE']
end
def admin_password
ENV['GITLAB_ADMIN_PASSWORD']
end
Loading
Loading
Loading
Loading
@@ -6,7 +6,7 @@ module QA
it 'user forks a project, submits a merge request and maintainer merges it' do
Flow::Login.sign_in
 
merge_request = Resource::MergeRequestFromFork.fabricate! do |merge_request|
merge_request = Resource::MergeRequestFromFork.fabricate_via_browser_ui! do |merge_request|
merge_request.fork_branch = 'feature-branch'
end
 
Loading
Loading
# frozen_string_literal: true
module QA
context 'Create' do
describe 'Gitaly repository storage', :orchestrated, :repository_storage, :requires_admin, quarantine: { type: :new } do
let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
let(:parent_project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'parent-project'
project.initialize_with_readme = true
end
end
let(:fork_project) do
Resource::Fork.fabricate_via_api! do |fork|
fork.user = user
fork.upstream = parent_project
end.project
end
before do
parent_project.add_member(user)
end
it 'creates a 2nd fork after moving the parent project' do
Flow::Login.sign_in(as: user)
fork_project.visit!
parent_project.change_repository_storage(QA::Runtime::Env.additional_repository_storage)
second_fork_project = Resource::Fork.fabricate_via_api! do |fork|
fork.name = "second-fork"
fork.user = user
fork.upstream = parent_project
end.project
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = second_fork_project
push.file_name = 'new_file'
push.file_content = '# This is a new file'
push.commit_message = 'Add new file'
push.new_branch = false
end.project.visit!
Page::Project::Show.perform do |show|
expect(show).to have_file('new_file')
expect(show).to have_name(second_fork_project.name)
expect(show).to be_forked_from(parent_project.name)
end
end
end
end
end
Loading
Loading
@@ -3,66 +3,96 @@
require 'spec_helper'
 
describe 'Projects > Show > Collaboration links', :js do
let(:project) { create(:project, :repository) }
using RSpec::Parameterized::TableSyntax
let(:project) { create(:project, :repository, :public) }
let(:user) { create(:user) }
 
before do
project.add_developer(user)
sign_in(user)
end
 
it 'shows all the expected links' do
visit project_path(project)
context 'with developer user' do
before do
project.add_developer(user)
end
 
# The navigation bar
page.within('.header-new') do
find('.qa-new-menu-toggle').click
it 'shows all the expected links' do
visit project_path(project)
 
aggregate_failures 'dropdown links in the navigation bar' do
expect(page).to have_link('New issue')
expect(page).to have_link('New merge request')
expect(page).to have_link('New snippet', href: new_project_snippet_path(project))
end
# The navigation bar
page.within('.header-new') do
find('.qa-new-menu-toggle').click
 
find('.qa-new-menu-toggle').click
end
aggregate_failures 'dropdown links in the navigation bar' do
expect(page).to have_link('New issue')
expect(page).to have_link('New merge request')
expect(page).to have_link('New snippet', href: new_project_snippet_path(project))
end
 
# The dropdown above the tree
page.within('.repo-breadcrumb') do
find('.qa-add-to-tree').click
find('.qa-new-menu-toggle').click
end
 
aggregate_failures 'dropdown links above the repo tree' do
expect(page).to have_link('New file')
expect(page).to have_link('Upload file')
expect(page).to have_link('New directory')
expect(page).to have_link('New branch')
expect(page).to have_link('New tag')
# The dropdown above the tree
page.within('.repo-breadcrumb') do
find('.qa-add-to-tree').click
aggregate_failures 'dropdown links above the repo tree' do
expect(page).to have_link('New file')
expect(page).to have_link('Upload file')
expect(page).to have_link('New directory')
expect(page).to have_link('New branch')
expect(page).to have_link('New tag')
end
end
# The Web IDE
expect(page).to have_link('Web IDE')
end
 
# The Web IDE
expect(page).to have_link('Web IDE')
end
it 'hides the links when the project is archived' do
project.update!(archived: true)
 
it 'hides the links when the project is archived' do
project.update!(archived: true)
visit project_path(project)
 
visit project_path(project)
page.within('.header-new') do
find('.qa-new-menu-toggle').click
 
page.within('.header-new') do
find('.qa-new-menu-toggle').click
aggregate_failures 'dropdown links' do
expect(page).not_to have_link('New issue')
expect(page).not_to have_link('New merge request')
expect(page).not_to have_link('New snippet', href: new_project_snippet_path(project))
end
 
aggregate_failures 'dropdown links' do
expect(page).not_to have_link('New issue')
expect(page).not_to have_link('New merge request')
expect(page).not_to have_link('New snippet', href: new_project_snippet_path(project))
find('.qa-new-menu-toggle').click
end
 
find('.qa-new-menu-toggle').click
expect(page).not_to have_selector('.qa-add-to-tree')
expect(page).not_to have_link('Web IDE')
end
end
 
expect(page).not_to have_selector('.qa-add-to-tree')
context "Web IDE link" do
where(:merge_requests_access_level, :user_level, :expect_ide_link) do
::ProjectFeature::DISABLED | :guest | false
::ProjectFeature::DISABLED | :developer | true
::ProjectFeature::PRIVATE | :guest | false
::ProjectFeature::PRIVATE | :developer | true
::ProjectFeature::ENABLED | :guest | true
::ProjectFeature::ENABLED | :developer | true
end
 
expect(page).not_to have_link('Web IDE')
with_them do
before do
project.project_feature.update!({ merge_requests_access_level: merge_requests_access_level })
project.add_user(user, user_level)
visit project_path(project)
end
it "updates Web IDE link" do
expect(page.has_link?('Web IDE')).to be(expect_ide_link)
end
end
end
end
{
"id": 283,
"name": "internal",
"path": "internal",
"owner_id": null,
"created_at": "2020-02-12T16:56:34.924Z",
"updated_at": "2020-02-12T16:56:38.710Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 10,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null,
"children": [
{
"id": 284,
"name": "public",
"path": "public",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 20,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
},
{
"id": 285,
"name": "internal",
"path": "internal",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 10,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
},
{
"id": 286,
"name": "private",
"path": "private",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 0,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
}
]
}
{
"id": 283,
"name": "private",
"path": "private",
"owner_id": null,
"created_at": "2020-02-12T16:56:34.924Z",
"updated_at": "2020-02-12T16:56:38.710Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 0,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null,
"children": [
{
"id": 284,
"name": "public",
"path": "public",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 20,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
},
{
"id": 285,
"name": "internal",
"path": "internal",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 10,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
},
{
"id": 286,
"name": "private",
"path": "private",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 0,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
}
]
}
{
"id": 283,
"name": "public",
"path": "public",
"owner_id": null,
"created_at": "2020-02-12T16:56:34.924Z",
"updated_at": "2020-02-12T16:56:38.710Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 20,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": null,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null,
"children": [
{
"id": 284,
"name": "public",
"path": "public",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 20,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
},
{
"id": 285,
"name": "internal",
"path": "internal",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 10,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
},
{
"id": 286,
"name": "private",
"path": "private",
"owner_id": null,
"created_at": "2020-02-12T17:33:00.575Z",
"updated_at": "2020-02-12T17:33:00.575Z",
"description": "",
"avatar": {
"url": null
},
"membership_lock": false,
"share_with_group_lock": false,
"visibility_level": 0,
"request_access_enabled": true,
"ldap_sync_status": "ready",
"ldap_sync_error": null,
"ldap_sync_last_update_at": null,
"ldap_sync_last_successful_update_at": null,
"ldap_sync_last_sync_at": null,
"lfs_enabled": null,
"parent_id": 283,
"shared_runners_minutes_limit": null,
"repository_size_limit": null,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"plan_id": null,
"project_creation_level": 2,
"trial_ends_on": null,
"file_template_project_id": null,
"custom_project_templates_group_id": null,
"auto_devops_enabled": null,
"extra_shared_runners_minutes_limit": null,
"last_ci_minutes_notification_at": null,
"last_ci_minutes_usage_notification_level": null,
"subgroup_creation_level": 1,
"emails_disabled": null,
"max_pages_size": null,
"max_artifacts_size": null,
"mentions_disabled": null
}
]
}
No preview for this file type
Loading
Loading
@@ -18,6 +18,7 @@ export const projectData = {
},
mergeRequests: {},
merge_requests_enabled: true,
userPermissions: {},
default_branch: 'master',
};
 
Loading
Loading
Loading
Loading
@@ -2,11 +2,17 @@ import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import services from '~/ide/services';
import Api from '~/api';
import gqClient from '~/ide/services/gql';
import { escapeFileUrl } from '~/lib/utils/url_utility';
import getUserPermissions from '~/ide/queries/getUserPermissions.query.graphql';
import { projectData } from '../mock_data';
 
jest.mock('~/api');
jest.mock('~/ide/services/gql');
 
const TEST_PROJECT_ID = 'alice/wonderland';
const TEST_NAMESPACE = 'alice';
const TEST_PROJECT = 'wonderland';
const TEST_PROJECT_ID = `${TEST_NAMESPACE}/${TEST_PROJECT}`;
const TEST_BRANCH = 'master-patch-123';
const TEST_COMMIT_SHA = '123456789';
const TEST_FILE_PATH = 'README2.md';
Loading
Loading
@@ -111,4 +117,27 @@ describe('IDE services', () => {
},
);
});
describe('getProjectData', () => {
it('combines gql and API requests', () => {
const gqlProjectData = {
userPermissions: {
bogus: true,
},
};
Api.project.mockReturnValue(Promise.resolve({ data: { ...projectData } }));
gqClient.query.mockReturnValue(Promise.resolve({ data: { project: gqlProjectData } }));
return services.getProjectData(TEST_NAMESPACE, TEST_PROJECT).then(response => {
expect(response).toEqual({ data: { ...projectData, ...gqlProjectData } });
expect(Api.project).toHaveBeenCalledWith(TEST_PROJECT_ID);
expect(gqClient.query).toHaveBeenCalledWith({
query: getUserPermissions,
variables: {
projectPath: TEST_PROJECT_ID,
},
});
});
});
});
});
Loading
Loading
@@ -2,6 +2,8 @@ import * as getters from '~/ide/stores/getters';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
 
const TEST_PROJECT_ID = 'test_project';
describe('IDE store getters', () => {
let localState;
let localStore;
Loading
Loading
@@ -398,4 +400,38 @@ describe('IDE store getters', () => {
},
);
});
describe('findProjectPermissions', () => {
it('returns false if project not found', () => {
expect(localStore.getters.findProjectPermissions(TEST_PROJECT_ID)).toEqual({});
});
it('finds permission in given project', () => {
const userPermissions = {
readMergeRequest: true,
createMergeRequestsIn: false,
};
localState.projects[TEST_PROJECT_ID] = { userPermissions };
expect(localStore.getters.findProjectPermissions(TEST_PROJECT_ID)).toBe(userPermissions);
});
});
describe.each`
getterName | permissionKey
${'canReadMergeRequests'} | ${'readMergeRequest'}
${'canCreateMergeRequests'} | ${'createMergeRequestIn'}
`('$getterName', ({ getterName, permissionKey }) => {
it.each([true, false])('finds permission for current project (%s)', val => {
localState.projects[TEST_PROJECT_ID] = {
userPermissions: {
[permissionKey]: val,
},
};
localState.currentProjectId = TEST_PROJECT_ID;
expect(localStore.getters[getterName]).toBe(val);
});
});
});
Loading
Loading
@@ -15,6 +15,7 @@ exports[`Repository table row component renders table row 1`] = `
<a
class="str-truncated"
data-qa-selector="file_name_link"
href="https://test.com"
>
Loading
Loading
@@ -64,6 +65,7 @@ exports[`Repository table row component renders table row for path with special
<a
class="str-truncated"
data-qa-selector="file_name_link"
href="https://test.com"
>
Loading
Loading
import Vue from 'vue';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { projectData, branches } from 'spec/ide/mock_data';
import { resetStore } from 'spec/ide/helpers';
import NewMergeRequestOption from '~/ide/components/commit_sidebar/new_merge_request_option.vue';
import store from '~/ide/stores';
import consts from '../../../../../app/assets/javascripts/ide/stores/modules/commit/constants';
import { createStore } from '~/ide/stores';
import { PERMISSION_CREATE_MR } from '~/ide/constants';
import consts from '~/ide/stores/modules/commit/constants';
 
describe('create new MR checkbox', () => {
let store;
let vm;
const setMR = () => {
vm.$store.state.currentMergeRequestId = '1';
vm.$store.state.projects[store.state.currentProjectId].mergeRequests[
Loading
Loading
@@ -15,6 +17,10 @@ describe('create new MR checkbox', () => {
] = { foo: 'bar' };
};
 
const setPermissions = permissions => {
store.state.projects[store.state.currentProjectId].userPermissions = permissions;
};
const createComponent = ({ currentBranchId = 'master', createNewBranch = false } = {}) => {
const Component = Vue.extend(NewMergeRequestOption);
 
Loading
Loading
@@ -25,20 +31,29 @@ describe('create new MR checkbox', () => {
: consts.COMMIT_TO_CURRENT_BRANCH;
 
vm.$store.state.currentBranchId = currentBranchId;
vm.$store.state.currentProjectId = 'abcproject';
 
const proj = JSON.parse(JSON.stringify(projectData));
proj.branches[currentBranchId] = branches.find(branch => branch.name === currentBranchId);
Vue.set(vm.$store.state.projects, 'abcproject', proj);
store.state.projects.abcproject.branches[currentBranchId] = branches.find(
branch => branch.name === currentBranchId,
);
 
return vm.$mount();
};
 
const findInput = () => vm.$el.querySelector('input[type="checkbox"]');
const findLabel = () => vm.$el.querySelector('.js-ide-commit-new-mr');
beforeEach(() => {
store = createStore();
store.state.currentProjectId = 'abcproject';
const proj = JSON.parse(JSON.stringify(projectData));
proj.userPermissions[PERMISSION_CREATE_MR] = true;
Vue.set(store.state.projects, 'abcproject', proj);
});
afterEach(() => {
vm.$destroy();
resetStore(vm.$store);
});
 
describe('for default branch', () => {
Loading
Loading
@@ -160,6 +175,24 @@ describe('create new MR checkbox', () => {
.then(done)
.catch(done.fail);
});
it('shows enablded checkbox', () => {
expect(findLabel().classList.contains('is-disabled')).toBe(false);
expect(findInput().disabled).toBe(false);
});
});
describe('when user cannot create MR', () => {
beforeEach(() => {
setPermissions({ [PERMISSION_CREATE_MR]: false });
createComponent({ currentBranchId: 'regular' });
});
it('disabled checkbox', () => {
expect(findLabel().classList.contains('is-disabled')).toBe(true);
expect(findInput().disabled).toBe(true);
});
});
 
it('dispatches toggleShouldCreateMR when clicking checkbox', () => {
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment