solidus_graphql_api 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (267) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +18 -2
  3. data/.github/dependabot.yml +23 -0
  4. data/.github/stale.yml +3 -3
  5. data/.github_changelog_generator +2 -0
  6. data/.rubocop.yml +7 -4
  7. data/CHANGELOG.md +170 -0
  8. data/Gemfile +0 -5
  9. data/LICENSE +1 -1
  10. data/README.md +25 -9
  11. data/Rakefile +21 -7
  12. data/app/assets/javascripts/spree/backend/solidus_graphql_api.js +2 -0
  13. data/app/assets/javascripts/spree/frontend/solidus_graphql_api.js +2 -0
  14. data/app/assets/stylesheets/spree/backend/solidus_graphql_api.css +4 -0
  15. data/app/assets/stylesheets/spree/frontend/solidus_graphql_api.css +4 -0
  16. data/app/controllers/spree/graphql_controller.rb +2 -0
  17. data/bin/console +2 -2
  18. data/bin/rails +0 -2
  19. data/bin/rails-engine +0 -3
  20. data/bin/rails-sandbox +1 -3
  21. data/bin/rake +0 -1
  22. data/bin/sandbox +3 -1
  23. data/docs/assets/images/graphiql-headers.png +0 -0
  24. data/docs/assets/images/graphiql-variables.png +0 -0
  25. data/docs/assets/images/graphiql.png +0 -0
  26. data/docs/assets/images/menu.png +0 -0
  27. data/docs/assets/images/navbar.png +0 -0
  28. data/docs/assets/style.css +1115 -0
  29. data/docs/assets/webfonts/2C4B9D_B_0.eot +0 -0
  30. data/docs/assets/webfonts/2C4B9D_B_0.ttf +0 -0
  31. data/docs/assets/webfonts/2C4B9D_B_0.woff +0 -0
  32. data/docs/assets/webfonts/2C4B9D_B_0.woff2 +0 -0
  33. data/docs/assets/webfonts/2C4B9D_C_0.eot +0 -0
  34. data/docs/assets/webfonts/2C4B9D_C_0.ttf +0 -0
  35. data/docs/assets/webfonts/2C4B9D_C_0.woff +0 -0
  36. data/docs/assets/webfonts/2C4B9D_C_0.woff2 +0 -0
  37. data/docs/assets/webfonts/2C4B9D_D_0.eot +0 -0
  38. data/docs/assets/webfonts/2C4B9D_D_0.ttf +0 -0
  39. data/docs/assets/webfonts/2C4B9D_D_0.woff +0 -0
  40. data/docs/assets/webfonts/2C4B9D_D_0.woff2 +0 -0
  41. data/docs/assets/webfonts/2C4B9D_E_0.eot +0 -0
  42. data/docs/assets/webfonts/2C4B9D_E_0.ttf +0 -0
  43. data/docs/assets/webfonts/2C4B9D_E_0.woff +0 -0
  44. data/docs/assets/webfonts/2C4B9D_E_0.woff2 +0 -0
  45. data/docs/directive/deprecated/index.html +1142 -0
  46. data/docs/directive/include/index.html +1141 -0
  47. data/docs/directive/index.html +1113 -0
  48. data/docs/directive/skip/index.html +1141 -0
  49. data/docs/enum/__directivelocation/index.html +1204 -0
  50. data/docs/enum/__typekind/index.html +1154 -0
  51. data/docs/enum/addresstypeinput/index.html +1121 -0
  52. data/docs/enum/index.html +1113 -0
  53. data/docs/index.html +1122 -0
  54. data/docs/input_object/addaddressestocheckoutinput/index.html +1135 -0
  55. data/docs/input_object/addpaymenttocheckoutinput/index.html +1135 -0
  56. data/docs/input_object/addressinput/index.html +1169 -0
  57. data/docs/input_object/addtocartinput/index.html +1130 -0
  58. data/docs/input_object/advancecheckoutinput/index.html +1120 -0
  59. data/docs/input_object/applycouponcodeinput/index.html +1125 -0
  60. data/docs/input_object/completecheckoutinput/index.html +1120 -0
  61. data/docs/input_object/createorderinput/index.html +1120 -0
  62. data/docs/input_object/emptycartinput/index.html +1120 -0
  63. data/docs/input_object/index.html +1113 -0
  64. data/docs/input_object/markdefaultshipaddressinput/index.html +1125 -0
  65. data/docs/input_object/nextcheckoutstateinput/index.html +1120 -0
  66. data/docs/input_object/productsqueryinput/index.html +1132 -0
  67. data/docs/input_object/removefromaddressbookinput/index.html +1125 -0
  68. data/docs/input_object/removefromcartinput/index.html +1125 -0
  69. data/docs/input_object/saveinaddressbookinput/index.html +1135 -0
  70. data/docs/input_object/selectshippingrateinput/index.html +1125 -0
  71. data/docs/input_object/setorderemailinput/index.html +1125 -0
  72. data/docs/input_object/updatecartquantityinput/index.html +1130 -0
  73. data/docs/interface/adjustment/index.html +1145 -0
  74. data/docs/interface/index.html +1113 -0
  75. data/docs/interface/node/index.html +1151 -0
  76. data/docs/interface/paymentsource/index.html +1134 -0
  77. data/docs/mutation/addaddressestocheckout/index.html +1137 -0
  78. data/docs/mutation/addpaymenttocheckout/index.html +1137 -0
  79. data/docs/mutation/addtocart/index.html +1137 -0
  80. data/docs/mutation/advancecheckout/index.html +1137 -0
  81. data/docs/mutation/applycouponcode/index.html +1137 -0
  82. data/docs/mutation/completecheckout/index.html +1137 -0
  83. data/docs/mutation/createorder/index.html +1137 -0
  84. data/docs/mutation/emptycart/index.html +1137 -0
  85. data/docs/mutation/markdefaultshipaddress/index.html +1132 -0
  86. data/docs/mutation/nextcheckoutstate/index.html +1137 -0
  87. data/docs/mutation/removefromaddressbook/index.html +1132 -0
  88. data/docs/mutation/removefromcart/index.html +1137 -0
  89. data/docs/mutation/saveinaddressbook/index.html +1137 -0
  90. data/docs/mutation/selectshippingrate/index.html +1137 -0
  91. data/docs/mutation/setorderemail/index.html +1137 -0
  92. data/docs/mutation/updatecartquantity/index.html +1137 -0
  93. data/docs/object/__directive/index.html +1182 -0
  94. data/docs/object/__enumvalue/index.html +1134 -0
  95. data/docs/object/__field/index.html +1164 -0
  96. data/docs/object/__inputvalue/index.html +1145 -0
  97. data/docs/object/__schema/index.html +1144 -0
  98. data/docs/object/__type/index.html +1220 -0
  99. data/docs/object/addaddressestocheckoutpayload/index.html +1130 -0
  100. data/docs/object/addpaymenttocheckoutpayload/index.html +1130 -0
  101. data/docs/object/address/index.html +1189 -0
  102. data/docs/object/addressconnection/index.html +1132 -0
  103. data/docs/object/addressedge/index.html +1126 -0
  104. data/docs/object/addtocartpayload/index.html +1130 -0
  105. data/docs/object/adjustmentconnection/index.html +1132 -0
  106. data/docs/object/adjustmentedge/index.html +1126 -0
  107. data/docs/object/advancecheckoutpayload/index.html +1130 -0
  108. data/docs/object/applycouponcodepayload/index.html +1130 -0
  109. data/docs/object/completecheckoutpayload/index.html +1130 -0
  110. data/docs/object/country/index.html +1218 -0
  111. data/docs/object/countryconnection/index.html +1132 -0
  112. data/docs/object/countryedge/index.html +1126 -0
  113. data/docs/object/createorderpayload/index.html +1130 -0
  114. data/docs/object/creditcard/index.html +1170 -0
  115. data/docs/object/currency/index.html +1144 -0
  116. data/docs/object/currencyconnection/index.html +1132 -0
  117. data/docs/object/currencyedge/index.html +1126 -0
  118. data/docs/object/emptycartpayload/index.html +1130 -0
  119. data/docs/object/image/index.html +1169 -0
  120. data/docs/object/imageconnection/index.html +1132 -0
  121. data/docs/object/imageedge/index.html +1126 -0
  122. data/docs/object/index.html +1113 -0
  123. data/docs/object/lineitem/index.html +1184 -0
  124. data/docs/object/lineitemconnection/index.html +1132 -0
  125. data/docs/object/lineitemedge/index.html +1126 -0
  126. data/docs/object/manifestitem/index.html +1124 -0
  127. data/docs/object/markdefaultshipaddresspayload/index.html +1125 -0
  128. data/docs/object/nextcheckoutstatepayload/index.html +1130 -0
  129. data/docs/object/optiontype/index.html +1203 -0
  130. data/docs/object/optiontypeconnection/index.html +1132 -0
  131. data/docs/object/optiontypeedge/index.html +1126 -0
  132. data/docs/object/optionvalue/index.html +1154 -0
  133. data/docs/object/optionvalueconnection/index.html +1132 -0
  134. data/docs/object/optionvalueedge/index.html +1126 -0
  135. data/docs/object/order/index.html +1412 -0
  136. data/docs/object/orderconnection/index.html +1132 -0
  137. data/docs/object/orderedge/index.html +1126 -0
  138. data/docs/object/pageinfo/index.html +1138 -0
  139. data/docs/object/payment/index.html +1149 -0
  140. data/docs/object/paymentmethod/index.html +1149 -0
  141. data/docs/object/price/index.html +1159 -0
  142. data/docs/object/priceconnection/index.html +1132 -0
  143. data/docs/object/priceedge/index.html +1126 -0
  144. data/docs/object/product/index.html +1327 -0
  145. data/docs/object/productconnection/index.html +1132 -0
  146. data/docs/object/productedge/index.html +1126 -0
  147. data/docs/object/productproperty/index.html +1149 -0
  148. data/docs/object/productpropertyconnection/index.html +1132 -0
  149. data/docs/object/productpropertyedge/index.html +1126 -0
  150. data/docs/object/promotionadjustment/index.html +1155 -0
  151. data/docs/object/property/index.html +1144 -0
  152. data/docs/object/removefromaddressbookpayload/index.html +1125 -0
  153. data/docs/object/removefromcartpayload/index.html +1130 -0
  154. data/docs/object/saveinaddressbookpayload/index.html +1130 -0
  155. data/docs/object/selectshippingratepayload/index.html +1130 -0
  156. data/docs/object/setorderemailpayload/index.html +1130 -0
  157. data/docs/object/shipment/index.html +1218 -0
  158. data/docs/object/shipmentconnection/index.html +1132 -0
  159. data/docs/object/shipmentedge/index.html +1126 -0
  160. data/docs/object/shippingmethod/index.html +1174 -0
  161. data/docs/object/shippingrate/index.html +1154 -0
  162. data/docs/object/shippingrateconnection/index.html +1132 -0
  163. data/docs/object/shippingrateedge/index.html +1126 -0
  164. data/docs/object/state/index.html +1144 -0
  165. data/docs/object/stateconnection/index.html +1132 -0
  166. data/docs/object/stateedge/index.html +1126 -0
  167. data/docs/object/store/index.html +1238 -0
  168. data/docs/object/taxadjustment/index.html +1150 -0
  169. data/docs/object/taxon/index.html +1228 -0
  170. data/docs/object/taxonconnection/index.html +1132 -0
  171. data/docs/object/taxonedge/index.html +1126 -0
  172. data/docs/object/taxonomy/index.html +1198 -0
  173. data/docs/object/taxonomyconnection/index.html +1132 -0
  174. data/docs/object/taxonomyedge/index.html +1126 -0
  175. data/docs/object/updatecartquantitypayload/index.html +1130 -0
  176. data/docs/object/user/index.html +1280 -0
  177. data/docs/object/usererror/index.html +1126 -0
  178. data/docs/object/variant/index.html +1332 -0
  179. data/docs/object/variantconnection/index.html +1132 -0
  180. data/docs/object/variantedge/index.html +1126 -0
  181. data/docs/object/walletpaymentsource/index.html +1144 -0
  182. data/docs/object/walletpaymentsourceconnection/index.html +1132 -0
  183. data/docs/object/walletpaymentsourceedge/index.html +1126 -0
  184. data/docs/operation/mutation/index.html +1114 -0
  185. data/docs/operation/query/index.html +1431 -0
  186. data/docs/scalar/boolean/index.html +1112 -0
  187. data/docs/scalar/float/index.html +1112 -0
  188. data/docs/scalar/id/index.html +1112 -0
  189. data/docs/scalar/index.html +1113 -0
  190. data/docs/scalar/int/index.html +1112 -0
  191. data/docs/scalar/iso8601datetime/index.html +1112 -0
  192. data/docs/scalar/json/index.html +1112 -0
  193. data/docs/scalar/string/index.html +1112 -0
  194. data/docs/union/index.html +1113 -0
  195. data/lib/generators/solidus_graphql_api/install/install_generator.rb +19 -0
  196. data/lib/generators/solidus_graphql_api/install/templates/initializer.rb +6 -0
  197. data/lib/graphql_docs/landing_pages/index.md +16 -0
  198. data/lib/solidus_graphql_api/batch_loader/has_many_through.rb +1 -0
  199. data/lib/solidus_graphql_api/configuration.rb +12 -8
  200. data/lib/solidus_graphql_api/context.rb +7 -1
  201. data/lib/solidus_graphql_api/engine.rb +2 -2
  202. data/lib/solidus_graphql_api/mutations/base_mutation.rb +3 -3
  203. data/lib/solidus_graphql_api/mutations/checkout/add_payment_to_checkout.rb +1 -1
  204. data/lib/solidus_graphql_api/mutations/user/{mark_default_address.rb → mark_default_ship_address.rb} +2 -2
  205. data/lib/solidus_graphql_api/mutations/user/save_in_address_book.rb +8 -2
  206. data/lib/solidus_graphql_api/queries/option_value/option_type_query.rb +19 -0
  207. data/lib/solidus_graphql_api/queries/shipping_rate/shipping_method_query.rb +19 -0
  208. data/lib/solidus_graphql_api/queries/variant/default_price_query.rb +1 -1
  209. data/lib/solidus_graphql_api/{factories → testing_support/factories}/address_factory.rb +1 -2
  210. data/lib/solidus_graphql_api/{factories → testing_support/factories}/country_factory.rb +0 -0
  211. data/lib/solidus_graphql_api/{factories → testing_support/factories}/store_factory.rb +0 -0
  212. data/lib/solidus_graphql_api/{factories → testing_support/factories}/taxonomy_factory.rb +10 -0
  213. data/lib/solidus_graphql_api/testing_support/factories.rb +9 -0
  214. data/lib/solidus_graphql_api/types/address.rb +1 -2
  215. data/lib/solidus_graphql_api/types/base/relay_node.rb +1 -1
  216. data/lib/solidus_graphql_api/types/input_objects/address_input.rb +1 -2
  217. data/lib/solidus_graphql_api/types/json.rb +6 -3
  218. data/lib/solidus_graphql_api/types/mutation.rb +1 -1
  219. data/lib/solidus_graphql_api/types/option_value.rb +5 -0
  220. data/lib/solidus_graphql_api/types/query.rb +2 -2
  221. data/lib/solidus_graphql_api/types/shipping_method.rb +20 -0
  222. data/lib/solidus_graphql_api/types/shipping_rate.rb +5 -0
  223. data/lib/solidus_graphql_api/types/user.rb +1 -1
  224. data/lib/solidus_graphql_api/version.rb +1 -1
  225. data/lib/solidus_graphql_api.rb +0 -3
  226. data/schema.graphql +128 -26
  227. data/solidus_graphql_api.gemspec +9 -7
  228. data/spec/integration/mutations/checkout/add_addresses_to_checkout_spec.rb +12 -18
  229. data/spec/integration/mutations/checkout/apply_coupon_code_spec.rb +3 -1
  230. data/spec/integration/mutations/{mark_default_address_spec.rb → mark_default_ship_address_spec.rb} +5 -5
  231. data/spec/integration/mutations/remove_from_address_book_spec.rb +4 -4
  232. data/spec/integration/mutations/save_in_address_book_spec.rb +25 -12
  233. data/spec/integration/queries/completed_orders_spec.rb +19 -15
  234. data/spec/integration/queries/current_order_spec.rb +4 -1
  235. data/spec/integration/queries/current_store_spec.rb +1 -1
  236. data/spec/integration/queries/products_spec.rb +4 -1
  237. data/spec/integration/queries/taxonomies_spec.rb +9 -4
  238. data/spec/integration/types/json_spec.rb +17 -0
  239. data/spec/lib/solidus_graphql_api/batch_loader/has_many_through_spec.rb +27 -15
  240. data/spec/lib/solidus_graphql_api/context_spec.rb +119 -6
  241. data/spec/lib/solidus_graphql_api/queries/option_value/option_type_query_spec.rb +10 -0
  242. data/spec/lib/solidus_graphql_api/queries/shipping_rate/shipping_method_query_spec.rb +11 -0
  243. data/spec/lib/solidus_graphql_api/queries/variant/default_price_query_spec.rb +1 -1
  244. data/spec/lib/solidus_graphql_api/types/base/object_spec.rb +5 -1
  245. data/spec/lib/solidus_graphql_api/types/json_spec.rb +2 -1
  246. data/spec/lib/solidus_graphql_api/types/option_value_spec.rb +22 -0
  247. data/spec/lib/solidus_graphql_api/types/product_spec.rb +3 -1
  248. data/spec/lib/solidus_graphql_api/types/query_spec.rb +3 -1
  249. data/spec/lib/solidus_graphql_api/types/shipping_rate_spec.rb +22 -0
  250. data/spec/requests/spree/graphql_controller_spec.rb +15 -2
  251. data/spec/spec_helper.rb +15 -9
  252. data/spec/support/expected_schema.graphql +128 -26
  253. data/spec/support/graphql/mutations/add_addresses_to_checkout.gql +2 -2
  254. data/spec/support/graphql/mutations/mark_default_ship_address.gql +9 -0
  255. data/spec/support/graphql/mutations/remove_from_address_book.gql +1 -1
  256. data/spec/support/graphql/mutations/save_in_address_book.gql +6 -5
  257. data/spec/support/graphql/queries/completed_orders/billing_address.gql +1 -2
  258. data/spec/support/graphql/queries/completed_orders/shipping_address.gql +1 -2
  259. data/spec/support/graphql/queries/current_user.gql +6 -11
  260. data/spec/support/graphql/responses/completed_orders/billing_address.json.erb +2 -4
  261. data/spec/support/graphql/responses/completed_orders/shipping_address.json.erb +2 -4
  262. data/spec/support/graphql/responses/current_store.json.erb +1 -1
  263. data/spec/support/graphql/responses/current_user.json.erb +7 -13
  264. data/spec/support/graphql/responses/taxonomies.json.erb +7 -7
  265. metadata +252 -37
  266. data/lib/solidus_graphql_api/factories.rb +0 -11
  267. data/spec/support/graphql/mutations/mark_default_address.gql +0 -9
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'JSON type' do
6
+ it 'coerces JSON custom type', type: :feature do
7
+ create(:product, name: 'Shirt')
8
+
9
+ post '/graphql',
10
+ params: {
11
+ query: "{ products(query: { search: { name_cont: \"Shirt\" } }) { nodes { name } } }"
12
+ },
13
+ headers: headers
14
+
15
+ expect(JSON.parse(response.body).dig(*%w[data products nodes])[0]['name']).to eq('Shirt')
16
+ end
17
+ end
@@ -5,43 +5,55 @@ require 'spec_helper'
5
5
  RSpec.describe SolidusGraphqlApi::BatchLoader::HasManyThrough do
