solidus_graphql_api 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }