shopify_api 9.0.4 → 9.5

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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/ISSUE_TEMPLATE.md +36 -0
  4. data/.github/workflows/build.yml +44 -0
  5. data/.gitignore +2 -1
  6. data/.rubocop.yml +23 -3
  7. data/.rubocop_todo.yml +75 -0
  8. data/CHANGELOG.md +41 -0
  9. data/CONTRIBUTING.md +1 -1
  10. data/Gemfile +5 -0
  11. data/Gemfile.lock +153 -0
  12. data/Gemfile_ar51 +1 -1
  13. data/README.md +42 -32
  14. data/RELEASING +10 -6
  15. data/Rakefile +16 -5
  16. data/SECURITY.md +59 -0
  17. data/dev.yml +11 -0
  18. data/docs/_config.yml +1 -0
  19. data/docs/_includes/footer.html +28 -0
  20. data/docs/_includes/head.html +28 -0
  21. data/docs/_layouts/index.html +57 -0
  22. data/docs/graphql.md +47 -2
  23. data/docs/index.md +639 -0
  24. data/lib/active_resource/connection_ext.rb +1 -0
  25. data/lib/active_resource/detailed_log_subscriber.rb +10 -7
  26. data/lib/active_resource/json_errors.rb +8 -2
  27. data/lib/shopify_api/api_access.rb +57 -0
  28. data/lib/shopify_api/api_version.rb +6 -5
  29. data/lib/shopify_api/connection.rb +1 -0
  30. data/lib/shopify_api/countable.rb +3 -2
  31. data/lib/shopify_api/disable_prefix_check.rb +2 -2
  32. data/lib/shopify_api/events.rb +2 -1
  33. data/lib/shopify_api/graphql.rb +28 -8
  34. data/lib/shopify_api/hmac_params.rb +23 -0
  35. data/lib/shopify_api/limits.rb +3 -2
  36. data/lib/shopify_api/message_enricher.rb +11 -9
  37. data/lib/shopify_api/meta.rb +0 -1
  38. data/lib/shopify_api/metafields.rb +5 -4
  39. data/lib/shopify_api/pagination_link_headers.rb +5 -4
  40. data/lib/shopify_api/resources/access_scope.rb +1 -1
  41. data/lib/shopify_api/resources/access_token.rb +1 -0
  42. data/lib/shopify_api/resources/address.rb +1 -0
  43. data/lib/shopify_api/resources/announcement.rb +2 -1
  44. data/lib/shopify_api/resources/application_charge.rb +1 -0
  45. data/lib/shopify_api/resources/application_credit.rb +1 -0
  46. data/lib/shopify_api/resources/article.rb +3 -2
  47. data/lib/shopify_api/resources/asset.rb +6 -5
  48. data/lib/shopify_api/resources/assigned_fulfillment_order.rb +1 -1
  49. data/lib/shopify_api/resources/base.rb +12 -8
  50. data/lib/shopify_api/resources/billing_address.rb +1 -0
  51. data/lib/shopify_api/resources/blog.rb +2 -1
  52. data/lib/shopify_api/resources/carrier_service.rb +1 -0
  53. data/lib/shopify_api/resources/cart.rb +2 -1
  54. data/lib/shopify_api/resources/collect.rb +1 -0
  55. data/lib/shopify_api/resources/collection_listing.rb +1 -0
  56. data/lib/shopify_api/resources/comment.rb +20 -5
  57. data/lib/shopify_api/resources/country.rb +1 -0
  58. data/lib/shopify_api/resources/custom_collection.rb +4 -3
  59. data/lib/shopify_api/resources/customer.rb +2 -1
  60. data/lib/shopify_api/resources/customer_group.rb +1 -0
  61. data/lib/shopify_api/resources/customer_invite.rb +1 -0
  62. data/lib/shopify_api/resources/customer_saved_search.rb +2 -1
  63. data/lib/shopify_api/resources/discount_code.rb +1 -0
  64. data/lib/shopify_api/resources/discount_code_batch.rb +4 -2
  65. data/lib/shopify_api/resources/draft_order.rb +1 -0
  66. data/lib/shopify_api/resources/draft_order_invoice.rb +1 -0
  67. data/lib/shopify_api/resources/event.rb +1 -0
  68. data/lib/shopify_api/resources/fulfillment.rb +12 -3
  69. data/lib/shopify_api/resources/fulfillment_event.rb +1 -0
  70. data/lib/shopify_api/resources/fulfillment_order.rb +30 -16
  71. data/lib/shopify_api/resources/fulfillment_order_locations_for_move.rb +1 -0
  72. data/lib/shopify_api/resources/fulfillment_request.rb +1 -0
  73. data/lib/shopify_api/resources/fulfillment_service.rb +1 -0
  74. data/lib/shopify_api/resources/fulfillment_v2.rb +3 -2
  75. data/lib/shopify_api/resources/gift_card.rb +1 -0
  76. data/lib/shopify_api/resources/image.rb +2 -1
  77. data/lib/shopify_api/resources/inventory_level.rb +3 -4
  78. data/lib/shopify_api/resources/line_item.rb +4 -3
  79. data/lib/shopify_api/resources/location.rb +1 -1
  80. data/lib/shopify_api/resources/marketing_event.rb +1 -0
  81. data/lib/shopify_api/resources/metafield.rb +1 -0
  82. data/lib/shopify_api/resources/note_attribute.rb +1 -0
  83. data/lib/shopify_api/resources/option.rb +1 -0
  84. data/lib/shopify_api/resources/order.rb +2 -1
  85. data/lib/shopify_api/resources/order_risk.rb +1 -0
  86. data/lib/shopify_api/resources/page.rb +1 -0
  87. data/lib/shopify_api/resources/payment_details.rb +1 -0
  88. data/lib/shopify_api/resources/policy.rb +1 -0
  89. data/lib/shopify_api/resources/price_rule.rb +1 -1
  90. data/lib/shopify_api/resources/product.rb +27 -3
  91. data/lib/shopify_api/resources/product_listing.rb +1 -0
  92. data/lib/shopify_api/resources/province.rb +1 -0
  93. data/lib/shopify_api/resources/receipt.rb +1 -0
  94. data/lib/shopify_api/resources/recurring_application_charge.rb +4 -1
  95. data/lib/shopify_api/resources/redirect.rb +1 -0
  96. data/lib/shopify_api/resources/refund.rb +2 -1
  97. data/lib/shopify_api/resources/report.rb +1 -0
  98. data/lib/shopify_api/resources/resource_feedback.rb +1 -1
  99. data/lib/shopify_api/resources/rule.rb +1 -0
  100. data/lib/shopify_api/resources/script_tag.rb +1 -0
  101. data/lib/shopify_api/resources/shipping_address.rb +1 -0
  102. data/lib/shopify_api/resources/shipping_line.rb +1 -0
  103. data/lib/shopify_api/resources/shipping_zone.rb +1 -0
  104. data/lib/shopify_api/resources/shop.rb +2 -1
  105. data/lib/shopify_api/resources/smart_collection.rb +4 -8
  106. data/lib/shopify_api/resources/storefront_access_token.rb +1 -0
  107. data/lib/shopify_api/resources/tax_line.rb +1 -0
  108. data/lib/shopify_api/resources/tax_service.rb +1 -0
  109. data/lib/shopify_api/resources/theme.rb +1 -0
  110. data/lib/shopify_api/resources/transaction.rb +1 -0
  111. data/lib/shopify_api/resources/usage_charge.rb +1 -0
  112. data/lib/shopify_api/resources/user.rb +1 -0
  113. data/lib/shopify_api/resources/variant.rb +35 -0
  114. data/lib/shopify_api/resources/webhook.rb +1 -0
  115. data/lib/shopify_api/resources.rb +1 -0
  116. data/lib/shopify_api/session.rb +51 -20
  117. data/lib/shopify_api/version.rb +2 -1
  118. data/lib/shopify_api.rb +9 -1
  119. data/lib/verify_docs.rb +8 -0
  120. data/service.yml +2 -5
  121. data/shopify_api.gemspec +13 -7
  122. data/test/access_token_test.rb +6 -5
  123. data/test/active_resource/json_errors_test.rb +6 -6
  124. data/test/api_access_test.rb +153 -0
  125. data/test/api_version_test.rb +3 -3
  126. data/test/application_charge_test.rb +30 -27
  127. data/test/application_credit_test.rb +10 -9
  128. data/test/article_test.rb +34 -35
  129. data/test/asset_test.rb +14 -6
  130. data/test/assigned_fulfillment_order_test.rb +5 -4
  131. data/test/base_test.rb +64 -49
  132. data/test/blog_test.rb +4 -3
  133. data/test/carrier_service_test.rb +7 -6
  134. data/test/cart_test.rb +2 -1
  135. data/test/collect_test.rb +4 -3
  136. data/test/collection_listing_test.rb +21 -16
  137. data/test/collection_publication_test.rb +8 -8
  138. data/test/collection_test.rb +20 -19
  139. data/test/countable_test.rb +3 -2
  140. data/test/currency_test.rb +5 -5
  141. data/test/custom_collection_test.rb +4 -3
  142. data/test/customer_saved_search_test.rb +18 -8
  143. data/test/customer_test.rb +22 -14
  144. data/test/detailed_log_subscriber_test.rb +16 -12
  145. data/test/discount_code_batch_test.rb +11 -10
  146. data/test/discount_code_test.rb +21 -15
  147. data/test/draft_order_test.rb +68 -52
  148. data/test/fixtures/assigned_fulfillment_orders.json +2 -0
  149. data/test/fixtures/fulfillment_order.json +1 -0
  150. data/test/fixtures/fulfillment_orders.json +2 -0
  151. data/test/fulfillment_event_test.rb +31 -26
  152. data/test/fulfillment_order_test.rb +217 -149
  153. data/test/fulfillment_order_test_helper.rb +1 -0
  154. data/test/fulfillment_request_test.rb +10 -8
  155. data/test/fulfillment_service_test.rb +13 -12
  156. data/test/fulfillment_test.rb +81 -66
  157. data/test/fulfillment_v2_test.rb +16 -12
  158. data/test/gift_card_test.rb +6 -4
  159. data/test/graphql_test.rb +55 -23
  160. data/test/hmac_params_test.rb +25 -0
  161. data/test/image_test.rb +19 -17
  162. data/test/inventory_level_test.rb +24 -15
  163. data/test/lib/webmock_extensions/last_request.rb +1 -1
  164. data/test/limits_test.rb +2 -1
  165. data/test/location_test.rb +2 -1
  166. data/test/marketing_event_test.rb +20 -20
  167. data/test/message_enricher_test.rb +6 -6
  168. data/test/meta_test.rb +9 -11
  169. data/test/metafield_test.rb +30 -20
  170. data/test/order_risk_test.rb +17 -16
  171. data/test/order_test.rb +43 -28
  172. data/test/pagination_test.rb +89 -56
  173. data/test/policy_test.rb +6 -5
  174. data/test/price_rule_test.rb +20 -15
  175. data/test/product_listing_test.rb +20 -20
  176. data/test/product_publication_test.rb +8 -8
  177. data/test/product_test.rb +71 -20
  178. data/test/publication_test.rb +3 -3
  179. data/test/recurring_application_charge_test.rb +104 -42
  180. data/test/redirect_test.rb +4 -3
  181. data/test/refund_test.rb +22 -17
  182. data/test/report_test.rb +12 -10
  183. data/test/resource_feedback_test.rb +14 -13
  184. data/test/script_tag_test.rb +10 -9
  185. data/test/session_test.rb +319 -45
  186. data/test/shipping_zone_test.rb +4 -3
  187. data/test/shop_test.rb +47 -33
  188. data/test/smart_collection_test.rb +5 -29
  189. data/test/storefront_access_token_test.rb +13 -15
  190. data/test/tax_service_test.rb +7 -4
  191. data/test/tender_transaction_test.rb +3 -3
  192. data/test/test_helper.rb +14 -12
  193. data/test/transaction_test.rb +4 -3
  194. data/test/usage_charge_test.rb +12 -8
  195. data/test/user_test.rb +4 -3
  196. data/test/variant_test.rb +50 -23
  197. data/test/webhook_test.rb +10 -7
  198. metadata +44 -17
  199. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
  200. data/.travis.yml +0 -23
  201. data/bin/shopify +0 -3
