diff options
Diffstat (limited to 'spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb')
-rw-r--r-- | spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb new file mode 100644 index 00000000000..fb7e24eecf2 --- /dev/null +++ b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +# Use this for testing how a GraphQL query handles sorting and pagination. +# This is particularly important when using keyset pagination connection, +# which is the default for ActiveRecord relations, as certain sort keys +# might not be supportable. +# +# sort_param: the value to specify the sort +# data_path: the keys necessary to dig into the return GraphQL data to get the +# returned results +# first_param: number of items expected (like a page size) +# expected_results: array of comparison data of all items sorted correctly +# pagination_query: method that specifies the GraphQL query +# pagination_results_data: method that extracts the sorted data used to compare against +# the expected results +# +# Example: +# describe 'sorting and pagination' do +# let(:sort_project) { create(:project, :public) } +# let(:data_path) { [:project, :issues] } +# +# def pagination_query(params, page_info) +# graphql_query_for( +# 'project', +# { 'fullPath' => sort_project.full_path }, +# "issues(#{params}) { #{page_info} edges { node { iid weight } } }" +# ) +# end +# +# def pagination_results_data(data) +# data.map { |issue| issue.dig('node', 'iid').to_i } +# end +# +# context 'when sorting by weight' do +# ... +# context 'when ascending' do +# it_behaves_like 'sorted paginated query' do +# let(:sort_param) { 'WEIGHT_ASC' } +# let(:first_param) { 2 } +# let(:expected_results) { [weight_issue3.iid, weight_issue5.iid, weight_issue1.iid, weight_issue4.iid, weight_issue2.iid] } +# end +# end +# +RSpec.shared_examples 'sorted paginated query' do + it_behaves_like 'requires variables' do + let(:required_variables) { [:sort_param, :first_param, :expected_results, :data_path, :current_user] } + end + + describe do + let(:params) { "sort: #{sort_param}" } + let(:start_cursor) { graphql_data_at(*data_path, :pageInfo, :startCursor) } + let(:end_cursor) { graphql_data_at(*data_path, :pageInfo, :endCursor) } + let(:sorted_edges) { graphql_data_at(*data_path, :edges) } + let(:page_info) { "pageInfo { startCursor endCursor }" } + + def pagination_query(params, page_info) + raise('pagination_query(params, page_info) must be defined in the test, see example in comment') unless defined?(super) + + super + end + + def pagination_results_data(data) + raise('pagination_results_data(data) must be defined in the test, see example in comment') unless defined?(super) + + super(data) + end + + before do + post_graphql(pagination_query(params, page_info), current_user: current_user) + end + + context 'when sorting' do + it 'sorts correctly' do + expect(pagination_results_data(sorted_edges)).to eq expected_results + end + + context 'when paginating' do + let(:params) { "sort: #{sort_param}, first: #{first_param}" } + + it 'paginates correctly' do + expect(pagination_results_data(sorted_edges)).to eq expected_results.first(first_param) + + cursored_query = pagination_query("sort: #{sort_param}, after: \"#{end_cursor}\"", page_info) + post_graphql(cursored_query, current_user: current_user) + response_data = graphql_dig_at(Gitlab::Json.parse(response.body), :data, *data_path, :edges) + + expect(pagination_results_data(response_data)).to eq expected_results.drop(first_param) + end + end + end + end +end |