6
6
  subject(:loader) do
7
7
  described_class.new(
8
- article,
9
- Article.reflect_on_association(:comment_authors)
8
+ physician,
9
+ Physician.reflect_on_association(:patients)
10
10
  )
11
11
  end
12
12
 
13
- with_model :Article, scope: :all do
13
+ with_model :Physician, scope: :all do
14
14
  model do
15
- has_many :comments
16
- has_many :comment_authors, through: :comments, source: :author
15
+ has_many :appointments
16
+ has_many :patients, through: :appointments
17
17
  end
18
18
  end
19
19
 
20
- with_model :Comment, scope: :all do
20
+ with_model :Appointment, scope: :all do
21
21
  table do |t|
22
- t.belongs_to :article
23
- t.belongs_to :author
22
+ t.belongs_to :physician, index: { name: :appointment_on_physician }
23
+ t.belongs_to :patient
24
24
  end
25
25
 
26
26
  model do
27
- belongs_to :article
28
- belongs_to :author
27
+ belongs_to :physician
28
+ belongs_to :patient
29
29
  end
30
30
  end
31
31
 
32
- with_model :Author, scope: :all do
32
+ with_model :Patient, scope: :all do
33
33
  model do
34
- has_many :comments
34
+ has_many :appointments
35
35
  end