data/test/session_test.rb CHANGED
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
  require 'timecop'
3
4
 
4
5
  class SessionTest < Test::Unit::TestCase
6
+ SECONDS_IN_A_DAY = 24 * 60 * 60
5
7
 
6
8
  def setup
7
9
  super
@@ -10,20 +12,37 @@ class SessionTest < Test::Unit::TestCase
10
12
 
11
13
  test "not be valid without a url" do
12
14
  session = ShopifyAPI::Session.new(domain: nil, token: "any-token", api_version: any_api_version)
13
- assert_not session.valid?
15
+ assert_not(session.valid?)
14
16
  end
15
17
 
16
18
  test "not be valid without token" do
17
19
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
18
- assert_not session.valid?
20
+ assert_not(session.valid?)
19
21
  end
20
22
 
21
- test "not be valid without an api version" do
23
+ test "not be valid without an API version" do
22
24
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: "any-token", api_version: nil)
23
- assert_not session.valid?
25
+ assert_not(session.valid?)
24
26
 
25
- session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: "any-token", api_version: ShopifyAPI::ApiVersion::NullVersion)
26
- assert_not session.valid?
27
+ session = ShopifyAPI::Session.new(
28
+ domain: "testshop.myshopify.com", token: "any-token", api_version: ShopifyAPI::ApiVersion::NullVersion
29
+ )
30
+ assert_not(session.valid?)
31
+ end
32
+
33
+ test "default to base API version" do
34
+ session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: "any-token")
35
+ assert(session.valid?)
36
+ assert_equal(session.api_version, ShopifyAPI::Base.api_version)
37
+ end
38
+
39
+ test "can override the base API version" do
40
+ different_api_version = '2020-01'
41
+ session = ShopifyAPI::Session.new(
42
+ domain: "testshop.myshopify.com", token: "any-token", api_version: different_api_version
43
+ )
44
+ assert(session.valid?)
45
+ assert_equal(session.api_version, ShopifyAPI::ApiVersion.find_version(different_api_version))
27
46
  end
28
47
 
29
48
  test "be valid with any token, any url and version" do
@@ -32,7 +51,40 @@ class SessionTest < Test::Unit::TestCase
32
51
  token: "any-token",
33
52
  api_version: any_api_version
34
53
  )
35
- assert session.valid?
54
+ assert(session.valid?)
55
+ end
56
+
57
+ test "be valid with nil access_scopes" do
58
+ session = ShopifyAPI::Session.new(
59
+ domain: "testshop.myshopify.com",
60
+ token: "any-token",
61
+ api_version: any_api_version,
62
+ access_scopes: nil
63
+ )
64
+
65
+ assert(session.valid?)
66
+ end
67
+
68
+ test "be valid with string of access_scopes" do
69
+ session = ShopifyAPI::Session.new(
70
+ domain: "testshop.myshopify.com",
71
+ token: "any-token",
72
+ api_version: any_api_version,
73
+ access_scopes: "read_products, write_orders"
74
+ )
75
+
76
+ assert(session.valid?)
77
+ end
78
+
79
+ test "be valid with a collection of access_scopes" do
80
+ session = ShopifyAPI::Session.new(
81
+ domain: "testshop.myshopify.com",
82
+ token: "any-token",
83
+ api_version: any_api_version,
84
+ access_scopes: %w(read_products write_orders)
85
+ )
86
+
87
+ assert(session.valid?)
36
88
  end
37
89
 
38
90
  test "not raise error without params" do
@@ -42,7 +94,7 @@ class SessionTest < Test::Unit::TestCase
42
94
  end
43
95
 
44
96
  test "ignore everything but the subdomain in the shop" do
45
- assert_equal(
97
+ assert_equal_uri(
46
98
  "https://testshop.myshopify.com",
47
99
  ShopifyAPI::Session.new(
48
100
  domain: "http://user:pass@testshop.notshopify.net/path",
@@ -53,7 +105,7 @@ class SessionTest < Test::Unit::TestCase
53
105
  end
54
106
 
55
107
  test "append the myshopify domain if not given" do
56
- assert_equal(
108
+ assert_equal_uri(
57
109
  "https://testshop.myshopify.com",
58
110
  ShopifyAPI::Session.new(domain: "testshop", token: "any-token", api_version: any_api_version).site
59
111
  )
@@ -65,26 +117,60 @@ class SessionTest < Test::Unit::TestCase
65
117
  end
66
118
  end
67
119
 
120
+ test "provides default nil access_scopes attribute" do
121
+ session = ShopifyAPI::Session.new(
122
+ domain: "testshop.myshopify.com",
123
+ token: "any-token",
124
+ api_version: any_api_version
125
+ )
126
+ assert_nil session.access_scopes
127
+ end
128
+
129
+ test "provides specified nil access_scopes attribute" do
130
+ session = ShopifyAPI::Session.new(
131
+ domain: "testshop.myshopify.com",
132
+ token: "any-token",
133
+ access_scopes: "read_products",
134
+ api_version: any_api_version
135
+ )
136
+ assert_equal "read_products", session.access_scopes.to_s
137
+ end
138
+
139
+ test "session instantiation raises error if bad access scopes are provided" do
140
+ assert_raises NoMethodError do
141
+ ShopifyAPI::Session.new(
142
+ domain: "testshop.myshopify.com",
143
+ token: "any-token",
144
+ access_scopes: { bad_input: "bad_input" },
145
+ api_version: any_api_version
146
+ )
147
+ end
148
+ end
149
+
68
150
  test "raise error if params passed but signature omitted" do
69
151
  assert_raises(ShopifyAPI::ValidationException) do
70
152
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
71
- session.request_token({'code' => 'any-code'})
153
+ session.request_token({ 'code' => 'any-code' })
72
154
  end
73
155
  end
74
156
 
75
157
  test "setup api_key and secret for all sessions" do
76
- ShopifyAPI::Session.setup(:api_key => "My test key", :secret => "My test secret")
77
- assert_equal "My test key", ShopifyAPI::Session.api_key
78
- assert_equal "My test secret", ShopifyAPI::Session.secret
158
+ ShopifyAPI::Session.setup(api_key: "My test key", secret: "My test secret")
159
+ assert_equal("My test key", ShopifyAPI::Session.api_key)
160
+ assert_equal("My test secret", ShopifyAPI::Session.secret)
79
161
  end
80
162
 
81
- test "#temp reset ShopifyAPI::Base.site to original value" do
163
+ test "#temp reset ShopifyAPI::Base values to original value" do
82
164
  session1 = ShopifyAPI::Session.new(domain: 'fakeshop.myshopify.com', token: 'token1', api_version: '2019-01')
165
+ ShopifyAPI::Base.user = 'foo'
166
+ ShopifyAPI::Base.password = 'bar'
83
167
  ShopifyAPI::Base.activate_session(session1)
84
168
 
85
169
  ShopifyAPI::Session.temp(domain: "testshop.myshopify.com", token: "any-token", api_version: :unstable) do
86
170
  @assigned_site = ShopifyAPI::Base.site
87
171
  @assigned_version = ShopifyAPI::Base.api_version
172
+ @assigned_user = ShopifyAPI::Base.user
173
+ @assigned_password = ShopifyAPI::Base.password
88
174
  end
89
175
 
90
176
  assert_equal('https://testshop.myshopify.com', @assigned_site.to_s)
@@ -92,6 +178,31 @@ class SessionTest < Test::Unit::TestCase
92
178
 
93
179
  assert_equal(ShopifyAPI::ApiVersion.new(handle: :unstable), @assigned_version)
94
180
  assert_equal(ShopifyAPI::ApiVersion.new(handle: '2019-01'), ShopifyAPI::Base.api_version)
181
+
182
+ assert_nil(@assigned_user)
183
+ assert_equal('foo', ShopifyAPI::Base.user)
184
+
185
+ assert_nil(@assigned_password)
186
+ assert_equal('bar', ShopifyAPI::Base.password)
187
+ end
188
+
189
+ test "#temp does not use basic auth values from Base.site" do
190
+ ShopifyAPI::Base.site = 'https://user:pass@fakeshop.myshopify.com'
191
+
192
+ ShopifyAPI::Session.temp(domain: "testshop.myshopify.com", token: "any-token", api_version: :unstable) do
193
+ @assigned_site = ShopifyAPI::Base.site
194
+ @assigned_user = ShopifyAPI::Base.user
195
+ @assigned_password = ShopifyAPI::Base.password
196
+ end
197
+
198
+ assert_equal('https://testshop.myshopify.com', @assigned_site.to_s)
199
+ assert_equal('https://fakeshop.myshopify.com', ShopifyAPI::Base.site.to_s)
200
+
201
+ assert_nil(@assigned_user)
202
+ assert_equal('user', ShopifyAPI::Base.user)
203
+
204
+ assert_nil(@assigned_password)
205
+ assert_equal('pass', ShopifyAPI::Base.password)
95
206
  end
96
207
 
97
208
  test "#with_session activates the session for the duration of the block" do
@@ -126,7 +237,7 @@ class SessionTest < Test::Unit::TestCase
126
237
  api_version: :unstable
127
238
  )
128
239
 
129
- assert_raises StandardError do
240
+ assert_raises(StandardError) do
130
241
  ShopifyAPI::Session.with_session(other_session) { raise StandardError, "" }
131
242
  end
132
243
 
@@ -172,7 +283,11 @@ class SessionTest < Test::Unit::TestCase
172
283
  )
173
284
  scope = ["write_products"]
174
285
  permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com")
175
- assert_equal "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&scope=write_products&redirect_uri=http://my_redirect_uri.com", permission_url
286
+ assert_equal_uri(
287
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
288
+ "scope=write_products&redirect_uri=http://my_redirect_uri.com",
289
+ permission_url
290
+ )
176
291
  end
177
292
 
178
293
  test "create_permission_url returns correct url with dual scope" do
@@ -182,9 +297,13 @@ class SessionTest < Test::Unit::TestCase
182
297
  token: 'any-token',
183
298
  api_version: any_api_version
184
299
  )
185
- scope = ["write_products","write_customers"]
300
+ scope = ["write_products", "write_customers"]
186
301
  permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com")
187
- assert_equal "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&scope=write_products,write_customers&redirect_uri=http://my_redirect_uri.com", permission_url
302
+ assert_equal_uri(
303
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
304
+ "scope=write_products,write_customers&redirect_uri=http://my_redirect_uri.com",
305
+ permission_url
306
+ )
188
307
  end
189
308
 
190
309
  test "create_permission_url returns correct url with no scope" do
@@ -196,7 +315,11 @@ class SessionTest < Test::Unit::TestCase
196
315
  )
197
316
  scope = []
198
317
  permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com")
199
- assert_equal "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&scope=&redirect_uri=http://my_redirect_uri.com", permission_url
318
+ assert_equal_uri(
319
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
320
+ "scope=&redirect_uri=http://my_redirect_uri.com",
321
+ permission_url
322
+ )
200
323
  end
201
324
 
202
325
  test "create_permission_url returns correct url with state" do
@@ -208,11 +331,31 @@ class SessionTest < Test::Unit::TestCase
208
331
  )
209
332
  scope = []
210
333
  permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com", state: "My nonce")
211
- assert_equal "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&scope=&redirect_uri=http://my_redirect_uri.com&state=My%20nonce", permission_url
334
+ assert_equal_uri(
335
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
336
+ "scope=&redirect_uri=http://my_redirect_uri.com&state=My+nonce",
337
+ permission_url
338
+ )
339
+ end
340
+
341
+ test "create_permission_url returns correct url with grant_options[]" do
342
+ ShopifyAPI::Session.setup(api_key: "My_test_key", secret: "My test secret")
343
+ session = ShopifyAPI::Session.new(
344
+ domain: 'http://localhost.myshopify.com',
345
+ token: 'any-token',
346
+ api_version: any_api_version
347
+ )
348
+ scope = []
349
+ permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com", grant_options: "per-user")
350
+ assert_equal_uri(
351
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
352
+ "scope=&redirect_uri=http://my_redirect_uri.com&grant_options[]=per-user",
353
+ permission_url
354
+ )
212
355
  end
