summaryrefslogtreecommitdiff
path: root/spec/requests/api
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/api')
-rw-r--r--spec/requests/api/admin/instance_clusters_spec.rb13
-rw-r--r--spec/requests/api/ci/runner/jobs_artifacts_spec.rb2
-rw-r--r--spec/requests/api/features_spec.rb166
-rw-r--r--spec/requests/api/go_proxy_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/add_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/releases/update_spec.rb255
-rw-r--r--spec/requests/api/group_clusters_spec.rb12
-rw-r--r--spec/requests/api/project_clusters_spec.rb12
-rw-r--r--spec/requests/api/usage_data_spec.rb81
-rw-r--r--spec/requests/api/users_spec.rb92
11 files changed, 577 insertions, 66 deletions
diff --git a/spec/requests/api/admin/instance_clusters_spec.rb b/spec/requests/api/admin/instance_clusters_spec.rb
index 1052080aad4..ab3b6b718e1 100644
--- a/spec/requests/api/admin/instance_clusters_spec.rb
+++ b/spec/requests/api/admin/instance_clusters_spec.rb
@@ -90,6 +90,8 @@ RSpec.describe ::API::Admin::InstanceClusters do
expect(json_response['environment_scope']).to eq('*')
expect(json_response['cluster_type']).to eq('instance_type')
expect(json_response['domain']).to eq('example.com')
+ expect(json_response['enabled']).to be_truthy
+ expect(json_response['managed']).to be_truthy
end
it 'returns kubernetes platform information' do
@@ -163,6 +165,7 @@ RSpec.describe ::API::Admin::InstanceClusters do
name: 'test-instance-cluster',
domain: 'domain.example.com',
managed: false,
+ enabled: false,
namespace_per_environment: false,
platform_kubernetes_attributes: platform_kubernetes_attributes,
clusterable: clusterable
@@ -205,9 +208,9 @@ RSpec.describe ::API::Admin::InstanceClusters do
expect(cluster_result.name).to eq('test-instance-cluster')
expect(cluster_result.domain).to eq('domain.example.com')
expect(cluster_result.environment_scope).to eq('*')
- expect(cluster_result.enabled).to eq(true)
- expect(platform_kubernetes.authorization_type).to eq('rbac')
expect(cluster_result.managed).to be_falsy
+ expect(cluster_result.enabled).to be_falsy
+ expect(platform_kubernetes.authorization_type).to eq('rbac')
expect(cluster_result.namespace_per_environment).to eq(false)
expect(platform_kubernetes.api_url).to eq("https://example.com")
expect(platform_kubernetes.token).to eq('sample-token')
@@ -301,6 +304,8 @@ RSpec.describe ::API::Admin::InstanceClusters do
let(:update_params) do
{
domain: domain,
+ managed: false,
+ enabled: false,
platform_kubernetes_attributes: platform_kubernetes_attributes
}
end
@@ -326,6 +331,8 @@ RSpec.describe ::API::Admin::InstanceClusters do
it 'updates cluster attributes' do
expect(cluster.domain).to eq('new-domain.com')
+ expect(cluster.managed).to be_falsy
+ expect(cluster.enabled).to be_falsy
end
end
@@ -338,6 +345,8 @@ RSpec.describe ::API::Admin::InstanceClusters do
it 'does not update cluster attributes' do
expect(cluster.domain).to eq('old-domain.com')
+ expect(cluster.managed).to be_truthy
+ expect(cluster.enabled).to be_truthy
end
it 'returns validation errors' do
diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
index 71be0c30f5a..4d8da50f8f0 100644
--- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
@@ -242,7 +242,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
}
expect { authorize_artifacts_with_token_in_headers(artifact_type: :lsif) }
- .to change { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(tracking_params) }
+ .to change { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(**tracking_params) }
.by(1)
end
end
diff --git a/spec/requests/api/features_spec.rb b/spec/requests/api/features_spec.rb
index 3f443b4f92b..acc49768545 100644
--- a/spec/requests/api/features_spec.rb
+++ b/spec/requests/api/features_spec.rb
@@ -6,6 +6,18 @@ RSpec.describe API::Features, stub_feature_flags: false do
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
+ # Find any `development` feature flag name
+ let(:known_feature_flag) do
+ Feature::Definition.definitions
+ .values.find(&:development?)
+ end
+
+ let(:known_feature_flag_definition_hash) do
+ a_hash_including(
+ 'type' => 'development'
+ )
+ end
+
before do
Feature.reset
Flipper.unregister_groups
@@ -22,12 +34,14 @@ RSpec.describe API::Features, stub_feature_flags: false do
{
'name' => 'feature_1',
'state' => 'on',
- 'gates' => [{ 'key' => 'boolean', 'value' => true }]
+ 'gates' => [{ 'key' => 'boolean', 'value' => true }],
+ 'definition' => nil
},
{
'name' => 'feature_2',
'state' => 'off',
- 'gates' => [{ 'key' => 'boolean', 'value' => false }]
+ 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'definition' => nil
},
{
'name' => 'feature_3',
@@ -35,7 +49,14 @@ RSpec.describe API::Features, stub_feature_flags: false do
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'groups', 'value' => ['perf_team'] }
- ]
+ ],
+ 'definition' => nil
+ },
+ {
+ 'name' => known_feature_flag.name,
+ 'state' => 'on',
+ 'gates' => [{ 'key' => 'boolean', 'value' => true }],
+ 'definition' => known_feature_flag_definition_hash
}
]
end
@@ -44,6 +65,7 @@ RSpec.describe API::Features, stub_feature_flags: false do
Feature.enable('feature_1')
Feature.disable('feature_2')
Feature.enable('feature_3', Feature.group(:perf_team))
+ Feature.enable(known_feature_flag.name)
end
it 'returns a 401 for anonymous users' do
@@ -67,7 +89,7 @@ RSpec.describe API::Features, stub_feature_flags: false do
end
describe 'POST /feature' do
- let(:feature_name) { 'my_feature' }
+ let(:feature_name) { known_feature_flag.name }
context 'when the feature does not exist' do
it 'returns a 401 for anonymous users' do
@@ -87,43 +109,49 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'true' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'on',
- 'gates' => [{ 'key' => 'boolean', 'value' => true }])
+ 'gates' => [{ 'key' => 'boolean', 'value' => true }],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'creates an enabled feature for the given Flipper group when passed feature_group=perf_team' do
post api("/features/#{feature_name}", admin), params: { value: 'true', feature_group: 'perf_team' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'groups', 'value' => ['perf_team'] }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'creates an enabled feature for the given user when passed user=username' do
post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'actors', 'value' => ["User:#{user.id}"] }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'creates an enabled feature for the given user and feature group when passed user=username and feature_group=perf_team' do
post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username, feature_group: 'perf_team' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response['name']).to eq('my_feature')
+ expect(json_response['name']).to eq(feature_name)
expect(json_response['state']).to eq('conditional')
expect(json_response['gates']).to contain_exactly(
{ 'key' => 'boolean', 'value' => false },
@@ -141,13 +169,15 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'true', project: project.full_path }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'actors', 'value' => ["Project:#{project.id}"] }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
end
@@ -156,12 +186,13 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'true', project: 'mep/to/the/mep/mep' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- "name" => "my_feature",
+ expect(json_response).to match(
+ "name" => feature_name,
"state" => "off",
"gates" => [
{ "key" => "boolean", "value" => false }
- ]
+ ],
+ 'definition' => known_feature_flag_definition_hash
)
end
end
@@ -175,13 +206,15 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'true', group: group.full_path }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'actors', 'value' => ["Group:#{group.id}"] }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
end
@@ -190,12 +223,13 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'true', group: 'not/a/group' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- "name" => "my_feature",
+ expect(json_response).to match(
+ "name" => feature_name,
"state" => "off",
"gates" => [
{ "key" => "boolean", "value" => false }
- ]
+ ],
+ 'definition' => known_feature_flag_definition_hash
)
end
end
@@ -205,26 +239,30 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: '50' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'percentage_of_time', 'value' => 50 }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'creates a feature with the given percentage of actors if passed an integer' do
post api("/features/#{feature_name}", admin), params: { value: '50', key: 'percentage_of_actors' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'percentage_of_actors', 'value' => 50 }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
end
@@ -238,36 +276,42 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'true' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'on',
- 'gates' => [{ 'key' => 'boolean', 'value' => true }])
+ 'gates' => [{ 'key' => 'boolean', 'value' => true }],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'enables the feature for the given Flipper group when passed feature_group=perf_team' do
post api("/features/#{feature_name}", admin), params: { value: 'true', feature_group: 'perf_team' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'groups', 'value' => ['perf_team'] }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'enables the feature for the given user when passed user=username' do
post api("/features/#{feature_name}", admin), params: { value: 'true', user: user.username }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'actors', 'value' => ["User:#{user.id}"] }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
end
@@ -279,10 +323,12 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'false' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'off',
- 'gates' => [{ 'key' => 'boolean', 'value' => false }])
+ 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'disables the feature for the given Flipper group when passed feature_group=perf_team' do
@@ -292,10 +338,12 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'false', feature_group: 'perf_team' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'off',
- 'gates' => [{ 'key' => 'boolean', 'value' => false }])
+ 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
it 'disables the feature for the given user when passed user=username' do
@@ -305,10 +353,12 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: 'false', user: user.username }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'off',
- 'gates' => [{ 'key' => 'boolean', 'value' => false }])
+ 'gates' => [{ 'key' => 'boolean', 'value' => false }],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
end
@@ -321,13 +371,15 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: '30' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'percentage_of_time', 'value' => 30 }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
end
@@ -340,13 +392,15 @@ RSpec.describe API::Features, stub_feature_flags: false do
post api("/features/#{feature_name}", admin), params: { value: '74', key: 'percentage_of_actors' }
expect(response).to have_gitlab_http_status(:created)
- expect(json_response).to eq(
- 'name' => 'my_feature',
+ expect(json_response).to match(
+ 'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'percentage_of_actors', 'value' => 74 }
- ])
+ ],
+ 'definition' => known_feature_flag_definition_hash
+ )
end
end
end
diff --git a/spec/requests/api/go_proxy_spec.rb b/spec/requests/api/go_proxy_spec.rb
index 9d422ebbce2..d45e24241b2 100644
--- a/spec/requests/api/go_proxy_spec.rb
+++ b/spec/requests/api/go_proxy_spec.rb
@@ -428,7 +428,7 @@ RSpec.describe API::GoProxy do
context 'with a non-existent project' do
def get_resource(user = nil, **params)
- get api("/projects/not%2fa%2fproject/packages/go/#{base}/@v/list", user, params)
+ get api("/projects/not%2fa%2fproject/packages/go/#{base}/@v/list", user, **params)
end
describe 'GET /projects/:id/packages/go/*module_name/@v/list' do
@@ -465,7 +465,7 @@ RSpec.describe API::GoProxy do
end
def get_resource(user = nil, headers: {}, **params)
- get api("/projects/#{project.id}/packages/go/#{module_name}/@v/#{resource}", user, params), headers: headers
+ get api("/projects/#{project.id}/packages/go/#{module_name}/@v/#{resource}", user, **params), headers: headers
end
def fmt_pseudo_version(prefix, commit)
diff --git a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
index 3aaebb5095a..b39062f2e71 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
@@ -56,10 +56,10 @@ RSpec.describe 'Adding an AwardEmoji' do
it_behaves_like 'a mutation that does not create an AwardEmoji'
it_behaves_like 'a mutation that returns top-level errors',
- errors: ['Cannot award emoji to this resource']
+ errors: ['You cannot award emoji to this resource.']
end
- context 'when the given awardable an Awardable' do
+ context 'when the given awardable is an Awardable' do
it 'creates an emoji' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
index 6910ad80a11..170e7ff3b44 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe 'Toggling an AwardEmoji' do
it_behaves_like 'a mutation that does not create or destroy an AwardEmoji'
it_behaves_like 'a mutation that returns top-level errors',
- errors: ['Cannot award emoji to this resource']
+ errors: ['You cannot award emoji to this resource.']
end
context 'when the given awardable is an Awardable' do
diff --git a/spec/requests/api/graphql/mutations/releases/update_spec.rb b/spec/requests/api/graphql/mutations/releases/update_spec.rb
new file mode 100644
index 00000000000..19320c3393c
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/releases/update_spec.rb
@@ -0,0 +1,255 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Updating an existing release' do
+ include GraphqlHelpers
+ include Presentable
+
+ let_it_be(:public_user) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:milestone_12_3) { create(:milestone, project: project, title: '12.3') }
+ let_it_be(:milestone_12_4) { create(:milestone, project: project, title: '12.4') }
+
+ let_it_be(:tag_name) { 'v1.1.0' }
+ let_it_be(:name) { 'Version 7.12.5'}
+ let_it_be(:description) { 'Release 7.12.5 :rocket:' }
+ let_it_be(:released_at) { '2018-12-10' }
+ let_it_be(:created_at) { '2018-11-05' }
+ let_it_be(:milestones) { [milestone_12_3, milestone_12_4] }
+
+ let_it_be(:release) do
+ create(:release, project: project, tag: tag_name, name: name,
+ description: description, released_at: Time.parse(released_at).utc,
+ created_at: Time.parse(created_at).utc, milestones: milestones)
+ end
+
+ let(:mutation_name) { :release_update }
+
+ let(:mutation_arguments) do
+ {
+ projectPath: project.full_path,
+ tagName: tag_name
+ }
+ end
+
+ let(:mutation) do
+ graphql_mutation(mutation_name, mutation_arguments, <<~FIELDS)
+ release {
+ tagName
+ name
+ description
+ releasedAt
+ createdAt
+ milestones {
+ nodes {
+ title
+ }
+ }
+ }
+ errors
+ FIELDS
+ end
+
+ let(:update_release) { post_graphql_mutation(mutation, current_user: current_user) }
+ let(:mutation_response) { graphql_mutation_response(mutation_name)&.with_indifferent_access }
+
+ let(:expected_attributes) do
+ {
+ tagName: tag_name,
+ name: name,
+ description: description,
+ releasedAt: Time.parse(released_at).utc.iso8601,
+ createdAt: Time.parse(created_at).utc.iso8601,
+ milestones: {
+ nodes: milestones.map { |m| { title: m.title } }
+ }
+ }.with_indifferent_access
+ end
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ before do
+ project.add_guest(guest)
+ project.add_reporter(reporter)
+ project.add_developer(developer)
+
+ stub_default_url_options(host: 'www.example.com')
+ end
+
+ shared_examples 'no errors' do
+ it 'returns no errors' do
+ update_release
+
+ expect(graphql_errors).not_to be_present
+ end
+ end
+
+ shared_examples 'top-level error with message' do |error_message|
+ it 'returns a top-level error with message' do
+ update_release
+
+ expect(mutation_response).to be_nil
+ expect(graphql_errors.count).to eq(1)
+ expect(graphql_errors.first['message']).to eq(error_message)
+ end
+ end
+
+ shared_examples 'errors-as-data with message' do |error_message|
+ it 'returns an error-as-data with message' do
+ update_release
+
+ expect(mutation_response[:release]).to be_nil
+ expect(mutation_response[:errors].count).to eq(1)
+ expect(mutation_response[:errors].first).to match(error_message)
+ end
+ end
+
+ shared_examples 'updates release fields' do |updates|
+ it_behaves_like 'no errors'
+
+ it 'updates the correct field and returns the release' do
+ update_release
+
+ expect(mutation_response[:release]).to include(expected_attributes.merge(updates).except(:milestones))
+
+ # Right now the milestones are returned in a non-deterministic order.
+ # Because of this, we need to test milestones separately to allow
+ # for them to be returned in any order.
+ # Once https://gitlab.com/gitlab-org/gitlab/-/issues/259012 has been
+ # fixed, this special milestone handling can be removed.
+ expected_milestones = expected_attributes.merge(updates)[:milestones]
+ expect(mutation_response[:release][:milestones][:nodes]).to match_array(expected_milestones[:nodes])
+ end
+ end
+
+ context 'when the current user has access to update releases' do
+ let(:current_user) { developer }
+
+ context 'name' do
+ context 'when a new name is provided' do
+ let(:mutation_arguments) { super().merge(name: 'Updated name') }
+
+ it_behaves_like 'updates release fields', name: 'Updated name'
+ end
+
+ context 'when null is provided' do
+ let(:mutation_arguments) { super().merge(name: nil) }
+
+ it_behaves_like 'updates release fields', name: 'v1.1.0'
+ end
+ end
+
+ context 'description' do
+ context 'when a new description is provided' do
+ let(:mutation_arguments) { super().merge(description: 'Updated description') }
+
+ it_behaves_like 'updates release fields', description: 'Updated description'
+ end
+
+ context 'when null is provided' do
+ let(:mutation_arguments) { super().merge(description: nil) }
+
+ it_behaves_like 'updates release fields', description: nil
+ end
+ end
+
+ context 'releasedAt' do
+ context 'when no time zone is provided' do
+ let(:mutation_arguments) { super().merge(releasedAt: '2015-05-05') }
+
+ it_behaves_like 'updates release fields', releasedAt: Time.parse('2015-05-05').utc.iso8601
+ end
+
+ context 'when a local time zone is provided' do
+ let(:mutation_arguments) { super().merge(releasedAt: Time.parse('2015-05-05').in_time_zone('Hawaii').iso8601) }
+
+ it_behaves_like 'updates release fields', releasedAt: Time.parse('2015-05-05').utc.iso8601
+ end
+
+ context 'when null is provided' do
+ let(:mutation_arguments) { super().merge(releasedAt: nil) }
+
+ it_behaves_like 'top-level error with message', 'if the releasedAt argument is provided, it cannot be null'
+ end
+ end
+
+ context 'milestones' do
+ context 'when a new set of milestones is provided provided' do
+ let(:mutation_arguments) { super().merge(milestones: ['12.3']) }
+
+ it_behaves_like 'updates release fields', milestones: { nodes: [{ title: '12.3' }] }
+ end
+
+ context 'when an empty array is provided' do
+ let(:mutation_arguments) { super().merge(milestones: []) }
+
+ it_behaves_like 'updates release fields', milestones: { nodes: [] }
+ end
+
+ context 'when null is provided' do
+ let(:mutation_arguments) { super().merge(milestones: nil) }
+
+ it_behaves_like 'top-level error with message', 'if the milestones argument is provided, it cannot be null'
+ end
+
+ context 'when a non-existent milestone title is provided' do
+ let(:mutation_arguments) { super().merge(milestones: ['not real']) }
+
+ it_behaves_like 'errors-as-data with message', 'Milestone(s) not found: not real'
+ end
+
+ context 'when a milestone title from a different project is provided' do
+ let(:milestone_in_different_project) { create(:milestone, title: 'milestone in different project') }
+ let(:mutation_arguments) { super().merge(milestones: [milestone_in_different_project.title]) }
+
+ it_behaves_like 'errors-as-data with message', 'Milestone(s) not found: milestone in different project'
+ end
+ end
+
+ context 'validation' do
+ context 'when no updated fields are provided' do
+ it_behaves_like 'errors-as-data with message', 'params is empty'
+ end
+
+ context 'when the tag does not exist' do
+ let(:mutation_arguments) { super().merge(tagName: 'not-a-real-tag') }
+
+ it_behaves_like 'errors-as-data with message', 'Tag does not exist'
+ end
+
+ context 'when the project does not exist' do
+ let(:mutation_arguments) { super().merge(projectPath: 'not/a/real/path') }
+
+ it_behaves_like 'top-level error with message', "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ end
+ end
+ end
+
+ context "when the current user doesn't have access to update releases" do
+ expected_error_message = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+
+ context 'when the current user is a Reporter' do
+ let(:current_user) { reporter }
+
+ it_behaves_like 'top-level error with message', expected_error_message
+ end
+
+ context 'when the current user is a Guest' do
+ let(:current_user) { guest }
+
+ it_behaves_like 'top-level error with message', expected_error_message
+ end
+
+ context 'when the current user is a public user' do
+ let(:current_user) { public_user }
+
+ it_behaves_like 'top-level error with message', expected_error_message
+ end
+ end
+end
diff --git a/spec/requests/api/group_clusters_spec.rb b/spec/requests/api/group_clusters_spec.rb
index eb21ae9468c..f65f9384efa 100644
--- a/spec/requests/api/group_clusters_spec.rb
+++ b/spec/requests/api/group_clusters_spec.rb
@@ -89,6 +89,8 @@ RSpec.describe API::GroupClusters do
expect(json_response['environment_scope']).to eq('*')
expect(json_response['cluster_type']).to eq('group_type')
expect(json_response['domain']).to eq('example.com')
+ expect(json_response['enabled']).to be_truthy
+ expect(json_response['managed']).to be_truthy
end
it 'returns group information' do
@@ -172,6 +174,7 @@ RSpec.describe API::GroupClusters do
name: 'test-cluster',
domain: 'domain.example.com',
managed: false,
+ enabled: false,
namespace_per_environment: false,
platform_kubernetes_attributes: platform_kubernetes_attributes,
management_project_id: management_project_id
@@ -206,6 +209,7 @@ RSpec.describe API::GroupClusters do
expect(cluster_result.name).to eq('test-cluster')
expect(cluster_result.domain).to eq('domain.example.com')
expect(cluster_result.managed).to be_falsy
+ expect(cluster_result.enabled).to be_falsy
expect(cluster_result.management_project_id).to eq management_project_id
expect(cluster_result.namespace_per_environment).to eq(false)
expect(platform_kubernetes.rbac?).to be_truthy
@@ -342,7 +346,9 @@ RSpec.describe API::GroupClusters do
{
domain: domain,
platform_kubernetes_attributes: platform_kubernetes_attributes,
- management_project_id: management_project_id
+ management_project_id: management_project_id,
+ managed: false,
+ enabled: false
}
end
@@ -381,6 +387,8 @@ RSpec.describe API::GroupClusters do
it 'updates cluster attributes' do
expect(cluster.domain).to eq('new-domain.com')
expect(cluster.management_project).to eq(management_project)
+ expect(cluster.managed).to be_falsy
+ expect(cluster.enabled).to be_falsy
end
end
@@ -394,6 +402,8 @@ RSpec.describe API::GroupClusters do
it 'does not update cluster attributes' do
expect(cluster.domain).to eq('old-domain.com')
expect(cluster.management_project).to be_nil
+ expect(cluster.managed).to be_truthy
+ expect(cluster.enabled).to be_truthy
end
it 'returns validation errors' do
diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb
index 7b37862af74..f784f677c25 100644
--- a/spec/requests/api/project_clusters_spec.rb
+++ b/spec/requests/api/project_clusters_spec.rb
@@ -88,6 +88,8 @@ RSpec.describe API::ProjectClusters do
expect(json_response['environment_scope']).to eq('*')
expect(json_response['cluster_type']).to eq('project_type')
expect(json_response['domain']).to eq('example.com')
+ expect(json_response['enabled']).to be_truthy
+ expect(json_response['managed']).to be_truthy
end
it 'returns project information' do
@@ -171,6 +173,7 @@ RSpec.describe API::ProjectClusters do
name: 'test-cluster',
domain: 'domain.example.com',
managed: false,
+ enabled: false,
namespace_per_environment: false,
platform_kubernetes_attributes: platform_kubernetes_attributes,
management_project_id: management_project_id
@@ -202,6 +205,7 @@ RSpec.describe API::ProjectClusters do
expect(cluster_result.name).to eq('test-cluster')
expect(cluster_result.domain).to eq('domain.example.com')
expect(cluster_result.managed).to be_falsy
+ expect(cluster_result.enabled).to be_falsy
expect(cluster_result.management_project_id).to eq management_project_id
expect(cluster_result.namespace_per_environment).to eq(false)
expect(platform_kubernetes.rbac?).to be_truthy
@@ -337,7 +341,9 @@ RSpec.describe API::ProjectClusters do
{
domain: 'new-domain.com',
platform_kubernetes_attributes: platform_kubernetes_attributes,
- management_project_id: management_project_id
+ management_project_id: management_project_id,
+ managed: false,
+ enabled: false
}
end
@@ -373,6 +379,8 @@ RSpec.describe API::ProjectClusters do
it 'updates cluster attributes' do
expect(response).to have_gitlab_http_status(:ok)
expect(cluster.domain).to eq('new-domain.com')
+ expect(cluster.managed).to be_falsy
+ expect(cluster.enabled).to be_falsy
expect(cluster.platform_kubernetes.namespace).to eq('new-namespace')
expect(cluster.management_project).to eq(management_project)
end
@@ -384,6 +392,8 @@ RSpec.describe API::ProjectClusters do
it 'does not update cluster attributes' do
expect(response).to have_gitlab_http_status(:bad_request)
expect(cluster.domain).not_to eq('new_domain.com')
+ expect(cluster.managed).to be_truthy
+ expect(cluster.enabled).to be_truthy
expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace')
expect(cluster.management_project).not_to eq(management_project)
end
diff --git a/spec/requests/api/usage_data_spec.rb b/spec/requests/api/usage_data_spec.rb
index 4f4f386e9db..d44f179eed8 100644
--- a/spec/requests/api/usage_data_spec.rb
+++ b/spec/requests/api/usage_data_spec.rb
@@ -5,6 +5,87 @@ require 'spec_helper'
RSpec.describe API::UsageData do
let_it_be(:user) { create(:user) }
+ describe 'POST /usage_data/increment_counter' do
+ let(:endpoint) { '/usage_data/increment_counter' }
+ let(:known_event) { "#{known_event_prefix}_#{known_event_postfix}" }
+ let(:known_event_prefix) { "static_site_editor" }
+ let(:known_event_postfix) { 'commits' }
+ let(:unknown_event) { 'unknown' }
+
+ context 'without CSRF token' do
+ it 'returns forbidden' do
+ stub_feature_flags(usage_data_api: true)
+ allow(Gitlab::RequestForgeryProtection).to receive(:verified?).and_return(false)
+
+ post api(endpoint, user), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'usage_data_api feature not enabled' do
+ it 'returns not_found' do
+ stub_feature_flags(usage_data_api: false)
+
+ post api(endpoint, user), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'without authentication' do
+ it 'returns 401 response' do
+ post api(endpoint), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'with authentication' do
+ before do
+ stub_feature_flags(usage_data_api: true)
+ stub_feature_flags("usage_data_#{known_event}" => true)
+ stub_application_setting(usage_ping_enabled: true)
+ allow(Gitlab::RequestForgeryProtection).to receive(:verified?).and_return(true)
+ end
+
+ context 'when event is missing from params' do
+ it 'returns bad request' do
+ post api(endpoint, user), params: {}
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ %w[merge_requests commits].each do |postfix|
+ context 'with correct params' do
+ let(:known_event_postfix) { postfix }
+
+ it 'returns status ok' do
+ expect(Gitlab::UsageDataCounters::BaseCounter).to receive(:count).with(known_event_postfix)
+ post api(endpoint, user), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'with unknown event' do
+ before do
+ skip_feature_flags_yaml_validation
+ end
+
+ it 'returns status ok' do
+ expect(Gitlab::UsageDataCounters::BaseCounter).not_to receive(:count)
+
+ post api(endpoint, user), params: { event: unknown_event }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+ end
+
describe 'POST /usage_data/increment_unique_users' do
let(:endpoint) { '/usage_data/increment_unique_users' }
let(:known_event) { 'g_compliance_dashboard' }
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 98840d6238a..381e0b03589 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -2510,6 +2510,98 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
end
end
+ context 'approve pending user' do
+ shared_examples '404' do
+ it 'returns 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 User Not Found')
+ end
+ end
+
+ describe 'POST /users/:id/approve' do
+ subject(:approve) { post api("/users/#{user_id}/approve", api_user) }
+
+ let_it_be(:pending_user) { create(:user, :blocked_pending_approval) }
+ let_it_be(:deactivated_user) { create(:user, :deactivated) }
+ let_it_be(:blocked_user) { create(:user, :blocked) }
+
+ context 'performed by a non-admin user' do
+ let(:api_user) { user }
+ let(:user_id) { pending_user.id }
+
+ it 'is not authorized to perform the action' do
+ expect { approve }.not_to change { pending_user.reload.state }
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response['message']).to eq('You are not allowed to approve a user')
+ end
+ end
+
+ context 'performed by an admin user' do
+ let(:api_user) { admin }
+
+ context 'for a deactivated user' do
+ let(:user_id) { deactivated_user.id }
+
+ it 'does not approve a deactivated user' do
+ expect { approve }.not_to change { deactivated_user.reload.state }
+ expect(response).to have_gitlab_http_status(:conflict)
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ end
+ end
+
+ context 'for an pending approval user' do
+ let(:user_id) { pending_user.id }
+
+ it 'returns 201' do
+ expect { approve }.to change { pending_user.reload.state }.to('active')
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['message']).to eq('Success')
+ end
+ end
+
+ context 'for an active user' do
+ let(:user_id) { user.id }
+
+ it 'returns 201' do
+ expect { approve }.not_to change { user.reload.state }
+ expect(response).to have_gitlab_http_status(:conflict)
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ end
+ end
+
+ context 'for a blocked user' do
+ let(:user_id) { blocked_user.id }
+
+ it 'returns 403' do
+ expect { approve }.not_to change { blocked_user.reload.state }
+ expect(response).to have_gitlab_http_status(:conflict)
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ end
+ end
+
+ context 'for a ldap blocked user' do
+ let(:user_id) { ldap_blocked_user.id }
+
+ it 'returns 403' do
+ expect { approve }.not_to change { ldap_blocked_user.reload.state }
+ expect(response).to have_gitlab_http_status(:conflict)
+ expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
+ end
+ end
+
+ context 'for a user that does not exist' do
+ let(:user_id) { non_existing_record_id }
+
+ before do
+ approve
+ end
+
+ it_behaves_like '404'
+ end
+ end
+ end
+ end
+
describe 'POST /users/:id/block' do
let(:blocked_user) { create(:user, state: 'blocked') }