36
36
  end
37
37
 
38
- let!(:article) { Article.create! }
38
+ let!(:physician) { Physician.create! }
39
39
 
40
40
  before do
41
- article.comments.create!(author: Author.create!)
41
+ physician.appointments.create!(patient: Patient.create!)
42
42
  end
43
43
 
44
44
  it 'loads the association properly' do
45
- expect(loader.load.sync).to eq(article.comment_authors)
45
+ expect(loader.load.sync).to eq(physician.patients)
46
+ end
47
+
48
+ it "doesn't duplicate result when another record loaded in the batch is also associated to the same target record" do
49
+ second_physician = Physician.create!
50
+ Appointment.create!(patient: physician.patients.first, physician: second_physician)
51
+
52
+ described_class.new(
53
+ second_physician,
54
+ Physician.reflect_on_association(:patients)
55
+ ).load
56
+
57
+ expect(loader.load.sync.length).to be(1)
46
58
  end
47
59
  end
@@ -7,7 +7,10 @@ RSpec.describe SolidusGraphqlApi::Context do
7
7
 
8
8
  let(:headers) do
9
9
  headers_hash = {}
10
- headers_hash['Authorization'] = "Bearer #{authorization_token}" if defined?(authorization_token) && authorization_token
10
+ if defined?(authorization_token) && authorization_token
11
+ headers_hash['Authorization'] =
12
+ "Bearer #{authorization_token}"
13
+ end
11
14
  headers_hash['X-Spree-Order-Token'] = order_token if defined?(order_token) && order_token
12
15
  headers_hash
13
16
  end
@@ -55,8 +58,62 @@ RSpec.describe SolidusGraphqlApi::Context do
55
58
  describe '#current_user' do
56
59
  subject { schema_context.current_user }
57
60
 
58
- context 'when headers do not contains the authorization token' do
59
- it { is_expected.to be_nil }
61
+ context 'when headers do not contain the authorization token' do
62
+ context "and there's no user with nil or empty spree_api_key" do
63
+ it { is_expected.to be_nil }
64
+ end
65
+
66
+ context "and there's a user with nil spree_api_key" do
67
+ before { FactoryBot.create(:user, spree_api_key: nil) }
68
+
69
+ it { is_expected.to be_nil }
70
+ end
71
+
72
+ context "and there's a user with empty string as spree_api_key" do
73
+ before { FactoryBot.create(:user, spree_api_key: '') }
74
+
75
+ it { is_expected.to be_nil }
76
+ end
77
+ end
78
+
79
+ context 'when headers contain an empty authorization token' do
80
+ let(:authorization_token) { '' }
81
+
82
+ context "and there's no user with nil or empty spree_api_key" do
83
+ it { is_expected.to be_nil }
84
+ end
85
+
86
+ context "and there's a user with nil spree_api_key" do
87
+ before { FactoryBot.create(:user, spree_api_key: nil) }
88
+
89
+ it { is_expected.to be_nil }
90
+ end
91
+
92
+ context "and there's a user with empty string as spree_api_key" do
93
+ before { FactoryBot.create(:user, spree_api_key: '') }
94
+
95
+ it { is_expected.to be_nil }
96
+ end
97
+ end
98
+
99
+ context "when headers contain a authorization header that doesn't match" do
100
+ let(:headers) { { 'Authorization' => 'abc' } }
101
+
102
+ context "and there's no user with nil or empty spree_api_key" do
103
+ it { is_expected.to be_nil }
104
+ end
105
+
106
+ context "and there's a user with nil spree_api_key" do
107
+ before { FactoryBot.create(:user, spree_api_key: nil) }
108
+
109
+ it { is_expected.to be_nil }
110
+ end
111
+
112
+ context "and there's a user with empty string as spree_api_key" do
113
+ before { FactoryBot.create(:user, spree_api_key: '') }
114
+
115
+ it { is_expected.to be_nil }
116
+ end
60
117
  end
