search_spec.rb 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. # Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Gql::Queries::Search, type: :graphql do
  4. context 'when performing generic searches' do
  5. let(:group) { create(:group) }
  6. let(:organization) { create(:organization, name: search) }
  7. let(:agent) { create(:agent, firstname: search, groups: [ticket.group]) }
  8. let!(:ticket) do
  9. create(:ticket, title: search, organization: organization).tap do |ticket|
  10. # Article required to find ticket via SQL
  11. create(:ticket_article, ticket: ticket)
  12. end
  13. end
  14. let(:search) { SecureRandom.uuid }
  15. let(:query) do
  16. <<~QUERY
  17. query search($search: String!, $onlyIn: EnumSearchableModels!, $offset: Int = 0, $limit: Int = 10) {
  18. search(search: $search, onlyIn: $onlyIn, offset: $offset, limit: $limit) {
  19. totalCount
  20. items {
  21. ... on Ticket {
  22. __typename
  23. number
  24. title
  25. }
  26. ... on User {
  27. __typename
  28. firstname
  29. lastname
  30. }
  31. ... on Organization {
  32. __typename
  33. name
  34. }
  35. }
  36. }
  37. }
  38. QUERY
  39. end
  40. let(:only_in) { 'Ticket' }
  41. let(:variables) { { search: search, onlyIn: only_in } }
  42. let(:es_setup) do
  43. Setting.set('es_url', nil)
  44. end
  45. before do
  46. es_setup
  47. gql.execute(query, variables: variables)
  48. end
  49. shared_examples 'test search query' do
  50. context 'with an agent', authenticated_as: :agent do
  51. let(:expected_result) do
  52. { 'items' => [{ '__typename' => 'Ticket', 'number' => ticket.number, 'title' => ticket.title }], 'totalCount' => 1 }
  53. end
  54. it 'finds expected objects across models' do
  55. expect(gql.result.data).to eq(expected_result)
  56. end
  57. context 'with offset in a non-matching window' do
  58. let(:variables) { { search:, onlyIn: only_in, limit: 10, offset: 10 } }
  59. let(:expected_result) do
  60. { 'items' => [], 'totalCount' => 1 }
  61. end
  62. it 'finds expected objects across models' do
  63. expect(gql.result.data).to eq(expected_result)
  64. end
  65. end
  66. end
  67. context 'with a customer', authenticated_as: :customer do
  68. let(:customer) { create(:customer, firstname: search, organization: organization) }
  69. let(:only_in) { 'Organization' }
  70. let(:expected_result) do
  71. { 'items' => [{ '__typename' => 'Organization', 'name' => organization.name }], 'totalCount' => 1 }
  72. end
  73. it 'finds objects available to the customer' do
  74. expect(gql.result.data).to eq(expected_result)
  75. end
  76. context 'when searching for inacessible models' do
  77. let(:only_in) { 'User' }
  78. let(:expected_result) do
  79. { 'items' => [], 'totalCount' => 0 }
  80. end
  81. it 'gets no result' do
  82. expect(gql.result.data).to eq(expected_result)
  83. end
  84. end
  85. end
  86. end
  87. context 'without search index' do
  88. include_examples 'test search query'
  89. end
  90. context 'with search index', searchindex: true do
  91. let(:es_setup) do
  92. searchindex_model_reload([Ticket, User, Organization])
  93. end
  94. include_examples 'test search query'
  95. end
  96. it_behaves_like 'graphql responds with error if unauthenticated'
  97. end
  98. end