summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/clusters/clusters.rb20
-rw-r--r--spec/graphql/features/authorization_spec.rb3
-rw-r--r--spec/graphql/gitlab_schema_spec.rb2
-rw-r--r--spec/helpers/gitlab_routing_helper_spec.rb6
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset/conditions/not_null_condition_spec.rb56
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset/conditions/null_condition_spec.rb42
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset/connection_spec.rb303
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset/legacy_keyset_connection_spec.rb127
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset/order_info_spec.rb61
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset/query_builder_spec.rb108
-rw-r--r--spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb117
-rw-r--r--spec/models/clusters/cluster_spec.rb103
-rw-r--r--spec/models/merge_request_spec.rb15
-rw-r--r--spec/requests/api/graphql/current_user/todos_query_spec.rb38
-rw-r--r--spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb2
-rw-r--r--spec/rubocop/cop/avoid_return_from_blocks_spec.rb2
-rw-r--r--spec/rubocop/cop/destroy_all_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/httparty_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/predicate_memoization_spec.rb2
-rw-r--r--spec/rubocop/cop/group_public_or_visible_to_user_spec.rb2
-rw-r--r--spec/rubocop/cop/include_sidekiq_worker_spec.rb2
-rw-r--r--spec/rubocop/cop/line_break_around_conditional_block_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_concurrent_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_reference_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/add_timestamps_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/datetime_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/hash_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/remove_column_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/remove_concurrent_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/remove_index_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/safer_boolean_column_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/timestamps_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/update_column_in_batches_spec.rb2
-rw-r--r--spec/rubocop/cop/migration/update_large_table_spec.rb2
-rw-r--r--spec/rubocop/cop/project_path_helper_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/env_assignment_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb2
-rw-r--r--spec/rubocop/cop/sidekiq_options_queue_spec.rb2
-rw-r--r--spec/serializers/blob_entity_spec.rb12
-rw-r--r--spec/serializers/diff_file_base_entity_spec.rb15
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb62
-rwxr-xr-xspec/support/generate-seed-repo-rb7
-rwxr-xr-xspec/support/prepare-gitlab-git-test-for-commit1
-rw-r--r--spec/support/shared_examples/ci/auto_merge_merge_requests_examples.rb40
-rwxr-xr-xspec/support/unpack-gitlab-git-test6
-rw-r--r--spec/views/projects/tree/_tree_header.html.haml_spec.rb2
50 files changed, 1015 insertions, 187 deletions
diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb
index 63f33633a3c..609e7e20187 100644
--- a/spec/factories/clusters/clusters.rb
+++ b/spec/factories/clusters/clusters.rb
@@ -93,5 +93,25 @@ FactoryBot.define do
trait :not_managed do
managed { false }
end
+
+ trait :cleanup_not_started do
+ cleanup_status { 1 }
+ end
+
+ trait :cleanup_uninstalling_applications do
+ cleanup_status { 2 }
+ end
+
+ trait :cleanup_removing_project_namespaces do
+ cleanup_status { 3 }
+ end
+
+ trait :cleanup_removing_service_account do
+ cleanup_status { 4 }
+ end
+
+ trait :cleanup_errored do
+ cleanup_status { 5 }
+ end
end
end
diff --git a/spec/graphql/features/authorization_spec.rb b/spec/graphql/features/authorization_spec.rb
index 9a60ff3b78c..7ad6a622b4b 100644
--- a/spec/graphql/features/authorization_spec.rb
+++ b/spec/graphql/features/authorization_spec.rb
@@ -259,7 +259,8 @@ describe 'Gitlab::Graphql::Authorization' do
let(:project_type) do |type|
type_factory do |type|
type.graphql_name 'FakeProjectType'
- type.field :test_issues, issue_type.connection_type, null: false, resolve: -> (_, _, _) { Issue.where(project: [visible_project, other_project]) }
+ type.field :test_issues, issue_type.connection_type, null: false,
+ resolve: -> (_, _, _) { Issue.where(project: [visible_project, other_project]).order(id: :asc) }
end
end
let(:query_type) do
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index 0a27bbecfef..dcf3c989047 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -36,7 +36,7 @@ describe GitlabSchema do
it 'paginates active record relations using `Gitlab::Graphql::Connections::KeysetConnection`' do
connection = GraphQL::Relay::BaseConnection::CONNECTION_IMPLEMENTATIONS[ActiveRecord::Relation.name]
- expect(connection).to eq(Gitlab::Graphql::Connections::KeysetConnection)
+ expect(connection).to eq(Gitlab::Graphql::Connections::Keyset::Connection)
end
describe '.execute' do
diff --git a/spec/helpers/gitlab_routing_helper_spec.rb b/spec/helpers/gitlab_routing_helper_spec.rb
index bf043f3f013..38699108b06 100644
--- a/spec/helpers/gitlab_routing_helper_spec.rb
+++ b/spec/helpers/gitlab_routing_helper_spec.rb
@@ -75,6 +75,12 @@ describe GitlabRoutingHelper do
expect(preview_markdown_path(group)).to eq("/groups/#{group.path}/preview_markdown")
end
+ it 'returns group preview markdown path for a group parent with args' do
+ group = create(:group)
+
+ expect(preview_markdown_path(group, { type_id: 5 })).to eq("/groups/#{group.path}/preview_markdown?type_id=5")
+ end
+
it 'returns project preview markdown path for a project parent' do
expect(preview_markdown_path(project)).to eq("/#{project.full_path}/preview_markdown")
end
diff --git a/spec/lib/gitlab/graphql/connections/keyset/conditions/not_null_condition_spec.rb b/spec/lib/gitlab/graphql/connections/keyset/conditions/not_null_condition_spec.rb
new file mode 100644
index 00000000000..d943540fe1f
--- /dev/null
+++ b/spec/lib/gitlab/graphql/connections/keyset/conditions/not_null_condition_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Connections::Keyset::Conditions::NotNullCondition do
+ describe '#build' do
+ let(:condition) { described_class.new(Issue.arel_table, %w(relative_position id), [1500, 500], ['>', '>'], before_or_after) }
+
+ context 'when there is only one ordering field' do
+ let(:condition) { described_class.new(Issue.arel_table, ['id'], [500], ['>'], :after) }
+
+ it 'generates a single condition sql' do
+ expected_sql = <<~SQL
+ ("issues"."id" > 500)
+ SQL
+
+ expect(condition.build.squish).to eq expected_sql.squish
+ end
+ end
+
+ context 'when :after' do
+ let(:before_or_after) { :after }
+
+ it 'generates :after sql' do
+ expected_sql = <<~SQL
+ ("issues"."relative_position" > 1500)
+ OR (
+ "issues"."relative_position" = 1500
+ AND
+ "issues"."id" > 500
+ )
+ OR ("issues"."relative_position" IS NULL)
+ SQL
+
+ expect(condition.build.squish).to eq expected_sql.squish
+ end
+ end
+
+ context 'when :before' do
+ let(:before_or_after) { :before }
+
+ it 'generates :before sql' do
+ expected_sql = <<~SQL
+ ("issues"."relative_position" > 1500)
+ OR (
+ "issues"."relative_position" = 1500
+ AND
+ "issues"."id" > 500
+ )
+ SQL
+
+ expect(condition.build.squish).to eq expected_sql.squish
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/connections/keyset/conditions/null_condition_spec.rb b/spec/lib/gitlab/graphql/connections/keyset/conditions/null_condition_spec.rb
new file mode 100644
index 00000000000..7fce94adb81
--- /dev/null
+++ b/spec/lib/gitlab/graphql/connections/keyset/conditions/null_condition_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Connections::Keyset::Conditions::NullCondition do
+ describe '#build' do
+ let(:condition) { described_class.new(Issue.arel_table, %w(relative_position id), [nil, 500], [nil, '>'], before_or_after) }
+
+ context 'when :after' do
+ let(:before_or_after) { :after }
+
+ it 'generates sql' do
+ expected_sql = <<~SQL
+ (
+ "issues"."relative_position" IS NULL
+ AND
+ "issues"."id" > 500
+ )
+ SQL
+
+ expect(condition.build.squish).to eq expected_sql.squish
+ end
+ end
+
+ context 'when :before' do
+ let(:before_or_after) { :before }
+
+ it 'generates :before sql' do
+ expected_sql = <<~SQL
+ (
+ "issues"."relative_position" IS NULL
+ AND
+ "issues"."id" > 500
+ )
+ OR ("issues"."relative_position" IS NOT NULL)
+ SQL
+
+ expect(condition.build.squish).to eq expected_sql.squish
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/connections/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/connections/keyset/connection_spec.rb
new file mode 100644
index 00000000000..ba1addadb5a
--- /dev/null
+++ b/spec/lib/gitlab/graphql/connections/keyset/connection_spec.rb
@@ -0,0 +1,303 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Connections::Keyset::Connection do
+ let(:nodes) { Project.all.order(id: :asc) }
+ let(:arguments) { {} }
+ subject(:connection) do
+ described_class.new(nodes, arguments, max_page_size: 3)
+ end
+
+ def encoded_cursor(node)
+ described_class.new(nodes, {}).cursor_from_node(node)
+ end
+
+ def decoded_cursor(cursor)
+ JSON.parse(Base64Bp.urlsafe_decode64(cursor))
+ end
+
+ describe '#cursor_from_nodes' do
+ let(:project) { create(:project) }
+ let(:cursor) { connection.cursor_from_node(project) }
+
+ it 'returns an encoded ID' do
+ expect(decoded_cursor(cursor)).to eq('id' => project.id.to_s)
+ end
+
+ context 'when an order is specified' do
+ let(:nodes) { Project.order(:updated_at) }
+
+ it 'returns the encoded value of the order' do
+ expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s)
+ end
+
+ it 'includes the :id even when not specified in the order' do
+ expect(decoded_cursor(cursor)).to include('id' => project.id.to_s)
+ end
+ end
+
+ context 'when multiple orders are specified' do
+ let(:nodes) { Project.order(:updated_at).order(:created_at) }
+
+ it 'returns the encoded value of the order' do
+ expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s)
+ end
+ end
+
+ context 'when multiple orders with SQL are specified' do
+ let(:nodes) { Project.order(Arel.sql('projects.updated_at IS NULL')).order(:updated_at).order(:id) }
+
+ it 'returns the encoded value of the order' do
+ expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s)
+ end
+ end
+ end
+
+ describe '#sliced_nodes' do
+ let(:projects) { create_list(:project, 4) }
+
+ context 'when before is passed' do
+ let(:arguments) { { before: encoded_cursor(projects[1]) } }
+
+ it 'only returns the project before the selected one' do
+ expect(subject.sliced_nodes).to contain_exactly(projects.first)
+ end
+
+ context 'when the sort order is descending' do
+ let(:nodes) { Project.all.order(id: :desc) }
+
+ it 'returns the correct nodes' do
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ end
+ end
+ end
+
+ context 'when after is passed' do
+ let(:arguments) { { after: encoded_cursor(projects[1]) } }
+
+ it 'only returns the project before the selected one' do
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ end
+
+ context 'when the sort order is descending' do
+ let(:nodes) { Project.all.order(id: :desc) }
+
+ it 'returns the correct nodes' do
+ expect(subject.sliced_nodes).to contain_exactly(projects.first)
+ end
+ end
+ end
+
+ context 'when both before and after are passed' do
+ let(:arguments) do
+ {
+ after: encoded_cursor(projects[1]),
+ before: encoded_cursor(projects[3])
+ }
+ end
+
+ it 'returns the expected set' do
+ expect(subject.sliced_nodes).to contain_exactly(projects[2])
+ end
+ end
+
+ context 'when multiple orders are defined' do
+ let!(:project1) { create(:project, last_repository_check_at: 10.days.ago) } # Asc: project5 Desc: project3
+ let!(:project2) { create(:project, last_repository_check_at: nil) } # Asc: project1 Desc: project1
+ let!(:project3) { create(:project, last_repository_check_at: 5.days.ago) } # Asc: project3 Desc: project5
+ let!(:project4) { create(:project, last_repository_check_at: nil) } # Asc: project2 Desc: project2
+ let!(:project5) { create(:project, last_repository_check_at: 20.days.ago) } # Asc: project4 Desc: project4
+
+ context 'when ascending' do
+ let(:nodes) do
+ Project.order(Arel.sql('projects.last_repository_check_at IS NULL')).order(last_repository_check_at: :asc).order(id: :asc)
+ end
+
+ context 'when no cursor is passed' do
+ let(:arguments) { {} }
+
+ it 'returns projects in ascending order' do
+ expect(subject.sliced_nodes).to eq([project5, project1, project3, project2, project4])
+ end
+ end
+
+ context 'when before cursor value is NULL' do
+ let(:arguments) { { before: encoded_cursor(project4) } }
+
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq([project5, project1, project3, project2])
+ end
+ end
+
+ context 'when before cursor value is not NULL' do
+ let(:arguments) { { before: encoded_cursor(project3) } }
+
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq([project5, project1])
+ end
+ end
+
+ context 'when after cursor value is NULL' do
+ let(:arguments) { { after: encoded_cursor(project2) } }
+
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project4])
+ end
+ end
+
+ context 'when after cursor value is not NULL' do
+ let(:arguments) { { after: encoded_cursor(project1) } }
+
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project3, project2, project4])
+ end
+ end
+
+ context 'when before and after cursor' do
+ let(:arguments) { { before: encoded_cursor(project4), after: encoded_cursor(project5) } }
+
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project1, project3, project2])
+ end
+ end
+ end
+
+ context 'when descending' do
+ let(:nodes) do
+ Project.order(Arel.sql('projects.last_repository_check_at IS NULL')).order(last_repository_check_at: :desc).order(id: :asc)
+ end
+
+ context 'when no cursor is passed' do
+ let(:arguments) { {} }
+
+ it 'only returns projects in descending order' do
+ expect(subject.sliced_nodes).to eq([project3, project1, project5, project2, project4])
+ end
+ end
+
+ context 'when before cursor value is NULL' do
+ let(:arguments) { { before: encoded_cursor(project4) } }
+
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq([project3, project1, project5, project2])
+ end
+ end
+
+ context 'when before cursor value is not NULL' do
+ let(:arguments) { { before: encoded_cursor(project5) } }
+
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq([project3, project1])
+ end
+ end
+
+ context 'when after cursor value is NULL' do
+ let(:arguments) { { after: encoded_cursor(project2) } }
+
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project4])
+ end
+ end
+
+ context 'when after cursor value is not NULL' do
+ let(:arguments) { { after: encoded_cursor(project1) } }
+
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project5, project2, project4])
+ end
+ end
+
+ context 'when before and after cursor' do
+ let(:arguments) { { before: encoded_cursor(project4), after: encoded_cursor(project3) } }
+
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project1, project5, project2])
+ end
+ end
+ end
+ end
+
+ # TODO Enable this as part of below issue
+ # https://gitlab.com/gitlab-org/gitlab/issues/32933
+ # context 'when an invalid cursor is provided' do
+ # let(:arguments) { { before: 'invalidcursor' } }
+ #
+ # it 'raises an error' do
+ # expect { expect(subject.sliced_nodes) }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ # end
+ # end
+
+ # TODO Remove this as part of below issue
+ # https://gitlab.com/gitlab-org/gitlab/issues/32933
+ context 'when an old style cursor is provided' do
+ let(:arguments) { { before: Base64Bp.urlsafe_encode64(projects[1].id.to_s, padding: false) } }
+
+ it 'only returns the project before the selected one' do
+ expect(subject.sliced_nodes).to contain_exactly(projects.first)
+ end
+ end
+ end
+
+ describe '#paged_nodes' do
+ let!(:projects) { create_list(:project, 5) }
+
+ it 'returns the collection limited to max page size' do
+ expect(subject.paged_nodes.size).to eq(3)
+ end
+
+ it 'is a loaded memoized array' do
+ expect(subject.paged_nodes).to be_an(Array)
+ expect(subject.paged_nodes.object_id).to eq(subject.paged_nodes.object_id)
+ end
+
+ context 'when `first` is passed' do
+ let(:arguments) { { first: 2 } }
+
+ it 'returns only the first elements' do
+ expect(subject.paged_nodes).to contain_exactly(projects.first, projects.second)
+ end
+ end
+
+ context 'when `last` is passed' do
+ let(:arguments) { { last: 2 } }
+
+ it 'returns only the last elements' do
+ expect(subject.paged_nodes).to contain_exactly(projects[3], projects[4])
+ end
+ end
+
+ context 'when both are passed' do
+ let(:arguments) { { first: 2, last: 2 } }
+
+ it 'raises an error' do
+ expect { subject.paged_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
+ end
+
+ context 'when primary key is not in original order' do
+ let(:nodes) { Project.order(last_repository_check_at: :desc) }
+
+ it 'is added to end' do
+ sliced = subject.sliced_nodes
+ last_order_name = sliced.order_values.last.expr.name
+
+ expect(last_order_name).to eq sliced.primary_key
+ end
+ end
+
+ context 'when there is no primary key' do
+ let(:nodes) { NoPrimaryKey.all }
+
+ it 'raises an error' do
+ expect(NoPrimaryKey.primary_key).to be_nil
+ expect { subject.sliced_nodes }.to raise_error(ArgumentError, 'Relation must have a primary key')
+ end
+ end
+ end
+
+ class NoPrimaryKey < ActiveRecord::Base
+ self.table_name = 'no_primary_key'
+ self.primary_key = nil
+ end
+end
diff --git a/spec/lib/gitlab/graphql/connections/keyset/legacy_keyset_connection_spec.rb b/spec/lib/gitlab/graphql/connections/keyset/legacy_keyset_connection_spec.rb
new file mode 100644
index 00000000000..aaf28fed684
--- /dev/null
+++ b/spec/lib/gitlab/graphql/connections/keyset/legacy_keyset_connection_spec.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+# TODO https://gitlab.com/gitlab-org/gitlab/issues/35104
+require 'spec_helper'
+
+describe Gitlab::Graphql::Connections::Keyset::LegacyKeysetConnection do
+ describe 'old keyset_connection' do
+ let(:described_class) { Gitlab::Graphql::Connections::Keyset::Connection }
+ let(:nodes) { Project.all.order(id: :asc) }
+ let(:arguments) { {} }
+ subject(:connection) do
+ described_class.new(nodes, arguments, max_page_size: 3)
+ end
+
+ before do
+ stub_feature_flags(graphql_keyset_pagination: false)
+ end
+
+ def encoded_property(value)
+ Base64Bp.urlsafe_encode64(value.to_s, padding: false)
+ end
+
+ describe '#cursor_from_nodes' do
+ let(:project) { create(:project) }
+
+ it 'returns an encoded ID' do
+ expect(connection.cursor_from_node(project))
+ .to eq(encoded_property(project.id))
+ end
+
+ context 'when an order was specified' do
+ let(:nodes) { Project.order(:updated_at) }
+
+ it 'returns the encoded value of the order' do
+ expect(connection.cursor_from_node(project))
+ .to eq(encoded_property(project.updated_at))
+ end
+ end
+ end
+
+ describe '#sliced_nodes' do
+ let(:projects) { create_list(:project, 4) }
+
+ context 'when before is passed' do
+ let(:arguments) { { before: encoded_property(projects[1].id) } }
+
+ it 'only returns the project before the selected one' do
+ expect(subject.sliced_nodes).to contain_exactly(projects.first)
+ end
+
+ context 'when the sort order is descending' do
+ let(:nodes) { Project.all.order(id: :desc) }
+
+ it 'returns the correct nodes' do
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ end
+ end
+ end
+
+ context 'when after is passed' do
+ let(:arguments) { { after: encoded_property(projects[1].id) } }
+
+ it 'only returns the project before the selected one' do
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ end
+
+ context 'when the sort order is descending' do
+ let(:nodes) { Project.all.order(id: :desc) }
+
+ it 'returns the correct nodes' do
+ expect(subject.sliced_nodes).to contain_exactly(projects.first)
+ end
+ end
+ end
+
+ context 'when both before and after are passed' do
+ let(:arguments) do
+ {
+ after: encoded_property(projects[1].id),
+ before: encoded_property(projects[3].id)
+ }
+ end
+
+ it 'returns the expected set' do
+ expect(subject.sliced_nodes).to contain_exactly(projects[2])
+ end
+ end
+ end
+
+ describe '#paged_nodes' do
+ let!(:projects) { create_list(:project, 5) }
+
+ it 'returns the collection limited to max page size' do
+ expect(subject.paged_nodes.size).to eq(3)
+ end
+
+ it 'is a loaded memoized array' do
+ expect(subject.paged_nodes).to be_an(Array)
+ expect(subject.paged_nodes.object_id).to eq(subject.paged_nodes.object_id)
+ end
+
+ context 'when `first` is passed' do
+ let(:arguments) { { first: 2 } }
+
+ it 'returns only the first elements' do
+ expect(subject.paged_nodes).to contain_exactly(projects.first, projects.second)
+ end
+ end
+
+ context 'when `last` is passed' do
+ let(:arguments) { { last: 2 } }
+
+ it 'returns only the last elements' do
+ expect(subject.paged_nodes).to contain_exactly(projects[3], projects[4])
+ end
+ end
+
+ context 'when both are passed' do
+ let(:arguments) { { first: 2, last: 2 } }
+
+ it 'raises an error' do
+ expect { subject.paged_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/connections/keyset/order_info_spec.rb b/spec/lib/gitlab/graphql/connections/keyset/order_info_spec.rb
new file mode 100644
index 00000000000..608a9ed1d85
--- /dev/null
+++ b/spec/lib/gitlab/graphql/connections/keyset/order_info_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Connections::Keyset::OrderInfo do
+ describe '#build_order_list' do
+ let(:order_list) { described_class.build_order_list(relation) }
+
+ context 'when multiple orders with SQL is specified' do
+ let(:relation) { Project.order(Arel.sql('projects.updated_at IS NULL')).order(:updated_at).order(:id) }
+
+ it 'ignores the SQL order' do
+ expect(order_list.count).to eq 2
+ expect(order_list.first.attribute_name).to eq 'updated_at'
+ expect(order_list.first.operator_for(:after)).to eq '>'
+ expect(order_list.last.attribute_name).to eq 'id'
+ expect(order_list.last.operator_for(:after)).to eq '>'
+ end
+ end
+ end
+
+ describe '#validate_ordering' do
+ let(:order_list) { described_class.build_order_list(relation) }
+
+ context 'when number of ordering fields is 0' do
+ let(:relation) { Project.all }
+
+ it 'raises an error' do
+ expect { described_class.validate_ordering(relation, order_list) }
+ .to raise_error(ArgumentError, 'A minimum of 1 ordering field is required')
+ end
+ end
+
+ context 'when number of ordering fields is over 2' do
+ let(:relation) { Project.order(last_repository_check_at: :desc).order(updated_at: :desc).order(:id) }
+
+ it 'raises an error' do
+ expect { described_class.validate_ordering(relation, order_list) }
+ .to raise_error(ArgumentError, 'A maximum of 2 ordering fields are allowed')
+ end
+ end
+
+ context 'when the second (or first) column is nullable' do
+ let(:relation) { Project.order(last_repository_check_at: :desc).order(updated_at: :desc) }
+
+ it 'raises an error' do
+ expect { described_class.validate_ordering(relation, order_list) }
+ .to raise_error(ArgumentError, "Column `updated_at` must not allow NULL")
+ end
+ end
+
+ context 'for last ordering field' do
+ let(:relation) { Project.order(namespace_id: :desc) }
+
+ it 'raises error if primary key is not last field' do
+ expect { described_class.validate_ordering(relation, order_list) }
+ .to raise_error(ArgumentError, "Last ordering field must be the primary key, `#{relation.primary_key}`")
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/connections/keyset/query_builder_spec.rb b/spec/lib/gitlab/graphql/connections/keyset/query_builder_spec.rb
new file mode 100644
index 00000000000..59e153d9e07
--- /dev/null
+++ b/spec/lib/gitlab/graphql/connections/keyset/query_builder_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Graphql::Connections::Keyset::QueryBuilder do
+ context 'when number of ordering fields is 0' do
+ it 'raises an error' do
+ expect { described_class.new(Issue.arel_table, [], {}, :after) }
+ .to raise_error(ArgumentError, 'No ordering scopes have been supplied')
+ end
+ end
+
+ describe '#conditions' do
+ let(:relation) { Issue.order(relative_position: :desc).order(:id) }
+ let(:order_list) { Gitlab::Graphql::Connections::Keyset::OrderInfo.build_order_list(relation) }
+ let(:builder) { described_class.new(arel_table, order_list, decoded_cursor, before_or_after) }
+ let(:before_or_after) { :after }
+
+ context 'when only a single ordering' do
+ let(:relation) { Issue.order(id: :desc) }
+
+ context 'when the value is nil' do
+ let(:decoded_cursor) { { 'id' => nil } }
+
+ it 'raises an error' do
+ expect { builder.conditions }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'Before/after cursor invalid: `nil` was provided as only sortable value')
+ end
+ end
+
+ context 'when value is not nil' do
+ let(:decoded_cursor) { { 'id' => 100 } }
+ let(:conditions) { builder.conditions }
+
+ context 'when :after' do
+ it 'generates the correct condition' do
+ expect(conditions.strip).to eq '("issues"."id" < 100)'
+ end
+ end
+
+ context 'when :before' do
+ let(:before_or_after) { :before }
+
+ it 'generates the correct condition' do
+ expect(conditions.strip).to eq '("issues"."id" > 100)'
+ end
+ end
+ end
+ end
+
+ context 'when two orderings' do
+ let(:decoded_cursor) { { 'relative_position' => 1500, 'id' => 100 } }
+
+ context 'when no values are nil' do
+ context 'when :after' do
+ it 'generates the correct condition' do
+ conditions = builder.conditions
+
+ expect(conditions).to include '"issues"."relative_position" < 1500'
+ expect(conditions).to include '"issues"."id" > 100'
+ expect(conditions).to include 'OR ("issues"."relative_position" IS NULL)'
+ end
+ end
+
+ context 'when :before' do
+ let(:before_or_after) { :before }
+
+ it 'generates the correct condition' do
+ conditions = builder.conditions
+
+ expect(conditions).to include '("issues"."relative_position" > 1500)'
+ expect(conditions).to include '"issues"."id" < 100'
+ expect(conditions).to include '"issues"."relative_position" = 1500'
+ end
+ end
+ end
+
+ context 'when first value is nil' do
+ let(:decoded_cursor) { { 'relative_position' => nil, 'id' => 100 } }
+
+ context 'when :after' do
+ it 'generates the correct condition' do
+ conditions = builder.conditions
+
+ expect(conditions).to include '"issues"."relative_position" IS NULL'
+ expect(conditions).to include '"issues"."id" > 100'
+ end
+ end
+
+ context 'when :before' do
+ let(:before_or_after) { :before }
+
+ it 'generates the correct condition' do
+ conditions = builder.conditions
+
+ expect(conditions).to include '"issues"."relative_position" IS NULL'
+ expect(conditions).to include '"issues"."id" < 100'
+ expect(conditions).to include 'OR ("issues"."relative_position" IS NOT NULL)'
+ end
+ end
+ end
+ end
+ end
+
+ def arel_table
+ Issue.arel_table
+ end
+end
diff --git a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb b/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
deleted file mode 100644
index 4eb121794e1..00000000000
--- a/spec/lib/gitlab/graphql/connections/keyset_connection_spec.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Graphql::Connections::KeysetConnection do
- let(:nodes) { Project.all.order(id: :asc) }
- let(:arguments) { {} }
- subject(:connection) do
- described_class.new(nodes, arguments, max_page_size: 3)
- end
-
- def encoded_property(value)
- Base64Bp.urlsafe_encode64(value.to_s, padding: false)
- end
-
- describe '#cursor_from_nodes' do
- let(:project) { create(:project) }
-
- it 'returns an encoded ID' do
- expect(connection.cursor_from_node(project))
- .to eq(encoded_property(project.id))
- end
-
- context 'when an order was specified' do
- let(:nodes) { Project.order(:updated_at) }
-
- it 'returns the encoded value of the order' do
- expect(connection.cursor_from_node(project))
- .to eq(encoded_property(project.updated_at))
- end
- end
- end
-
- describe '#sliced_nodes' do
- let(:projects) { create_list(:project, 4) }
-
- context 'when before is passed' do
- let(:arguments) { { before: encoded_property(projects[1].id) } }
-
- it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(projects.first)
- end
-
- context 'when the sort order is descending' do
- let(:nodes) { Project.all.order(id: :desc) }
-
- it 'returns the correct nodes' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
- end
- end
- end
-
- context 'when after is passed' do
- let(:arguments) { { after: encoded_property(projects[1].id) } }
-
- it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
- end
-
- context 'when the sort order is descending' do
- let(:nodes) { Project.all.order(id: :desc) }
-
- it 'returns the correct nodes' do
- expect(subject.sliced_nodes).to contain_exactly(projects.first)
- end
- end
- end
-
- context 'when both before and after are passed' do
- let(:arguments) do
- {
- after: encoded_property(projects[1].id),
- before: encoded_property(projects[3].id)
- }
- end
-
- it 'returns the expected set' do
- expect(subject.sliced_nodes).to contain_exactly(projects[2])
- end
- end
- end
-
- describe '#paged_nodes' do
- let!(:projects) { create_list(:project, 5) }
-
- it 'returns the collection limited to max page size' do
- expect(subject.paged_nodes.size).to eq(3)
- end
-
- it 'is a loaded memoized array' do
- expect(subject.paged_nodes).to be_an(Array)
- expect(subject.paged_nodes.object_id).to eq(subject.paged_nodes.object_id)
- end
-
- context 'when `first` is passed' do
- let(:arguments) { { first: 2 } }
-
- it 'returns only the first elements' do
- expect(subject.paged_nodes).to contain_exactly(projects.first, projects.second)
- end
- end
-
- context 'when `last` is passed' do
- let(:arguments) { { last: 2 } }
-
- it 'returns only the last elements' do
- expect(subject.paged_nodes).to contain_exactly(projects[3], projects[4])
- end
- end
-
- context 'when both are passed' do
- let(:arguments) { { first: 2, last: 2 } }
-
- it 'raises an error' do
- expect { subject.paged_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
- end
- end
- end
-end
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 8a3a7eee25d..47530025620 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -686,12 +686,36 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
context 'the cluster has a provider' do
let(:cluster) { create(:cluster, :provided_by_gcp) }
+ let(:provider_status) { :errored }
before do
cluster.provider.make_errored!
end
- it { is_expected.to eq :errored }
+ it { is_expected.to eq provider_status }
+
+ context 'when cluster cleanup is ongoing' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status_name, :cleanup_status) do
+ provider_status | :cleanup_not_started
+ :cleanup_ongoing | :cleanup_uninstalling_applications
+ :cleanup_ongoing | :cleanup_removing_project_namespaces
+ :cleanup_ongoing | :cleanup_removing_service_account
+ :cleanup_errored | :cleanup_errored
+ end
+
+ with_them do
+ it 'returns cleanup_ongoing when uninstalling applications' do
+ cluster.cleanup_status = described_class
+ .state_machines[:cleanup_status]
+ .states[cleanup_status]
+ .value
+
+ is_expected.to eq status_name
+ end
+ end
+ end
end
context 'there is a cached connection status' do
@@ -715,6 +739,83 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
+ describe 'cleanup_status state_machine' do
+ shared_examples 'cleanup_status transition' do
+ let(:cluster) { create(:cluster, from_state) }
+
+ it 'transitions cleanup_status correctly' do
+ expect { subject }.to change { cluster.cleanup_status_name }
+ .from(from_state).to(to_state)
+ end
+
+ it 'schedules a Clusters::Cleanup::*Worker' do
+ expect(expected_worker_class).to receive(:perform_async).with(cluster.id)
+ subject
+ end
+ end
+
+ describe '#start_cleanup!' do
+ let(:expected_worker_class) { Clusters::Cleanup::AppWorker }
+ let(:to_state) { :cleanup_uninstalling_applications }
+
+ subject { cluster.start_cleanup! }
+
+ context 'when cleanup_status is cleanup_not_started' do
+ let(:from_state) { :cleanup_not_started }
+
+ it_behaves_like 'cleanup_status transition'
+ end
+
+ context 'when cleanup_status is errored' do
+ let(:from_state) { :cleanup_errored }
+
+ it_behaves_like 'cleanup_status transition'
+ end
+ end
+
+ describe '#make_cleanup_errored!' do
+ NON_ERRORED_STATES = Clusters::Cluster.state_machines[:cleanup_status].states.keys - [:cleanup_errored]
+
+ NON_ERRORED_STATES.each do |state|
+ it "transitions cleanup_status from #{state} to cleanup_errored" do
+ cluster = create(:cluster, state)
+
+ expect { cluster.make_cleanup_errored! }.to change { cluster.cleanup_status_name }
+ .from(state).to(:cleanup_errored)
+ end
+
+ it "sets error message" do
+ cluster = create(:cluster, state)
+
+ expect { cluster.make_cleanup_errored!("Error Message") }.to change { cluster.cleanup_status_reason }
+ .from(nil).to("Error Message")
+ end
+ end
+ end
+
+ describe '#continue_cleanup!' do
+ context 'when cleanup_status is cleanup_uninstalling_applications' do
+ let(:expected_worker_class) { Clusters::Cleanup::ProjectNamespaceWorker }
+ let(:from_state) { :cleanup_uninstalling_applications }
+ let(:to_state) { :cleanup_removing_project_namespaces }
+
+ subject { cluster.continue_cleanup! }
+
+ it_behaves_like 'cleanup_status transition'
+ end
+
+ context 'when cleanup_status is cleanup_removing_project_namespaces' do
+ let(:expected_worker_class) { Clusters::Cleanup::ServiceAccountWorker }
+ let(:from_state) { :cleanup_removing_project_namespaces }
+ let(:to_state) { :cleanup_removing_service_account }
+
+ subject { cluster.continue_cleanup! }
+
+ it_behaves_like 'cleanup_status transition'
+ end
+ end
+ end
+
describe '#connection_status' do
let(:cluster) { create(:cluster) }
let(:status) { :connected }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 91a743c4377..62f73c3867b 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -3368,7 +3368,7 @@ describe MergeRequest do
end
end
- describe '.with_open_merge_when_pipeline_succeeds' do
+ describe '.with_auto_merge_enabled' do
let!(:project) { create(:project) }
let!(:fork) { fork_project(project) }
let!(:merge_request1) do
@@ -3380,15 +3380,6 @@ describe MergeRequest do
source_branch: 'feature-1')
end
- let!(:merge_request2) do
- create(:merge_request,
- :merge_when_pipeline_succeeds,
- target_project: project,
- target_branch: 'master',
- source_project: fork,
- source_branch: 'fork-feature-1')
- end
-
let!(:merge_request4) do
create(:merge_request,
target_project: project,
@@ -3397,9 +3388,9 @@ describe MergeRequest do
source_branch: 'fork-feature-2')
end
- let(:query) { described_class.with_open_merge_when_pipeline_succeeds }
+ let(:query) { described_class.with_auto_merge_enabled }
- it { expect(query).to contain_exactly(merge_request1, merge_request2) }
+ it { expect(query).to contain_exactly(merge_request1) }
end
it_behaves_like 'versioned description'
diff --git a/spec/requests/api/graphql/current_user/todos_query_spec.rb b/spec/requests/api/graphql/current_user/todos_query_spec.rb
new file mode 100644
index 00000000000..6817e37e64b
--- /dev/null
+++ b/spec/requests/api/graphql/current_user/todos_query_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Query current user todos' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:commit_todo) { create(:on_commit_todo, user: current_user, project: create(:project, :repository)) }
+ let_it_be(:issue_todo) { create(:todo, user: current_user, target: create(:issue)) }
+ let_it_be(:merge_request_todo) { create(:todo, user: current_user, target: create(:merge_request)) }
+
+ let(:fields) do
+ <<~QUERY
+ nodes {
+ id
+ }
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for('currentUser', {}, query_graphql_field('todos', {}, fields))
+ end
+
+ subject { graphql_data.dig('currentUser', 'todos', 'nodes') }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it 'contains the expected ids' do
+ is_expected.to include(
+ a_hash_including('id' => commit_todo.to_global_id.to_s),
+ a_hash_including('id' => issue_todo.to_global_id.to_s),
+ a_hash_including('id' => merge_request_todo.to_global_id.to_s)
+ )
+ end
+end
diff --git a/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb b/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
index ac7b1575ec0..62f6c7a3414 100644
--- a/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
+++ b/spec/rubocop/cop/avoid_break_from_strong_memoize_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/avoid_return_from_blocks_spec.rb b/spec/rubocop/cop/avoid_return_from_blocks_spec.rb
index a5c280a7adc..133d286ccd2 100644
--- a/spec/rubocop/cop/avoid_return_from_blocks_spec.rb
+++ b/spec/rubocop/cop/avoid_return_from_blocks_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/destroy_all_spec.rb b/spec/rubocop/cop/destroy_all_spec.rb
index b0bc40552b3..ac8aa56e040 100644
--- a/spec/rubocop/cop/destroy_all_spec.rb
+++ b/spec/rubocop/cop/destroy_all_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb b/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
index 7f689b196c5..7af98b66218 100644
--- a/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
+++ b/spec/rubocop/cop/gitlab/finder_with_find_by_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/gitlab/httparty_spec.rb b/spec/rubocop/cop/gitlab/httparty_spec.rb
index 510839a21d7..42da97679ec 100644
--- a/spec/rubocop/cop/gitlab/httparty_spec.rb
+++ b/spec/rubocop/cop/gitlab/httparty_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb b/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
index 8e2d5f70353..9cb55ced1fa 100644
--- a/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
+++ b/spec/rubocop/cop/gitlab/module_with_instance_variables_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb b/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
index 21fc4584654..ae9466368d2 100644
--- a/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
+++ b/spec/rubocop/cop/gitlab/predicate_memoization_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb b/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
index 7b5235a3da7..8e027ad59f7 100644
--- a/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
+++ b/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/include_sidekiq_worker_spec.rb b/spec/rubocop/cop/include_sidekiq_worker_spec.rb
index f5109287876..39965646aff 100644
--- a/spec/rubocop/cop/include_sidekiq_worker_spec.rb
+++ b/spec/rubocop/cop/include_sidekiq_worker_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/line_break_around_conditional_block_spec.rb b/spec/rubocop/cop/line_break_around_conditional_block_spec.rb
index cc933ce12c8..d09de4c6614 100644
--- a/spec/rubocop/cop/line_break_around_conditional_block_spec.rb
+++ b/spec/rubocop/cop/line_break_around_conditional_block_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
diff --git a/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb b/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb
index 1df1fffb94e..419d74c298a 100644
--- a/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb
+++ b/spec/rubocop/cop/migration/add_concurrent_foreign_key_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/add_concurrent_index_spec.rb b/spec/rubocop/cop/migration/add_concurrent_index_spec.rb
index 9c1ebcc0ced..9812e64216f 100644
--- a/spec/rubocop/cop/migration/add_concurrent_index_spec.rb
+++ b/spec/rubocop/cop/migration/add_concurrent_index_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/add_reference_spec.rb b/spec/rubocop/cop/migration/add_reference_spec.rb
index 0b56fe8ed83..03348ecc744 100644
--- a/spec/rubocop/cop/migration/add_reference_spec.rb
+++ b/spec/rubocop/cop/migration/add_reference_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/add_timestamps_spec.rb b/spec/rubocop/cop/migration/add_timestamps_spec.rb
index 33f1bb85af8..a3314d878e5 100644
--- a/spec/rubocop/cop/migration/add_timestamps_spec.rb
+++ b/spec/rubocop/cop/migration/add_timestamps_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/datetime_spec.rb b/spec/rubocop/cop/migration/datetime_spec.rb
index f2d9483d8d3..0a771003100 100644
--- a/spec/rubocop/cop/migration/datetime_spec.rb
+++ b/spec/rubocop/cop/migration/datetime_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/hash_index_spec.rb b/spec/rubocop/cop/migration/hash_index_spec.rb
index 5d53dde9a79..e8b05a94653 100644
--- a/spec/rubocop/cop/migration/hash_index_spec.rb
+++ b/spec/rubocop/cop/migration/hash_index_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/remove_column_spec.rb b/spec/rubocop/cop/migration/remove_column_spec.rb
index f1a64f431bd..bc2fa04ce64 100644
--- a/spec/rubocop/cop/migration/remove_column_spec.rb
+++ b/spec/rubocop/cop/migration/remove_column_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb b/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb
index a23d5d022e3..9de4c756f12 100644
--- a/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb
+++ b/spec/rubocop/cop/migration/remove_concurrent_index_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/remove_index_spec.rb b/spec/rubocop/cop/migration/remove_index_spec.rb
index bbf2227e512..d343d27484a 100644
--- a/spec/rubocop/cop/migration/remove_index_spec.rb
+++ b/spec/rubocop/cop/migration/remove_index_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb b/spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb
index ba8cd2c6c4a..b3c5b855004 100644
--- a/spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb
+++ b/spec/rubocop/cop/migration/reversible_add_column_with_default_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/safer_boolean_column_spec.rb b/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
index 1c4f18fbcc3..915b73ed5a7 100644
--- a/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
+++ b/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/timestamps_spec.rb b/spec/rubocop/cop/migration/timestamps_spec.rb
index cafe255dc9a..d03c75e7cfc 100644
--- a/spec/rubocop/cop/migration/timestamps_spec.rb
+++ b/spec/rubocop/cop/migration/timestamps_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/update_column_in_batches_spec.rb b/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
index cba01400d85..f72efaf2eb2 100644
--- a/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
+++ b/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/migration/update_large_table_spec.rb b/spec/rubocop/cop/migration/update_large_table_spec.rb
index 5e08eb4f772..0463b6550a8 100644
--- a/spec/rubocop/cop/migration/update_large_table_spec.rb
+++ b/spec/rubocop/cop/migration/update_large_table_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/project_path_helper_spec.rb b/spec/rubocop/cop/project_path_helper_spec.rb
index 84e6eb7d87f..1b69030c798 100644
--- a/spec/rubocop/cop/project_path_helper_spec.rb
+++ b/spec/rubocop/cop/project_path_helper_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/rspec/env_assignment_spec.rb b/spec/rubocop/cop/rspec/env_assignment_spec.rb
index 621afbad3ba..2a2bd1434d6 100644
--- a/spec/rubocop/cop/rspec/env_assignment_spec.rb
+++ b/spec/rubocop/cop/rspec/env_assignment_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb b/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
index 94324bc615d..20013519db4 100644
--- a/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
+++ b/spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/rubocop/cop/sidekiq_options_queue_spec.rb b/spec/rubocop/cop/sidekiq_options_queue_spec.rb
index 7f237d5ffbb..c10fd7bd32b 100644
--- a/spec/rubocop/cop/sidekiq_options_queue_spec.rb
+++ b/spec/rubocop/cop/sidekiq_options_queue_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
require 'rubocop'
diff --git a/spec/serializers/blob_entity_spec.rb b/spec/serializers/blob_entity_spec.rb
index c0687d0232e..7e3a0a87bd5 100644
--- a/spec/serializers/blob_entity_spec.rb
+++ b/spec/serializers/blob_entity_spec.rb
@@ -15,8 +15,16 @@ describe BlobEntity do
context 'as json' do
subject { entity.as_json }
- it 'exposes needed attributes' do
- expect(subject).to include(:readable_text, :url)
+ it 'contains needed attributes' do
+ expect(subject).to include({
+ id: blob.id,
+ path: blob.path,
+ name: blob.name,
+ mode: "100644",
+ readable_text: true,
+ icon: "file-text-o",
+ url: "/#{project.full_path}/blob/master/bar/branch-test.txt"
+ })
end
end
end
diff --git a/spec/serializers/diff_file_base_entity_spec.rb b/spec/serializers/diff_file_base_entity_spec.rb
index 68c5c665ed6..80f5bc8f159 100644
--- a/spec/serializers/diff_file_base_entity_spec.rb
+++ b/spec/serializers/diff_file_base_entity_spec.rb
@@ -5,15 +5,15 @@ require 'spec_helper'
describe DiffFileBaseEntity do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
+ let(:entity) { described_class.new(diff_file, options).as_json }
context 'diff for a changed submodule' do
let(:commit_sha_with_changed_submodule) do
"cfe32cf61b73a0d5e9f13e774abde7ff789b1660"
end
let(:commit) { project.commit(commit_sha_with_changed_submodule) }
- let(:diff_file) { commit.diffs.diff_files.to_a.last }
let(:options) { { request: {}, submodule_links: Gitlab::SubmoduleLinks.new(repository) } }
- let(:entity) { described_class.new(diff_file, options).as_json }
+ let(:diff_file) { commit.diffs.diff_files.to_a.last }
it do
expect(entity[:submodule]).to eq(true)
@@ -23,4 +23,15 @@ describe DiffFileBaseEntity do
)
end
end
+
+ context 'contains raw sizes for the blob' do
+ let(:commit) { project.commit('png-lfs') }
+ let(:options) { { request: {} } }
+ let(:diff_file) { commit.diffs.diff_files.to_a.second }
+
+ it do
+ expect(entity[:old_size]).to eq(1219696)
+ expect(entity[:new_size]).to eq(132)
+ end
+ end
end
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 58302ce14ba..9d0ad60a624 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -769,7 +769,7 @@ describe MergeRequests::RefreshService do
fork_project(target_project, author, repository: true)
end
- let_it_be(:merge_request) do
+ let_it_be(:merge_request, refind: true) do
create(:merge_request,
author: author,
source_project: source_project,
@@ -795,88 +795,58 @@ describe MergeRequests::RefreshService do
.parent_id
end
+ let(:auto_merge_strategy) { AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS }
let(:refresh_service) { service.new(project, user) }
before do
target_project.merge_method = merge_method
target_project.save!
+ merge_request.auto_merge_strategy = auto_merge_strategy
+ merge_request.save!
refresh_service.execute(oldrev, newrev, 'refs/heads/master')
merge_request.reload
end
- let(:aborted_message) do
- /aborted the automatic merge because target branch was updated/
- end
-
- shared_examples 'aborted MWPS' do
- it 'aborts auto_merge' do
- expect(merge_request.auto_merge_enabled?).to be_falsey
- expect(merge_request.notes.last.note).to match(aborted_message)
- end
-
- it 'removes merge_user' do
- expect(merge_request.merge_user).to be_nil
- end
-
- it 'does not add todos for merge user' do
- expect(user.todos.for_target(merge_request)).to be_empty
- end
-
- it 'adds todos for merge author' do
- expect(author.todos.for_target(merge_request)).to be_present.and be_all(&:pending?)
- end
- end
-
context 'when Project#merge_method is set to FF' do
let(:merge_method) { :ff }
- it_behaves_like 'aborted MWPS'
+ it_behaves_like 'aborted merge requests for MWPS'
context 'with forked project' do
let(:source_project) { forked_project }
- it_behaves_like 'aborted MWPS'
+ it_behaves_like 'aborted merge requests for MWPS'
+ end
+
+ context 'with bogus auto merge strategy' do
+ let(:auto_merge_strategy) { 'bogus' }
+
+ it_behaves_like 'maintained merge requests for MWPS'
end
end
context 'when Project#merge_method is set to rebase_merge' do
let(:merge_method) { :rebase_merge }
- it_behaves_like 'aborted MWPS'
+ it_behaves_like 'aborted merge requests for MWPS'
context 'with forked project' do
let(:source_project) { forked_project }
- it_behaves_like 'aborted MWPS'
+ it_behaves_like 'aborted merge requests for MWPS'
end
end
context 'when Project#merge_method is set to merge' do
let(:merge_method) { :merge }
- shared_examples 'maintained MWPS' do
- it 'does not cancel auto merge' do
- expect(merge_request.auto_merge_enabled?).to be_truthy
- expect(merge_request.notes).to be_empty
- end
-
- it 'does not change merge_user' do
- expect(merge_request.merge_user).to eq(user)
- end
-
- it 'does not add todos' do
- expect(author.todos.for_target(merge_request)).to be_empty
- expect(user.todos.for_target(merge_request)).to be_empty
- end
- end
-
- it_behaves_like 'maintained MWPS'
+ it_behaves_like 'maintained merge requests for MWPS'
context 'with forked project' do
let(:source_project) { forked_project }
- it_behaves_like 'maintained MWPS'
+ it_behaves_like 'maintained merge requests for MWPS'
end
end
end
diff --git a/spec/support/generate-seed-repo-rb b/spec/support/generate-seed-repo-rb
index bee9d419376..b63ff7147ec 100755
--- a/spec/support/generate-seed-repo-rb
+++ b/spec/support/generate-seed-repo-rb
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
#
# # generate-seed-repo-rb
#
@@ -15,9 +16,9 @@
require 'erb'
require 'tempfile'
-SOURCE = File.expand_path('gitlab-git-test.git', __dir__).freeze
-SCRIPT_NAME = 'generate-seed-repo-rb'.freeze
-REPO_NAME = 'gitlab-git-test.git'.freeze
+SOURCE = File.expand_path('gitlab-git-test.git', __dir__)
+SCRIPT_NAME = 'generate-seed-repo-rb'
+REPO_NAME = 'gitlab-git-test.git'
def main
Dir.mktmpdir do |dir|
diff --git a/spec/support/prepare-gitlab-git-test-for-commit b/spec/support/prepare-gitlab-git-test-for-commit
index d08e3ba5481..77c7f309312 100755
--- a/spec/support/prepare-gitlab-git-test-for-commit
+++ b/spec/support/prepare-gitlab-git-test-for-commit
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
abort unless [
system('spec/support/generate-seed-repo-rb', out: 'spec/support/helpers/seed_repo.rb'),
diff --git a/spec/support/shared_examples/ci/auto_merge_merge_requests_examples.rb b/spec/support/shared_examples/ci/auto_merge_merge_requests_examples.rb
new file mode 100644
index 00000000000..c11448ffe0f
--- /dev/null
+++ b/spec/support/shared_examples/ci/auto_merge_merge_requests_examples.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+shared_examples 'aborted merge requests for MWPS' do
+ let(:aborted_message) do
+ /aborted the automatic merge because target branch was updated/
+ end
+
+ it 'aborts auto_merge' do
+ expect(merge_request.auto_merge_enabled?).to be_falsey
+ expect(merge_request.notes.last.note).to match(aborted_message)
+ end
+
+ it 'removes merge_user' do
+ expect(merge_request.merge_user).to be_nil
+ end
+
+ it 'does not add todos for merge user' do
+ expect(user.todos.for_target(merge_request)).to be_empty
+ end
+
+ it 'adds todos for merge author' do
+ expect(author.todos.for_target(merge_request)).to be_present.and be_all(&:pending?)
+ end
+end
+
+shared_examples 'maintained merge requests for MWPS' do
+ it 'does not cancel auto merge' do
+ expect(merge_request.auto_merge_enabled?).to be_truthy
+ expect(merge_request.notes).to be_empty
+ end
+
+ it 'does not change merge_user' do
+ expect(merge_request.merge_user).to eq(user)
+ end
+
+ it 'does not add todos' do
+ expect(author.todos.for_target(merge_request)).to be_empty
+ expect(user.todos.for_target(merge_request)).to be_empty
+ end
+end
diff --git a/spec/support/unpack-gitlab-git-test b/spec/support/unpack-gitlab-git-test
index d5b4912457d..5d5f1b7d082 100755
--- a/spec/support/unpack-gitlab-git-test
+++ b/spec/support/unpack-gitlab-git-test
@@ -1,10 +1,12 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
+
require 'fileutils'
-REPO = 'spec/support/gitlab-git-test.git'.freeze
+REPO = 'spec/support/gitlab-git-test.git'
PACK_DIR = REPO + '/objects/pack'
GIT = %W[git --git-dir=#{REPO}].freeze
-BASE_PACK = 'pack-691247af2a6acb0b63b73ac0cb90540e93614043'.freeze
+BASE_PACK = 'pack-691247af2a6acb0b63b73ac0cb90540e93614043'
def main
unpack
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 4b71ea9ffe3..caf8c4d1969 100644
--- a/spec/views/projects/tree/_tree_header.html.haml_spec.rb
+++ b/spec/views/projects/tree/_tree_header.html.haml_spec.rb
@@ -8,6 +8,8 @@ describe 'projects/tree/_tree_header' do
let(:repository) { project.repository }
before do
+ stub_feature_flags(vue_file_list: false)
+
assign(:project, project)
assign(:repository, repository)
assign(:id, File.join('master', ''))