61
118
 
62
119
  context 'when headers contains the authorization token' do
@@ -171,8 +228,12 @@ RSpec.describe SolidusGraphqlApi::Context do
171
228
  end
172
229
 
173
230
  context 'when the current user has many incompleted orders in the current store' do
174
- let!(:first_created_order) { create :order, user: current_user, store: current_store, created_at: Time.zone.yesterday }
175
- let!(:last_created_order) { create :order, user: current_user, store: current_store, created_at: Time.zone.today }
231
+ let!(:first_created_order) {
232
+ create :order, user: current_user, store: current_store, created_at: Time.zone.yesterday
233
+ }
234
+ let!(:last_created_order) {
235
+ create :order, user: current_user, store: current_store, created_at: Time.zone.today
236
+ }
176
237
 
177
238
  it { is_expected.to eq last_created_order }
178
239
  end
@@ -228,9 +289,61 @@ RSpec.describe SolidusGraphqlApi::Context do
228
289
  it { is_expected.to be_nil }
229
290
  end
230
291
 
292
+ # Need to bypass application layer to reproduce race database state
293
+ # rubocop:disable Rails/SkipsModelValidations
231
294
  context 'when is provided no order token' do
232
- it { is_expected.to be_nil }
295
+ context "and there's no order with nil or empty guest_token" do
296
+ it { is_expected.to be_nil }
297
+ end
298
+
299
+ context "and there's an order with nil guest_token" do
300
+ before do
301
+ order = FactoryBot.create(:order)
302
+ order.update_column(:guest_token, nil)
303
+ end
304
+
305
+ it { is_expected.to be_nil }
306
+ end
307
+
308
+ context "and there's an order with empty string as guest_token" do
309
+ before do
310
+ order = FactoryBot.create(:order)
311
+ order.update_column(:guest_token, '')
312
+ end
313
+
314
+ it { is_expected.to be_nil }
315
+ end
316
+ end
317
+ # rubocop:enable Rails/SkipsModelValidations
318
+
319
+ # Need to bypass application layer to reproduce race database state
320
+ # rubocop:disable Rails/SkipsModelValidations
321
+ context 'when is provided an empty order token' do
322
+ let(:order_token) { '' }
323
+
324
+ context "and there's no order with nil or empty guest_token" do
325
+ it { is_expected.to be_nil }
326
+ end
327
+
328
+ context "and there's an order with nil guest_token" do
329
+ before do
330
+ order = FactoryBot.create(:order)
331
+ order.update_column(:guest_token, nil)
332
+ end
333
+
334
+ it { is_expected.to be_nil }
335
+ end
336
+
337
+ context "and there's an order with empty string as guest_token" do
338
+ before do
339
+ order = FactoryBot.create(:order)
340
+ order.update_column(:guest_token, '')
341
+ end
342
+
343
+ it { is_expected.to be_nil }
344
+ end
233
345
  end
346
+ # rubocop:enable Rails/SkipsModelValidations
234
347
  end
235
348
  end
