Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-14 18:09:08 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-14 18:09:08 +0300
commitb3a736ed88a1db0391cd9881e70b987bab7d89d1 (patch)
treea91ca3a06abd4c3412775ac3c49b11e3151df2be /spec
parent5366964a10484c2783a646b35a6da9eece01b242 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/projects/show/user_sees_collaboration_links_spec.rb106
-rw-r--r--spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/internal/group.json166
-rw-r--r--spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/private/group.json166
-rw-r--r--spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/public/group.json166
-rw-r--r--spec/fixtures/lsif.json.gzbin739 -> 759 bytes
-rw-r--r--spec/frontend/ide/mock_data.js1
-rw-r--r--spec/frontend/ide/services/index_spec.js31
-rw-r--r--spec/frontend/ide/stores/getters_spec.js36
-rw-r--r--spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap2
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js53
-rw-r--r--spec/javascripts/ide/components/nav_dropdown_button_spec.js104
-rw-r--r--spec/javascripts/ide/components/nav_dropdown_spec.js30
-rw-r--r--spec/javascripts/ide/stores/actions/merge_request_spec.js18
-rw-r--r--spec/javascripts/ide/stores/modules/commit/actions_spec.js5
-rw-r--r--spec/lib/gitlab/import_export/group_tree_restorer_spec.rb27
-rw-r--r--spec/lib/gitlab/import_export/group_tree_saver_spec.rb2
-rw-r--r--spec/requests/api/group_import_spec.rb36
-rw-r--r--spec/requests/api/lsif_data_spec.rb6
-rw-r--r--spec/requests/api/merge_requests_spec.rb102
-rw-r--r--spec/requests/self_monitoring_project_spec.rb24
-rw-r--r--spec/services/projects/lsif_data_service_spec.rb25
-rw-r--r--spec/support/helpers/api_helpers.rb7
-rw-r--r--spec/support/shared_examples/requests/self_monitoring_shared_examples.rb18
-rw-r--r--spec/views/projects/tree/_tree_header.html.haml_spec.rb13
24 files changed, 956 insertions, 188 deletions
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index ff133b58f89..63fcec4f9b3 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -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
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/internal/group.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/internal/group.json
new file mode 100644
index 00000000000..f747088f87e
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/internal/group.json
@@ -0,0 +1,166 @@
+{
+ "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
+ }
+ ]
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/private/group.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/private/group.json
new file mode 100644
index 00000000000..1328e596fa5
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/private/group.json
@@ -0,0 +1,166 @@
+{
+ "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
+ }
+ ]
+}
diff --git a/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/public/group.json b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/public/group.json
new file mode 100644
index 00000000000..29020e92004
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/group_exports/visibility_levels/public/group.json
@@ -0,0 +1,166 @@
+{
+ "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
+ }
+ ]
+}
diff --git a/spec/fixtures/lsif.json.gz b/spec/fixtures/lsif.json.gz
index 275a87e738b..3f74588cd7e 100644
--- a/spec/fixtures/lsif.json.gz
+++ b/spec/fixtures/lsif.json.gz
Binary files differ
diff --git a/spec/frontend/ide/mock_data.js b/spec/frontend/ide/mock_data.js
index a1b57dca6bc..472516b6a2c 100644
--- a/spec/frontend/ide/mock_data.js
+++ b/spec/frontend/ide/mock_data.js
@@ -18,6 +18,7 @@ export const projectData = {
},
mergeRequests: {},
merge_requests_enabled: true,
+ userPermissions: {},
default_branch: 'master',
};
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index 83a3cfe618b..55f174f4663 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -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';
@@ -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,
+ },
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index 21c5e886738..011be95c1d2 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -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;
@@ -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);
+ });
+ });
});
diff --git a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
index 49feae0884e..2d411fcce79 100644
--- a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
+++ b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap
@@ -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"
>
@@ -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"
>
diff --git a/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js b/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
index 02caf689c50..7c0b4000229 100644
--- a/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/new_merge_request_option_spec.js
@@ -1,13 +1,15 @@
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[
@@ -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);
@@ -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', () => {
@@ -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', () => {
diff --git a/spec/javascripts/ide/components/nav_dropdown_button_spec.js b/spec/javascripts/ide/components/nav_dropdown_button_spec.js
index 0d63869fba2..bbaf97164ea 100644
--- a/spec/javascripts/ide/components/nav_dropdown_button_spec.js
+++ b/spec/javascripts/ide/components/nav_dropdown_button_spec.js
@@ -2,62 +2,92 @@ import Vue from 'vue';
import { trimText } from 'spec/helpers/text_helper';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue';
-import store from '~/ide/stores';
-import { resetStore } from '../helpers';
+import { createStore } from '~/ide/stores';
describe('NavDropdown', () => {
const TEST_BRANCH_ID = 'lorem-ipsum-dolar';
const TEST_MR_ID = '12345';
- const Component = Vue.extend(NavDropdownButton);
+ let store;
let vm;
beforeEach(() => {
- vm = mountComponentWithStore(Component, { store });
-
- vm.$mount();
+ store = createStore();
});
afterEach(() => {
vm.$destroy();
-
- resetStore(store);
});
- it('renders empty placeholders, if state is falsey', () => {
- expect(trimText(vm.$el.textContent)).toEqual('- -');
- });
+ const createComponent = (props = {}) => {
+ vm = mountComponentWithStore(Vue.extend(NavDropdownButton), { props, store });
+ vm.$mount();
+ };
- it('renders branch name, if state has currentBranchId', done => {
- vm.$store.state.currentBranchId = TEST_BRANCH_ID;
+ const findIcon = name => vm.$el.querySelector(`.ic-${name}`);
+ const findMRIcon = () => findIcon('merge-request');
+ const findBranchIcon = () => findIcon('branch');
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} -`);
- })
- .then(done)
- .catch(done.fail);
- });
+ describe('normal', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders empty placeholders, if state is falsey', () => {
+ expect(trimText(vm.$el.textContent)).toEqual('- -');
+ });
- it('renders mr id, if state has currentMergeRequestId', done => {
- vm.$store.state.currentMergeRequestId = TEST_MR_ID;
+ it('renders branch name, if state has currentBranchId', done => {
+ vm.$store.state.currentBranchId = TEST_BRANCH_ID;
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`- !${TEST_MR_ID}`);
- })
- .then(done)
- .catch(done.fail);
+ vm.$nextTick()
+ .then(() => {
+ expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} -`);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('renders mr id, if state has currentMergeRequestId', done => {
+ vm.$store.state.currentMergeRequestId = TEST_MR_ID;
+
+ vm.$nextTick()
+ .then(() => {
+ expect(trimText(vm.$el.textContent)).toEqual(`- !${TEST_MR_ID}`);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('renders branch and mr, if state has both', done => {
+ vm.$store.state.currentBranchId = TEST_BRANCH_ID;
+ vm.$store.state.currentMergeRequestId = TEST_MR_ID;
+
+ vm.$nextTick()
+ .then(() => {
+ expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} !${TEST_MR_ID}`);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('shows icons', () => {
+ expect(findBranchIcon()).toBeTruthy();
+ expect(findMRIcon()).toBeTruthy();
+ });
});
- it('renders branch and mr, if state has both', done => {
- vm.$store.state.currentBranchId = TEST_BRANCH_ID;
- vm.$store.state.currentMergeRequestId = TEST_MR_ID;
+ describe('with showMergeRequests false', () => {
+ beforeEach(() => {
+ createComponent({ showMergeRequests: false });
+ });
+
+ it('shows single empty placeholder, if state is falsey', () => {
+ expect(trimText(vm.$el.textContent)).toEqual('-');
+ });
- vm.$nextTick()
- .then(() => {
- expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} !${TEST_MR_ID}`);
- })
- .then(done)
- .catch(done.fail);
+ it('shows only branch icon', () => {
+ expect(findBranchIcon()).toBeTruthy();
+ expect(findMRIcon()).toBe(null);
+ });
});
});
diff --git a/spec/javascripts/ide/components/nav_dropdown_spec.js b/spec/javascripts/ide/components/nav_dropdown_spec.js
index fe1d0ca371d..dfb4d03540f 100644
--- a/spec/javascripts/ide/components/nav_dropdown_spec.js
+++ b/spec/javascripts/ide/components/nav_dropdown_spec.js
@@ -3,6 +3,9 @@ import Vue from 'vue';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import store from '~/ide/stores';
import NavDropdown from '~/ide/components/nav_dropdown.vue';
+import { PERMISSION_READ_MR } from '~/ide/constants';
+
+const TEST_PROJECT_ID = 'lorem-ipsum';
describe('IDE NavDropdown', () => {
const Component = Vue.extend(NavDropdown);
@@ -10,6 +13,12 @@ describe('IDE NavDropdown', () => {
let $dropdown;
beforeEach(() => {
+ store.state.currentProjectId = TEST_PROJECT_ID;
+ Vue.set(store.state.projects, TEST_PROJECT_ID, {
+ userPermissions: {
+ [PERMISSION_READ_MR]: true,
+ },
+ });
vm = mountComponentWithStore(Component, { store });
$dropdown = $(vm.$el);
@@ -21,6 +30,9 @@ describe('IDE NavDropdown', () => {
vm.$destroy();
});
+ const findIcon = name => vm.$el.querySelector(`.ic-${name}`);
+ const findMRIcon = () => findIcon('merge-request');
+
it('renders nothing initially', () => {
expect(vm.$el).not.toContainElement('.ide-nav-form');
});
@@ -47,4 +59,22 @@ describe('IDE NavDropdown', () => {
.then(done)
.catch(done.fail);
});
+
+ it('renders merge request icon', () => {
+ expect(findMRIcon()).not.toBeNull();
+ });
+
+ describe('when user cannot read merge requests', () => {
+ beforeEach(done => {
+ store.state.projects[TEST_PROJECT_ID].userPermissions = {};
+
+ vm.$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not render merge requests', () => {
+ expect(findMRIcon()).toBeNull();
+ });
+ });
});
diff --git a/spec/javascripts/ide/stores/actions/merge_request_spec.js b/spec/javascripts/ide/stores/actions/merge_request_spec.js
index 498e5142f0c..4917984cd42 100644
--- a/spec/javascripts/ide/stores/actions/merge_request_spec.js
+++ b/spec/javascripts/ide/stores/actions/merge_request_spec.js
@@ -8,7 +8,7 @@ import actions, {
openMergeRequest,
} from '~/ide/stores/actions/merge_request';
import service from '~/ide/services';
-import { activityBarViews } from '~/ide/constants';
+import { activityBarViews, PERMISSION_READ_MR } from '~/ide/constants';
import { resetStore } from '../../helpers';
const TEST_PROJECT = 'abcproject';
@@ -23,6 +23,9 @@ describe('IDE store merge request actions', () => {
store.state.projects[TEST_PROJECT] = {
id: TEST_PROJECT_ID,
mergeRequests: {},
+ userPermissions: {
+ [PERMISSION_READ_MR]: true,
+ },
};
});
@@ -79,6 +82,19 @@ describe('IDE store merge request actions', () => {
})
.catch(done.fail);
});
+
+ it('does nothing if user cannot read MRs', done => {
+ store.state.projects[TEST_PROJECT].userPermissions[PERMISSION_READ_MR] = false;
+
+ store
+ .dispatch('getMergeRequestsForBranch', { projectId: TEST_PROJECT, branchId: 'bar' })
+ .then(() => {
+ expect(service.getProjectMergeRequests).not.toHaveBeenCalled();
+ expect(store.state.currentMergeRequestId).toBe('');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
});
describe('no merge requests for branch available case', () => {
diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
index 056822bcfe5..fb8cb300209 100644
--- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
@@ -7,7 +7,7 @@ import eventHub from '~/ide/eventhub';
import consts from '~/ide/stores/modules/commit/constants';
import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
import * as actions from '~/ide/stores/modules/commit/actions';
-import { commitActionTypes } from '~/ide/constants';
+import { commitActionTypes, PERMISSION_CREATE_MR } from '~/ide/constants';
import testAction from '../../../../helpers/vuex_action_helper';
const TEST_COMMIT_SHA = '123456789';
@@ -313,6 +313,9 @@ describe('IDE commit module actions', () => {
},
},
},
+ userPermissions: {
+ [PERMISSION_CREATE_MR]: true,
+ },
},
},
});
diff --git a/spec/lib/gitlab/import_export/group_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/group_tree_restorer_spec.rb
index 9aa9471d155..d6bda7507c6 100644
--- a/spec/lib/gitlab/import_export/group_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/group_tree_restorer_spec.rb
@@ -125,4 +125,31 @@ describe Gitlab::ImportExport::GroupTreeRestorer do
end
end
end
+
+ context 'group visibility levels' do
+ let(:user) { create(:user) }
+ let(:shared) { Gitlab::ImportExport::Shared.new(group) }
+ let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group, group_hash: nil) }
+
+ before do
+ setup_import_export_config(filepath)
+
+ group_tree_restorer.restore
+ end
+
+ shared_examples 'with visibility level' do |visibility_level, expected_visibilities|
+ context "when visibility level is #{visibility_level}" do
+ let(:group) { create(:group, visibility_level) }
+ let(:filepath) { "group_exports/visibility_levels/#{visibility_level}" }
+
+ it "imports all subgroups as #{visibility_level}" do
+ expect(group.children.map(&:visibility_level)).to eq(expected_visibilities)
+ end
+ end
+ end
+
+ include_examples 'with visibility level', :public, [20, 10, 0]
+ include_examples 'with visibility level', :private, [0, 0, 0]
+ include_examples 'with visibility level', :internal, [10, 10, 0]
+ end
end
diff --git a/spec/lib/gitlab/import_export/group_tree_saver_spec.rb b/spec/lib/gitlab/import_export/group_tree_saver_spec.rb
index d6aea8d1e69..d5ab8ca1e8d 100644
--- a/spec/lib/gitlab/import_export/group_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/group_tree_saver_spec.rb
@@ -80,7 +80,7 @@ describe Gitlab::ImportExport::GroupTreeSaver do
end
it 'saves the correct json' do
- expect(saved_group_json).to include({ 'description' => 'description', 'visibility_level' => 20 })
+ expect(saved_group_json).to include({ 'description' => 'description' })
end
it 'has milestones' do
diff --git a/spec/requests/api/group_import_spec.rb b/spec/requests/api/group_import_spec.rb
index 016ed6ff491..1594881677f 100644
--- a/spec/requests/api/group_import_spec.rb
+++ b/spec/requests/api/group_import_spec.rb
@@ -45,6 +45,14 @@ describe API::GroupImport do
expect(response).to have_gitlab_http_status(202)
end
+ it 'creates private group' do
+ expect { subject }.to change { Group.count }.by(1)
+
+ group = Group.find_by(name: 'test-import-group')
+
+ expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+
context 'when importing to a parent group' do
before do
group.add_owner(user)
@@ -59,6 +67,34 @@ describe API::GroupImport do
expect(group.children.count).to eq(1)
end
+ context 'when parent group is private or internal' do
+ let(:public_parent_group) { create(:group, :public) }
+ let(:internal_parent_group) { create(:group, :internal) }
+
+ before do
+ public_parent_group.add_owner(user)
+ internal_parent_group.add_owner(user)
+ end
+
+ it 'imports public group' do
+ params[:parent_id] = public_parent_group.id
+
+ subject
+
+ expect(response).to have_gitlab_http_status(202)
+ expect(public_parent_group.children.first.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ it 'imports internal group' do
+ params[:parent_id] = internal_parent_group.id
+
+ subject
+
+ expect(response).to have_gitlab_http_status(202)
+ expect(internal_parent_group.children.first.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
+ end
+ end
+
context 'when parent group is invalid' do
it 'returns 404 and does not create new group' do
params[:parent_id] = 99999
diff --git a/spec/requests/api/lsif_data_spec.rb b/spec/requests/api/lsif_data_spec.rb
index 2e0670ded95..214bc832cda 100644
--- a/spec/requests/api/lsif_data_spec.rb
+++ b/spec/requests/api/lsif_data_spec.rb
@@ -61,7 +61,11 @@ describe API::LsifData do
'end_line' => 8,
'start_char' => 13,
'start_line' => 8,
- 'definition_url' => project_blob_path(project, "#{commit.id}/morestrings/reverse.go", anchor: 'L5')
+ 'definition_url' => project_blob_path(project, "#{commit.id}/morestrings/reverse.go", anchor: 'L5'),
+ 'hover' => [{
+ 'language' => 'go',
+ 'value' => Gitlab::Highlight.highlight(nil, 'func Func2(i int) string', language: 'go')
+ }]
})
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 00af0937dd7..58190beb38a 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -267,8 +267,7 @@ describe API::MergeRequests do
it 'returns an array of merge requests with any label when filtering by any label' do
get api(endpoint_path, user), params: { labels: [" #{label.title} ", " #{label2.title} "] }
- expect_successful_response_with_paginated_array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response([merge_request.id])
expect(json_response.first['labels']).to eq([label2.title, label.title])
expect(json_response.first['id']).to eq(merge_request.id)
end
@@ -276,8 +275,7 @@ describe API::MergeRequests do
it 'returns an array of merge requests with any label when filtering by any label' do
get api(endpoint_path, user), params: { labels: ["#{label.title} , #{label2.title}"] }
- expect_successful_response_with_paginated_array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response([merge_request.id])
expect(json_response.first['labels']).to eq([label2.title, label.title])
expect(json_response.first['id']).to eq(merge_request.id)
end
@@ -285,17 +283,16 @@ describe API::MergeRequests do
it 'returns an array of merge requests with any label when filtering by any label' do
get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_ANY }
- expect_successful_response_with_paginated_array
- expect(json_response.length).to eq(1)
+ expect_paginated_array_response([merge_request.id])
expect(json_response.first['id']).to eq(merge_request.id)
end
it 'returns an array of merge requests without a label when filtering by no label' do
get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_NONE }
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id, merge_request_closed.id
- ])
+ )
end
end
@@ -315,7 +312,7 @@ describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([mr2.id])
+ expect_response_contain_exactly(mr2.id)
end
context 'with ordering' do
@@ -413,9 +410,9 @@ describe API::MergeRequests do
it 'returns merge requests with the given source branch' do
get api(endpoint_path, user), params: { source_branch: merge_request_closed.source_branch, state: 'all' }
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id, merge_request_closed.id
- ])
+ )
end
end
@@ -423,9 +420,9 @@ describe API::MergeRequests do
it 'returns merge requests with the given target branch' do
get api(endpoint_path, user), params: { target_branch: merge_request_closed.target_branch, state: 'all' }
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id, merge_request_closed.id
- ])
+ )
end
end
end
@@ -448,10 +445,10 @@ describe API::MergeRequests do
it 'returns an array of all merge requests' do
get api('/merge_requests', user), params: { scope: 'all' }
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id,
merge_request_closed.id, merge_request.id
- ])
+ )
end
it "returns authentication error without any scope" do
@@ -487,9 +484,10 @@ describe API::MergeRequests do
it 'returns an array of all merge requests except unauthorized ones' do
get api('/merge_requests', user), params: { scope: :all }
- expect_paginated_array_response([
- merge_request_merged.id, merge_request2.id, merge_request_locked.id, merge_request_closed.id, merge_request.id
- ])
+ expect_response_contain_exactly(
+ merge_request_merged.id, merge_request2.id, merge_request_locked.id,
+ merge_request_closed.id, merge_request.id
+ )
end
it "returns an array of no merge_requests when wip=yes" do
@@ -501,9 +499,10 @@ describe API::MergeRequests do
it "returns an array of no merge_requests when wip=no" do
get api("/merge_requests", user), params: { wip: 'no' }
- expect_paginated_array_response([
- merge_request_merged.id, merge_request2.id, merge_request_locked.id, merge_request_closed.id, merge_request.id
- ])
+ expect_response_contain_exactly(
+ merge_request_merged.id, merge_request2.id, merge_request_locked.id,
+ merge_request_closed.id, merge_request.id
+ )
end
it 'does not return unauthorized merge requests' do
@@ -512,9 +511,10 @@ describe API::MergeRequests do
get api('/merge_requests', user), params: { scope: :all }
- expect_paginated_array_response([
- merge_request_merged.id, merge_request2.id, merge_request_locked.id, merge_request_closed.id, merge_request.id
- ])
+ expect_response_contain_exactly(
+ merge_request_merged.id, merge_request2.id, merge_request_locked.id,
+ merge_request_closed.id, merge_request.id
+ )
expect(json_response.map { |mr| mr['id'] }).not_to include(merge_request3.id)
end
@@ -523,7 +523,7 @@ describe API::MergeRequests do
get api('/merge_requests', user2)
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns an array of merge requests authored by the given user' do
@@ -531,7 +531,7 @@ describe API::MergeRequests do
get api('/merge_requests', user), params: { author_id: user2.id, scope: :all }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns an array of merge requests assigned to the given user' do
@@ -539,7 +539,7 @@ describe API::MergeRequests do
get api('/merge_requests', user), params: { assignee_id: user2.id, scope: :all }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns an array of merge requests with no assignee' do
@@ -547,7 +547,7 @@ describe API::MergeRequests do
get api('/merge_requests', user), params: { assignee_id: 'None', scope: :all }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns an array of merge requests with any assignee' do
@@ -556,10 +556,10 @@ describe API::MergeRequests do
get api('/merge_requests', user), params: { assignee_id: 'Any', scope: :all }
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request2.id, merge_request_locked.id,
merge_request_closed.id, merge_request.id
- ])
+ )
end
it 'returns an array of merge requests assigned to me' do
@@ -567,7 +567,7 @@ describe API::MergeRequests do
get api('/merge_requests', user2), params: { scope: 'assigned_to_me' }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns an array of merge requests assigned to me (kebab-case)' do
@@ -575,7 +575,7 @@ describe API::MergeRequests do
get api('/merge_requests', user2), params: { scope: 'assigned-to-me' }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns an array of merge requests created by me' do
@@ -583,7 +583,7 @@ describe API::MergeRequests do
get api('/merge_requests', user2), params: { scope: 'created_by_me' }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns an array of merge requests created by me (kebab-case)' do
@@ -591,7 +591,7 @@ describe API::MergeRequests do
get api('/merge_requests', user2), params: { scope: 'created-by-me' }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
it 'returns merge requests reacted by the authenticated user by the given emoji' do
@@ -600,16 +600,16 @@ describe API::MergeRequests do
get api('/merge_requests', user2), params: { my_reaction_emoji: award_emoji.name, scope: 'all' }
- expect_paginated_array_response([merge_request3.id])
+ expect_response_contain_exactly(merge_request3.id)
end
context 'source_branch param' do
it 'returns merge requests with the given source branch' do
get api('/merge_requests', user), params: { source_branch: merge_request_closed.source_branch, state: 'all' }
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id, merge_request_closed.id
- ])
+ )
end
end
@@ -617,9 +617,9 @@ describe API::MergeRequests do
it 'returns merge requests with the given target branch' do
get api('/merge_requests', user), params: { target_branch: merge_request_closed.target_branch, state: 'all' }
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id, merge_request_closed.id
- ])
+ )
end
end
@@ -628,7 +628,7 @@ describe API::MergeRequests do
get api('/merge_requests?created_before=2000-01-02T00:00:00.060Z', user)
- expect_paginated_array_response([merge_request2.id])
+ expect_response_contain_exactly(merge_request2.id)
end
it 'returns merge requests created after a specific date' do
@@ -636,7 +636,7 @@ describe API::MergeRequests do
get api("/merge_requests?created_after=#{merge_request2.created_at}", user)
- expect_paginated_array_response([merge_request2.id])
+ expect_response_contain_exactly(merge_request2.id)
end
it 'returns merge requests updated before a specific date' do
@@ -644,7 +644,7 @@ describe API::MergeRequests do
get api('/merge_requests?updated_before=2000-01-02T00:00:00.060Z', user)
- expect_paginated_array_response([merge_request2.id])
+ expect_response_contain_exactly(merge_request2.id)
end
it 'returns merge requests updated after a specific date' do
@@ -652,7 +652,7 @@ describe API::MergeRequests do
get api("/merge_requests?updated_after=#{merge_request2.updated_at}", user)
- expect_paginated_array_response([merge_request2.id])
+ expect_response_contain_exactly(merge_request2.id)
end
context 'search params' do
@@ -663,13 +663,13 @@ describe API::MergeRequests do
it 'returns merge requests matching given search string for title' do
get api("/merge_requests", user), params: { search: merge_request.title }
- expect_paginated_array_response([merge_request.id])
+ expect_response_contain_exactly(merge_request.id)
end
it 'returns merge requests matching given search string for title and scoped in title' do
get api("/merge_requests", user), params: { search: merge_request.title, in: 'title' }
- expect_paginated_array_response([merge_request.id])
+ expect_response_contain_exactly(merge_request.id)
end
it 'returns an empty array if no merge request matches given search string for description and scoped in title' do
@@ -681,7 +681,7 @@ describe API::MergeRequests do
it 'returns merge requests for project matching given search string for description' do
get api("/merge_requests", user), params: { project_id: project.id, search: merge_request.description }
- expect_paginated_array_response([merge_request.id])
+ expect_response_contain_exactly(merge_request.id)
end
end
@@ -689,7 +689,7 @@ describe API::MergeRequests do
it 'returns merge requests with the given state' do
get api('/merge_requests', user), params: { state: 'locked' }
- expect_paginated_array_response([merge_request_locked.id])
+ expect_response_contain_exactly(merge_request_locked.id)
end
end
end
@@ -792,10 +792,10 @@ describe API::MergeRequests do
it 'returns an array excluding merge_requests from archived projects' do
get api(endpoint_path, user)
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_locked.id,
merge_request_closed.id, merge_request.id
- ])
+ )
end
context 'with non_archived param set as false' do
@@ -804,10 +804,10 @@ describe API::MergeRequests do
get api(path, user)
- expect_paginated_array_response([
+ expect_response_contain_exactly(
merge_request_merged.id, merge_request_archived.id, merge_request_locked.id,
merge_request_closed.id, merge_request.id
- ])
+ )
end
end
end
diff --git a/spec/requests/self_monitoring_project_spec.rb b/spec/requests/self_monitoring_project_spec.rb
index 5e46645e7a0..6a0258c349f 100644
--- a/spec/requests/self_monitoring_project_spec.rb
+++ b/spec/requests/self_monitoring_project_spec.rb
@@ -17,11 +17,7 @@ describe 'Self-Monitoring project requests' do
login_as(admin)
end
- context 'with feature flag disabled' do
- it_behaves_like 'not accessible if feature flag is disabled'
- end
-
- context 'with feature flag enabled' do
+ context 'when the self monitoring project is created' do
let(:status_api) { status_create_self_monitoring_project_admin_application_settings_path }
it_behaves_like 'triggers async worker, returns sidekiq job_id with response accepted'
@@ -45,11 +41,7 @@ describe 'Self-Monitoring project requests' do
login_as(admin)
end
- context 'with feature flag disabled' do
- it_behaves_like 'not accessible if feature flag is disabled'
- end
-
- context 'with feature flag enabled' do
+ context 'when the self monitoring project is being created' do
it_behaves_like 'handles invalid job_id'
context 'when job is in progress' do
@@ -129,11 +121,7 @@ describe 'Self-Monitoring project requests' do
login_as(admin)
end
- context 'with feature flag disabled' do
- it_behaves_like 'not accessible if feature flag is disabled'
- end
-
- context 'with feature flag enabled' do
+ context 'when the self monitoring project is deleted' do
let(:status_api) { status_delete_self_monitoring_project_admin_application_settings_path }
it_behaves_like 'triggers async worker, returns sidekiq job_id with response accepted'
@@ -157,11 +145,7 @@ describe 'Self-Monitoring project requests' do
login_as(admin)
end
- context 'with feature flag disabled' do
- it_behaves_like 'not accessible if feature flag is disabled'
- end
-
- context 'with feature flag enabled' do
+ context 'when the self monitoring project is being deleted' do
it_behaves_like 'handles invalid job_id'
context 'when job is in progress' do
diff --git a/spec/services/projects/lsif_data_service_spec.rb b/spec/services/projects/lsif_data_service_spec.rb
index 29a99a96c41..93579869d1d 100644
--- a/spec/services/projects/lsif_data_service_spec.rb
+++ b/spec/services/projects/lsif_data_service_spec.rb
@@ -12,6 +12,10 @@ describe Projects::LsifDataService do
let(:service) { described_class.new(artifact.file, project, params) }
describe '#execute' do
+ def highlighted_value(value)
+ [{ language: 'go', value: Gitlab::Highlight.highlight(nil, value, language: 'go') }]
+ end
+
context 'fetched lsif file', :use_clean_rails_memory_store_caching do
it 'is cached' do
service.execute
@@ -32,42 +36,48 @@ describe Projects::LsifDataService do
end_line: 6,
start_char: 5,
start_line: 6,
- definition_url: "#{path_prefix}/main.go#L7"
+ definition_url: "#{path_prefix}/main.go#L7",
+ hover: highlighted_value('func main()')
},
{
end_char: 36,
end_line: 3,
start_char: 1,
start_line: 3,
- definition_url: "#{path_prefix}/main.go#L4"
+ definition_url: "#{path_prefix}/main.go#L4",
+ hover: highlighted_value('package "github.com/user/hello/morestrings" ("github.com/user/hello/morestrings")')
},
{
end_char: 12,
end_line: 7,
start_char: 1,
start_line: 7,
- definition_url: "#{path_prefix}/main.go#L4"
+ definition_url: "#{path_prefix}/main.go#L4",
+ hover: highlighted_value('package "github.com/user/hello/morestrings" ("github.com/user/hello/morestrings")')
},
{
end_char: 20,
end_line: 7,
start_char: 13,
start_line: 7,
- definition_url: "#{path_prefix}/morestrings/reverse.go#L11"
+ definition_url: "#{path_prefix}/morestrings/reverse.go#L11",
+ hover: highlighted_value('func Reverse(s string) string') + [{ value: "This method reverses a string \n\n" }]
},
{
end_char: 12,
end_line: 8,
start_char: 1,
start_line: 8,
- definition_url: "#{path_prefix}/main.go#L4"
+ definition_url: "#{path_prefix}/main.go#L4",
+ hover: highlighted_value('package "github.com/user/hello/morestrings" ("github.com/user/hello/morestrings")')
},
{
end_char: 18,
end_line: 8,
start_char: 13,
start_line: 8,
- definition_url: "#{path_prefix}/morestrings/reverse.go#L5"
+ definition_url: "#{path_prefix}/morestrings/reverse.go#L5",
+ hover: highlighted_value('func Func2(i int) string')
}
])
end
@@ -82,7 +92,8 @@ describe Projects::LsifDataService do
end_line: 11,
start_char: 1,
start_line: 11,
- definition_url: "/#{project.full_path}/-/blob/#{commit_id}/morestrings/reverse.go#L12"
+ definition_url: "/#{project.full_path}/-/blob/#{commit_id}/morestrings/reverse.go#L12",
+ hover: highlighted_value('var a string')
})
end
end
diff --git a/spec/support/helpers/api_helpers.rb b/spec/support/helpers/api_helpers.rb
index 44c38df71b0..dc263d64bcc 100644
--- a/spec/support/helpers/api_helpers.rb
+++ b/spec/support/helpers/api_helpers.rb
@@ -58,6 +58,13 @@ module ApiHelpers
expect(json_response.map { |item| item['id'] }).to eq(Array(items))
end
+ def expect_response_contain_exactly(*items)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(items.size)
+ expect(json_response.map { |item| item['id'] }).to contain_exactly(*items)
+ end
+
def stub_last_activity_update
allow_any_instance_of(Users::ActivityService).to receive(:execute)
end
diff --git a/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb b/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb
index f6cb2555450..db11b1fe07d 100644
--- a/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb
+++ b/spec/support/shared_examples/requests/self_monitoring_shared_examples.rb
@@ -1,23 +1,5 @@
# frozen_string_literal: true
-RSpec.shared_examples 'not accessible if feature flag is disabled' do
- before do
- stub_feature_flags(self_monitoring_project: false)
- end
-
- it 'returns not_implemented' do
- subject
-
- aggregate_failures do
- expect(response).to have_gitlab_http_status(:not_implemented)
- expect(json_response).to eq(
- 'message' => _('Self-monitoring is not enabled on this GitLab server, contact your administrator.'),
- 'documentation_url' => help_page_path('administration/monitoring/gitlab_self_monitoring_project/index')
- )
- end
- end
-end
-
RSpec.shared_examples 'not accessible to non-admin users' do
context 'with unauthenticated user' do
it 'redirects to signin page' do
diff --git a/spec/views/projects/tree/_tree_header.html.haml_spec.rb b/spec/views/projects/tree/_tree_header.html.haml_spec.rb
index caf8c4d1969..69ad331f880 100644
--- a/spec/views/projects/tree/_tree_header.html.haml_spec.rb
+++ b/spec/views/projects/tree/_tree_header.html.haml_spec.rb
@@ -19,12 +19,12 @@ describe 'projects/tree/_tree_header' do
allow(view).to receive(:can_collaborate_with_project?) { true }
end
- it 'does not render the WebIDE button when user cannot create fork or cannot open MR' do
+ it 'renders the WebIDE button when user can collaborate but not create fork or MR' do
allow(view).to receive(:can?) { false }
render
- expect(rendered).not_to have_link('Web IDE')
+ expect(rendered).to have_link('Web IDE')
end
it 'renders the WebIDE button when user can create fork and can open MR in project' do
@@ -43,4 +43,13 @@ describe 'projects/tree/_tree_header' do
expect(rendered).to have_link('Web IDE', href: '#modal-confirm-fork')
end
+
+ it 'does not render the WebIDE button when user cannot collaborate or create mr' do
+ allow(view).to receive(:can?) { false }
+ allow(view).to receive(:can_collaborate_with_project?) { false }
+
+ render
+
+ expect(rendered).not_to have_link('Web IDE')
+ end
end