diff --git a/ee/spec/graphql/mutations/dast/profiles/delete_spec.rb b/ee/spec/graphql/mutations/dast/profiles/delete_spec.rb index 6985d51208c74c4b3924b02cd8f3b37ad83136fd..e0dc5cf9875f5de940c0de543332d87b8759634c 100644 --- a/ee/spec/graphql/mutations/dast/profiles/delete_spec.rb +++ b/ee/spec/graphql/mutations/dast/profiles/delete_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::Dast::Profiles::Delete do + include GraphqlHelpers + let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } let_it_be(:dast_profile) { create(:dast_profile, project: project) } @@ -36,7 +38,7 @@ end context 'when the dast_profile does not exist' do - let(:dast_profile_gid) { Gitlab::GlobalId.build(nil, model_name: 'Dast::Profile', id: 'does_not_exist') } + let(:dast_profile_gid) { global_id_of(id: 'does_not_exist', model_name: 'Dast::Profile') } it 'raises an exception' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/ee/spec/graphql/mutations/dast/profiles/run_spec.rb b/ee/spec/graphql/mutations/dast/profiles/run_spec.rb index a925848a2bf9b3e2ce11fd46f04a064324f456d4..52381bdd9df781600e34d54a526057b6506d9687 100644 --- a/ee/spec/graphql/mutations/dast/profiles/run_spec.rb +++ b/ee/spec/graphql/mutations/dast/profiles/run_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::Dast::Profiles::Run do + include GraphqlHelpers + let_it_be_with_refind(:project) { create(:project, :repository) } let_it_be(:user) { create(:user) } @@ -60,7 +62,7 @@ end context 'when the dast_profile does not exist' do - let(:dast_profile_id) { Gitlab::GlobalId.build(nil, model_name: 'Dast::Profile', id: 'does_not_exist') } + let(:dast_profile_id) { global_id_of(model_name: 'Dast::Profile', id: 'does_not_exist') } it 'raises an exception' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/ee/spec/graphql/mutations/dast/profiles/update_spec.rb b/ee/spec/graphql/mutations/dast/profiles/update_spec.rb index 7c24fb7117cdaa2b1e567c900a9d8a86c905987e..891f69e54ab0398a5566c13fa4c9c7d3efa2c525 100644 --- a/ee/spec/graphql/mutations/dast/profiles/update_spec.rb +++ b/ee/spec/graphql/mutations/dast/profiles/update_spec.rb @@ -159,7 +159,7 @@ end context 'when the dast_profile does not exist' do - let(:dast_profile_gid) { Gitlab::GlobalId.build(nil, model_name: 'Dast::Profile', id: 'does_not_exist') } + let(:dast_profile_gid) { global_id_of(model_name: 'Dast::Profile', id: 'does_not_exist') } it_behaves_like 'an unrecoverable failure' end diff --git a/ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb b/ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb index 0e6bed204dfd5eca6caa641f64f1ddbeb3828225..3275e3096ff49d7e83279c7086495c240fcd0f18 100644 --- a/ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb +++ b/ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::DastScannerProfiles::Delete do + include GraphqlHelpers + let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } let_it_be(:dast_scanner_profile) { create(:dast_scanner_profile, project: project) } @@ -38,7 +40,7 @@ end context 'when the dast_scanner_profile does not exist' do - let(:dast_scanner_profile_id) { Gitlab::GlobalId.build(nil, model_name: 'DastScannerProfile', id: 'does_not_exist') } + let(:dast_scanner_profile_id) { global_id_of(model_name: 'DastScannerProfile', id: 'does_not_exist') } it 'raises an exception' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/ee/spec/graphql/mutations/dast_scanner_profiles/update_spec.rb b/ee/spec/graphql/mutations/dast_scanner_profiles/update_spec.rb index 9f66936eadae139711e128ffeb48459ae99b2044..0006158e590834ece1cd2795c5660ef1df14d066 100644 --- a/ee/spec/graphql/mutations/dast_scanner_profiles/update_spec.rb +++ b/ee/spec/graphql/mutations/dast_scanner_profiles/update_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::DastScannerProfiles::Update do + include GraphqlHelpers + let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, group: group) } let_it_be(:user) { create(:user) } @@ -83,7 +85,7 @@ end context 'when dast scanner profile does not exist' do - let(:scanner_profile_id) { Gitlab::GlobalId.build(nil, model_name: 'DastScannerProfile', id: 'does_not_exist') } + let(:scanner_profile_id) { global_id_of(model_name: 'DastScannerProfile', id: 'does_not_exist') } it 'raises an exception' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/ee/spec/graphql/mutations/namespaces/increase_storage_temporarily_spec.rb b/ee/spec/graphql/mutations/namespaces/increase_storage_temporarily_spec.rb index 530023a4a63900067890fb7f78a82b39f6f692f5..c1391565a4ad3d4f289296f9605a18a2dc08f497 100644 --- a/ee/spec/graphql/mutations/namespaces/increase_storage_temporarily_spec.rb +++ b/ee/spec/graphql/mutations/namespaces/increase_storage_temporarily_spec.rb @@ -9,7 +9,7 @@ subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) } describe '#resolve' do - subject { mutation.resolve(id: namespace.to_global_id.to_s) } + subject { mutation.resolve(id: namespace.to_global_id) } before do allow_next_instance_of(EE::Namespace::RootStorageSize, namespace) do |root_storage| diff --git a/ee/spec/graphql/mutations/vulnerabilities/dismiss_spec.rb b/ee/spec/graphql/mutations/vulnerabilities/dismiss_spec.rb index 5eeacee54997263caf72b6ee7f9d510ee5f87342..927f5d101c2d3be330f0a3dfe8af5c78cc871831 100644 --- a/ee/spec/graphql/mutations/vulnerabilities/dismiss_spec.rb +++ b/ee/spec/graphql/mutations/vulnerabilities/dismiss_spec.rb @@ -9,7 +9,7 @@ describe '#resolve' do let_it_be(:vulnerability) { create(:vulnerability, :with_findings) } let_it_be(:user) { create(:user) } - let_it_be(:vulnerability_id) { GitlabSchema.id_from_object(vulnerability).to_s } + let_it_be(:vulnerability_id) { GitlabSchema.id_from_object(vulnerability) } let(:comment) { 'Dismissal Feedback' } let(:mutated_vulnerability) { subject[:vulnerability] } diff --git a/ee/spec/graphql/mutations/vulnerabilities/finding_dismiss_spec.rb b/ee/spec/graphql/mutations/vulnerabilities/finding_dismiss_spec.rb index 1a5f260f2660c60b240e27e1ac28c42a95d705f0..21a26c7f1d205596f4bb59c07e5ebc1b05d78595 100644 --- a/ee/spec/graphql/mutations/vulnerabilities/finding_dismiss_spec.rb +++ b/ee/spec/graphql/mutations/vulnerabilities/finding_dismiss_spec.rb @@ -9,7 +9,7 @@ describe '#resolve' do let_it_be(:finding) { create(:vulnerabilities_finding) } let_it_be(:user) { create(:user) } - let_it_be(:finding_id) { GitlabSchema.id_from_object(finding).to_s } + let_it_be(:finding_id) { global_id_of(finding) } let(:comment) { 'Dismissal Feedback' } let(:mutated_finding) { subject[:finding] } diff --git a/ee/spec/graphql/resolvers/network_policy_resolver_spec.rb b/ee/spec/graphql/resolvers/network_policy_resolver_spec.rb index ca0407b3b33ebbba71ee1e4928a2c82d9b109eab..257ec17868b7b54c55a81d90e147e82e6bb632ab 100644 --- a/ee/spec/graphql/resolvers/network_policy_resolver_spec.rb +++ b/ee/spec/graphql/resolvers/network_policy_resolver_spec.rb @@ -86,7 +86,7 @@ end context 'when environment_id is provided' do - let(:environment_id) { 'gid://gitlab/Environment/31' } + let(:environment_id) { global_id_of(model_name: 'Environment', id: 31) } it 'uses NetworkPolicies::ResourceService with resolved environment_id to fetch policies' do expect(NetworkPolicies::ResourcesService).to receive(:new).with(project: project, environment_id: '31') diff --git a/ee/spec/requests/api/graphql/boards/epic_board_list_epics_query_spec.rb b/ee/spec/requests/api/graphql/boards/epic_board_list_epics_query_spec.rb index 9f58329fe8b90f616ac9be47a65745dac83af693..e9071cc6e88c7f193995ecf300201034791c0854 100644 --- a/ee/spec/requests/api/graphql/boards/epic_board_list_epics_query_spec.rb +++ b/ee/spec/requests/api/graphql/boards/epic_board_list_epics_query_spec.rb @@ -45,10 +45,6 @@ def pagination_query(params = {}) let(:epic_fields) { all_graphql_fields_for('epics'.classify) } let(:all_records) { [epic2.to_global_id.to_s, epic1.to_global_id.to_s, epic3.to_global_id.to_s] } - def pagination_results_data(nodes) - nodes.map { |list| list['id'] } - end - it_behaves_like 'sorted paginated query' do # currently we don't support custom sorting for epic lists, # nil value will be ignored by ::Graphql::Arguments @@ -66,8 +62,8 @@ def pagination_results_data(nodes) post_graphql(query, current_user: current_user) - boards = graphql_data_at(*data_path, :nodes, :id) - expect(boards).to contain_exactly(global_id_of(epic3)) + boards = graphql_data_at(*data_path, :nodes) + expect(boards).to contain_exactly(a_graphql_entity_for(epic3)) end context 'when negated' do @@ -77,8 +73,8 @@ def pagination_results_data(nodes) post_graphql(query, current_user: current_user) - boards = graphql_data_at(*data_path, :nodes, :id) - expect(boards).to contain_exactly(global_id_of(epic1), global_id_of(epic2)) + boards = graphql_data_at(*data_path, :nodes) + expect(boards).to contain_exactly(a_graphql_entity_for(epic1), a_graphql_entity_for(epic2)) end end end diff --git a/ee/spec/requests/api/graphql/boards/epic_lists_query_spec.rb b/ee/spec/requests/api/graphql/boards/epic_lists_query_spec.rb index b4042fe83dbb2e503c83fea42d50c157bfbc7691..5e78c6713d4111b3efd993c83bc5e9aaad3ec838 100644 --- a/ee/spec/requests/api/graphql/boards/epic_lists_query_spec.rb +++ b/ee/spec/requests/api/graphql/boards/epic_lists_query_spec.rb @@ -78,8 +78,11 @@ def pagination_results_data(nodes) post_graphql(pagination_query, current_user: current_user) # ordered by list_type then position - backlog first and closed last. - assert_field_value('id', [global_id_of(list3), global_id_of(list1), global_id_of(list2)]) - assert_field_value('collapsed', [false, true, false]) + expect(list_nodes).to match [ + a_graphql_entity_for(list3, collapsed: false), + a_graphql_entity_for(list1, collapsed: true), + a_graphql_entity_for(list2, collapsed: false) + ] end it 'returns the correct metadata values' do @@ -97,13 +100,11 @@ def pagination_results_data(nodes) params = { epicFilters: { labelName: label.title, confidential: false } } post_graphql(pagination_query(params), current_user: current_user) - assert_field_value('epicsCount', [1, 0, 0]) - expected_metadata = [ - { 'epicsCount' => 1, 'totalWeight' => 7 }, - { 'epicsCount' => 0, 'totalWeight' => nil }, - { 'epicsCount' => 0, 'totalWeight' => nil } + expect(list_nodes).to match [ + a_hash_including('epicsCount' => 1, 'metadata' => { 'epicsCount' => 1, 'totalWeight' => 7 }), + a_hash_including('epicsCount' => 0, 'metadata' => { 'epicsCount' => 0, 'totalWeight' => nil }), + a_hash_including('epicsCount' => 0, 'metadata' => { 'epicsCount' => 0, 'totalWeight' => nil }) ] - assert_field_value('metadata', expected_metadata) end context 'when totalWeight not requested' do @@ -112,17 +113,17 @@ def pagination_results_data(nodes) it 'does not required the value from the service' do post_graphql(pagination_query, current_user: current_user) - expect(dig_data('metadata').first.keys).to match_array(['epicsCount']) + expect(list_nodes('metadata').first.keys).to match_array(['epicsCount']) end end end end def assert_field_value(field, expected_value) - expect(dig_data(field)).to eq(expected_value) + expect(list_nodes(field)).to eq(expected_value) end - def dig_data(field) - graphql_dig_at(graphql_data, 'group', 'epicBoard', 'lists', 'nodes', field) + def list_nodes(*fields) + graphql_dig_at(graphql_data, 'group', 'epicBoard', 'lists', 'nodes', *fields) end end diff --git a/ee/spec/requests/api/graphql/instance_security_dashboard_spec.rb b/ee/spec/requests/api/graphql/instance_security_dashboard_spec.rb index a1204eca52644428b727e8a6252f77f94374cb8d..42d85d9235df7e0a94861152deba68381fb3b27d 100644 --- a/ee/spec/requests/api/graphql/instance_security_dashboard_spec.rb +++ b/ee/spec/requests/api/graphql/instance_security_dashboard_spec.rb @@ -34,7 +34,7 @@ end it 'finds only projects that were added to instance security dashboard' do - expect(projects).to contain_exactly({ "id" => global_id_of(project) }) + expect(projects).to contain_exactly(a_graphql_entity_for(project)) end end end diff --git a/ee/spec/requests/api/graphql/merge_request_reviewer_spec.rb b/ee/spec/requests/api/graphql/merge_request_reviewer_spec.rb index a508ff6820a3601530a05143c78687266bcdd3ba..db31725f444d2d4b6729343dfb08d2d4e262607b 100644 --- a/ee/spec/requests/api/graphql/merge_request_reviewer_spec.rb +++ b/ee/spec/requests/api/graphql/merge_request_reviewer_spec.rb @@ -58,9 +58,8 @@ end it 'returns appropriate data' do - the_rule = { - 'id' => global_id_of(rule), - 'name' => rule.name, + the_rule = a_graphql_entity_for( + rule, :name, 'type' => 'CODE_OWNER', 'approvalsRequired' => 0, 'approved' => true, @@ -68,11 +67,11 @@ 'overridden' => false, 'section' => 'codeowners', 'sourceRule' => nil - } + ) post_graphql(query) - expect(interaction['applicableApprovalRules'].first).to include(the_rule) + expect(interaction['applicableApprovalRules'].first).to match the_rule end end end diff --git a/ee/spec/requests/api/graphql/merge_requests/approval_state_spec.rb b/ee/spec/requests/api/graphql/merge_requests/approval_state_spec.rb index e54756293e5d55e157ce0227187395fdf8c4849f..5f5ecea1676fe59eb051dc1134b9b359ee332566 100644 --- a/ee/spec/requests/api/graphql/merge_requests/approval_state_spec.rb +++ b/ee/spec/requests/api/graphql/merge_requests/approval_state_spec.rb @@ -93,24 +93,25 @@ it 'returns appropriate data' do post_graphql(query) - expect(approval_state).to eq({ + expect(approval_state).to match a_hash_including( 'approvalRulesOverwritten' => false, - 'rules' => [{ - 'approvalsRequired' => 0, - 'approved' => true, - 'approvedBy' => { 'nodes' => [] }, - 'containsHiddenGroups' => false, - 'eligibleApprovers' => [{ 'id' => global_id_of(user) }], - 'groups' => { 'nodes' => [] }, - 'id' => global_id_of(code_owner_rule), - 'name' => code_owner_rule.name, - 'overridden' => false, - 'section' => 'codeowners', - 'sourceRule' => nil, - 'type' => 'CODE_OWNER', - 'users' => { 'nodes' => [{ 'id' => global_id_of(user) }] } - }] - }) + 'rules' => contain_exactly( + a_graphql_entity_for( + code_owner_rule, :name, + 'approvalsRequired' => 0, + 'approved' => true, + 'approvedBy' => { 'nodes' => [] }, + 'containsHiddenGroups' => false, + 'eligibleApprovers' => contain_exactly(a_graphql_entity_for(user)), + 'groups' => { 'nodes' => [] }, + 'overridden' => false, + 'section' => 'codeowners', + 'sourceRule' => nil, + 'type' => 'CODE_OWNER', + 'users' => { 'nodes' => contain_exactly(a_graphql_entity_for(user)) } + ) + ) + ) end end end diff --git a/ee/spec/requests/api/graphql/mutations/dast/profiles/create_spec.rb b/ee/spec/requests/api/graphql/mutations/dast/profiles/create_spec.rb index eab23cb92da1b84008512635e016e49e22b0fcbe..fddba08e0f26d7c521d8f8b7979140ff7923e102 100644 --- a/ee/spec/requests/api/graphql/mutations/dast/profiles/create_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/dast/profiles/create_spec.rb @@ -33,7 +33,7 @@ it 'returns dastProfile.id' do subject - expect(mutation_response.dig('dastProfile', 'id')).to eq(global_id_of(dast_profile)) + expect(mutation_response['dastProfile']).to match a_graphql_entity_for(dast_profile) end it 'returns dastProfile.editPath' do diff --git a/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/create_spec.rb b/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/create_spec.rb index 3c10a6a8cd6ab6d3a1b47a103a6358639d66a2ed..5f23280a79081b9859ec4a5d5a3d7733da8d9411 100644 --- a/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/create_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/create_spec.rb @@ -26,11 +26,11 @@ it 'returns the dast_scanner_profile id' do post_graphql_mutation(mutation, current_user: current_user) - expect(mutation_response['id']).to eq(global_id_of(dast_scanner_profile)) + expect(mutation_response).to match a_graphql_entity_for(dast_scanner_profile) expect(mutation_response).to have_key('dastScannerProfile') profile = mutation_response['dastScannerProfile'] - expect(profile['id']).to eq(global_id_of(dast_scanner_profile)) + expect(profile).to match a_graphql_entity_for(dast_scanner_profile) expect(profile['profileName']).to eq(dast_scanner_profile.name) end diff --git a/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/update_spec.rb b/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/update_spec.rb index c999796fc76df6bd9385a1308ecb30d1f65165d3..43c6be0a1738b44a2f9517981df22d494c46893e 100644 --- a/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/update_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/update_spec.rb @@ -39,15 +39,14 @@ def mutation_response it_behaves_like 'an on-demand scan mutation when user cannot run an on-demand scan' it_behaves_like 'an on-demand scan mutation when user can run an on-demand scan' do - it 'returns the dast_scanner_profile' do + it 'returns the dast_scanner_profile', :aggregate_failures do subject - expect(mutation_response['id']).to eq(global_id_of(dast_scanner_profile)) + expect(mutation_response).to match a_graphql_entity_for(dast_scanner_profile) expect(mutation_response).to have_key('dastScannerProfile') profile = mutation_response['dastScannerProfile'] - expect(profile['id']).to eq(global_id_of(dast_scanner_profile)) - expect(profile['profileName']).to eq(new_profile_name) + expect(profile).to match a_graphql_entity_for(dast_scanner_profile, profile_name: new_profile_name) end it 'updates the dast_scanner_profile' do diff --git a/ee/spec/requests/api/graphql/mutations/dast_site_profiles/create_spec.rb b/ee/spec/requests/api/graphql/mutations/dast_site_profiles/create_spec.rb index fae7544c1406d9aa20a1baf84a0460dedac8eb3f..221a0a0bc0750b58d3c962ef8b21cb19e129d775 100644 --- a/ee/spec/requests/api/graphql/mutations/dast_site_profiles/create_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/dast_site_profiles/create_spec.rb @@ -43,7 +43,7 @@ dast_site_profile = DastSiteProfile.find_by(project: project, name: profile_name) - expect(mutation_response).to include('id' => global_id_of(dast_site_profile)) + expect(mutation_response).to match(a_graphql_entity_for(dast_site_profile)) end end end diff --git a/ee/spec/requests/api/graphql/mutations/dast_site_tokens/create_spec.rb b/ee/spec/requests/api/graphql/mutations/dast_site_tokens/create_spec.rb index d7c462418729543cd20353535b4957acf162da64..0904a2df2c05d1cde9677aa58da3aa0d40beb190 100644 --- a/ee/spec/requests/api/graphql/mutations/dast_site_tokens/create_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/dast_site_tokens/create_spec.rb @@ -31,7 +31,7 @@ dast_site_token = DastSiteToken.find_by!(project: project, token: uuid) - expect(mutation_response["id"]).to eq(global_id_of(dast_site_token)) + expect(mutation_response).to match a_graphql_entity_for(dast_site_token) end it 'creates a new dast_site_token' do diff --git a/ee/spec/requests/api/graphql/mutations/dast_site_validations/create_spec.rb b/ee/spec/requests/api/graphql/mutations/dast_site_validations/create_spec.rb index ceee690c3a9408fa034e125f295435145b7b8795..513a478be34ebb023244b1817a7730057f1638ce 100644 --- a/ee/spec/requests/api/graphql/mutations/dast_site_validations/create_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/dast_site_validations/create_spec.rb @@ -31,7 +31,7 @@ dast_site_validation = DastSiteValidation.find_by!(url_path: validation_path) - expect(mutation_response["id"]).to eq(global_id_of(dast_site_validation)) + expect(mutation_response).to match a_graphql_entity_for(dast_site_validation) end it 'creates a new dast_site_validation' do diff --git a/ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb b/ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb index d6142035aeb112205da2fb9222db01ea476db6ea..08d2f9994f6321baff39a275a979450e559d8488 100644 --- a/ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb @@ -71,8 +71,8 @@ expect(response).to have_gitlab_http_status(:success) - expect(oncall_rotation_response.slice(*%w[id name length lengthUnit])).to eq( - 'id' => global_id_of(new_oncall_rotation), + expect(oncall_rotation_response.slice(*%w[id name length lengthUnit])).to match a_graphql_entity_for( + new_oncall_rotation, 'name' => args[:name], 'length' => 1, 'lengthUnit' => 'DAYS' @@ -81,13 +81,8 @@ start_time = "#{args[:starts_at][:date]} #{args[:starts_at][:time]}".in_time_zone(schedule.timezone) expect(Time.parse(oncall_rotation_response['startsAt'])).to eq(start_time) - expect(oncall_rotation_response.dig('participants', 'nodes')).to contain_exactly( - { - 'user' => { - 'id' => global_id_of(current_user), - 'username' => current_user.username - } - } + expect(oncall_rotation_response.dig('participants', 'nodes')).to contain_exactly a_hash_including( + 'user' => a_graphql_entity_for(current_user, :username) ) end diff --git a/ee/spec/requests/api/graphql/mutations/issues/set_escalation_policy_spec.rb b/ee/spec/requests/api/graphql/mutations/issues/set_escalation_policy_spec.rb index e7009b150343261ce3a6c8b3123d19ef85cddc8e..21574e8e4abaddce546eacecd78be1ff7202883b 100644 --- a/ee/spec/requests/api/graphql/mutations/issues/set_escalation_policy_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/issues/set_escalation_policy_spec.rb @@ -67,8 +67,9 @@ expect(response).to have_gitlab_http_status(:success) expect(mutation_response['errors']).to be_empty - expect(mutation_response['issue']['escalationPolicy']['id']).to eq(global_id_of(escalation_policy)) - expect(mutation_response['issue']['escalationPolicy']['name']).to eq(escalation_policy.name) + expect(mutation_response['issue']['escalationPolicy']).to match a_graphql_entity_for( + escalation_policy, :name + ) expect(escalation_status.reload.policy).to eq(escalation_policy) end diff --git a/ee/spec/requests/api/graphql/mutations/issues/update_spec.rb b/ee/spec/requests/api/graphql/mutations/issues/update_spec.rb index edbd20be2bae382b9fdc4126ce2aee0dbc87bf59..31cadccb8e622145af158a0958aa0676aea05331 100644 --- a/ee/spec/requests/api/graphql/mutations/issues/update_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/issues/update_spec.rb @@ -51,7 +51,7 @@ expect(response).to have_gitlab_http_status(:success) expect(graphql_errors).to be_blank expect(mutated_issue).to include( - 'epic' => include('id' => global_id_of(epic)) + 'epic' => a_graphql_entity_for(epic) ) end diff --git a/ee/spec/requests/api/graphql/namespace/compliance_frameworks_spec.rb b/ee/spec/requests/api/graphql/namespace/compliance_frameworks_spec.rb index 4e2e7b273dd6235cdaddd37579e1ced67d3f4e54..d96845aa264c1b548bb963aea2c63480c5dd38be 100644 --- a/ee/spec/requests/api/graphql/namespace/compliance_frameworks_spec.rb +++ b/ee/spec/requests/api/graphql/namespace/compliance_frameworks_spec.rb @@ -28,8 +28,8 @@ post_graphql(query, current_user: current_user) expect(graphql_data_at(*path)).to contain_exactly( - a_hash_including('id' => global_id_of(compliance_framework_1)), - a_hash_including('id' => global_id_of(compliance_framework_2)) + a_graphql_entity_for(compliance_framework_1), + a_graphql_entity_for(compliance_framework_2) ) end @@ -43,7 +43,7 @@ it 'returns only a single compliance framework' do post_graphql(query, current_user: current_user) - expect(graphql_data_at(:namespace, :complianceFrameworks, :nodes).map { |n| n['id'] }).to contain_exactly(global_id_of(compliance_framework_1)) + expect(graphql_data_at(:namespace, :complianceFrameworks, :nodes)).to contain_exactly(a_graphql_entity_for(compliance_framework_1)) end end diff --git a/ee/spec/requests/api/graphql/project/alert_management/http_integrations_spec.rb b/ee/spec/requests/api/graphql/project/alert_management/http_integrations_spec.rb index b8a23767f6bac08905335f7ad140f7e07a3437c9..d6b04a97437e6ab52205bbff3d835e005e841168 100644 --- a/ee/spec/requests/api/graphql/project/alert_management/http_integrations_spec.rb +++ b/ee/spec/requests/api/graphql/project/alert_management/http_integrations_spec.rb @@ -107,13 +107,10 @@ it 'returns the correct properties of the integrations' do expect(integrations).to include( - { - 'id' => global_id_of(active_http_integration), + a_graphql_entity_for( + active_http_integration, + :token, :name, :active, :url, 'type' => 'HTTP', - 'name' => active_http_integration.name, - 'active' => active_http_integration.active, - 'token' => active_http_integration.token, - 'url' => active_http_integration.url, 'apiUrl' => nil, 'payloadExample' => payload_example.to_json, 'payloadAttributeMappings' => [ @@ -142,19 +139,16 @@ 'type' => 'STRING' } ] - }, - { - 'id' => global_id_of(inactive_http_integration), + ), + a_graphql_entity_for( + inactive_http_integration, + :name, :active, :token, :url, 'type' => 'HTTP', - 'name' => inactive_http_integration.name, - 'active' => inactive_http_integration.active, - 'token' => inactive_http_integration.token, - 'url' => inactive_http_integration.url, 'apiUrl' => nil, 'payloadExample' => "{}", 'payloadAttributeMappings' => [], 'payloadAlertFields' => [] - } + ) ) end end @@ -164,22 +158,15 @@ it_behaves_like 'a working graphql query' - specify { expect(integrations).to be_one } - it 'returns the correct properties of the integration' do - expect(integrations).to include( - { - 'id' => global_id_of(inactive_http_integration), - 'type' => 'HTTP', - 'name' => inactive_http_integration.name, - 'active' => inactive_http_integration.active, - 'token' => inactive_http_integration.token, - 'url' => inactive_http_integration.url, - 'apiUrl' => nil, - 'payloadExample' => "{}", - 'payloadAttributeMappings' => [], - 'payloadAlertFields' => [] - } + expect(integrations).to contain_exactly a_graphql_entity_for( + inactive_http_integration, + :name, :active, :token, :url, + 'type' => 'HTTP', + 'apiUrl' => nil, + 'payloadExample' => "{}", + 'payloadAttributeMappings' => [], + 'payloadAlertFields' => [] ) end end diff --git a/ee/spec/requests/projects/on_demand_scans_controller_spec.rb b/ee/spec/requests/projects/on_demand_scans_controller_spec.rb index 97593b2243f02a379d96ad4e08f127a4d98c702a..0cd5fcd627a2051866f0bd26f027a4d4084026fe 100644 --- a/ee/spec/requests/projects/on_demand_scans_controller_spec.rb +++ b/ee/spec/requests/projects/on_demand_scans_controller_spec.rb @@ -106,12 +106,12 @@ get edit_path json_data = { - id: global_id_of(dast_profile), + **a_graphql_entity_for(dast_profile), name: dast_profile.name, description: dast_profile.description, branch: { name: project.default_branch_or_main }, - dastSiteProfile: { id: global_id_of(DastSiteProfile.new(id: dast_profile.dast_site_profile_id)) }, - dastScannerProfile: { id: global_id_of(DastScannerProfile.new(id: dast_profile.dast_scanner_profile_id)) }, + dastSiteProfile: a_graphql_entity_for(DastSiteProfile.new(id: dast_profile.dast_site_profile_id)), + dastScannerProfile: a_graphql_entity_for(DastScannerProfile.new(id: dast_profile.dast_scanner_profile_id)), dastProfileSchedule: { active: dast_profile_schedule.active, cadence: { @@ -125,7 +125,7 @@ on_demand_div = Nokogiri::HTML.parse(response.body).at_css('div#js-on-demand-scans-form') - expect(on_demand_div.attributes['data-dast-scan'].value).to include(json_data) + expect(on_demand_div.attributes['data-dast-scan'].value).to eq json_data end end diff --git a/ee/spec/requests/projects/security/dast_site_profiles_controller_spec.rb b/ee/spec/requests/projects/security/dast_site_profiles_controller_spec.rb index 1432748112d31df3f9fb8f020fd2734c8f618606..b713a0b0784964dd7d84aecbd8f318a8de4e4b76 100644 --- a/ee/spec/requests/projects/security/dast_site_profiles_controller_spec.rb +++ b/ee/spec/requests/projects/security/dast_site_profiles_controller_spec.rb @@ -106,14 +106,12 @@ def with_user_authorized it 'includes a serialized dast_profile in the response body' do get edit_path - json_data = { - id: global_id_of(dast_site_profile), - name: dast_site_profile.name, + json_data = a_graphql_entity_for( + dast_site_profile, :name, :excluded_urls, :referenced_in_security_policies, targetUrl: dast_site_profile.dast_site.url, targetType: dast_site_profile.target_type.upcase, - excludedUrls: dast_site_profile.excluded_urls, requestHeaders: Dast::SiteProfilePresenter::REDACTED_REQUEST_HEADERS, - auth: { + auth: a_graphql_entity_for( enabled: dast_site_profile.auth_enabled, url: dast_site_profile.auth_url, username: dast_site_profile.auth_username, @@ -121,13 +119,13 @@ def with_user_authorized password: Dast::SiteProfilePresenter::REDACTED_PASSWORD, passwordField: dast_site_profile.auth_password_field, submitField: dast_site_profile.auth_submit_field - }, - referencedInSecurityPolicies: dast_site_profile.referenced_in_security_policies - }.to_json + ) + ) form = Nokogiri::HTML.parse(response.body).at_css('div.js-dast-site-profile-form') + serialized = Gitlab::Json.parse(form.attributes['data-site-profile'].value) - expect(form.attributes['data-site-profile'].value).to include(json_data) + expect(serialized).to match(json_data) end end diff --git a/spec/graphql/mutations/container_repositories/destroy_spec.rb b/spec/graphql/mutations/container_repositories/destroy_spec.rb index 3903196a51115f51e642bca450b4e3c07b241f62..7c674dddb1514e850eb7fa516a8568a507f71961 100644 --- a/spec/graphql/mutations/container_repositories/destroy_spec.rb +++ b/spec/graphql/mutations/container_repositories/destroy_spec.rb @@ -9,7 +9,7 @@ let_it_be(:user) { create(:user) } let(:project) { container_repository.project } - let(:id) { container_repository.to_global_id.to_s } + let(:id) { container_repository.to_global_id } specify { expect(described_class).to require_graphql_authorizations(:destroy_container_image) } diff --git a/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb b/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb index f22d9ffe753b3fee9859c3dbf4daedb8fad5fdc7..3e5f28ee244fd1e571c27f00085e88b9b718aa5c 100644 --- a/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb +++ b/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb @@ -3,10 +3,12 @@ require 'spec_helper' RSpec.describe Mutations::ContainerRepositories::DestroyTags do + include GraphqlHelpers + include_context 'container repository delete tags service shared context' using RSpec::Parameterized::TableSyntax - let(:id) { repository.to_global_id.to_s } + let(:id) { repository.to_global_id } specify { expect(described_class).to require_graphql_authorizations(:destroy_container_image) } @@ -67,8 +69,8 @@ end end - context 'with invalid id' do - let(:id) { 'gid://gitlab/ContainerRepository/5555' } + context 'with non-existing id' do + let(:id) { global_id_of(id: non_existing_record_id, model_name: 'ContainerRepository') } it_behaves_like 'denying access to container respository' end diff --git a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb index d17d11305b1fa8ea2a28764d6de82803f2dfd1f4..dafc7b4c367c2a2738ba77d0a2f9a1b5f6f3a14f 100644 --- a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb +++ b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::CustomerRelations::Contacts::Create do + include GraphqlHelpers + let_it_be(:user) { create(:user) } let(:group) { create(:group, :crm_enabled) } @@ -78,9 +80,9 @@ end end - context 'when organization_id is invalid' do + context 'when organization does not exist' do before do - valid_params[:organization_id] = "gid://gitlab/CustomerRelations::Organization/#{non_existing_record_id}" + valid_params[:organization_id] = global_id_of(model_name: 'CustomerRelations::Organization', id: non_existing_record_id) end it 'returns the relevant error' do diff --git a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb index 2041b86d6e7656dd122bbb24785897f8e0f5a249..e5dc6f85c2ace44dea402b524448683958079c49 100644 --- a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb +++ b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::Discussions::ToggleResolve do + include GraphqlHelpers + subject(:mutation) do described_class.new(object: nil, context: { current_user: user }, field: nil) end @@ -15,7 +17,7 @@ mutation.resolve(id: id_arg, resolve: resolve_arg) end - let(:id_arg) { discussion.to_global_id.to_s } + let(:id_arg) { global_id_of(discussion) } let(:resolve_arg) { true } let(:mutated_discussion) { subject[:discussion] } let(:errors) { subject[:errors] } @@ -36,7 +38,7 @@ let_it_be(:user) { create(:user, developer_projects: [project]) } context 'when discussion cannot be found' do - let(:id_arg) { "#{discussion.to_global_id}foo" } + let(:id_arg) { global_id_of(id: non_existing_record_id, model_name: discussion.class.name) } it 'raises an error' do expect { subject }.to raise_error( @@ -52,7 +54,7 @@ it 'raises an error' do expect { subject }.to raise_error( GraphQL::CoercionError, - "\"#{discussion.to_global_id}\" does not represent an instance of Discussion" + "\"#{global_id_of(discussion)}\" does not represent an instance of Discussion" ) end end diff --git a/spec/graphql/mutations/environments/canary_ingress/update_spec.rb b/spec/graphql/mutations/environments/canary_ingress/update_spec.rb index fdf9cbaf25b447b7670772ba72664069c0d9d535..e719ca050a86d72de1589ac25d5aae4ac78d043a 100644 --- a/spec/graphql/mutations/environments/canary_ingress/update_spec.rb +++ b/spec/graphql/mutations/environments/canary_ingress/update_spec.rb @@ -20,7 +20,7 @@ describe '#resolve' do subject { mutation.resolve(id: environment_id, weight: weight) } - let(:environment_id) { environment.to_global_id.to_s } + let(:environment_id) { environment.to_global_id } let(:weight) { 50 } let(:update_service) { double('update_service') } diff --git a/spec/graphql/mutations/release_asset_links/delete_spec.rb b/spec/graphql/mutations/release_asset_links/delete_spec.rb index cda292f2ffa99ce70535587ca00b3fd3fd8dc3e9..67576bdda573aecf92956661b4370c44bf3938f0 100644 --- a/spec/graphql/mutations/release_asset_links/delete_spec.rb +++ b/spec/graphql/mutations/release_asset_links/delete_spec.rb @@ -52,7 +52,9 @@ end context "when the link doesn't exist" do - let(:mutation_arguments) { super().merge(id: "gid://gitlab/Releases::Link/#{non_existing_record_id}") } + let(:mutation_arguments) do + super().merge(id: global_id_of(id: non_existing_record_id, model_name: release_link.class.name)) + end it 'raises an error' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/spec/graphql/mutations/release_asset_links/update_spec.rb b/spec/graphql/mutations/release_asset_links/update_spec.rb index 6464868733685024b4956c7af7356c2c224f33a5..cb7474123ada01699ea2f874afcdf9bf3aff3ce7 100644 --- a/spec/graphql/mutations/release_asset_links/update_spec.rb +++ b/spec/graphql/mutations/release_asset_links/update_spec.rb @@ -186,7 +186,9 @@ end context "when the link doesn't exist" do - let(:mutation_arguments) { super().merge(id: "gid://gitlab/Releases::Link/#{non_existing_record_id}") } + let(:mutation_arguments) do + super().merge(id: global_id_of(id: non_existing_record_id, model_name: "Releases::Link")) + end it 'raises an error' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/spec/graphql/mutations/timelogs/delete_spec.rb b/spec/graphql/mutations/timelogs/delete_spec.rb index 5012d10f32e316b30e4a6dacfd4ee67c565e9a09..f4a258e0f78b9287e62d1951c69bb3e5f562d23d 100644 --- a/spec/graphql/mutations/timelogs/delete_spec.rb +++ b/spec/graphql/mutations/timelogs/delete_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Mutations::Timelogs::Delete do + include GraphqlHelpers + let_it_be(:author) { create(:user) } let_it_be(:maintainer) { create(:user) } let_it_be(:administrator) { create(:user, :admin) } @@ -11,7 +13,7 @@ let_it_be_with_reload(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) } let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) } - let(:timelog_id) { timelog.to_global_id.to_s } + let(:timelog_id) { global_id_of(timelog) } let(:mutation_arguments) { { id: timelog_id } } describe '#resolve' do @@ -21,7 +23,7 @@ context 'when the timelog id is not valid' do let(:current_user) { author } - let(:timelog_id) { 'gid://gitlab/Timelog/%d' % non_existing_record_id } + let(:timelog_id) { global_id_of(model_name: 'Timelog', id: non_existing_record_id) } it 'raises Gitlab::Graphql::Errors::ResourceNotAvailable' do expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/spec/graphql/resolvers/concerns/resolves_ids_spec.rb b/spec/graphql/resolvers/concerns/resolves_ids_spec.rb index 1dd27c0eff06d92e03169b06ec5c6fbcb248bce2..732b7cd2bbc55a1a7248a0f405dc554f4a68124a 100644 --- a/spec/graphql/resolvers/concerns/resolves_ids_spec.rb +++ b/spec/graphql/resolvers/concerns/resolves_ids_spec.rb @@ -3,33 +3,35 @@ require 'spec_helper' RSpec.describe ResolvesIds do + include GraphqlHelpers + # gid://gitlab/Project/6 # gid://gitlab/Issue/6 # gid://gitlab/Project/6 gid://gitlab/Issue/6 context 'with a single project' do - let(:ids) { 'gid://gitlab/Project/6' } + let(:ids) { global_id_of(model_name: 'Project', id: 6) } let(:type) { ::Types::GlobalIDType[::Project] } it 'returns the correct array' do - expect(resolve_ids).to match_array(['6']) + expect(resolve_ids).to contain_exactly('6') end end context 'with a single issue' do - let(:ids) { 'gid://gitlab/Issue/9' } + let(:ids) { global_id_of(model_name: 'Issue', id: 9) } let(:type) { ::Types::GlobalIDType[::Issue] } it 'returns the correct array' do - expect(resolve_ids).to match_array(['9']) + expect(resolve_ids).to contain_exactly('9') end end context 'with multiple users' do - let(:ids) { ['gid://gitlab/User/7', 'gid://gitlab/User/13', 'gid://gitlab/User/21'] } + let(:ids) { [7, 13, 21].map { global_id_of(model_name: 'User', id: _1) } } let(:type) { ::Types::GlobalIDType[::User] } it 'returns the correct array' do - expect(resolve_ids).to match_array(%w[7 13 21]) + expect(resolve_ids).to eq %w[7 13 21] end end diff --git a/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb b/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb index a16e8821cb5641f2cef9053ce1071a8abcbc416f..3fe1ec4b5a4c2643f2d4f934bde9ff539f18a3d4 100644 --- a/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/design_at_version_resolver_spec.rb @@ -14,7 +14,7 @@ let(:current_user) { user } let(:object) { issue.design_collection } - let(:global_id) { GitlabSchema.id_from_object(design_at_version).to_s } + let(:global_id) { GitlabSchema.id_from_object(design_at_version) } let(:design_at_version) { ::DesignManagement::DesignAtVersion.new(design: design_a, version: version_a) } diff --git a/spec/graphql/resolvers/design_management/design_resolver_spec.rb b/spec/graphql/resolvers/design_management/design_resolver_spec.rb index 4c8b311687584185a12c2139adf59d990acf1d9a..5b530b68a5b3f809355127d72648f8e7ffb830a2 100644 --- a/spec/graphql/resolvers/design_management/design_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/design_resolver_spec.rb @@ -24,7 +24,7 @@ create(:design, issue: create(:issue, project: project), versions: [create(:design_version)]) end - let(:args) { { id: GitlabSchema.id_from_object(first_design).to_s } } + let(:args) { { id: GitlabSchema.id_from_object(first_design) } } let(:gql_context) { { current_user: current_user } } before do @@ -50,7 +50,7 @@ end context 'when both arguments have been passed' do - let(:args) { { filename: first_design.filename, id: GitlabSchema.id_from_object(first_design).to_s } } + let(:args) { { filename: first_design.filename, id: GitlabSchema.id_from_object(first_design) } } it 'generates an error' do expect_graphql_error_to_be_created(::Gitlab::Graphql::Errors::ArgumentError, /may/) do diff --git a/spec/graphql/resolvers/design_management/designs_resolver_spec.rb b/spec/graphql/resolvers/design_management/designs_resolver_spec.rb index b091e58b06f703f805a7eb2457553aead349d28c..64eae14d8883b8d37026d918d1620f24a6630b61 100644 --- a/spec/graphql/resolvers/design_management/designs_resolver_spec.rb +++ b/spec/graphql/resolvers/design_management/designs_resolver_spec.rb @@ -109,6 +109,8 @@ end def resolve_designs - resolve(described_class, obj: issue.design_collection, args: args, ctx: gql_context) + Gitlab::Graphql::Lazy.force( + resolve(described_class, obj: issue.design_collection, args: args, ctx: gql_context) + ) end end diff --git a/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb index 32c53ba23027a4f7e33504650d985ed320c3a287..4b34a750883580c9c3fb1c478820dd31618d1287 100644 --- a/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb +++ b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb @@ -74,6 +74,6 @@ def resolve_error(args = {}, context = { current_user: current_user }) end def issue_global_id(issue_id) - Gitlab::ErrorTracking::DetailedError.new(id: issue_id).to_global_id.to_s + Gitlab::ErrorTracking::DetailedError.new(id: issue_id).to_global_id end end diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb index 84fa29328294604417b813f24e4b2d7e2d7142c7..da2747fdf72509995d505157226ac5ab37a423b6 100644 --- a/spec/graphql/resolvers/timelog_resolver_spec.rb +++ b/spec/graphql/resolvers/timelog_resolver_spec.rb @@ -265,7 +265,7 @@ context 'when > `default_max_page_size` records' do let(:object) { nil } let!(:timelog_list) { create_list(:timelog, 101, issue: issue) } - let(:args) { { project_id: "gid://gitlab/Project/#{project.id}" } } + let(:args) { { project_id: global_id_of(project) } } let(:extra_args) { {} } it 'pagination returns `default_max_page_size` and sets `has_next_page` true' do diff --git a/spec/graphql/resolvers/work_item_resolver_spec.rb b/spec/graphql/resolvers/work_item_resolver_spec.rb index bfa0cf1d8a2a1923c294fe0a989b9bb6f9671018..c44ed39510241c2335cad9a523cc15cfd76bac91 100644 --- a/spec/graphql/resolvers/work_item_resolver_spec.rb +++ b/spec/graphql/resolvers/work_item_resolver_spec.rb @@ -12,7 +12,7 @@ let(:current_user) { developer } - subject(:resolved_work_item) { resolve_work_item('id' => work_item.to_gid.to_s) } + subject(:resolved_work_item) { resolve_work_item('id' => work_item.to_gid) } context 'when the user can read the work item' do it { is_expected.to eq(work_item) } diff --git a/spec/graphql/types/terraform/state_version_type_spec.rb b/spec/graphql/types/terraform/state_version_type_spec.rb index b015a2045da7a179e8a1fdc67cfb13fe6a1c974e..6a17d932d034efe2eb5979204432ed87c1a8efe2 100644 --- a/spec/graphql/types/terraform/state_version_type_spec.rb +++ b/spec/graphql/types/terraform/state_version_type_spec.rb @@ -52,8 +52,8 @@ shared_examples 'returning latest version' do it 'returns latest version of terraform state' do - expect(execute.dig('data', 'project', 'terraformState', 'latestVersion', 'id')).to eq( - global_id_of(terraform_state.latest_version) + expect(execute.dig('data', 'project', 'terraformState', 'latestVersion')).to match a_graphql_entity_for( + terraform_state.latest_version ) end end diff --git a/spec/requests/api/graphql/boards/board_lists_query_spec.rb b/spec/requests/api/graphql/boards/board_lists_query_spec.rb index e8fb9daa43b503cc7471c57a303fe82b90f860da..eb206465bce5c5129f8e4e9e50da5c6b9151673f 100644 --- a/spec/requests/api/graphql/boards/board_lists_query_spec.rb +++ b/spec/requests/api/graphql/boards/board_lists_query_spec.rb @@ -69,6 +69,10 @@ def query(list_params = params) let(:data_path) { [board_parent_type, :boards, :nodes, 0, :lists] } + def pagination_results_data(lists) + lists + end + def pagination_query(params) graphql_query_for( board_parent_type, @@ -94,7 +98,7 @@ def pagination_query(params) it_behaves_like 'sorted paginated query' do let(:sort_param) { } let(:first_param) { 2 } - let(:all_records) { lists.map { |list| global_id_of(list) } } + let(:all_records) { lists.map { |list| a_graphql_entity_for(list) } } end end end diff --git a/spec/requests/api/graphql/ci/job_spec.rb b/spec/requests/api/graphql/ci/job_spec.rb index ddb2664d353dcd639e6d9c6c6bb3205be975f543..2fb90dcd92b469b96c2c13a9e00be66e3ce00399 100644 --- a/spec/requests/api/graphql/ci/job_spec.rb +++ b/spec/requests/api/graphql/ci/job_spec.rb @@ -47,10 +47,8 @@ ) post_graphql(query, current_user: user) - expect(graphql_data_at(*path)).to match a_hash_including( - 'id' => global_id_of(job_2), - 'name' => job_2.name, - 'allowFailure' => job_2.allow_failure, + expect(graphql_data_at(*path)).to match a_graphql_entity_for( + job_2, :name, :allow_failure, 'duration' => 25, 'kind' => 'BUILD', 'queuedDuration' => 2.0, @@ -66,10 +64,7 @@ it 'retrieves scalar fields' do post_graphql(query, current_user: user) - expect(graphql_data_at(*path)).to match a_hash_including( - 'id' => global_id_of(job_2), - 'name' => job_2.name - ) + expect(graphql_data_at(*path)).to match a_graphql_entity_for(job_2, :name) end end end @@ -102,8 +97,8 @@ 'name' => test_stage.name, 'jobs' => a_hash_including( 'nodes' => contain_exactly( - a_hash_including('id' => global_id_of(job_2)), - a_hash_including('id' => global_id_of(job_3)) + a_graphql_entity_for(job_2), + a_graphql_entity_for(job_3) ) ) ) diff --git a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb index 922a9ab277ef6ffeb475bb40961158b00a2a8b5f..847fa72522e2a14bb0f1c83ed2d5500d37ea7e1f 100644 --- a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb +++ b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb @@ -127,7 +127,7 @@ let(:query) do <<~GQL - query($id: ID!, $n: Int) { + query($id: ContainerRepositoryID!, $n: Int) { containerRepository(id: $id) { tags(first: $n) { edges { @@ -157,7 +157,7 @@ let(:query) do <<~GQL - query($id: ID!, $n: ContainerRepositoryTagSort) { + query($id: ContainerRepositoryID!, $n: ContainerRepositoryTagSort) { containerRepository(id: $id) { tags(sort: $n) { edges { @@ -194,7 +194,7 @@ let(:query) do <<~GQL - query($id: ID!, $n: String) { + query($id: ContainerRepositoryID!, $n: String) { containerRepository(id: $id) { tags(name: $n) { edges { @@ -232,7 +232,7 @@ let(:query) do <<~GQL - query($id: ID!) { + query($id: ContainerRepositoryID!) { containerRepository(id: $id) { size } diff --git a/spec/requests/api/graphql/current_user_todos_spec.rb b/spec/requests/api/graphql/current_user_todos_spec.rb index 7f37abba74aa76a8328816529b9a4e8c10495b8d..da1c893ec2bb684242f33b789d84caebf5b933d2 100644 --- a/spec/requests/api/graphql/current_user_todos_spec.rb +++ b/spec/requests/api/graphql/current_user_todos_spec.rb @@ -37,8 +37,8 @@ post_graphql(query, current_user: current_user) expect(todoable_response).to contain_exactly( - a_hash_including('id' => global_id_of(done_todo)), - a_hash_including('id' => global_id_of(pending_todo)) + a_graphql_entity_for(done_todo), + a_graphql_entity_for(pending_todo) ) end @@ -63,7 +63,7 @@ post_graphql(query, current_user: current_user) expect(todoable_response).to contain_exactly( - a_hash_including('id' => global_id_of(pending_todo)) + a_graphql_entity_for(pending_todo) ) end end @@ -75,7 +75,7 @@ post_graphql(query, current_user: current_user) expect(todoable_response).to contain_exactly( - a_hash_including('id' => global_id_of(done_todo)) + a_graphql_entity_for(done_todo) ) end end diff --git a/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb b/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb index 3527c8183f6a49e9e0b91b82d27fb02d917f6491..c7149c100b25a6caaf8dedc709085e9ee725c137 100644 --- a/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb +++ b/spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb @@ -122,12 +122,12 @@ let(:current_user) { owner } context 'with default sorting' do - let_it_be(:descending_manifests) { manifests.reverse.map { |manifest| global_id_of(manifest)} } + let_it_be(:descending_manifests) { manifests.reverse.map { |manifest| global_id_of(manifest) } } it_behaves_like 'sorted paginated query' do let(:sort_param) { '' } let(:first_param) { 2 } - let(:all_records) { descending_manifests } + let(:all_records) { descending_manifests.map(&:to_s) } end end diff --git a/spec/requests/api/graphql/group/group_members_spec.rb b/spec/requests/api/graphql/group/group_members_spec.rb index 8830320c6f7524a4ceb396a18054d981c6fd1f83..fec866486ae893cff59716669c1f2573ae651e45 100644 --- a/spec/requests/api/graphql/group/group_members_spec.rb +++ b/spec/requests/api/graphql/group/group_members_spec.rb @@ -24,8 +24,8 @@ expect(graphql_errors).to be_nil expect(graphql_data_at(:group, :group_members, :edges, :node)).to contain_exactly( - { 'user' => { 'id' => global_id_of(user_1) } }, - { 'user' => { 'id' => global_id_of(user_2) } }, + { 'user' => a_graphql_entity_for(user_1) }, + { 'user' => a_graphql_entity_for(user_2) }, 'user' => nil ) end @@ -224,8 +224,8 @@ def member_notification_email_query(group_path) def expect_array_response(*items) expect(response).to have_gitlab_http_status(:success) - member_gids = graphql_data_at(:group, :group_members, :edges, :node, :user, :id) + members = graphql_data_at(:group, :group_members, :edges, :node, :user) - expect(member_gids).to match_array(items.map { |u| global_id_of(u) }) + expect(members).to match_array(items.map { |u| a_graphql_entity_for(u) }) end end diff --git a/spec/requests/api/graphql/group/merge_requests_spec.rb b/spec/requests/api/graphql/group/merge_requests_spec.rb index c0faff11c8d2dfede3407d25322e72e7ea0f2efc..434b0d16569962521074a457219e9c1618728799 100644 --- a/spec/requests/api/graphql/group/merge_requests_spec.rb +++ b/spec/requests/api/graphql/group/merge_requests_spec.rb @@ -39,7 +39,7 @@ end def expected_mrs(mrs) - mrs.map { |mr| a_hash_including('id' => global_id_of(mr)) } + mrs.map { |mr| a_graphql_entity_for(mr) } end describe 'not passing any arguments' do diff --git a/spec/requests/api/graphql/group/milestones_spec.rb b/spec/requests/api/graphql/group/milestones_spec.rb index 2b80b5239c891726590f7c3939d36918f29cca7c..7c51409f9074e617959182b4625723dbfa32c230 100644 --- a/spec/requests/api/graphql/group/milestones_spec.rb +++ b/spec/requests/api/graphql/group/milestones_spec.rb @@ -170,10 +170,8 @@ def post_query end it 'returns correct values for scalar fields' do - expect(post_query).to eq({ - 'id' => global_id_of(milestone), - 'title' => milestone.title, - 'description' => milestone.description, + expect(post_query).to match a_graphql_entity_for( + milestone, :title, :description, 'state' => 'active', 'webPath' => milestone_path(milestone), 'dueDate' => milestone.due_date.iso8601, @@ -183,7 +181,7 @@ def post_query 'projectMilestone' => false, 'groupMilestone' => true, 'subgroupMilestone' => false - }) + ) end context 'milestone statistics' do diff --git a/spec/requests/api/graphql/issue/issue_spec.rb b/spec/requests/api/graphql/issue/issue_spec.rb index 42ca3348384abb3c9750e2ec3bd60b2826946511..05fd6bf30226a7034f03b140e6b5a5ecf5c4a6d7 100644 --- a/spec/requests/api/graphql/issue/issue_spec.rb +++ b/spec/requests/api/graphql/issue/issue_spec.rb @@ -8,8 +8,8 @@ let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:issue, project: project) } let_it_be(:current_user) { create(:user) } - let_it_be(:issue_params) { { 'id' => issue.to_global_id.to_s } } + let(:issue_params) { { 'id' => global_id_of(issue) } } let(:issue_data) { graphql_data['issue'] } let(:issue_fields) { all_graphql_fields_for('Issue'.classify) } @@ -100,7 +100,8 @@ def query(fields) let_it_be(:issue_fields) { ['moved', 'movedTo { title }'] } let_it_be(:new_issue) { create(:issue) } let_it_be(:issue) { create(:issue, project: project, moved_to: new_issue) } - let_it_be(:issue_params) { { 'id' => issue.to_global_id.to_s } } + + let(:issue_params) { { 'id' => global_id_of(issue) } } before_all do new_issue.project.add_developer(current_user) diff --git a/spec/requests/api/graphql/merge_request/merge_request_spec.rb b/spec/requests/api/graphql/merge_request/merge_request_spec.rb index 75dd01a07630a7566d75028cc3f617af37254f35..d89f381753ea5a24cd729ed8ac7c3610db9c0c9d 100644 --- a/spec/requests/api/graphql/merge_request/merge_request_spec.rb +++ b/spec/requests/api/graphql/merge_request/merge_request_spec.rb @@ -8,8 +8,8 @@ let_it_be(:project) { create(:project, :empty_repo) } let_it_be(:merge_request) { create(:merge_request, source_project: project) } let_it_be(:current_user) { create(:user) } - let_it_be(:merge_request_params) { { 'id' => merge_request.to_global_id.to_s } } + let(:merge_request_params) { { 'id' => global_id_of(merge_request) } } let(:merge_request_data) { graphql_data['mergeRequest'] } let(:merge_request_fields) { all_graphql_fields_for('MergeRequest'.classify) } diff --git a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb index 02b79dac489a9f97cd683430f74a16138d4e7e23..715507c3cc536db4b4219fc9b2bac176be39fd02 100644 --- a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb @@ -15,7 +15,7 @@ let(:operation_mode) { Types::MutationOperationModeEnum.default_mode } let(:initial_contacts) { contacts[0..1] } let(:mutation_contacts) { contacts[1..2] } - let(:contact_ids) { contact_global_ids(mutation_contacts) } + let(:contact_ids) { mutation_contacts.map { global_id_of(_1) } } let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" } let(:mutation) do @@ -45,8 +45,8 @@ def mutation_response graphql_mutation_response(:issue_set_crm_contacts) end - def contact_global_ids(contacts) - contacts.map { |contact| global_id_of(contact) } + def expected_contacts(contacts) + contacts.map { |contact| a_graphql_entity_for(contact) } end before do @@ -58,8 +58,8 @@ def contact_global_ids(contacts) it 'updates the issue with correct contacts' do post_graphql_mutation(mutation, current_user: user) - expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes, :id)) - .to match_array(contact_global_ids(mutation_contacts)) + expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes)) + .to match_array(expected_contacts(mutation_contacts)) end end @@ -70,8 +70,8 @@ def contact_global_ids(contacts) it 'updates the issue with correct contacts' do post_graphql_mutation(mutation, current_user: user) - expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes, :id)) - .to match_array(contact_global_ids(initial_contacts + mutation_contacts)) + expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes)) + .to match_array(expected_contacts(initial_contacts + mutation_contacts)) end end @@ -82,8 +82,8 @@ def contact_global_ids(contacts) it 'updates the issue with correct contacts' do post_graphql_mutation(mutation, current_user: user) - expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes, :id)) - .to match_array(contact_global_ids(initial_contacts - mutation_contacts)) + expect(graphql_data_at(:issue_set_crm_contacts, :issue, :customer_relations_contacts, :nodes)) + .to match_array(expected_contacts(initial_contacts - mutation_contacts)) end end end @@ -117,7 +117,7 @@ def contact_global_ids(contacts) it_behaves_like 'successful mutation' context 'when the contact does not exist' do - let(:contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] } + let(:contact_ids) { [global_id_of(model_name: 'CustomerRelations::Contact', id: non_existing_record_id)] } it 'returns expected error' do post_graphql_mutation(mutation, current_user: user) @@ -159,7 +159,7 @@ def contact_global_ids(contacts) context 'when trying to remove non-existent contact' do let(:operation_mode) { Types::MutationOperationModeEnum.enum[:remove] } - let(:contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] } + let(:contact_ids) { [global_id_of(model_name: 'CustomerRelations::Contact', id: non_existing_record_id)] } it 'raises expected error' do post_graphql_mutation(mutation, current_user: user) diff --git a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb index 63b94dccca0cd056d4cfc039ed3f7bc90522a917..dee8f80bc5d9d125690e72a85d847ddd91c3bee6 100644 --- a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb @@ -64,7 +64,7 @@ def mutation_response it 'creates a Note in a discussion' do post_graphql_mutation(mutation, current_user: current_user) - expect(mutation_response['note']['discussion']['id']).to eq(discussion.to_global_id.to_s) + expect(mutation_response['note']['discussion']).to match a_graphql_entity_for(discussion) end context 'when the discussion_id is not for a Discussion' do diff --git a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb index 89e3a71280f6730f6ddd882eec18f8fdd9cb50d3..0f7ccac3179d765fe90ce7d004e57fe91e671776 100644 --- a/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb +++ b/spec/requests/api/graphql/mutations/notes/reposition_image_diff_note_spec.rb @@ -39,7 +39,7 @@ def mutation_response post_graphql_mutation(mutation, current_user: current_user) end.to change { note.reset.position.x }.to(10) - expect(mutation_response['note']).to eq('id' => global_id_of(note)) + expect(mutation_response['note']).to match a_graphql_entity_for(note) expect(mutation_response['errors']).to be_empty end @@ -59,7 +59,7 @@ def mutation_response post_graphql_mutation(mutation, current_user: current_user) end.not_to change { note.reset.position.x } - expect(mutation_response['note']).to eq('id' => global_id_of(note)) + expect(mutation_response['note']).to match a_graphql_entity_for(note) expect(mutation_response['errors']).to be_empty end end diff --git a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb index c5c34e167177d0f2df9f4683e367ccdcc03490dd..dc20fde8e3cb4b8fa8053a875f74131c6a4f6373 100644 --- a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb @@ -46,8 +46,8 @@ def mutation_response expect(todo3.reload.state).to eq('done') expect(other_user_todo.reload.state).to eq('pending') - updated_todo_ids = mutation_response['todos'].map { |todo| todo['id'] } - expect(updated_todo_ids).to contain_exactly(global_id_of(todo1), global_id_of(todo3)) + updated_todos = mutation_response['todos'] + expect(updated_todos).to contain_exactly(a_graphql_entity_for(todo1), a_graphql_entity_for(todo3)) end context 'when target_id is given', :aggregate_failures do @@ -66,8 +66,8 @@ def mutation_response expect(todo1.reload.state).to eq('pending') expect(todo3.reload.state).to eq('pending') - updated_todo_ids = mutation_response['todos'].map { |todo| todo['id'] } - expect(updated_todo_ids).to contain_exactly(global_id_of(target_todo1), global_id_of(target_todo2)) + updated_todos = mutation_response['todos'] + expect(updated_todos).to contain_exactly(a_graphql_entity_for(target_todo1), a_graphql_entity_for(target_todo2)) end context 'when target does not exist' do diff --git a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb index 70e3cc7f5cdc67db9013254fa08032b38e2263f9..4316bd060c175c9d230fe3ba98f4961935fb1bc9 100644 --- a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb @@ -11,8 +11,8 @@ let_it_be(:author) { create(:user) } let_it_be(:other_user) { create(:user) } - let_it_be(:todo1) { create(:todo, user: current_user, author: author, state: :done, target: issue) } - let_it_be(:todo2) { create(:todo, user: current_user, author: author, state: :done, target: issue) } + let_it_be_with_reload(:todo1) { create(:todo, user: current_user, author: author, state: :done, target: issue) } + let_it_be_with_reload(:todo2) { create(:todo, user: current_user, author: author, state: :done, target: issue) } let_it_be(:other_user_todo) { create(:todo, user: other_user, author: author, state: :done) } @@ -50,8 +50,8 @@ def mutation_response expect(mutation_response).to include( 'errors' => be_empty, 'todos' => contain_exactly( - { 'id' => global_id_of(todo1), 'state' => 'pending' }, - { 'id' => global_id_of(todo2), 'state' => 'pending' } + a_graphql_entity_for(todo1, 'state' => 'pending'), + a_graphql_entity_for(todo2, 'state' => 'pending') ) ) end diff --git a/spec/requests/api/graphql/packages/conan_spec.rb b/spec/requests/api/graphql/packages/conan_spec.rb index 84c5af33e5d634343769fb865dbb23a7f4b05bf8..1f3732980d90c690e4d78d0501cb1ffb8de4e1ab 100644 --- a/spec/requests/api/graphql/packages/conan_spec.rb +++ b/spec/requests/api/graphql/packages/conan_spec.rb @@ -37,22 +37,19 @@ it_behaves_like 'a package with files' it 'has the correct metadata' do - expect(metadata_response).to include( - 'id' => global_id_of(package.conan_metadatum), - 'recipe' => package.conan_metadatum.recipe, - 'packageChannel' => package.conan_metadatum.package_channel, - 'packageUsername' => package.conan_metadatum.package_username, - 'recipePath' => package.conan_metadatum.recipe_path + expect(metadata_response).to match( + a_graphql_entity_for(package.conan_metadatum, + :recipe, :package_channel, :package_username, :recipe_path) ) end it 'has the correct file metadata' do - expect(first_file_response_metadata).to include( - 'id' => global_id_of(first_file.conan_file_metadatum), - 'packageRevision' => first_file.conan_file_metadatum.package_revision, - 'conanPackageReference' => first_file.conan_file_metadatum.conan_package_reference, - 'recipeRevision' => first_file.conan_file_metadatum.recipe_revision, - 'conanFileType' => first_file.conan_file_metadatum.conan_file_type.upcase + expect(first_file_response_metadata).to match( + a_graphql_entity_for( + first_file.conan_file_metadatum, + :package_revision, :conan_package_reference, :recipe_revision, + conan_file_type: first_file.conan_file_metadatum.conan_file_type.upcase + ) ) end end diff --git a/spec/requests/api/graphql/packages/maven_spec.rb b/spec/requests/api/graphql/packages/maven_spec.rb index d28d32b0df5e92a3e616e05e21095725bbd5e531..9d59a9226609d27df49ce013f0bb0c9df743b2ac 100644 --- a/spec/requests/api/graphql/packages/maven_spec.rb +++ b/spec/requests/api/graphql/packages/maven_spec.rb @@ -11,12 +11,8 @@ shared_examples 'correct maven metadata' do it 'has the correct metadata' do - expect(metadata_response).to include( - 'id' => global_id_of(package.maven_metadatum), - 'path' => package.maven_metadatum.path, - 'appGroup' => package.maven_metadatum.app_group, - 'appVersion' => package.maven_metadatum.app_version, - 'appName' => package.maven_metadatum.app_name + expect(metadata_response).to match a_graphql_entity_for( + package.maven_metadatum, :path, :app_group, :app_version, :app_name ) end end diff --git a/spec/requests/api/graphql/packages/nuget_spec.rb b/spec/requests/api/graphql/packages/nuget_spec.rb index ba8d2ca42d22541d714ff9f405a66500847f9441..87cffc67ce56205c6388d11cd0e16520ea33172d 100644 --- a/spec/requests/api/graphql/packages/nuget_spec.rb +++ b/spec/requests/api/graphql/packages/nuget_spec.rb @@ -22,24 +22,19 @@ it_behaves_like 'a package with files' it 'has the correct metadata' do - expect(metadata_response).to include( - 'id' => global_id_of(package.nuget_metadatum), - 'licenseUrl' => package.nuget_metadatum.license_url, - 'projectUrl' => package.nuget_metadatum.project_url, - 'iconUrl' => package.nuget_metadatum.icon_url + expect(metadata_response).to match a_graphql_entity_for( + package.nuget_metadatum, :license_url, :project_url, :icon_url ) end it 'has dependency links' do - expect(dependency_link_response).to include( - 'id' => global_id_of(dependency_link), + expect(dependency_link_response).to match a_graphql_entity_for( + dependency_link, 'dependencyType' => dependency_link.dependency_type.upcase ) - expect(dependency_response).to include( - 'id' => global_id_of(dependency_link.dependency), - 'name' => dependency_link.dependency.name, - 'versionPattern' => dependency_link.dependency.version_pattern + expect(dependency_response).to match a_graphql_entity_for( + dependency_link.dependency, :name, :version_pattern ) end diff --git a/spec/requests/api/graphql/packages/pypi_spec.rb b/spec/requests/api/graphql/packages/pypi_spec.rb index 64fe7d29a7af78bc0fcf19d87081da4bb86a14d2..0cc5bd2e3b2afd07064e70944ff9bd14562d3e8b 100644 --- a/spec/requests/api/graphql/packages/pypi_spec.rb +++ b/spec/requests/api/graphql/packages/pypi_spec.rb @@ -19,9 +19,8 @@ it_behaves_like 'a package with files' it 'has the correct metadata' do - expect(metadata_response).to include( - 'id' => global_id_of(package.pypi_metadatum), - 'requiredPython' => package.pypi_metadatum.required_python + expect(metadata_response).to match a_graphql_entity_for( + package.pypi_metadatum, :required_python ) end end diff --git a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb index 1793d4961eb3361c8220903cc48dae7ba553dd82..773922c1864d14e4dbc0dc89913ade3fbc73b82d 100644 --- a/spec/requests/api/graphql/project/alert_management/integrations_spec.rb +++ b/spec/requests/api/graphql/project/alert_management/integrations_spec.rb @@ -53,33 +53,24 @@ end context 'when no extra params given' do - let(:http_integration_response) { integrations.first } - let(:prometheus_integration_response) { integrations.second } - it_behaves_like 'a working graphql query' - it { expect(integrations.size).to eq(2) } - it 'returns the correct properties of the integrations' do - expect(http_integration_response).to include( - 'id' => global_id_of(active_http_integration), - 'type' => 'HTTP', - 'name' => active_http_integration.name, - 'active' => active_http_integration.active, - 'token' => active_http_integration.token, - 'url' => active_http_integration.url, - 'apiUrl' => nil - ) - - expect(prometheus_integration_response).to include( - 'id' => global_id_of(prometheus_integration), - 'type' => 'PROMETHEUS', - 'name' => 'Prometheus', - 'active' => prometheus_integration.manual_configuration?, - 'token' => project_alerting_setting.token, - 'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json", - 'apiUrl' => prometheus_integration.api_url - ) + expect(integrations).to match [ + a_graphql_entity_for( + active_http_integration, + :name, :active, :token, :url, type: 'HTTP', api_url: nil + ), + a_graphql_entity_for( + prometheus_integration, + 'type' => 'PROMETHEUS', + 'name' => 'Prometheus', + 'active' => prometheus_integration.manual_configuration?, + 'token' => project_alerting_setting.token, + 'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json", + 'apiUrl' => prometheus_integration.api_url + ) + ] end end @@ -88,17 +79,9 @@ it_behaves_like 'a working graphql query' - it { expect(integrations).to be_one } - it 'returns the correct properties of the HTTP integration' do - expect(integrations.first).to include( - 'id' => global_id_of(active_http_integration), - 'type' => 'HTTP', - 'name' => active_http_integration.name, - 'active' => active_http_integration.active, - 'token' => active_http_integration.token, - 'url' => active_http_integration.url, - 'apiUrl' => nil + expect(integrations).to contain_exactly a_graphql_entity_for( + active_http_integration, :name, :active, :token, :url, type: 'HTTP', api_url: nil ) end end @@ -108,11 +91,9 @@ it_behaves_like 'a working graphql query' - it { expect(integrations).to be_one } - it 'returns the correct properties of the Prometheus Integration' do - expect(integrations.first).to include( - 'id' => global_id_of(prometheus_integration), + expect(integrations).to contain_exactly a_graphql_entity_for( + prometheus_integration, 'type' => 'PROMETHEUS', 'name' => 'Prometheus', 'active' => prometheus_integration.manual_configuration?, diff --git a/spec/requests/api/graphql/project/cluster_agents_spec.rb b/spec/requests/api/graphql/project/cluster_agents_spec.rb index c9900fea277b045493a484ced832d110657b1d6b..a34df0ee6f4f12236b94910b6ad5585b396c5f3a 100644 --- a/spec/requests/api/graphql/project/cluster_agents_spec.rb +++ b/spec/requests/api/graphql/project/cluster_agents_spec.rb @@ -29,7 +29,7 @@ post_graphql(query, current_user: current_user) expect(graphql_data_at(:project, :cluster_agents, :nodes)).to match_array( - agents.map { |agent| a_hash_including('id' => global_id_of(agent)) } + agents.map { |agent| a_graphql_entity_for(agent) } ) end @@ -62,9 +62,9 @@ tokens = graphql_data_at(:project, :cluster_agents, :nodes, :tokens, :nodes) expect(tokens).to match([ - a_hash_including('id' => global_id_of(token_3)), - a_hash_including('id' => global_id_of(token_2)), - a_hash_including('id' => global_id_of(token_1)) + a_graphql_entity_for(token_3), + a_graphql_entity_for(token_2), + a_graphql_entity_for(token_1) ]) end diff --git a/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb b/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb index f544d78ecbb256be85438b6879a895b2eed5c091..8cda61f0628b29c391bff17cef1b377629d6699d 100644 --- a/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb +++ b/spec/requests/api/graphql/project/issue/design_collection/version_spec.rb @@ -71,11 +71,7 @@ def query(vq = version_fields) it 'finds all the designs as of the given version' do post_query - expect(data).to match( - a_hash_including( - 'id' => global_id_of(design_at_version), - 'filename' => design.filename - )) + expect(data).to match a_graphql_entity_for(design_at_version, filename: design.filename) end context 'when the current_user is not authorized' do @@ -119,7 +115,8 @@ def query(vq = version_fields) let(:results) do issue.designs.visible_at_version(version).map do |d| dav = build(:design_at_version, design: d, version: version) - { 'id' => global_id_of(dav), 'filename' => d.filename } + + a_graphql_entity_for(dav, filename: d.filename) end end @@ -132,8 +129,8 @@ def query(vq = version_fields) describe 'filtering' do let(:designs) { issue.designs.sample(3) } let(:filenames) { designs.map(&:filename) } - let(:ids) do - designs.map { |d| global_id_of(build(:design_at_version, design: d, version: version)) } + let(:expected_designs) do + designs.map { |d| a_graphql_entity_for(build(:design_at_version, design: d, version: version)) } end before do @@ -144,7 +141,7 @@ def query(vq = version_fields) let(:dav_params) { { filenames: filenames } } it 'finds the designs by filename' do - expect(data.map { |e| e.dig('node', 'id') }).to match_array(ids) + expect(data.map { |e| e['node'] }).to match_array expected_designs end end @@ -160,9 +157,9 @@ def query(vq = version_fields) describe 'pagination' do let(:end_cursor) { graphql_data_at(*path_prefix, :designs_at_version, :page_info, :end_cursor) } - let(:ids) do + let(:entities) do ::DesignManagement::Design.visible_at_version(version).order(:id).map do |d| - global_id_of(build(:design_at_version, design: d, version: version)) + a_graphql_entity_for(build(:design_at_version, design: d, version: version)) end end @@ -178,19 +175,19 @@ def query(vq = version_fields) let(:fields) { ['pageInfo { endCursor }', 'edges { node { id } }'] } def response_values(data = graphql_data) - data.dig(*path).map { |e| e.dig('node', 'id') } + data.dig(*path).map { |e| e['node'] } end it 'sorts designs for reliable pagination' do post_graphql(query, current_user: current_user) - expect(response_values).to match_array(ids.take(2)) + expect(response_values).to match_array(entities.take(2)) post_graphql(cursored_query, current_user: current_user) new_data = Gitlab::Json.parse(response.body).fetch('data') - expect(response_values(new_data)).to match_array(ids.drop(2)) + expect(response_values(new_data)).to match_array(entities.drop(2)) end end end @@ -202,9 +199,7 @@ def response_values(data = graphql_data) end let(:results) do - version.designs.map do |design| - { 'id' => global_id_of(design), 'filename' => design.filename } - end + version.designs.map { |design| a_graphql_entity_for(design, :filename) } end it 'finds all the designs as of the given version' do diff --git a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb index 459a30508ebf3e4f87bc9c90ddc2bb916a98ca40..02bc9457c0710b1b6b276fefdb72f2c2e90b5d6f 100644 --- a/spec/requests/api/graphql/project/issue/designs/designs_spec.rb +++ b/spec/requests/api/graphql/project/issue/designs/designs_spec.rb @@ -58,8 +58,8 @@ def design_image_url(design, ref: nil, size: nil) post_graphql(query, current_user: current_user) - expect(design_response).to eq( - 'id' => design.to_global_id.to_s, + expect(design_response).to match a_graphql_entity_for( + design, 'event' => 'CREATION', 'fullPath' => design.full_path, 'filename' => design.filename, @@ -93,7 +93,7 @@ def design_image_url(design, ref: nil, size: nil) let(:end_cursor) { design_collection.dig('designs', 'pageInfo', 'endCursor') } - let(:ids) { issue.designs.order(:id).map { |d| global_id_of(d) } } + let(:expected_designs) { issue.designs.order(:id).map { |d| a_graphql_entity_for(d) } } let(:query) { make_query(designs_fragment(first: 2)) } @@ -107,19 +107,19 @@ def designs_fragment(params) query_graphql_field(:designs, params, design_query_fields) end - def response_ids(data = graphql_data) + def response_designs(data = graphql_data) path = %w[project issue designCollection designs edges] - data.dig(*path).map { |e| e.dig('node', 'id') } + data.dig(*path).map { |e| e['node'] } end it 'sorts designs for reliable pagination' do - expect(response_ids).to match_array(ids.take(2)) + expect(response_designs).to match_array(expected_designs.take(2)) post_graphql(cursored_query, current_user: current_user) new_data = Gitlab::Json.parse(response.body).fetch('data') - expect(response_ids(new_data)).to match_array(ids.drop(2)) + expect(response_designs(new_data)).to match_array(expected_designs.drop(2)) end end diff --git a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb index de2ace95757177ce2ef5efd2c740ed4b89db51f2..3b1eb0b4b0254d9e360a360a2bcd430b0a5ac8ef 100644 --- a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb +++ b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb @@ -51,7 +51,7 @@ def query(fields) design_data = designs_data['nodes'].first note_data = design_data['notes']['nodes'].first - expect(note_data['id']).to eq(note.to_global_id.to_s) + expect(note_data).to match(a_graphql_entity_for(note)) end def query(note_fields = all_graphql_fields_for(Note, max_depth: 1)) diff --git a/spec/requests/api/graphql/project/issue_spec.rb b/spec/requests/api/graphql/project/issue_spec.rb index ddf63a8f2c962e9cea191ebc995c5c95a3926c97..2415e9ef60f18109a0fa807497dc7c2bdc7aed29 100644 --- a/spec/requests/api/graphql/project/issue_spec.rb +++ b/spec/requests/api/graphql/project/issue_spec.rb @@ -144,10 +144,7 @@ data = graphql_data.dig(*path) - expect(data).to match( - a_hash_including('id' => global_id_of(version), - 'sha' => version.sha) - ) + expect(data).to match a_graphql_entity_for(version, :sha) end end @@ -184,6 +181,6 @@ end def id_hash(object) - a_hash_including('id' => global_id_of(object)) + a_graphql_entity_for(object) end end diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb index cefe88aafc89bd133674faa07355ef3157a1e742..395b052369e0180b59fc324b367d2de5eedcf48e 100644 --- a/spec/requests/api/graphql/project/merge_request_spec.rb +++ b/spec/requests/api/graphql/project/merge_request_spec.rb @@ -66,7 +66,7 @@ it 'includes reviewers' do expected = merge_request.reviewers.map do |r| - a_hash_including('id' => global_id_of(r), 'username' => r.username) + a_graphql_entity_for(r, :username) end post_graphql(query, current_user: current_user) diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb index 303748bc70ecc170cacfdc06f13df3e40ca96d6f..c7f121c48ab8b8537c15bac6cfc5fe8d3444f07c 100644 --- a/spec/requests/api/graphql/project/merge_requests_spec.rb +++ b/spec/requests/api/graphql/project/merge_requests_spec.rb @@ -9,7 +9,7 @@ let_it_be(:current_user) { create(:user) } let_it_be(:label) { create(:label, project: project) } - let_it_be(:merge_request_a) do + let_it_be_with_reload(:merge_request_a) do create(:labeled_merge_request, :unique_branches, source_project: project, labels: [label]) end @@ -412,6 +412,10 @@ def user_collection describe 'sorting and pagination' do let(:data_path) { [:project, :mergeRequests] } + def pagination_results_data(nodes) + nodes + end + def pagination_query(params) graphql_query_for(:project, { full_path: project.full_path }, <<~QUERY) mergeRequests(#{params}) { @@ -429,7 +433,7 @@ def pagination_query(params) merge_request_c, merge_request_e, merge_request_a - ].map { |mr| global_id_of(mr) } + ].map { |mr| a_graphql_entity_for(mr) } end before do @@ -455,7 +459,7 @@ def pagination_query(params) query = pagination_query(params) post_graphql(query, current_user: current_user) - expect(results.map { |item| item["id"] }).to eq(all_records.last(2)) + expect(results).to match(all_records.last(2)) end end end @@ -469,7 +473,7 @@ def pagination_query(params) merge_request_c, merge_request_e, merge_request_a - ].map { |mr| global_id_of(mr) } + ].map { |mr| a_graphql_entity_for(mr) } end before do @@ -495,7 +499,7 @@ def pagination_query(params) query = pagination_query(params) post_graphql(query, current_user: current_user) - expect(results.map { |item| item["id"] }).to eq(all_records.last(2)) + expect(results).to match(all_records.last(2)) end end end diff --git a/spec/requests/api/graphql/project/milestones_spec.rb b/spec/requests/api/graphql/project/milestones_spec.rb index 2fede4c728537080d77dce6e4c5e2d5a0368b4d6..3e8948d83b18b1cda3960492ae50722e061e1dbb 100644 --- a/spec/requests/api/graphql/project/milestones_spec.rb +++ b/spec/requests/api/graphql/project/milestones_spec.rb @@ -33,7 +33,7 @@ def query_milestones(fields) def result_list(expected) expected.map do |milestone| - a_hash_including('id' => global_id_of(milestone)) + a_graphql_entity_for(milestone) end end diff --git a/spec/requests/api/graphql/project/pipeline_spec.rb b/spec/requests/api/graphql/project/pipeline_spec.rb index 73e02e2a4b1214ed0a9104690483a5073820e3ce..ccf97918021f65bcfef73de7c9d68eb96f8814de 100644 --- a/spec/requests/api/graphql/project/pipeline_spec.rb +++ b/spec/requests/api/graphql/project/pipeline_spec.rb @@ -89,17 +89,16 @@ def successful_pipeline post_graphql(query, current_user: current_user) expect(graphql_data_at(*path, :jobs, :nodes)).to contain_exactly( - a_hash_including( - 'name' => build_job.name, - 'status' => build_job.status.upcase, - 'duration' => build_job.duration + a_graphql_entity_for( + build_job, :name, :duration, + 'status' => build_job.status.upcase ), - a_hash_including( - 'id' => global_id_of(failed_build), + a_graphql_entity_for( + failed_build, 'status' => failed_build.status.upcase ), - a_hash_including( - 'id' => global_id_of(bridge), + a_graphql_entity_for( + bridge, 'status' => bridge.status.upcase ) ) @@ -135,7 +134,7 @@ def successful_pipeline post_graphql(query, current_user: current_user, variables: variables) expect(graphql_data_at(*path, :jobs, :nodes)) - .to contain_exactly(a_hash_including('id' => global_id_of(failed_build))) + .to contain_exactly(a_graphql_entity_for(failed_build)) end end @@ -166,7 +165,7 @@ def successful_pipeline end let(:the_job) do - a_hash_including('name' => build_job.name, 'id' => global_id_of(build_job)) + a_graphql_entity_for(build_job, :name) end it 'can request a build by name' do diff --git a/spec/requests/api/graphql/project/project_members_spec.rb b/spec/requests/api/graphql/project/project_members_spec.rb index 315d44884ffc08a001ddd05be309971122edace0..c3281b44954833e68a1759500a3803b920f5e1f3 100644 --- a/spec/requests/api/graphql/project/project_members_spec.rb +++ b/spec/requests/api/graphql/project/project_members_spec.rb @@ -60,7 +60,10 @@ fetch_members(project: parent_project, args: { relations: [:DIRECT] }) expect(graphql_errors).to be_nil - expect(graphql_data_at(:project, :project_members, :edges, :node)).to contain_exactly({ 'user' => { 'id' => global_id_of(user) } }, 'user' => nil) + expect(graphql_data_at(:project, :project_members, :edges, :node)).to contain_exactly( + a_graphql_entity_for(user: a_graphql_entity_for(user)), + { 'user' => nil } + ) end end @@ -238,7 +241,7 @@ def members_query(group_path, args = {}) def expect_array_response(*items) expect(response).to have_gitlab_http_status(:success) - member_gids = graphql_data_at(:project, :project_members, :edges, :node, :user, :id) - expect(member_gids).to match_array(items.map { |u| global_id_of(u) }) + members = graphql_data_at(:project, :project_members, :edges, :node, :user) + expect(members).to match_array(items.map { |u| a_graphql_entity_for(u) }) end end diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb index 77abac4ef04b41e37e0a654ee4e1f910ef6ef179..c4899dbb71e7a8a1142bdac319ea152eaea3ba60 100644 --- a/spec/requests/api/graphql/project/release_spec.rb +++ b/spec/requests/api/graphql/project/release_spec.rb @@ -77,10 +77,10 @@ def query(rq = release_fields) post_query expected = release.milestones.order_by_dates_and_title.map do |milestone| - { 'id' => global_id_of(milestone), 'title' => milestone.title } + a_graphql_entity_for(milestone, :title) end - expect(data).to eq(expected) + expect(data).to match(expected) end end @@ -94,10 +94,7 @@ def query(rq = release_fields) it 'finds the author of the release' do post_query - expect(data).to eq( - 'id' => global_id_of(release.author), - 'username' => release.author.username - ) + expect(data).to match a_graphql_entity_for(release.author, :username) end end @@ -142,13 +139,11 @@ def query(rq = release_fields) post_query expected = release.links.map do |link| - { - 'id' => global_id_of(link), - 'name' => link.name, - 'url' => link.url, + a_graphql_entity_for( + link, :name, :url, 'external' => link.external?, 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << "/downloads#{link.filepath}" : link.url - } + ) end expect(data).to match_array(expected) @@ -218,10 +213,8 @@ def query(rq = release_fields) evidence = release.evidences.first.present - expect(data["nodes"].first).to eq( - 'id' => global_id_of(evidence), - 'sha' => evidence.sha, - 'filepath' => evidence.filepath, + expect(data["nodes"].first).to match a_graphql_entity_for( + evidence, :sha, :filepath, 'collectedAt' => evidence.collected_at.utc.iso8601 ) end @@ -274,10 +267,10 @@ def query(rq = release_fields) post_query expected = release.milestones.order_by_dates_and_title.map do |milestone| - { 'id' => global_id_of(milestone), 'title' => milestone.title } + a_graphql_entity_for(milestone, :title) end - expect(data).to eq(expected) + expect(data).to match(expected) end end @@ -291,10 +284,7 @@ def query(rq = release_fields) it 'finds the author of the release' do post_query - expect(data).to eq( - 'id' => global_id_of(release.author), - 'username' => release.author.username - ) + expect(data).to match a_graphql_entity_for(release.author, :username) end end @@ -339,13 +329,11 @@ def query(rq = release_fields) post_query expected = release.links.map do |link| - { - 'id' => global_id_of(link), - 'name' => link.name, - 'url' => link.url, + a_graphql_entity_for( + link, :name, :url, 'external' => true, 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << "/downloads#{link.filepath}" : link.url - } + ) end expect(data).to match_array(expected) diff --git a/spec/requests/api/graphql/project/terraform/state_spec.rb b/spec/requests/api/graphql/project/terraform/state_spec.rb index 9f1d9ab204a89b5d8a03bc797a34e00b7cd40fbe..8f2d2cffef2a77d17d5de3745b3270727f85df98 100644 --- a/spec/requests/api/graphql/project/terraform/state_spec.rb +++ b/spec/requests/api/graphql/project/terraform/state_spec.rb @@ -57,22 +57,22 @@ it_behaves_like 'a working graphql query' it 'returns terraform state data' do - expect(data).to match(a_hash_including({ - 'id' => global_id_of(terraform_state), - 'name' => terraform_state.name, + expect(data).to match a_graphql_entity_for( + terraform_state, + :name, 'lockedAt' => terraform_state.locked_at.iso8601, 'createdAt' => terraform_state.created_at.iso8601, 'updatedAt' => terraform_state.updated_at.iso8601, - 'lockedByUser' => { 'id' => global_id_of(terraform_state.locked_by_user) }, - 'latestVersion' => { - 'id' => eq(global_id_of(latest_version)), + 'lockedByUser' => a_graphql_entity_for(terraform_state.locked_by_user), + 'latestVersion' => a_graphql_entity_for( + latest_version, 'serial' => eq(latest_version.version), 'createdAt' => eq(latest_version.created_at.iso8601), 'updatedAt' => eq(latest_version.updated_at.iso8601), - 'createdByUser' => { 'id' => eq(global_id_of(latest_version.created_by_user)) }, + 'createdByUser' => a_graphql_entity_for(latest_version.created_by_user), 'job' => { 'name' => eq(latest_version.build.name) } - } - })) + ) + ) end context 'unauthorized users' do diff --git a/spec/requests/api/graphql/project/terraform/states_spec.rb b/spec/requests/api/graphql/project/terraform/states_spec.rb index 2879530acc5d017afe98afd8d5c7278076dbdf8b..a7ec6f697765746fa596e0ede366cb8d0d97bb7e 100644 --- a/spec/requests/api/graphql/project/terraform/states_spec.rb +++ b/spec/requests/api/graphql/project/terraform/states_spec.rb @@ -62,23 +62,22 @@ ) ) - expect(data['nodes']).to contain_exactly({ - 'id' => global_id_of(terraform_state), - 'name' => terraform_state.name, + expect(data['nodes']).to contain_exactly a_graphql_entity_for( + terraform_state, :name, 'lockedAt' => terraform_state.locked_at.iso8601, 'createdAt' => terraform_state.created_at.iso8601, 'updatedAt' => terraform_state.updated_at.iso8601, - 'lockedByUser' => { 'id' => global_id_of(terraform_state.locked_by_user) }, - 'latestVersion' => { - 'id' => eq(global_id_of(latest_version)), + 'lockedByUser' => a_graphql_entity_for(terraform_state.locked_by_user), + 'latestVersion' => a_graphql_entity_for( + latest_version, 'serial' => eq(latest_version.version), 'downloadPath' => eq(download_path), 'createdAt' => eq(latest_version.created_at.iso8601), 'updatedAt' => eq(latest_version.updated_at.iso8601), - 'createdByUser' => { 'id' => eq(global_id_of(latest_version.created_by_user)) }, + 'createdByUser' => a_graphql_entity_for(latest_version.created_by_user), 'job' => { 'name' => eq(latest_version.build.name) } - } - }) + ) + ) end it 'returns count of terraform states' do diff --git a/spec/requests/api/graphql/query_spec.rb b/spec/requests/api/graphql/query_spec.rb index d650acc8354e4a495de2657368e1a73c57df2c2e..4aa9c4b825455c670ddbd71c267a0b455b269416 100644 --- a/spec/requests/api/graphql/query_spec.rb +++ b/spec/requests/api/graphql/query_spec.rb @@ -76,10 +76,8 @@ it_behaves_like 'a working graphql query' it_behaves_like 'a query that needs authorization' - context 'the current user is able to read designs' do - it 'fetches the expected data' do - expect(query_result).to eq('id' => global_id_of(version), 'sha' => version.sha) - end + it 'fetches the expected data' do + expect(query_result).to match a_graphql_entity_for(version, :sha) end end @@ -106,13 +104,13 @@ context 'the current user is able to read designs' do it 'fetches the expected data, including the correct associations' do - expect(query_result).to eq( - 'id' => global_id_of(design_at_version), + expect(query_result).to match a_graphql_entity_for( + design_at_version, 'filename' => design_at_version.design.filename, - 'version' => { 'id' => global_id_of(version), 'sha' => version.sha }, - 'design' => { 'id' => global_id_of(design) }, + 'version' => a_graphql_entity_for(version, :sha), + 'design' => a_graphql_entity_for(design), 'issue' => { 'title' => issue.title, 'iid' => issue.iid.to_s }, - 'project' => { 'id' => global_id_of(project), 'fullPath' => project.full_path } + 'project' => a_graphql_entity_for(project, :full_path) ) end end diff --git a/spec/requests/api/graphql/user/starred_projects_query_spec.rb b/spec/requests/api/graphql/user/starred_projects_query_spec.rb index a8c087d1fbf0ee5de3c81822cc879387ae0a20d8..37a85b98e5f7bbde39a46e20d0c456aff1587eee 100644 --- a/spec/requests/api/graphql/user/starred_projects_query_spec.rb +++ b/spec/requests/api/graphql/user/starred_projects_query_spec.rb @@ -42,7 +42,7 @@ it 'found only public project' do expect(starred_projects).to contain_exactly( - a_hash_including('id' => global_id_of(project_a)) + a_graphql_entity_for(project_a) ) end @@ -51,9 +51,9 @@ it 'found all projects' do expect(starred_projects).to contain_exactly( - a_hash_including('id' => global_id_of(project_a)), - a_hash_including('id' => global_id_of(project_b)), - a_hash_including('id' => global_id_of(project_c)) + a_graphql_entity_for(project_a), + a_graphql_entity_for(project_b), + a_graphql_entity_for(project_c) ) end end @@ -69,8 +69,8 @@ it 'finds public and member projects' do expect(starred_projects).to contain_exactly( - a_hash_including('id' => global_id_of(project_a)), - a_hash_including('id' => global_id_of(project_b)) + a_graphql_entity_for(project_a), + a_graphql_entity_for(project_b) ) end end @@ -93,9 +93,9 @@ it 'finds all projects starred by the user, which the current user has access to' do expect(starred_projects).to contain_exactly( - a_hash_including('id' => global_id_of(project_a)), - a_hash_including('id' => global_id_of(project_b)), - a_hash_including('id' => global_id_of(project_c)) + a_graphql_entity_for(project_a), + a_graphql_entity_for(project_b), + a_graphql_entity_for(project_c) ) end end diff --git a/spec/requests/api/graphql/user_query_spec.rb b/spec/requests/api/graphql/user_query_spec.rb index 1cba3674d2571165972e6bfa4ec77333324da445..8f286180617241eaf26a7da4f37d4e405a5facd2 100644 --- a/spec/requests/api/graphql/user_query_spec.rb +++ b/spec/requests/api/graphql/user_query_spec.rb @@ -91,11 +91,11 @@ presenter = UserPresenter.new(user) expect(graphql_data['user']).to match( - a_hash_including( - 'id' => global_id_of(user), + a_graphql_entity_for( + user, + :username, 'state' => presenter.state, 'name' => presenter.name, - 'username' => presenter.username, 'webUrl' => presenter.web_url, 'avatarUrl' => presenter.avatar_url, 'email' => presenter.public_email, @@ -121,9 +121,9 @@ it 'can be found' do expect(assigned_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(assigned_mr)), - a_hash_including('id' => global_id_of(assigned_mr_b)), - a_hash_including('id' => global_id_of(assigned_mr_c)) + a_graphql_entity_for(assigned_mr), + a_graphql_entity_for(assigned_mr_b), + a_graphql_entity_for(assigned_mr_c) ) end @@ -145,7 +145,7 @@ it 'selects the correct MRs' do expect(assigned_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(assigned_mr_b)) + a_graphql_entity_for(assigned_mr_b) ) end end @@ -157,8 +157,8 @@ it 'selects the correct MRs' do expect(assigned_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(assigned_mr_b)), - a_hash_including('id' => global_id_of(assigned_mr_c)) + a_graphql_entity_for(assigned_mr_b), + a_graphql_entity_for(assigned_mr_c) ) end end @@ -169,7 +169,7 @@ it 'finds the authored mrs' do expect(assigned_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(assigned_mr_b)) + a_graphql_entity_for(assigned_mr_b) ) end end @@ -185,8 +185,8 @@ post_graphql(query, current_user: current_user) expect(assigned_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(assigned_mr_b)), - a_hash_including('id' => global_id_of(assigned_mr_c)) + a_graphql_entity_for(assigned_mr_b), + a_graphql_entity_for(assigned_mr_c) ) end end @@ -212,9 +212,9 @@ it 'can be found' do expect(reviewed_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(reviewed_mr)), - a_hash_including('id' => global_id_of(reviewed_mr_b)), - a_hash_including('id' => global_id_of(reviewed_mr_c)) + a_graphql_entity_for(reviewed_mr), + a_graphql_entity_for(reviewed_mr_b), + a_graphql_entity_for(reviewed_mr_c) ) end @@ -236,7 +236,7 @@ it 'selects the correct MRs' do expect(reviewed_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(reviewed_mr_b)) + a_graphql_entity_for(reviewed_mr_b) ) end end @@ -248,8 +248,8 @@ it 'selects the correct MRs' do expect(reviewed_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(reviewed_mr_b)), - a_hash_including('id' => global_id_of(reviewed_mr_c)) + a_graphql_entity_for(reviewed_mr_b), + a_graphql_entity_for(reviewed_mr_c) ) end end @@ -260,7 +260,7 @@ it 'finds the authored mrs' do expect(reviewed_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(reviewed_mr_b)) + a_graphql_entity_for(reviewed_mr_b) ) end end @@ -275,7 +275,7 @@ post_graphql(query, current_user: current_user) expect(reviewed_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(reviewed_mr_c)) + a_graphql_entity_for(reviewed_mr_c) ) end end @@ -301,9 +301,9 @@ it 'can be found' do expect(authored_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(authored_mr)), - a_hash_including('id' => global_id_of(authored_mr_b)), - a_hash_including('id' => global_id_of(authored_mr_c)) + a_graphql_entity_for(authored_mr), + a_graphql_entity_for(authored_mr_b), + a_graphql_entity_for(authored_mr_c) ) end @@ -329,8 +329,8 @@ post_graphql(query, current_user: current_user) expect(authored_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(authored_mr)), - a_hash_including('id' => global_id_of(authored_mr_c)) + a_graphql_entity_for(authored_mr), + a_graphql_entity_for(authored_mr_c) ) end end @@ -346,8 +346,8 @@ post_graphql(query, current_user: current_user) expect(authored_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(authored_mr_b)), - a_hash_including('id' => global_id_of(authored_mr_c)) + a_graphql_entity_for(authored_mr_b), + a_graphql_entity_for(authored_mr_c) ) end end @@ -359,7 +359,7 @@ it 'selects the correct MRs' do expect(authored_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(authored_mr_b)) + a_graphql_entity_for(authored_mr_b) ) end end @@ -371,8 +371,8 @@ it 'selects the correct MRs' do expect(authored_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(authored_mr_b)), - a_hash_including('id' => global_id_of(authored_mr_c)) + a_graphql_entity_for(authored_mr_b), + a_graphql_entity_for(authored_mr_c) ) end end @@ -417,7 +417,7 @@ it 'can be found' do expect(group_memberships).to include( - a_hash_including('id' => global_id_of(membership_a)) + a_graphql_entity_for(membership_a) ) end end @@ -440,7 +440,7 @@ it 'can be found' do expect(project_memberships).to include( - a_hash_including('id' => global_id_of(membership_a)) + a_graphql_entity_for(membership_a) ) end end @@ -460,7 +460,7 @@ it 'can be found' do expect(authored_mrs).to include( - a_hash_including('id' => global_id_of(authored_mr)) + a_graphql_entity_for(authored_mr) ) end end @@ -480,9 +480,9 @@ it 'can be found' do expect(assigned_mrs).to contain_exactly( - a_hash_including('id' => global_id_of(assigned_mr)), - a_hash_including('id' => global_id_of(assigned_mr_b)), - a_hash_including('id' => global_id_of(assigned_mr_c)) + a_graphql_entity_for(assigned_mr), + a_graphql_entity_for(assigned_mr_b), + a_graphql_entity_for(assigned_mr_c) ) end end diff --git a/spec/requests/api/graphql/users_spec.rb b/spec/requests/api/graphql/users_spec.rb index fe824834a2c6de4978f9d483c5bf792cba06d45d..a6bbfc75451b82e7ca88049ed1a11efd56c7f1a4 100644 --- a/spec/requests/api/graphql/users_spec.rb +++ b/spec/requests/api/graphql/users_spec.rb @@ -72,12 +72,12 @@ post_query expect(graphql_data.dig('users', 'nodes')).to include( - { "id" => user0.to_global_id.to_s }, - { "id" => user1.to_global_id.to_s }, - { "id" => user2.to_global_id.to_s }, - { "id" => user3.to_global_id.to_s }, - { "id" => admin.to_global_id.to_s }, - { "id" => another_admin.to_global_id.to_s } + a_graphql_entity_for(user0), + a_graphql_entity_for(user1), + a_graphql_entity_for(user2), + a_graphql_entity_for(user3), + a_graphql_entity_for(admin), + a_graphql_entity_for(another_admin) ) end end @@ -91,15 +91,15 @@ post_graphql(query, current_user: current_user) expect(graphql_data.dig('users', 'nodes')).to include( - { "id" => another_admin.to_global_id.to_s }, - { "id" => admin.to_global_id.to_s } + a_graphql_entity_for(another_admin), + a_graphql_entity_for(admin) ) expect(graphql_data.dig('users', 'nodes')).not_to include( - { "id" => user0.to_global_id.to_s }, - { "id" => user1.to_global_id.to_s }, - { "id" => user2.to_global_id.to_s }, - { "id" => user3.to_global_id.to_s } + a_graphql_entity_for(user0), + a_graphql_entity_for(user1), + a_graphql_entity_for(user2), + a_graphql_entity_for(user3) ) end end diff --git a/spec/support/graphql/arguments.rb b/spec/support/graphql/arguments.rb index 20e940030f8250e0578a1f4db82ec955bf138e48..a5bb01c31a3cf76cc5185bbd0c2570ba237588a8 100644 --- a/spec/support/graphql/arguments.rb +++ b/spec/support/graphql/arguments.rb @@ -40,7 +40,7 @@ def self.as_graphql_literal(value) when Array then "[#{value.map { |v| as_graphql_literal(v) }.join(',')}]" when Hash then "{#{new(value)}}" when Integer, Float, Symbol then value.to_s - when String then "\"#{value.gsub(/"/, '\\"')}\"" + when String, GlobalID then "\"#{value.to_s.gsub(/"/, '\\"')}\"" when Time, Date then "\"#{value.iso8601}\"" when nil then 'null' when true then 'true' @@ -49,7 +49,7 @@ def self.as_graphql_literal(value) value.to_graphql_value end rescue NoMethodError - raise ArgumentError, "Cannot represent #{value} as GraphQL literal" + raise ArgumentError, "Cannot represent #{value} (instance of #{value.class}) as GraphQL literal" end def merge(other) diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index 652cc51fcc02df1b96751a43a8540648567895b2..eb0e5a2573386213d432825a53a4a7bc7602e14d 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -244,6 +244,7 @@ def wrap_query(query) def graphql_mutation(name, input, fields = nil, &block) raise ArgumentError, 'Please pass either `fields` parameter or a block to `#graphql_mutation`, but not both.' if fields.present? && block_given? + name = name.graphql_name if name.respond_to?(:graphql_name) mutation_name = GraphqlHelpers.fieldnamerize(name) input_variable_name = "$#{input_variable_name_for_mutation(name)}" mutation_field = GitlabSchema.mutation.fields[mutation_name] @@ -264,7 +265,7 @@ def graphql_mutation(name, input, fields = nil, &block) end def variables_for_mutation(name, input) - graphql_input = prepare_input_for_mutation(input) + graphql_input = prepare_variables(input) { input_variable_name_for_mutation(name) => graphql_input } end @@ -273,18 +274,28 @@ def serialize_variables(variables) return unless variables return variables if variables.is_a?(String) - ::Gitlab::Utils::MergeHash.merge(Array.wrap(variables).map(&:to_h)).to_json + # Combine variables into a single hash. + hash = ::Gitlab::Utils::MergeHash.merge(Array.wrap(variables).map(&:to_h)) + + prepare_variables(hash).to_json end - # Recursively convert a Hash with Ruby-style keys to GraphQL fieldname-style keys + # Recursively convert any ruby object we can pass as a variable value + # to an object we can serialize with JSON, using fieldname-style keys # - # prepare_input_for_mutation({ 'my_key' => 1 }) - # => { 'myKey' => 1} - def prepare_input_for_mutation(input) - input.to_h do |name, value| - value = prepare_input_for_mutation(value) if value.is_a?(Hash) + # prepare_variables({ 'my_key' => 1 }) + # => { 'myKey' => 1 } + # prepare_variables({ enums: [:FOO, :BAR], user_id: global_id_of(user) }) + # => { 'enums' => ['FOO', 'BAR'], 'userId' => "gid://User/123" } + # prepare_variables({ nested: { hash_values: { are_supported: true } } }) + # => { 'nested' => { 'hashValues' => { 'areSupported' => true } } } + def prepare_variables(input) + return input.map { prepare_variables(_1) } if input.is_a?(Array) + return input.to_s if input.is_a?(GlobalID) || input.is_a?(Symbol) + return input unless input.is_a?(Hash) - [GraphqlHelpers.fieldnamerize(name), value] + input.to_h do |name, value| + [GraphqlHelpers.fieldnamerize(name), prepare_variables(value)] end end @@ -650,9 +661,9 @@ def node_array(data, extract_attribute = nil) end end - def global_id_of(model, id: nil, model_name: nil) + def global_id_of(model = nil, id: nil, model_name: nil) if id || model_name - ::Gitlab::GlobalId.build(model, id: id, model_name: model_name).to_s + ::Gitlab::GlobalId.as_global_id(id || model.id, model_name: model_name || model.class.name).to_s else model.to_global_id.to_s end @@ -714,6 +725,67 @@ def empty_schema end end + # Wrapper around a_hash_including that supports unpacking with ** + class UnpackableMatcher < SimpleDelegator + include RSpec::Matchers + + attr_reader :to_hash + + def initialize(hash) + @to_hash = hash + super(a_hash_including(hash)) + end + + def to_json(_opts = {}) + to_hash.to_json + end + + def as_json(opts = {}) + to_hash.as_json(opts) + end + end + + # Construct a matcher for GraphQL entity response objects, of the form + # `{ "id" => "some-gid" }`. + # + # Usage: + # + # ```ruby + # expect(graphql_data_at(:path, :to, :entity)).to match a_graphql_entity_for(user) + # ``` + # + # This can be called as: + # + # ```ruby + # a_graphql_entity_for(project, :full_path) # also checks that `entity['fullPath'] == project.full_path + # a_graphql_entity_for(project, full_path: 'some/path') # same as above, with explicit values + # a_graphql_entity_for(user, :username, foo: 'bar') # combinations of the above + # a_graphql_entity_for(foo: 'bar') # if properties are defined, the model is not necessary + # ``` + # + # Note that the model instance must not be nil, unless some properties are + # explicitly passed in. The following are rejected with `ArgumentError`: + # + # ``` + # a_graphql_entity_for(nil, :username) + # a_graphql_entity_for(:username) + # a_graphql_entity_for + # ``` + # + def a_graphql_entity_for(model = nil, *fields, **attrs) + raise ArgumentError, 'model is nil' if model.nil? && fields.any? + + attrs.transform_keys! { GraphqlHelpers.fieldnamerize(_1) } + attrs['id'] = global_id_of(model) if model + fields.each do |name| + attrs[GraphqlHelpers.fieldnamerize(name)] = model.public_send(name) + end + + raise ArgumentError, 'no attributes' if attrs.empty? + + UnpackableMatcher.new(attrs) + end + # A lookahead that selects everything def positive_lookahead double(selects?: true).tap do |selection| diff --git a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb index 13e7ecf2669850f2ad349dbdb2e0d77f5576f08d..b29a231f3a6fbd79f32db7f922d1df462b29de96 100644 --- a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb +++ b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb @@ -14,7 +14,7 @@ let(:user) { project.first_owner } let(:package_details) { graphql_data_at(:package) } let(:metadata_response) { graphql_data_at(:package, :metadata) } - let(:first_file) { package.package_files.find { |f| global_id_of(f) == first_file_response['id'] } } + let(:first_file) { package.package_files.find { |f| a_graphql_entity_for(f).matches?(first_file_response) } } let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) } let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)} let(:first_file_response_metadata) { graphql_data_at(:package, :package_files, :nodes, 0, :file_metadata)} 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 index 37a805902a9aa9d187c0aa3f92c98864d6bbe28f..6d6e7b761f6c893753e3c53a1f81e16cf250329d 100644 --- a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb +++ b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb @@ -101,7 +101,7 @@ def start_cursor context 'when sorting' do it 'sorts correctly' do - expect(results).to eq all_records + expect(results).to match all_records end context 'when paginating' do @@ -110,17 +110,17 @@ def start_cursor let(:rest) { all_records.drop(first_param) } it 'paginates correctly' do - expect(results).to eq first_page + expect(results).to match first_page fwds = pagination_query(sort_argument.merge(after: end_cursor)) post_graphql(fwds, current_user: current_user) - expect(results).to eq rest + expect(results).to match rest bwds = pagination_query(sort_argument.merge(before: start_cursor)) post_graphql(bwds, current_user: current_user) - expect(results).to eq first_page + expect(results).to match first_page end end @@ -130,7 +130,7 @@ def start_cursor it 'fetches last elements without error' do post_graphql(pagination_query(params), current_user: current_user) - expect(results.first).to eq(all_records.last) + expect(results.first).to match all_records.last end end end diff --git a/spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb index 7e1f45007790c7b73d1f02fe4f25c7ac0e0b8685..31f2519a132bae0378fb1dac3ec1149c5c3b1a85 100644 --- a/spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb @@ -12,8 +12,8 @@ def expected noteable.discussions.map do |discussion| - include( - 'id' => global_id_of(discussion), + a_graphql_entity_for( + discussion, 'replyId' => global_id_of(discussion, id: discussion.reply_id), 'createdAt' => discussion.created_at.iso8601, 'notes' => include( @@ -50,8 +50,8 @@ def expected post_graphql(query(fields), current_user: current_user) - data = graphql_data_at(*path_to_noteable, :discussions, :nodes, :noteable, :id) - expect(data[0]).to eq(global_id_of(noteable)) + entities = graphql_data_at(*path_to_noteable, :discussions, :nodes, :noteable) + expect(entities).to all(match(a_graphql_entity_for(noteable))) end end @@ -62,10 +62,10 @@ def expected def expected noteable.notes.map do |note| - include( - 'id' => global_id_of(note), - 'project' => include('id' => global_id_of(project)), - 'author' => include('id' => global_id_of(note.author)), + a_graphql_entity_for( + note, + 'project' => a_graphql_entity_for(project), + 'author' => a_graphql_entity_for(note.author), 'createdAt' => note.created_at.iso8601, 'body' => eq(note.note) ) diff --git a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb index 127b1a6d4c40afa1578c2320d959c7054cf5ae27..4c1a443eb4d44fb5d03c169603dd5488f8c880ff 100644 --- a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb @@ -104,7 +104,7 @@ } end - let(:expected_packages) { sorted_packages.map { |package| global_id_of(package) } } + let(:expected_packages) { sorted_packages.map { |package| global_id_of(package).to_s } } let(:data_path) { [resource_type, :packages] } diff --git a/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb index ab93f54111b295817c2f54c0ba5796f713adec7a..b4019d7c232a8a58a819ad16f26dc4444136501e 100644 --- a/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb @@ -28,14 +28,10 @@ end it 'has the basic package files data' do - expect(first_file_response).to include( - 'id' => global_id_of(first_file), - 'fileName' => first_file.file_name, - 'size' => first_file.size.to_s, - 'downloadPath' => first_file.download_path, - 'fileSha1' => first_file.file_sha1, - 'fileMd5' => first_file.file_md5, - 'fileSha256' => first_file.file_sha256 + expect(first_file_response).to match a_graphql_entity_for( + first_file, + :file_name, :download_path, :file_sha1, :file_md5, :file_sha256, + 'size' => first_file.size.to_s ) end diff --git a/spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb index c134f7d1839fd7691416eb26862c2896d7c2a476..3c5f25baaa1d78e4bad6a6475bd9e10351fbc626 100644 --- a/spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/projects/alert_management/integrations_shared_examples.rb @@ -30,14 +30,12 @@ it 'returns the correct properties of the integrations', :aggregate_failures do post_graphql(multi_selection_query, current_user: current_user) - expect(graphql_data.dig('project', 'ai', 'nodes')).to include( - 'id' => global_id_of(active_http_integration), - 'name' => active_http_integration.name + expect(graphql_data.dig('project', 'ai', 'nodes')).to match a_graphql_entity_for( + active_http_integration, :name ) - expect(graphql_data.dig('project', 'ii', 'nodes')).to include( - 'id' => global_id_of(inactive_http_integration), - 'name' => inactive_http_integration.name + expect(graphql_data.dig('project', 'ii', 'nodes')).to match a_graphql_entity_for( + inactive_http_integration, :name ) end diff --git a/spec/support_specs/helpers/graphql_helpers_spec.rb b/spec/support_specs/helpers/graphql_helpers_spec.rb index fae29ec32f53238ea4473b1d7d4dd7f474053995..0f9918351e2cf79e8a772553eb9ca55beea422e8 100644 --- a/spec/support_specs/helpers/graphql_helpers_spec.rb +++ b/spec/support_specs/helpers/graphql_helpers_spec.rb @@ -10,6 +10,81 @@ def norm(query) query.tr("\n", ' ').gsub(/\s+/, ' ').strip end + describe 'a_graphql_entity_for' do + context 'when no arguments are passed' do + it 'raises an error' do + expect { a_graphql_entity_for }.to raise_error(ArgumentError) + end + end + + context 'when the model is nil, with no properties' do + it 'raises an error' do + expect { a_graphql_entity_for(nil) }.to raise_error(ArgumentError) + end + end + + context 'when the model is nil, any fields are passed' do + it 'raises an error' do + expect { a_graphql_entity_for(nil, :username) }.to raise_error(ArgumentError) + end + end + + context 'with no model' do + it 'behaves like hash-inclusion with camel-casing' do + response = { 'foo' => 1, 'bar' => 2, 'camelCased' => 3 } + + expect(response).to match a_graphql_entity_for(foo: 1, camel_cased: 3) + expect(response).not_to match a_graphql_entity_for(missing: 5) + end + end + + context 'with just a model' do + it 'only considers the ID' do + user = build_stubbed(:user) + response = { 'username' => 'foo', 'id' => global_id_of(user) } + + expect(response).to match a_graphql_entity_for(user) + end + end + + context 'with a model and some method names' do + it 'also considers the method names' do + user = build_stubbed(:user) + response = { 'username' => user.username, 'id' => global_id_of(user) } + + expect(response).to match a_graphql_entity_for(user, :username) + expect(response).not_to match a_graphql_entity_for(user, :name) + end + end + + context 'with a model and some other properties' do + it 'behaves like the superset' do + user = build_stubbed(:user) + response = { 'username' => 'foo', 'id' => global_id_of(user) } + + expect(response).to match a_graphql_entity_for(user, username: 'foo') + expect(response).not_to match a_graphql_entity_for(user, name: 'foo') + end + end + + context 'with a model, method names, and some other properties' do + it 'behaves like the superset' do + user = build_stubbed(:user) + response = { + 'username' => user.username, + 'name' => user.name, + 'foo' => 'bar', + 'baz' => 'fop', + 'id' => global_id_of(user) + } + + expect(response).to match a_graphql_entity_for(user, :username, :name, foo: 'bar') + expect(response).to match a_graphql_entity_for(user, :name, foo: 'bar') + expect(response).not_to match a_graphql_entity_for(user, :name, bar: 'foo') + end + end + end + describe 'graphql_dig_at' do it 'transforms symbol keys to graphql field names' do data = { 'camelCased' => 'names' }