236
349
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe SolidusGraphqlApi::Queries::OptionValue::OptionTypeQuery do
6
+ let(:option_type) { create(:option_type) }
7
+ let(:option_value) { create(:option_value, option_type: option_type) }
8
+
9
+ it { expect(described_class.new(option_value: option_value).call.sync).to eq(option_type) }
10
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe SolidusGraphqlApi::Queries::ShippingRate::ShippingMethodQuery do
6
+ let(:shipping_method) { create(:shipping_method) }
7
+
8
+ let(:shipping_rate) { create(:shipping_rate, shipping_method: shipping_method) }
9
+
10
+ it { expect(described_class.new(shipping_rate: shipping_rate).call.sync).to eq(shipping_method) }
11
+ end
@@ -5,5 +5,5 @@ require 'spec_helper'
5
5
  RSpec.describe SolidusGraphqlApi::Queries::Variant::DefaultPriceQuery do
6
6
  let(:variant) { create(:variant) }
7
7
 
8
- it { expect(described_class.new(variant: variant).call.sync).to eq(variant.default_price) }
8
+ it { expect(described_class.new(variant: variant).call).to eq(variant.default_price) }
9
9
  end
@@ -3,7 +3,11 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe SolidusGraphqlApi::Types::Base::Object do
6
- subject { Class.new(described_class) }
6
+ subject do
7
+ Class.new(described_class) do
8
+ graphql_name :test
9
+ end
10
+ end
7
11
 
8
12
  describe '.remove_field' do
9
13
  context 'when the field is defined' do
@@ -37,7 +37,8 @@ RSpec.describe SolidusGraphqlApi::Types::Json do
37
37
  hash_array: [
38
38
  {
39
39
  ids_array: [
40
- 'U3ByZWU6OlByb21vdGlvbkFjdGlvbi02', 'U3ByZWU6OlByb21vdGlvbkFjdGlvbi04' # Spree::PromotionAction-6, Spree::PromotionAction-8
40
+ 'U3ByZWU6OlByb21vdGlvbkFjdGlvbi02',
41
+ 'U3ByZWU6OlByb21vdGlvbkFjdGlvbi04' # Spree::PromotionAction-6, Spree::PromotionAction-8
41
42
  ],
42
43
  ids_hash: {
43
44
  id: 'U3ByZWU6OkFkanVzdG1lbnQtNQ==', # Spree::Adjustment-5
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe SolidusGraphqlApi::Types::OptionValue do
6
+ let(:option_value) { create(:option_value) }
7
+ let(:query_object) { spy(:query_object) }
8
+
9
+ subject { described_class.send(:new, option_value, {}) }
10
+
11
+ describe '#option_type' do
12
+ before do
13
+ allow(SolidusGraphqlApi::Queries::OptionValue::OptionTypeQuery).
14
+ to receive(:new).with(option_value: option_value).
15
+ and_return(query_object)
16
+ end
17
+
18
+ after { subject.option_type }
19
+
20
+ it { expect(query_object).to receive(:call) }
21
+ end
22
+ end
@@ -34,7 +34,9 @@ RSpec.describe SolidusGraphqlApi::Types::Product do
34
34
 
35
35
  describe '#product_properties' do
36
36
  before do
37
- allow(SolidusGraphqlApi::Queries::Product::ProductPropertiesQuery).to receive(:new).with(product: product).and_return(query_object)
37
+ allow(SolidusGraphqlApi::Queries::Product::ProductPropertiesQuery).
38
+ to receive(:new).with(product: product).
39
+ and_return(query_object)
38
40
  end
39
41
 
40
42
  after { subject.product_properties }
@@ -24,7 +24,9 @@ RSpec.describe SolidusGraphqlApi::Types::Query do
24
24
 
25
25
  let(:slug) { 'slug' }
26
26
 
27
- before { allow(SolidusGraphqlApi::Queries::ProductBySlugQuery).to receive(:new).with(no_args).and_return(query_object) }
27
+ before {
28
+ allow(SolidusGraphqlApi::Queries::ProductBySlugQuery).to receive(:new).with(no_args).and_return(query_object)
29
+ }
28
30
 
29
31
  after { subject.product_by_slug(slug: slug) }
30
32
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe SolidusGraphqlApi::Types::ShippingRate do
6
+ let(:shipping_rate) { create(:shipping_rate) }
7
+ let(:query_object) { spy(:query_object) }
8
+
9
+ subject { described_class.send(:new, shipping_rate, {}) }
10
+
11
+ describe '#shipping_method' do
12
+ before do
13
+ allow(SolidusGraphqlApi::Queries::ShippingRate::ShippingMethodQuery).
14
+ to receive(:new).with(shipping_rate: shipping_rate).
15
+ and_return(query_object)
16
+ end
17
+
18
+ after { subject.shipping_method }
19
+
20
+ it { expect(query_object).to receive(:call) }
21
+ end
22
+ end
@@ -7,11 +7,24 @@ RSpec.describe Spree::GraphqlController do
7
7
 
8
8
  before { allow_any_instance_of(SolidusGraphqlApi::Context).to receive(:to_h).and_return(context) }
9
9
 
10
- after { post '/graphql', headers: headers }
11
-
12
10
  it 'passes the right context to the schema' do
13
11
  expect(SolidusGraphqlApi::Schema).to receive(:execute).with(
14
12
  nil, hash_including(context: context)
15
13
  )
14
+
15
+ post '/graphql', headers: headers
16
+ end
17
+
18
+ it 'can return blob URLs on disk storage' do
19
+ product = create(:product)
20
+ product.images.create(attributes_for(:image))
21
+
22
+ post '/graphql',
23
+ params: {
24
+ query: "{ productBySlug(slug: \"#{product.slug}\") { masterVariant { images { nodes { smallUrl } } } } }"
25
+ },
26
+ headers: headers
27
+
28
+ expect(JSON.parse(response.body).dig(*%w[data productBySlug masterVariant images nodes])[0]['smallUrl']).to match('http://')
16
29
  end
17
30
  end
data/spec/spec_helper.rb CHANGED
@@ -6,24 +6,23 @@ ENV['RAILS_ENV'] = 'test'
6
6
  # Run Coverage report
7
7
  require 'solidus_dev_support/rspec/coverage'
8
8
 
9
- require(File.expand_path('dummy/config/environment.rb', __dir__).tap { |file|
10
- # Create the dummy app if it's still missing.
11
- system 'bin/rake extension:test_app' unless File.exist? file
12
- })
9
+ # Create the dummy app if it's still missing.
10
+ dummy_env = "#{__dir__}/dummy/config/environment.rb"
11
+ system 'bin/rake extension:test_app' unless File.exist? dummy_env
12
+ require dummy_env
13
13
 
14
14
  # Requires factories and other useful helpers defined in spree_core.
15
- require 'solidus_dev_support/rspec/rails_helper'
16
- require 'pry'
15
+ require 'solidus_dev_support/rspec/feature_helper'
17
16
  require "graphql/schema_comparator"
18
17
  require 'with_model'
19
18
  require 'timecop'
20
19
 
21
20
  # Requires supporting ruby files with custom matchers and macros, etc,
22
21
  # in spec/support/ and its subdirectories.
23
- Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
22
+ Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
24
23
 
25
- # Requires factories defined in lib/solidus_graphql_api/factories.rb
26
- require 'solidus_graphql_api/factories'
24
+ # Requires factories defined in lib/solidus_graphql_api/testing_support/factories.rb
25
+ SolidusDevSupport::TestingSupport::Factories.load_for(SolidusGraphqlApi::Engine)
27
26
 
28
27
  RSpec.configure do |config|
29
28
  config.add_setting :default_freeze_date, default: "21/12/2012 12:00:00"
@@ -33,6 +32,13 @@ RSpec.configure do |config|
33
32
 
34
33
  config.infer_spec_type_from_file_location!
35
34
  config.use_transactional_fixtures = false
35
+
36
+ if defined?(ActiveStorage::Current)
37
+ config.before(:all) do
38
+ ActiveStorage::Current.host = 'https://www.example.com'
39
+ end
40
+ end
41
+
36
42
  config.include Helpers::Graphql
37
43
  config.include Matchers::Graphql
38
44
 
@@ -85,9 +85,8 @@ type Address implements Node {
85
85
  company: String
86
86
  country: Country!
87
87
  createdAt: ISO8601DateTime
88
- firstname: String!
89
88
  id: ID!
90
- lastname: String
89
+ name: String!
91
90
  phone: String!
92
91
  state: State
93
92
  stateName: String
@@ -140,14 +139,18 @@ input AddressInput {
140
139
  city: String!
141
140
  company: String
142
141
  countryId: ID!
143
- firstname: String!
144
- lastname: String
142
+ name: String!
145
143
  phone: String!
146
144
  stateId: ID
147
145
  stateName: String
148
146
  zipcode: String!
149
147
  }
150
148
 
149
+ enum AddressTypeInput {
150
+ billing
151
+ shipping
152
+ }
153
+
151
154
  """
152
155
  Adjustment.
153
156
  """
@@ -562,9 +565,9 @@ type ManifestItem {
562
565
  }
563
566
 
564
567
  """
565
- Autogenerated input type of MarkDefaultAddress
568
+ Autogenerated input type of MarkDefaultShipAddress
566
569
  """
567
- input MarkDefaultAddressInput {
570
+ input MarkDefaultShipAddressInput {
568
571
  addressId: ID!
569
572
 
570
573
  """
@@ -574,9 +577,9 @@ input MarkDefaultAddressInput {
574
577
  }
575
578
 
576
579
  """
577
- Autogenerated return type of MarkDefaultAddress
580
+ Autogenerated return type of MarkDefaultShipAddress
578
581
  """
579
- type MarkDefaultAddressPayload {
582
+ type MarkDefaultShipAddressPayload {
580
583
  """
581
584
  A unique identifier for the client performing the mutation.
582
585
  """
@@ -585,22 +588,102 @@ type MarkDefaultAddressPayload {
585
588
  }
586
589
 
587
590
  type Mutation {
588
- addAddressesToCheckout(input: AddAddressesToCheckoutInput!): AddAddressesToCheckoutPayload
589
- addPaymentToCheckout(input: AddPaymentToCheckoutInput!): AddPaymentToCheckoutPayload
590
- addToCart(input: AddToCartInput!): AddToCartPayload
591
- advanceCheckout(input: AdvanceCheckoutInput!): AdvanceCheckoutPayload
592
- applyCouponCode(input: ApplyCouponCodeInput!): ApplyCouponCodePayload
593
- completeCheckout(input: CompleteCheckoutInput!): CompleteCheckoutPayload
594
- createOrder(input: CreateOrderInput!): CreateOrderPayload
595
- emptyCart(input: EmptyCartInput!): EmptyCartPayload
596
- markDefaultAddress(input: MarkDefaultAddressInput!): MarkDefaultAddressPayload
597
- nextCheckoutState(input: NextCheckoutStateInput!): NextCheckoutStatePayload
598
- removeFromAddressBook(input: RemoveFromAddressBookInput!): RemoveFromAddressBookPayload
599
- removeFromCart(input: RemoveFromCartInput!): RemoveFromCartPayload
600
- saveInAddressBook(input: SaveInAddressBookInput!): SaveInAddressBookPayload
601
- selectShippingRate(input: SelectShippingRateInput!): SelectShippingRatePayload
602
- setOrderEmail(input: SetOrderEmailInput!): SetOrderEmailPayload
603
- updateCartQuantity(input: UpdateCartQuantityInput!): UpdateCartQuantityPayload
591
+ addAddressesToCheckout(
592
+ """
593
+ Parameters for AddAddressesToCheckout
594
+ """
595
+ input: AddAddressesToCheckoutInput!
596
+ ): AddAddressesToCheckoutPayload
597
+ addPaymentToCheckout(
598
+ """
599
+ Parameters for AddPaymentToCheckout
600
+ """
601
+ input: AddPaymentToCheckoutInput!
602
+ ): AddPaymentToCheckoutPayload
603
+ addToCart(
604
+ """
605
+ Parameters for AddToCart
606
+ """
607
+ input: AddToCartInput!
608
+ ): AddToCartPayload
609
+ advanceCheckout(
610
+ """
611
+ Parameters for AdvanceCheckout
612
+ """
613
+ input: AdvanceCheckoutInput!
614
+ ): AdvanceCheckoutPayload
615
+ applyCouponCode(
616
+ """
617
+ Parameters for ApplyCouponCode
618
+ """
619
+ input: ApplyCouponCodeInput!
620
+ ): ApplyCouponCodePayload
621
+ completeCheckout(
622
+ """
623
+ Parameters for CompleteCheckout
624
+ """
625
+ input: CompleteCheckoutInput!
626
+ ): CompleteCheckoutPayload
627
+ createOrder(
628
+ """
629
+ Parameters for CreateOrder
630
+ """
631
+ input: CreateOrderInput!
632
+ ): CreateOrderPayload
633
+ emptyCart(
634
+ """
635
+ Parameters for EmptyCart
636
+ """
637
+ input: EmptyCartInput!
638
+ ): EmptyCartPayload
639
+ markDefaultShipAddress(
640
+ """
641
+ Parameters for MarkDefaultShipAddress
642
+ """
643
+ input: MarkDefaultShipAddressInput!
644
+ ): MarkDefaultShipAddressPayload
645
+ nextCheckoutState(
646
+ """
647
+ Parameters for NextCheckoutState
648
+ """
649
+ input: NextCheckoutStateInput!
650
+ ): NextCheckoutStatePayload
651
+ removeFromAddressBook(
652
+ """
653
+ Parameters for RemoveFromAddressBook
654
+ """
655
+ input: RemoveFromAddressBookInput!
656
+ ): RemoveFromAddressBookPayload
657
+ removeFromCart(
658
+ """
659
+ Parameters for RemoveFromCart
660
+ """
661
+ input: RemoveFromCartInput!
662
+ ): RemoveFromCartPayload
663
+ saveInAddressBook(
664
+ """
665
+ Parameters for SaveInAddressBook
666
+ """
667
+ input: SaveInAddressBookInput!
668
+ ): SaveInAddressBookPayload
669
+ selectShippingRate(
670
+ """
671
+ Parameters for SelectShippingRate
672
+ """
673
+ input: SelectShippingRateInput!
674
+ ): SelectShippingRatePayload
675
+ setOrderEmail(
676
+ """
677
+ Parameters for SetOrderEmail
678
+ """
679
+ input: SetOrderEmailInput!
680
+ ): SetOrderEmailPayload
681
+ updateCartQuantity(
682
+ """
683
+ Parameters for UpdateCartQuantity
684
+ """
685
+ input: UpdateCartQuantityInput!
686
+ ): UpdateCartQuantityPayload
604
687
  }
605
688
 
606
689
  """
@@ -710,6 +793,7 @@ type OptionValue implements Node {
710
793
  createdAt: ISO8601DateTime
711
794
  id: ID!
712
795
  name: String!
796
+ optionType: OptionType!
713
797
  position: String!
714
798
  presentation: String!
715
799
  updatedAt: ISO8601DateTime
@@ -1387,6 +1471,7 @@ Autogenerated input type of SaveInAddressBook
1387
1471
  """
1388
1472
  input SaveInAddressBookInput {
1389
1473
  address: AddressInput!
1474
+ addressType: AddressTypeInput = shipping
1390
1475
 
1391
1476
  """
1392
1477
  A unique identifier for the client performing the mutation.
@@ -1524,6 +1609,23 @@ type ShipmentEdge {
1524
1609
  node: Shipment
1525
1610
  }
1526
1611
 
1612
+ """
1613
+ Shipping Method.
1614
+ """
1615
+ type ShippingMethod implements Node {
1616
+ adminName: String
1617
+ availableToAll: Boolean!
1618
+ availableToUsers: Boolean!
1619
+ carrier: String
1620
+ code: String
1621
+ createdAt: ISO8601DateTime
1622
+ id: ID!
1623
+ name: String!
1624
+ serviceLevel: String
1625
+ trackingUrl: String
1626
+ updatedAt: ISO8601DateTime
1627
+ }
1628
+
1527
1629
  """
1528
1630
  Shipping Rate.
1529
1631
  """
@@ -1533,6 +1635,7 @@ type ShippingRate implements Node {
1533
1635
  currency: String!
1534
1636
  id: ID!
1535
1637
  selected: Boolean!
1638
+ shippingMethod: ShippingMethod!
1536
1639
  updatedAt: ISO8601DateTime
1537
1640
  }
1538
1641
 
@@ -1861,7 +1964,6 @@ type User implements Node {
1861
1964
  billAddress: Address
1862
1965
  createdAt: ISO8601DateTime
1863
1966
  currentSignInAt: ISO8601DateTime
1864
- defaultAddress: Address
1865
1967
  email: String!
1866
1968
  id: ID!
1867
1969
  lastSignInAt: ISO8601DateTime
@@ -2067,4 +2169,4 @@ type WalletPaymentSourceEdge {
2067
2169
  The item at the end of the edge.
2068
2170
  """
2069
2171
  node: WalletPaymentSource
2070
- }
2172
+ }