213
356
 
214
357
  test "raise exception if code invalid in request token" do
215
- ShopifyAPI::Session.setup(:api_key => "My test key", :secret => "My test secret")
358
+ ShopifyAPI::Session.setup(api_key: "My test key", secret: "My test secret")
216
359
  session = ShopifyAPI::Session.new(
217
360
  domain: 'http://localhost.myshopify.com',
218
361
  token: nil,
@@ -228,7 +371,7 @@ class SessionTest < Test::Unit::TestCase
228
371
  assert_raises(ShopifyAPI::ValidationException) do
229
372
  session.request_token(code: "bad-code")
230
373
  end
231
- assert_equal false, session.valid?
374
+ assert_equal(false, session.valid?)
232
375
  end
233
376
 
234
377
  test "return site for session" do
@@ -237,87 +380,93 @@ class SessionTest < Test::Unit::TestCase
237
380
  token: "any-token",
238
381
  api_version: any_api_version
239
382
  )
240
- assert_equal "https://testshop.myshopify.com", session.site
383
+ assert_equal_uri("https://testshop.myshopify.com", session.site)
241
384
  end
242
385
 
243
386
  test "return_token_if_signature_is_valid" do
244
387
  api_version = any_api_version
245
- fake nil,
388
+ fake(
389
+ nil,
246
390
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
247
391
  method: :post,
248
392
  body: '{"access_token":"any-token"}'
393
+ )
249
394
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
250
395
 
251
396
  params = { code: 'any-code', timestamp: Time.now }
252
397
  token = session.request_token(params.merge(hmac: generate_signature(params)))
253
398
 
254
- assert_equal "any-token", token
255
- assert_equal "any-token", session.token
399
+ assert_equal("any-token", token)
400
+ assert_equal("any-token", session.token)
256
401
  end
257
402
 
258
403
  test "extra parameters are stored in session" do
259
404
  api_version = ShopifyAPI::ApiVersion.new(handle: :unstable)
260
- fake nil,
405
+ fake(
406
+ nil,
261
407
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
262
408
  method: :post,
263
409
  body: '{"access_token":"any-token","foo":"example"}'
410
+ )
264
411
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
265
412
 
266
413
  params = { code: 'any-code', timestamp: Time.now }
267
- assert session.request_token(params.merge(hmac: generate_signature(params)))
414
+ assert(session.request_token(params.merge(hmac: generate_signature(params))))
268
415
 
269
- assert_equal ({ "foo" => "example" }), session.extra
416
+ assert_equal({ "foo" => "example" }, session.extra)
270
417
  end
271
418
 
272
419
  test "expires_in is automatically converted in expires_at" do
273
420
  api_version = any_api_version
274
- fake nil,
421
+ fake(
422
+ nil,
275
423
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
276
424
  method: :post,
277
425
  body: '{"access_token":"any-token","expires_in":86393}'
426
+ )
278
427
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
279
428
 
280
429
  Timecop.freeze do
281
430
  params = { code: 'any-code', timestamp: Time.now }
282
- assert session.request_token(params.merge(hmac: generate_signature(params)))
431
+ assert(session.request_token(params.merge(hmac: generate_signature(params))))
283
432
 
