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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/graphql/pagination')
-rw-r--r--spec/lib/gitlab/graphql/pagination/active_record_array_connection_spec.rb135
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb13
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb127
3 files changed, 211 insertions, 64 deletions
diff --git a/spec/lib/gitlab/graphql/pagination/active_record_array_connection_spec.rb b/spec/lib/gitlab/graphql/pagination/active_record_array_connection_spec.rb
new file mode 100644
index 00000000000..320c6b52308
--- /dev/null
+++ b/spec/lib/gitlab/graphql/pagination/active_record_array_connection_spec.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Graphql::Pagination::ActiveRecordArrayConnection do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:items) { create_list(:package_build_info, 3) }
+
+ let_it_be(:context) do
+ GraphQL::Query::Context.new(
+ query: GraphQL::Query.new(GitlabSchema, document: nil, context: {}, variables: {}),
+ values: {},
+ object: nil
+ )
+ end
+
+ let(:first) { nil }
+ let(:last) { nil }
+ let(:after) { nil }
+ let(:before) { nil }
+ let(:max_page_size) { nil }
+
+ let(:connection) do
+ described_class.new(
+ items,
+ context: context,
+ first: first,
+ last: last,
+ after: after,
+ before: before,
+ max_page_size: max_page_size
+ )
+ end
+
+ it_behaves_like 'a connection with collection methods'
+
+ it_behaves_like 'a redactable connection' do
+ let(:unwanted) { items[1] }
+ end
+
+ describe '#nodes' do
+ subject { connection.nodes }
+
+ it { is_expected.to match_array(items) }
+
+ context 'with first set' do
+ let(:first) { 2 }
+
+ it { is_expected.to match_array([items[0], items[1]]) }
+ end
+
+ context 'with last set' do
+ let(:last) { 2 }
+
+ it { is_expected.to match_array([items[1], items[2]]) }
+ end
+ end
+
+ describe '#next_page?' do
+ subject { connection.next_page? }
+
+ where(:before, :first, :max_page_size, :result) do
+ nil | nil | nil | false
+ 1 | nil | nil | true
+ nil | 1 | nil | true
+ nil | 10 | nil | false
+ nil | 1 | 1 | true
+ nil | 1 | 10 | true
+ nil | 10 | 10 | false
+ end
+
+ with_them do
+ it { is_expected.to eq(result) }
+ end
+ end
+
+ describe '#previous_page?' do
+ subject { connection.previous_page? }
+
+ where(:after, :last, :max_page_size, :result) do
+ nil | nil | nil | false
+ 1 | nil | nil | true
+ nil | 1 | nil | true
+ nil | 10 | nil | false
+ nil | 1 | 1 | true
+ nil | 1 | 10 | true
+ nil | 10 | 10 | false
+ end
+
+ with_them do
+ it { is_expected.to eq(result) }
+ end
+ end
+
+ describe '#cursor_for' do
+ let(:item) { items[0] }
+ let(:expected_result) do
+ GitlabSchema.cursor_encoder.encode(
+ Gitlab::Json.dump(id: item.id.to_s),
+ nonce: true
+ )
+ end
+
+ subject { connection.cursor_for(item) }
+
+ it { is_expected.to eq(expected_result) }
+
+ context 'with a BatchLoader::GraphQL item' do
+ let_it_be(:user) { create(:user) }
+
+ let(:item) { ::Gitlab::Graphql::Loaders::BatchModelLoader.new(::User, user.id).find }
+ let(:expected_result) do
+ GitlabSchema.cursor_encoder.encode(
+ Gitlab::Json.dump(id: user.id.to_s),
+ nonce: true
+ )
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
+
+ describe '#dup' do
+ subject { connection.dup }
+
+ it 'properly handles items duplication' do
+ connection2 = subject
+
+ connection2 << create(:package_build_info)
+
+ expect(connection.items).not_to eq(connection2.items)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
index 0741088c915..86e7d4e344c 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
@@ -19,8 +19,8 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: 'last_repository_check_at',
column_expression: Project.arel_table[:last_repository_check_at],
- order_expression: Gitlab::Database.nulls_last_order('last_repository_check_at', :asc),
- reversed_order_expression: Gitlab::Database.nulls_last_order('last_repository_check_at', :desc),
+ order_expression: Project.arel_table[:last_repository_check_at].asc.nulls_last,
+ reversed_order_expression: Project.arel_table[:last_repository_check_at].desc.nulls_last,
order_direction: :asc,
nullable: :nulls_last,
distinct: false)
@@ -30,8 +30,8 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: 'last_repository_check_at',
column_expression: Project.arel_table[:last_repository_check_at],
- order_expression: Gitlab::Database.nulls_last_order('last_repository_check_at', :desc),
- reversed_order_expression: Gitlab::Database.nulls_last_order('last_repository_check_at', :asc),
+ order_expression: Project.arel_table[:last_repository_check_at].desc.nulls_last,
+ reversed_order_expression: Project.arel_table[:last_repository_check_at].asc.nulls_last,
order_direction: :desc,
nullable: :nulls_last,
distinct: false)
@@ -256,11 +256,6 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
end
end
- # rubocop: disable RSpec/EmptyExampleGroup
- context 'when ordering uses LOWER' do
- end
- # rubocop: enable RSpec/EmptyExampleGroup
-
context 'when ordering by similarity' do
let_it_be(:project1) { create(:project, name: 'test') }
let_it_be(:project2) { create(:project, name: 'testing') }
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
index b511a294f97..f31ec6c09fd 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -77,6 +77,17 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
expect(decoded_cursor(cursor)).to eq('id' => project.id.to_s)
end
+ context 'when SimpleOrderBuilder cannot build keyset paginated query' do
+ it 'increments the `old_keyset_pagination_usage` counter', :prometheus do
+ expect(Gitlab::Pagination::Keyset::SimpleOrderBuilder).to receive(:build).and_return([false, nil])
+
+ decoded_cursor(cursor)
+
+ counter = Gitlab::Metrics.registry.get(:old_keyset_pagination_usage)
+ expect(counter.get(model: 'Project')).to eq(1)
+ end
+ end
+
context 'when an order is specified' do
let(:nodes) { Project.order(:updated_at) }
@@ -222,91 +233,97 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
end
end
- context 'when multiple orders with nil values 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 ordering uses LOWER' do
+ let!(:project1) { create(:project, name: 'A') } # Asc: project1 Desc: project4
+ let!(:project2) { create(:project, name: 'c') } # Asc: project5 Desc: project2
+ let!(:project3) { create(:project, name: 'b') } # Asc: project3 Desc: project3
+ let!(:project4) { create(:project, name: 'd') } # Asc: project2 Desc: project5
+ let!(:project5) { create(:project, name: 'a') } # Asc: project4 Desc: project1
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)
+ Project.order(Arel::Table.new(:projects)['name'].lower.asc).order(id: :asc)
end
- let(:ascending_nodes) { [project5, project1, project3, project2, project4] }
+ let(:ascending_nodes) { [project1, project5, project3, project2, project4] }
it_behaves_like 'nodes are in ascending order'
-
- 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 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
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)
+ Project.order(Arel::Table.new(:projects)['name'].lower.desc).order(id: :desc)
end
- let(:descending_nodes) { [project3, project1, project5, project2, project4] }
+ let(:descending_nodes) { [project4, project2, project3, project5, project1] }
it_behaves_like 'nodes are in descending order'
+ end
+ end
- context 'when before cursor value is NULL' do
- let(:arguments) { { before: encoded_cursor(project4) } }
+ context 'NULLS order' do
+ using RSpec::Parameterized::TableSyntax
- it 'returns all projects before the cursor' do
- expect(subject.sliced_nodes).to eq([project3, project1, project5, project2])
- end
- end
+ let_it_be(:issue1) { create(:issue, relative_position: nil) }
+ let_it_be(:issue2) { create(:issue, relative_position: 100) }
+ let_it_be(:issue3) { create(:issue, relative_position: 200) }
+ let_it_be(:issue4) { create(:issue, relative_position: nil) }
+ let_it_be(:issue5) { create(:issue, relative_position: 300) }
+
+ context 'when ascending NULLS LAST (ties broken by id DESC implicitly)' do
+ let(:ascending_nodes) { [issue2, issue3, issue5, issue4, issue1] }
- context 'when after cursor value is NULL' do
- let(:arguments) { { after: encoded_cursor(project2) } }
+ where(:nodes) do
+ [
+ lazy { Issue.order(Issue.arel_table[:relative_position].asc.nulls_last) }
+ ]
+ end
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq([project4])
- end
+ with_them do
+ it_behaves_like 'nodes are in ascending order'
end
end
- end
- context 'when ordering uses LOWER' do
- let!(:project1) { create(:project, name: 'A') } # Asc: project1 Desc: project4
- let!(:project2) { create(:project, name: 'c') } # Asc: project5 Desc: project2
- let!(:project3) { create(:project, name: 'b') } # Asc: project3 Desc: project3
- let!(:project4) { create(:project, name: 'd') } # Asc: project2 Desc: project5
- let!(:project5) { create(:project, name: 'a') } # Asc: project4 Desc: project1
+ context 'when descending NULLS LAST (ties broken by id DESC implicitly)' do
+ let(:descending_nodes) { [issue5, issue3, issue2, issue4, issue1] }
- context 'when ascending' do
- let(:nodes) do
- Project.order(Arel::Table.new(:projects)['name'].lower.asc).order(id: :asc)
+ where(:nodes) do
+ [
+ lazy { Issue.order(Issue.arel_table[:relative_position].desc.nulls_last) }
+]
end
- let(:ascending_nodes) { [project1, project5, project3, project2, project4] }
-
- it_behaves_like 'nodes are in ascending order'
+ with_them do
+ it_behaves_like 'nodes are in descending order'
+ end
end
- context 'when descending' do
- let(:nodes) do
- Project.order(Arel::Table.new(:projects)['name'].lower.desc).order(id: :desc)
+ context 'when ascending NULLS FIRST with a tie breaker' do
+ let(:ascending_nodes) { [issue1, issue4, issue2, issue3, issue5] }
+
+ where(:nodes) do
+ [
+ lazy { Issue.order(Issue.arel_table[:relative_position].asc.nulls_first).order(id: :asc) }
+]
end
- let(:descending_nodes) { [project4, project2, project3, project5, project1] }
+ with_them do
+ it_behaves_like 'nodes are in ascending order'
+ end
+ end
- it_behaves_like 'nodes are in descending order'
+ context 'when descending NULLS FIRST with a tie breaker' do
+ let(:descending_nodes) { [issue1, issue4, issue5, issue3, issue2] }
+
+ where(:nodes) do
+ [
+ lazy { Issue.order(Issue.arel_table[:relative_position].desc.nulls_first).order(id: :asc) }
+]
+ end
+
+ with_them do
+ it_behaves_like 'nodes are in descending order'
+ end
end
end