284
433
  expires_at = Time.now.utc + 86393
285
- assert_equal ({ "expires_at" => expires_at.to_i }), session.extra
286
- assert session.expires_at.is_a?(Time)
287
- assert_equal expires_at.to_i, session.expires_at.to_i
288
- assert_equal 86393, session.expires_in
289
- assert_equal false, session.expired?
434
+ assert_equal({ "expires_at" => expires_at.to_i }, session.extra)
435
+ assert(session.expires_at.is_a?(Time))
436
+ assert_equal(expires_at.to_i, session.expires_at.to_i)
437
+ assert_equal(86393, session.expires_in)
438
+ assert_equal(false, session.expired?)
290
439
 
291
440
  Timecop.travel(session.expires_at) do
292
- assert_equal true, session.expired?
441
+ assert_equal(true, session.expired?)
293
442
  end
294
443
  end
295
444
  end
296
445
 
297
446
  test "raise error if signature does not match expected" do
298
- params = {:code => "any-code", :timestamp => Time.now}
447
+ params = { code: "any-code", timestamp: Time.now }
299
448
  signature = generate_signature(params)
300
449
  params[:foo] = 'world'
301
450
  assert_raises(ShopifyAPI::ValidationException) do
302
451
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
303
- session.request_token(params.merge(:hmac => signature))
452
+ session.request_token(params.merge(hmac: signature))
304
453
  end
305
454
  end
306
455
 
307
456
  test "raise error if timestamp is too old" do
308
- params = {:code => "any-code", :timestamp => Time.now - 2.days}
457
+ params = { code: "any-code", timestamp: Time.now - 2 * SECONDS_IN_A_DAY }
309
458
  signature = generate_signature(params)
310
459
  params[:foo] = 'world'
311
460
  assert_raises(ShopifyAPI::ValidationException) do
312
461
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
313
- session.request_token(params.merge(:hmac => signature))
462
+ session.request_token(params.merge(hmac: signature))
314
463
  end
315
464
  end
316
465
 
317
466
  test "return true when the signature is valid and the keys of params are strings" do
318
467
  params = { 'code' => 'any-code', 'timestamp' => Time.now }
319
468
  params[:hmac] = generate_signature(params)
320
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
469
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
321
470
  end
322
471
 
323
472
  test "return true when validating signature of params with ampersand and equal sign characters" do
@@ -325,7 +474,7 @@ class SessionTest < Test::Unit::TestCase
325
474
  params = { 'a' => '1&b=2', 'c=3&d' => '4' }
326
475
  to_sign = 'a=1%26b=2&c%3D3%26d=4'
327
476
  params[:hmac] = generate_signature(to_sign)
328
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
477
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
329
478
  end
330
479
 
331
480
  test "return true when validating signature of params with percent sign characters" do
@@ -333,7 +482,7 @@ class SessionTest < Test::Unit::TestCase
333
482
  params = { 'a%3D1%26b' => '2%26c%3D3' }
334
483
  to_sign = 'a%253D1%2526b=2%2526c%253D3'
335
484
  params[:hmac] = generate_signature(to_sign)
336
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
485
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
337
486
  end
338
487
 
339
488
  test "url is aliased to domain to minimize the upgrade changes" do
@@ -346,8 +495,133 @@ class SessionTest < Test::Unit::TestCase
346
495
  assert_equal('testshop.myshopify.com', session.url)
347
496
  end
348
497
 
498
+ test "#hash returns the same value for equal Sessions" do
499
+ session = ShopifyAPI::Session.new(
500
+ domain: "http://testshop.myshopify.com",
501
+ token: "any-token",
502
+ api_version: '2019-01',
503
+ extra: { foo: "bar" }
504
+ )
505
+ other_session = ShopifyAPI::Session.new(
506
+ domain: "http://testshop.myshopify.com",
507
+ token: "any-token",
508
+ api_version: '2019-01',
509
+ extra: { foo: "bar" }
510
+ )
511
+ assert_equal(session.hash, other_session.hash)
512
+ end
513
+
514
+ test "equality verifies domain" do
515
+ session = ShopifyAPI::Session.new(
516
+ domain: "http://testshop.myshopify.com",
517
+ token: "any-token",
518
+ api_version: '2019-01',
519
+ extra: { foo: "bar" }
520
+ )
521
+ other_session = ShopifyAPI::Session.new(
522
+ domain: "http://testshop.myshopify.com",
523
+ token: "any-token",
524
+ api_version: '2019-01',
525
+ extra: { foo: "bar" }
526
+ )
527
+ different_session = ShopifyAPI::Session.new(
528
+ domain: "http://another_testshop.myshopify.com",
529
+ token: "any-token",
530
+ api_version: '2019-01',
531
+ extra: { foo: "bar" }
532
+ )
533
+ assert_equal(session, other_session)
534
+ refute_equal(session, different_session)
535
+ end
536
+
537
+ test "equality verifies token" do
538
+ session = ShopifyAPI::Session.new(
539
+ domain: "http://testshop.myshopify.com",
540
+ token: "any-token",
541
+ api_version: '2019-01',
542
+ extra: { foo: "bar" }
543
+ )
544
+ different_session = ShopifyAPI::Session.new(
545
+ domain: "http://testshop.myshopify.com",
546
+ token: "very-different-token",
547
+ api_version: '2019-01',
548
+ extra: { foo: "bar" }
549
+ )
550
+ refute_equal(session, different_session)
551
+ end
552
+
553
+ test "equality verifies api_version" do
554
+ session = ShopifyAPI::Session.new(
555
+ domain: "http://testshop.myshopify.com",
556
+ token: "any-token",
557
+ api_version: '2019-01',
558
+ extra: { foo: "bar" }
559
+ )
560
+ different_session = ShopifyAPI::Session.new(
561
+ domain: "http://testshop.myshopify.com",
562
+ token: "any-token",
563
+ api_version: :unstable,
564
+ extra: { foo: "bar" }
565
+ )
566
+ refute_equal(session, different_session)
567
+ end
568
+
569
+ test "equality verifies extra" do
570
+ session = ShopifyAPI::Session.new(
571
+ domain: "http://testshop.myshopify.com",
572
+ token: "any-token",
573
+ api_version: '2019-01',
574
+ extra: { foo: "bar" }
575
+ )
576
+ different_session = ShopifyAPI::Session.new(
577
+ domain: "http://testshop.myshopify.com",
578
+ token: "any-token",
579
+ api_version: '2019-01',
580
+ extra: { bar: "other-bar" }
581
+ )
582
+ refute_equal(session, different_session)
583
+ end
584
+
585
+ test "equality verifies other is a Session" do
586
+ session = ShopifyAPI::Session.new(
587
+ domain: "http://testshop.myshopify.com",
588
+ token: "any-token",
589
+ api_version: '2019-01',
590
+ extra: { foo: "bar" }
591
+ )
592
+ different_session = nil
593
+ refute_equal(session, different_session)
594
+ end
595
+
596
+ test "#eql? and #hash are implemented" do
597
+ session = ShopifyAPI::Session.new(
598
+ domain: "http://testshop.myshopify.com",
599
+ token: "any-token",
600
+ api_version: '2019-01',
601
+ extra: { foo: "bar" }
602
+ )
603
+ other_session = ShopifyAPI::Session.new(
604
+ domain: "http://testshop.myshopify.com",
605
+ token: "any-token",
606
+ api_version: '2019-01',
607
+ extra: { foo: "bar" }
608
+ )
609
+ different_session = ShopifyAPI::Session.new(
610
+ domain: "http://another_testshop.myshopify.com",
611
+ token: "any-token",
612
+ api_version: '2019-01',
613
+ extra: { foo: "bar" }
614
+ )
615
+
616
+ assert_equal([session, different_session], [session, other_session, different_session].uniq)
617
+ end
618
+
349
619
  private
350
620
 
621
+ def assert_equal_uri(expected, actual)
622
+ assert_equal(Addressable::URI.parse(expected), Addressable::URI.parse(actual))
623
+ end
624
+
351
625
  def make_sorted_params(params)
352
626
  params.with_indifferent_access.except(
353
627
  :signature, :hmac, :action, :controller
@@ -356,7 +630,7 @@ class SessionTest < Test::Unit::TestCase
356
630
 
357
631
  def generate_signature(params)
358
632
  params = make_sorted_params(params) if params.is_a?(Hash)
359
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, ShopifyAPI::Session.secret, params)
633
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA256'), ShopifyAPI::Session.secret, params)
360
634
  end
361
635
 
362
636
  def any_api_version
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class ShippingZoneTest < Test::Unit::TestCase
4
5
  test "get all should get all shipping zones" do
5
- fake 'shipping_zones', :method => :get, :status => 200, :body => load_fixture('shipping_zones')
6
+ fake('shipping_zones', method: :get, status: 200, body: load_fixture('shipping_zones'))
6
7
  checkout = ShopifyAPI::ShippingZone.all
7
- assert_equal 1, checkout.first.id
8
- assert_equal "Canada", checkout.first.name
8
+ assert_equal(1, checkout.first.id)
9
+ assert_equal("Canada", checkout.first.name)
9
10
  end
10
11
  end