shopify_api 9.0.2 → 9.3.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 (199) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +36 -0
  3. data/.github/workflows/build.yml +41 -0
  4. data/.gitignore +2 -1
  5. data/.rubocop.yml +23 -3
  6. data/.rubocop_todo.yml +75 -0
  7. data/CHANGELOG.md +43 -0
  8. data/CONTRIBUTING.md +1 -1
  9. data/Gemfile +5 -0
  10. data/Gemfile.lock +151 -0
  11. data/Gemfile_ar51 +1 -1
  12. data/README.md +47 -31
  13. data/RELEASING +10 -6
  14. data/Rakefile +16 -5
  15. data/SECURITY.md +59 -0
  16. data/docs/_config.yml +1 -0
  17. data/docs/_includes/footer.html +28 -0
  18. data/docs/_includes/head.html +28 -0
  19. data/docs/_layouts/index.html +57 -0
  20. data/docs/graphql.md +47 -2
  21. data/docs/index.md +639 -0
  22. data/lib/active_resource/connection_ext.rb +1 -0
  23. data/lib/active_resource/detailed_log_subscriber.rb +6 -7
  24. data/lib/active_resource/json_errors.rb +8 -2
  25. data/lib/shopify_api.rb +8 -1
  26. data/lib/shopify_api/api_access.rb +57 -0
  27. data/lib/shopify_api/api_version.rb +6 -5
  28. data/lib/shopify_api/connection.rb +1 -0
  29. data/lib/shopify_api/countable.rb +3 -2
  30. data/lib/shopify_api/disable_prefix_check.rb +2 -2
  31. data/lib/shopify_api/events.rb +2 -1
  32. data/lib/shopify_api/graphql.rb +28 -8
  33. data/lib/shopify_api/limits.rb +3 -2
  34. data/lib/shopify_api/message_enricher.rb +11 -9
  35. data/lib/shopify_api/meta.rb +0 -1
  36. data/lib/shopify_api/metafields.rb +5 -4
  37. data/lib/shopify_api/pagination_link_headers.rb +5 -4
  38. data/lib/shopify_api/resources.rb +1 -0
  39. data/lib/shopify_api/resources/access_scope.rb +1 -1
  40. data/lib/shopify_api/resources/access_token.rb +1 -0
  41. data/lib/shopify_api/resources/address.rb +1 -0
  42. data/lib/shopify_api/resources/announcement.rb +2 -1
  43. data/lib/shopify_api/resources/application_charge.rb +1 -0
  44. data/lib/shopify_api/resources/application_credit.rb +1 -0
  45. data/lib/shopify_api/resources/article.rb +3 -2
  46. data/lib/shopify_api/resources/asset.rb +6 -5
  47. data/lib/shopify_api/resources/assigned_fulfillment_order.rb +1 -1
  48. data/lib/shopify_api/resources/base.rb +12 -8
  49. data/lib/shopify_api/resources/billing_address.rb +1 -0
  50. data/lib/shopify_api/resources/blog.rb +2 -1
  51. data/lib/shopify_api/resources/carrier_service.rb +1 -0
  52. data/lib/shopify_api/resources/cart.rb +2 -1
  53. data/lib/shopify_api/resources/collect.rb +1 -0
  54. data/lib/shopify_api/resources/collection_listing.rb +1 -0
  55. data/lib/shopify_api/resources/comment.rb +20 -5
  56. data/lib/shopify_api/resources/country.rb +1 -0
  57. data/lib/shopify_api/resources/custom_collection.rb +4 -3
  58. data/lib/shopify_api/resources/customer.rb +2 -1
  59. data/lib/shopify_api/resources/customer_group.rb +1 -0
  60. data/lib/shopify_api/resources/customer_invite.rb +1 -0
  61. data/lib/shopify_api/resources/customer_saved_search.rb +2 -1
  62. data/lib/shopify_api/resources/discount_code.rb +1 -0
  63. data/lib/shopify_api/resources/discount_code_batch.rb +34 -0
  64. data/lib/shopify_api/resources/draft_order.rb +1 -0
  65. data/lib/shopify_api/resources/draft_order_invoice.rb +1 -0
  66. data/lib/shopify_api/resources/event.rb +1 -0
  67. data/lib/shopify_api/resources/fulfillment.rb +12 -3
  68. data/lib/shopify_api/resources/fulfillment_event.rb +1 -0
  69. data/lib/shopify_api/resources/fulfillment_order.rb +30 -16
  70. data/lib/shopify_api/resources/fulfillment_order_locations_for_move.rb +1 -0
  71. data/lib/shopify_api/resources/fulfillment_request.rb +1 -0
  72. data/lib/shopify_api/resources/fulfillment_service.rb +1 -0
  73. data/lib/shopify_api/resources/fulfillment_v2.rb +3 -2
  74. data/lib/shopify_api/resources/gift_card.rb +1 -0
  75. data/lib/shopify_api/resources/image.rb +2 -1
  76. data/lib/shopify_api/resources/inventory_level.rb +3 -4
  77. data/lib/shopify_api/resources/line_item.rb +4 -3
  78. data/lib/shopify_api/resources/location.rb +1 -1
  79. data/lib/shopify_api/resources/marketing_event.rb +1 -0
  80. data/lib/shopify_api/resources/metafield.rb +1 -0
  81. data/lib/shopify_api/resources/note_attribute.rb +1 -0
  82. data/lib/shopify_api/resources/option.rb +1 -0
  83. data/lib/shopify_api/resources/order.rb +2 -1
  84. data/lib/shopify_api/resources/order_risk.rb +1 -0
  85. data/lib/shopify_api/resources/page.rb +1 -0
  86. data/lib/shopify_api/resources/payment_details.rb +1 -0
  87. data/lib/shopify_api/resources/policy.rb +1 -0
  88. data/lib/shopify_api/resources/price_rule.rb +1 -1
  89. data/lib/shopify_api/resources/product.rb +27 -3
  90. data/lib/shopify_api/resources/product_listing.rb +1 -0
  91. data/lib/shopify_api/resources/province.rb +1 -0
  92. data/lib/shopify_api/resources/receipt.rb +1 -0
  93. data/lib/shopify_api/resources/recurring_application_charge.rb +4 -1
  94. data/lib/shopify_api/resources/redirect.rb +1 -0
  95. data/lib/shopify_api/resources/refund.rb +2 -1
  96. data/lib/shopify_api/resources/report.rb +1 -0
  97. data/lib/shopify_api/resources/resource_feedback.rb +1 -1
  98. data/lib/shopify_api/resources/rule.rb +1 -0
  99. data/lib/shopify_api/resources/script_tag.rb +1 -0
  100. data/lib/shopify_api/resources/shipping_address.rb +1 -0
  101. data/lib/shopify_api/resources/shipping_line.rb +1 -0
  102. data/lib/shopify_api/resources/shipping_zone.rb +1 -0
  103. data/lib/shopify_api/resources/shop.rb +2 -1
  104. data/lib/shopify_api/resources/smart_collection.rb +4 -8
  105. data/lib/shopify_api/resources/storefront_access_token.rb +1 -0
  106. data/lib/shopify_api/resources/tax_line.rb +1 -0
  107. data/lib/shopify_api/resources/tax_service.rb +1 -0
  108. data/lib/shopify_api/resources/theme.rb +1 -0
  109. data/lib/shopify_api/resources/transaction.rb +1 -0
  110. data/lib/shopify_api/resources/usage_charge.rb +1 -0
  111. data/lib/shopify_api/resources/user.rb +1 -0
  112. data/lib/shopify_api/resources/variant.rb +35 -0
  113. data/lib/shopify_api/resources/webhook.rb +1 -0
  114. data/lib/shopify_api/session.rb +43 -14
  115. data/lib/shopify_api/version.rb +2 -1
  116. data/lib/verify_docs.rb +8 -0
  117. data/service.yml +1 -1
  118. data/shopify_api.gemspec +13 -6
  119. data/test/access_token_test.rb +6 -5
  120. data/test/active_resource/json_errors_test.rb +6 -6
  121. data/test/api_access_test.rb +153 -0
  122. data/test/api_version_test.rb +3 -3
  123. data/test/application_charge_test.rb +30 -27
  124. data/test/application_credit_test.rb +10 -9
  125. data/test/article_test.rb +34 -35
  126. data/test/asset_test.rb +14 -6
  127. data/test/assigned_fulfillment_order_test.rb +5 -4
  128. data/test/base_test.rb +64 -49
  129. data/test/blog_test.rb +4 -3
  130. data/test/carrier_service_test.rb +7 -6
  131. data/test/cart_test.rb +2 -1
  132. data/test/collect_test.rb +4 -3
  133. data/test/collection_listing_test.rb +21 -16
  134. data/test/collection_publication_test.rb +8 -8
  135. data/test/collection_test.rb +20 -19
  136. data/test/countable_test.rb +3 -2
  137. data/test/currency_test.rb +5 -5
  138. data/test/custom_collection_test.rb +4 -3
  139. data/test/customer_saved_search_test.rb +18 -8
  140. data/test/customer_test.rb +22 -14
  141. data/test/detailed_log_subscriber_test.rb +15 -11
  142. data/test/discount_code_batch_test.rb +41 -0
  143. data/test/discount_code_test.rb +21 -15
  144. data/test/draft_order_test.rb +68 -52
  145. data/test/fixtures/assigned_fulfillment_orders.json +2 -0
  146. data/test/fixtures/discount_code_batch.json +14 -0
  147. data/test/fixtures/discount_code_batch_discount_codes.json +21 -0
  148. data/test/fixtures/fulfillment_order.json +1 -0
  149. data/test/fixtures/fulfillment_orders.json +2 -0
  150. data/test/fulfillment_event_test.rb +31 -26
  151. data/test/fulfillment_order_test.rb +215 -147
  152. data/test/fulfillment_order_test_helper.rb +1 -0
  153. data/test/fulfillment_request_test.rb +10 -8
  154. data/test/fulfillment_service_test.rb +13 -12
  155. data/test/fulfillment_test.rb +81 -66
  156. data/test/fulfillment_v2_test.rb +16 -12
  157. data/test/gift_card_test.rb +6 -4
  158. data/test/graphql_test.rb +55 -23
  159. data/test/image_test.rb +19 -17
  160. data/test/inventory_level_test.rb +24 -15
  161. data/test/lib/webmock_extensions/last_request.rb +1 -1
  162. data/test/limits_test.rb +2 -1
  163. data/test/location_test.rb +2 -1
  164. data/test/marketing_event_test.rb +20 -20
  165. data/test/message_enricher_test.rb +6 -6
  166. data/test/meta_test.rb +7 -9
  167. data/test/metafield_test.rb +30 -20
  168. data/test/order_risk_test.rb +17 -16
  169. data/test/order_test.rb +43 -28
  170. data/test/pagination_test.rb +89 -56
  171. data/test/policy_test.rb +6 -5
  172. data/test/price_rule_test.rb +20 -15
  173. data/test/product_listing_test.rb +20 -20
  174. data/test/product_publication_test.rb +8 -8
  175. data/test/product_test.rb +71 -20
  176. data/test/publication_test.rb +3 -3
  177. data/test/recurring_application_charge_test.rb +104 -42
  178. data/test/redirect_test.rb +4 -3
  179. data/test/refund_test.rb +22 -17
  180. data/test/report_test.rb +12 -10
  181. data/test/resource_feedback_test.rb +14 -13
  182. data/test/script_tag_test.rb +10 -9
  183. data/test/session_test.rb +234 -43
  184. data/test/shipping_zone_test.rb +4 -3
  185. data/test/shop_test.rb +47 -33
  186. data/test/smart_collection_test.rb +5 -29
  187. data/test/storefront_access_token_test.rb +13 -15
  188. data/test/tax_service_test.rb +7 -4
  189. data/test/tender_transaction_test.rb +3 -3
  190. data/test/test_helper.rb +14 -12
  191. data/test/transaction_test.rb +4 -3
  192. data/test/usage_charge_test.rb +12 -8
  193. data/test/user_test.rb +4 -3
  194. data/test/variant_test.rb +50 -23
  195. data/test/webhook_test.rb +10 -7
  196. metadata +30 -15
  197. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
  198. data/.travis.yml +0 -23
  199. data/bin/shopify +0 -3
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class RedirectTest < Test::Unit::TestCase
4
5
  test "#create should create a redirect" do
5
- fake "redirects", :method => :post, :status => 201, :body => load_fixture('redirect')
6
- redirect = ShopifyAPI::Redirect.create(:path => "/ipod", :target => "/pages/itunes")
7
- assert_equal 979034150, redirect.id
6
+ fake("redirects", method: :post, status: 201, body: load_fixture('redirect'))
7
+ redirect = ShopifyAPI::Redirect.create(path: "/ipod", target: "/pages/itunes")
8
+ assert_equal(979034150, redirect.id)
8
9
  end
9
10
  end
@@ -1,32 +1,37 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class RefundTest < Test::Unit::TestCase
4
-
5
5
  test '#create should create a refund' do
6
- fake "orders/450789469/refunds", :method => :post, :status => 201, :body => load_fixture('refund')
6
+ fake("orders/450789469/refunds", method: :post, status: 201, body: load_fixture('refund'))
7
7
  refund = ShopifyAPI::Refund.create(
8
- :order_id => 450789469,
9
- :restock => true,
10
- :note => "wrong size",
11
- :shipping => { :full_refund => true },
12
- :refund_line_items => [{ :line_item_id => 518995019, :quantity => 1 }]
8
+ order_id: 450789469,
9
+ restock: true,
10
+ note: "wrong size",
11
+ shipping: { full_refund: true },
12
+ refund_line_items: [{ line_item_id: 518995019, quantity: 1 }]
13
13
  )
14
- assert_equal 703073504, refund.refund_line_items.first.line_item_id
14
+ assert_equal(703073504, refund.refund_line_items.first.line_item_id)
15
15
  end
16
16
 
17
17
  test '#find should return a refund' do
18
- fake "orders/450789469/refunds/509562969.json?order_id=450789469", :extension => false, :method => :get, :body => load_fixture('refund')
19
- fake "orders/450789469/refunds/509562969", :method => :get, :body => load_fixture('refund')
20
- refund = ShopifyAPI::Refund.find(509562969, :params => {:order_id => 450789469})
21
- assert_equal 509562969, refund.id
18
+ fake(
19
+ "orders/450789469/refunds/509562969.json?order_id=450789469",
20
+ extension: false,
21
+ method: :get,
22
+ body: load_fixture('refund')
23
+ )
24
+ fake("orders/450789469/refunds/509562969", method: :get, body: load_fixture('refund'))
25
+ refund = ShopifyAPI::Refund.find(509562969, params: { order_id: 450789469 })
26
+ assert_equal(509562969, refund.id)
22
27
  end
23
28
 
24
29
  test '#calculate a refund' do
25
- fake "orders/450789469/refunds/calculate", :method => :post, :body => load_fixture('refund')
26
- data = { :shipping => { :amount => 0 } }
30
+ fake("orders/450789469/refunds/calculate", method: :post, body: load_fixture('refund'))
31
+ data = { shipping: { amount: 0 } }
27
32
 
28
- refund = ShopifyAPI::Refund.calculate(data, :params => {:order_id => 450789469})
29
- assert_equal 2, refund.refund_line_items.count
30
- assert_equal 703073504, refund.refund_line_items.first.line_item_id
33
+ refund = ShopifyAPI::Refund.calculate(data, params: { order_id: 450789469 })
34
+ assert_equal(2, refund.refund_line_items.count)
35
+ assert_equal(703073504, refund.refund_line_items.first.line_item_id)
31
36
  end
32
37
  end
@@ -1,35 +1,37 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class ReportTest < Test::Unit::TestCase
4
5
  test 'get should get a report' do
5
- fake 'reports/987', method: :get, status: 200, body: load_fixture('report')
6
+ fake('reports/987', method: :get, status: 200, body: load_fixture('report'))
6
7
 
7
8
  report = ShopifyAPI::Report.find(987)
8
- assert_equal 987, report.id
9
+ assert_equal(987, report.id)
9
10
  end
10
11
 
11
12
  test 'get all should get all reports' do
12
- fake 'reports', method: :get, status: 200, body: load_fixture('reports')
13
+ fake('reports', method: :get, status: 200, body: load_fixture('reports'))
13
14
 
14
15
  reports = ShopifyAPI::Report.all
15
- assert_equal 'custom_app_reports', reports.first.category
16
+ assert_equal('custom_app_reports', reports.first.category)
16
17
  end
17
18
 
18
19
  test 'create should create a report' do
19
- fake 'reports', method: :post, status: 201, body: load_fixture('report')
20
+ fake('reports', method: :post, status: 201, body: load_fixture('report'))
20
21
 
21
22
  report = ShopifyAPI::Report.create(
22
23
  name: 'Custom App Report',
23
- shopify_ql: 'SHOW quantity_count, total_sales BY product_type, vendor, product_title FROM products SINCE -1m UNTIL -0m ORDER BY total_sales DESC'
24
+ shopify_ql: 'SHOW quantity_count, total_sales BY product_type, vendor, product_title ' \
25
+ 'FROM products SINCE -1m UNTIL -0m ORDER BY total_sales DESC'
24
26
  )
25
- assert_equal 'custom_app_reports', report.category
27
+ assert_equal('custom_app_reports', report.category)
26
28
  end
27
29
 
28
30
  test 'delete should delete report' do
29
- fake 'reports/987', method: :get, status: 200, body: load_fixture('report')
30
- fake 'reports/987', method: :delete, status: 200, body: '[]'
31
+ fake('reports/987', method: :get, status: 200, body: load_fixture('report'))
32
+ fake('reports/987', method: :delete, status: 200, body: '[]')
31
33
 
32
34
  report = ShopifyAPI::Report.find(987)
33
- assert report.destroy
35
+ assert(report.destroy)
34
36
  end
35
37
  end
@@ -1,41 +1,42 @@
1
+ # frozen_string_literal: true
1
2
  class ResourceFeedbackTest < Test::Unit::TestCase
2
3
  def test_get_resource_feedback
3
- body = { resource_feedback: [ { resource_type: 'Shop' } ] }.to_json
4
- fake 'resource_feedback', method: :get, body: body
4
+ body = { resource_feedback: [{ resource_type: 'Shop' }] }.to_json
5
+ fake('resource_feedback', method: :get, body: body)
5
6
  resource_feedback = ShopifyAPI::ResourceFeedback.find(:all)
6
- assert_equal 'Shop', resource_feedback.first.resource_type
7
+ assert_equal('Shop', resource_feedback.first.resource_type)
7
8
  end
8
9
 
9
10
  def test_save_with_resource_feedback_endpoint
10
11
  body = { resource_feedback: {} }.to_json
11
- fake 'resource_feedback', method: :post, body: body
12
+ fake('resource_feedback', method: :post, body: body)
12
13
  ShopifyAPI::ResourceFeedback.new.save
13
- assert_request_body body
14
+ assert_request_body(body)
14
15
  end
15
16
 
16
17
  def test_get_resource_feedback_with_product_id
17
- body = { resource_feedback: [ { resource_type: 'Product' } ] }.to_json
18
- fake 'products/42/resource_feedback', method: :get, body: body
18
+ body = { resource_feedback: [{ resource_type: 'Product' }] }.to_json
19
+ fake('products/42/resource_feedback', method: :get, body: body)
19
20
  resource_feedback = ShopifyAPI::ResourceFeedback.find(:all, params: { product_id: 42 })
20
- assert_equal 'Product', resource_feedback.first.resource_type
21
+ assert_equal('Product', resource_feedback.first.resource_type)
21
22
  end
22
23
 
23
24
  def test_save_with_product_id_resource_feedback_endpoint
24
25
  body = { resource_feedback: {} }.to_json
25
- fake 'products/42/resource_feedback', method: :post, body: body
26
+ fake('products/42/resource_feedback', method: :post, body: body)
26
27
  ShopifyAPI::ResourceFeedback.new(product_id: 42).save
27
- assert_request_body body
28
+ assert_request_body(body)
28
29
  end
29
30
 
30
31
  def test_save_raises_exception_when_already_persisted
31
32
  body = { resource_feedback: {} }.to_json
32
- fake 'resource_feedback', method: :post, body: body
33
+ fake('resource_feedback', method: :post, body: body)
33
34
  resource_feedback = ShopifyAPI::ResourceFeedback.new
34
35
  resource_feedback.save
35
- assert_request_body body
36
+ assert_request_body(body)
36
37
 
37
38
  ShopifyAPI::ResourceFeedback.any_instance.expects(:persisted?).returns(true)
38
- assert_raises ShopifyAPI::ResourceFeedback::ExistingFeedbackSaved do
39
+ assert_raises(ShopifyAPI::ResourceFeedback::ExistingFeedbackSaved) do
39
40
  resource_feedback.save
40
41
  end
41
42
  end
@@ -1,30 +1,31 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class ScriptTagTest < Test::Unit::TestCase
4
5
  test "get all should get all script tags" do
5
- fake 'script_tags', :method => :get, :status => 200, :body => load_fixture('script_tags')
6
+ fake('script_tags', method: :get, status: 200, body: load_fixture('script_tags'))
6
7
  script_tags = ShopifyAPI::ScriptTag.all
7
- assert_equal "http://js-aplenty.com/bar.js", script_tags.first.src
8
+ assert_equal("http://js-aplenty.com/bar.js", script_tags.first.src)
8
9
  end
9
10
 
10
11
  test "get should get a script tag" do
11
- fake 'script_tags/421379493', :method => :get, :status => 200, :body => load_fixture('script_tag')
12
+ fake('script_tags/421379493', method: :get, status: 200, body: load_fixture('script_tag'))
12
13
  script_tag = ShopifyAPI::ScriptTag.find(421379493)
13
- assert_equal "http://js-aplenty.com/bar.js", script_tag.src
14
+ assert_equal("http://js-aplenty.com/bar.js", script_tag.src)
14
15
  end
15
16
 
16
17
  test "create should create a new script tag" do
17
- fake 'script_tags', :method => :post, :status => 201, :body => load_fixture('script_tag')
18
+ fake('script_tags', method: :post, status: 201, body: load_fixture('script_tag'))
18
19
  script_tag = ShopifyAPI::ScriptTag.create(event: "onload", src: "http://js-aplenty.com/bar.js")
19
- assert_equal "http://js-aplenty.com/bar.js", script_tag.src
20
+ assert_equal("http://js-aplenty.com/bar.js", script_tag.src)
20
21
  end
21
22
 
22
23
  test "editing script tag should update script tag" do
23
- fake 'script_tags/421379493', :method => :get, :status => 200, :body => load_fixture('script_tag')
24
+ fake('script_tags/421379493', method: :get, status: 200, body: load_fixture('script_tag'))
24
25
  script_tag = ShopifyAPI::ScriptTag.find(421379493)
25
26
  script_tag.src = "http://js-aplenty.com/bar.js"
26
- fake 'script_tags/421379493', :method => :put, :status => 200, :body => load_fixture('script_tag')
27
+ fake('script_tags/421379493', method: :put, status: 200, body: load_fixture('script_tag'))
27
28
  script_tag.save
28
- assert_equal "http://js-aplenty.com/bar.js", script_tag.src
29
+ assert_equal("http://js-aplenty.com/bar.js", script_tag.src)
29
30
  end
30
31
  end
@@ -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,7 @@ 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?)
36
55
  end
37
56
 
38
57
  test "not raise error without params" do
@@ -68,23 +87,27 @@ class SessionTest < Test::Unit::TestCase
68
87
  test "raise error if params passed but signature omitted" do
69
88
  assert_raises(ShopifyAPI::ValidationException) do
70
89
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
71
- session.request_token({'code' => 'any-code'})
90
+ session.request_token({ 'code' => 'any-code' })
72
91
  end
73
92
  end
74
93
 
75
94
  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
95
+ ShopifyAPI::Session.setup(api_key: "My test key", secret: "My test secret")
96
+ assert_equal("My test key", ShopifyAPI::Session.api_key)
97
+ assert_equal("My test secret", ShopifyAPI::Session.secret)
79
98
  end
80
99
 
81
- test "#temp reset ShopifyAPI::Base.site to original value" do
100
+ test "#temp reset ShopifyAPI::Base values to original value" do
82
101
  session1 = ShopifyAPI::Session.new(domain: 'fakeshop.myshopify.com', token: 'token1', api_version: '2019-01')
102
+ ShopifyAPI::Base.user = 'foo'
103
+ ShopifyAPI::Base.password = 'bar'
83
104
  ShopifyAPI::Base.activate_session(session1)
84
105
 
85
106
  ShopifyAPI::Session.temp(domain: "testshop.myshopify.com", token: "any-token", api_version: :unstable) do
86
107
  @assigned_site = ShopifyAPI::Base.site
87
108
  @assigned_version = ShopifyAPI::Base.api_version
109
+ @assigned_user = ShopifyAPI::Base.user
110
+ @assigned_password = ShopifyAPI::Base.password
88
111
  end
89
112
 
90
113
  assert_equal('https://testshop.myshopify.com', @assigned_site.to_s)
@@ -92,6 +115,31 @@ class SessionTest < Test::Unit::TestCase
92
115
 
93
116
  assert_equal(ShopifyAPI::ApiVersion.new(handle: :unstable), @assigned_version)
94
117
  assert_equal(ShopifyAPI::ApiVersion.new(handle: '2019-01'), ShopifyAPI::Base.api_version)
118
+
119
+ assert_nil(@assigned_user)
120
+ assert_equal('foo', ShopifyAPI::Base.user)
121
+
122
+ assert_nil(@assigned_password)
123
+ assert_equal('bar', ShopifyAPI::Base.password)
124
+ end
125
+
126
+ test "#temp does not use basic auth values from Base.site" do
127
+ ShopifyAPI::Base.site = 'https://user:pass@fakeshop.myshopify.com'
128
+
129
+ ShopifyAPI::Session.temp(domain: "testshop.myshopify.com", token: "any-token", api_version: :unstable) do
130
+ @assigned_site = ShopifyAPI::Base.site
131
+ @assigned_user = ShopifyAPI::Base.user
132
+ @assigned_password = ShopifyAPI::Base.password
133
+ end
134
+
135
+ assert_equal('https://testshop.myshopify.com', @assigned_site.to_s)
136
+ assert_equal('https://fakeshop.myshopify.com', ShopifyAPI::Base.site.to_s)
137
+
138
+ assert_nil(@assigned_user)
139
+ assert_equal('user', ShopifyAPI::Base.user)
140
+
141
+ assert_nil(@assigned_password)
142
+ assert_equal('pass', ShopifyAPI::Base.password)
95
143
  end
96
144
 
97
145
  test "#with_session activates the session for the duration of the block" do
@@ -126,7 +174,7 @@ class SessionTest < Test::Unit::TestCase
126
174
  api_version: :unstable
127
175
  )
128
176
 
129
- assert_raises StandardError do
177
+ assert_raises(StandardError) do
130
178
  ShopifyAPI::Session.with_session(other_session) { raise StandardError, "" }
131
179
  end
132
180
 
@@ -172,7 +220,11 @@ class SessionTest < Test::Unit::TestCase
172
220
  )
173
221
  scope = ["write_products"]
174
222
  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
223
+ assert_equal(
224
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
225
+ "scope=write_products&redirect_uri=http://my_redirect_uri.com",
226
+ permission_url
227
+ )
176
228
  end
177
229
 
178
230
  test "create_permission_url returns correct url with dual scope" do
@@ -182,9 +234,13 @@ class SessionTest < Test::Unit::TestCase
182
234
  token: 'any-token',
183
235
  api_version: any_api_version
184
236
  )
185
- scope = ["write_products","write_customers"]
237
+ scope = ["write_products", "write_customers"]
186
238
  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
239
+ assert_equal(
240
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
241
+ "scope=write_products,write_customers&redirect_uri=http://my_redirect_uri.com",
242
+ permission_url
243
+ )
188
244
  end
189
245
 
190
246
  test "create_permission_url returns correct url with no scope" do
@@ -196,7 +252,11 @@ class SessionTest < Test::Unit::TestCase
196
252
  )
197
253
  scope = []
198
254
  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
255
+ assert_equal(
256
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
257
+ "scope=&redirect_uri=http://my_redirect_uri.com",
258
+ permission_url
259
+ )
200
260
  end
201
261
 
202
262
  test "create_permission_url returns correct url with state" do
@@ -208,11 +268,15 @@ class SessionTest < Test::Unit::TestCase
208
268
  )
209
269
  scope = []
210
270
  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
271
+ assert_equal(
272
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
273
+ "scope=&redirect_uri=http://my_redirect_uri.com&state=My%20nonce",
274
+ permission_url
275
+ )
212
276
  end
213
277
 
214
278
  test "raise exception if code invalid in request token" do
215
- ShopifyAPI::Session.setup(:api_key => "My test key", :secret => "My test secret")
279
+ ShopifyAPI::Session.setup(api_key: "My test key", secret: "My test secret")
216
280
  session = ShopifyAPI::Session.new(
217
281
  domain: 'http://localhost.myshopify.com',
218
282
  token: nil,
@@ -228,7 +292,7 @@ class SessionTest < Test::Unit::TestCase
228
292
  assert_raises(ShopifyAPI::ValidationException) do
229
293
  session.request_token(code: "bad-code")
230
294
  end
231
- assert_equal false, session.valid?
295
+ assert_equal(false, session.valid?)
232
296
  end
233
297
 
234
298
  test "return site for session" do
@@ -237,87 +301,93 @@ class SessionTest < Test::Unit::TestCase
237
301
  token: "any-token",
238
302
  api_version: any_api_version
239
303
  )
240
- assert_equal "https://testshop.myshopify.com", session.site
304
+ assert_equal("https://testshop.myshopify.com", session.site)
241
305
  end
242
306
 
243
307
  test "return_token_if_signature_is_valid" do
244
308
  api_version = any_api_version
245
- fake nil,
309
+ fake(
310
+ nil,
246
311
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
247
312
  method: :post,
248
313
  body: '{"access_token":"any-token"}'
314
+ )
249
315
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
250
316
 
251
317
  params = { code: 'any-code', timestamp: Time.now }
252
318
  token = session.request_token(params.merge(hmac: generate_signature(params)))
253
319
 
254
- assert_equal "any-token", token
255
- assert_equal "any-token", session.token
320
+ assert_equal("any-token", token)
321
+ assert_equal("any-token", session.token)
256
322
  end
257
323
 
258
324
  test "extra parameters are stored in session" do
259
325
  api_version = ShopifyAPI::ApiVersion.new(handle: :unstable)
260
- fake nil,
326
+ fake(
327
+ nil,
261
328
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
262
329
  method: :post,
263
330
  body: '{"access_token":"any-token","foo":"example"}'
331
+ )
264
332
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
265
333
 
266
334
  params = { code: 'any-code', timestamp: Time.now }
267
- assert session.request_token(params.merge(hmac: generate_signature(params)))
335
+ assert(session.request_token(params.merge(hmac: generate_signature(params))))
268
336
 
269
- assert_equal ({ "foo" => "example" }), session.extra
337
+ assert_equal({ "foo" => "example" }, session.extra)
270
338
  end
271
339
 
272
340
  test "expires_in is automatically converted in expires_at" do
273
341
  api_version = any_api_version
274
- fake nil,
342
+ fake(
343
+ nil,
275
344
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
276
345
  method: :post,
277
346
  body: '{"access_token":"any-token","expires_in":86393}'
347
+ )
278
348
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
279
349
 
280
350
  Timecop.freeze do
281
351
  params = { code: 'any-code', timestamp: Time.now }
282
- assert session.request_token(params.merge(hmac: generate_signature(params)))
352
+ assert(session.request_token(params.merge(hmac: generate_signature(params))))
283
353
 
284
354
  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?
355
+ assert_equal({ "expires_at" => expires_at.to_i }, session.extra)
356
+ assert(session.expires_at.is_a?(Time))
357
+ assert_equal(expires_at.to_i, session.expires_at.to_i)
358
+ assert_equal(86393, session.expires_in)
359
+ assert_equal(false, session.expired?)
290
360
 
291
361
  Timecop.travel(session.expires_at) do
292
- assert_equal true, session.expired?
362
+ assert_equal(true, session.expired?)
293
363
  end
294
364
  end
295
365
  end
296
366
 
297
367
  test "raise error if signature does not match expected" do
298
- params = {:code => "any-code", :timestamp => Time.now}
368
+ params = { code: "any-code", timestamp: Time.now }
299
369
  signature = generate_signature(params)
300
370
  params[:foo] = 'world'
301
371
  assert_raises(ShopifyAPI::ValidationException) do
302
372
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
303
- session.request_token(params.merge(:hmac => signature))
373
+ session.request_token(params.merge(hmac: signature))
304
374
  end
305
375
  end
306
376
 
307
377
  test "raise error if timestamp is too old" do
308
- params = {:code => "any-code", :timestamp => Time.now - 2.days}
378
+ params = { code: "any-code", timestamp: Time.now - 2 * SECONDS_IN_A_DAY }
309
379
  signature = generate_signature(params)
310
380
  params[:foo] = 'world'
311
381
  assert_raises(ShopifyAPI::ValidationException) do
312
382
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
313
- session.request_token(params.merge(:hmac => signature))
383
+ session.request_token(params.merge(hmac: signature))
314
384
  end
315
385
  end
316
386
 
317
387
  test "return true when the signature is valid and the keys of params are strings" do
318
388
  params = { 'code' => 'any-code', 'timestamp' => Time.now }
319
389
  params[:hmac] = generate_signature(params)
320
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
390
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
321
391
  end
322
392
 
323
393
  test "return true when validating signature of params with ampersand and equal sign characters" do
@@ -325,7 +395,7 @@ class SessionTest < Test::Unit::TestCase
325
395
  params = { 'a' => '1&b=2', 'c=3&d' => '4' }
326
396
  to_sign = 'a=1%26b=2&c%3D3%26d=4'
327
397
  params[:hmac] = generate_signature(to_sign)
328
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
398
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
329
399
  end
330
400
 
331
401
  test "return true when validating signature of params with percent sign characters" do
@@ -333,7 +403,7 @@ class SessionTest < Test::Unit::TestCase
333
403
  params = { 'a%3D1%26b' => '2%26c%3D3' }
334
404
  to_sign = 'a%253D1%2526b=2%2526c%253D3'
335
405
  params[:hmac] = generate_signature(to_sign)
336
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
406
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
337
407
  end
338
408
 
339
409
  test "url is aliased to domain to minimize the upgrade changes" do
@@ -346,6 +416,127 @@ class SessionTest < Test::Unit::TestCase
346
416
  assert_equal('testshop.myshopify.com', session.url)
347
417
  end
348
418
 
419
+ test "#hash returns the same value for equal Sessions" do
420
+ session = ShopifyAPI::Session.new(
421
+ domain: "http://testshop.myshopify.com",
422
+ token: "any-token",
423
+ api_version: '2019-01',
424
+ extra: { foo: "bar" }
425
+ )
426
+ other_session = ShopifyAPI::Session.new(
427
+ domain: "http://testshop.myshopify.com",
428
+ token: "any-token",
429
+ api_version: '2019-01',
430
+ extra: { foo: "bar" }
431
+ )
432
+ assert_equal(session.hash, other_session.hash)
433
+ end
434
+
435
+ test "equality verifies domain" do
436
+ session = ShopifyAPI::Session.new(
437
+ domain: "http://testshop.myshopify.com",
438
+ token: "any-token",
439
+ api_version: '2019-01',
440
+ extra: { foo: "bar" }
441
+ )
442
+ other_session = ShopifyAPI::Session.new(
443
+ domain: "http://testshop.myshopify.com",
444
+ token: "any-token",
445
+ api_version: '2019-01',
446
+ extra: { foo: "bar" }
447
+ )
448
+ different_session = ShopifyAPI::Session.new(
449
+ domain: "http://another_testshop.myshopify.com",
450
+ token: "any-token",
451
+ api_version: '2019-01',
452
+ extra: { foo: "bar" }
453
+ )
454
+ assert_equal(session, other_session)
455
+ refute_equal(session, different_session)
456
+ end
457
+
458
+ test "equality verifies token" do
459
+ session = ShopifyAPI::Session.new(
460
+ domain: "http://testshop.myshopify.com",
461
+ token: "any-token",
462
+ api_version: '2019-01',
463
+ extra: { foo: "bar" }
464
+ )
465
+ different_session = ShopifyAPI::Session.new(
466
+ domain: "http://testshop.myshopify.com",
467
+ token: "very-different-token",
468
+ api_version: '2019-01',
469
+ extra: { foo: "bar" }
470
+ )
471
+ refute_equal(session, different_session)
472
+ end
473
+
474
+ test "equality verifies api_version" do
475
+ session = ShopifyAPI::Session.new(
476
+ domain: "http://testshop.myshopify.com",
477
+ token: "any-token",
478
+ api_version: '2019-01',
479
+ extra: { foo: "bar" }
480
+ )
481
+ different_session = ShopifyAPI::Session.new(
482
+ domain: "http://testshop.myshopify.com",
483
+ token: "any-token",
484
+ api_version: :unstable,
485
+ extra: { foo: "bar" }
486
+ )
487
+ refute_equal(session, different_session)
488
+ end
489
+
490
+ test "equality verifies extra" do
491
+ session = ShopifyAPI::Session.new(
492
+ domain: "http://testshop.myshopify.com",
493
+ token: "any-token",
494
+ api_version: '2019-01',
495
+ extra: { foo: "bar" }
496
+ )
497
+ different_session = ShopifyAPI::Session.new(
498
+ domain: "http://testshop.myshopify.com",
499
+ token: "any-token",
500
+ api_version: '2019-01',
501
+ extra: { bar: "other-bar" }
502
+ )
503
+ refute_equal(session, different_session)
504
+ end
505
+
506
+ test "equality verifies other is a Session" do
507
+ session = ShopifyAPI::Session.new(
508
+ domain: "http://testshop.myshopify.com",
509
+ token: "any-token",
510
+ api_version: '2019-01',
511
+ extra: { foo: "bar" }
512
+ )
513
+ different_session = nil
514
+ refute_equal(session, different_session)
515
+ end
516
+
517
+ test "#eql? and #hash are implemented" do
518
+ session = ShopifyAPI::Session.new(
519
+ domain: "http://testshop.myshopify.com",
520
+ token: "any-token",
521
+ api_version: '2019-01',
522
+ extra: { foo: "bar" }
523
+ )
524
+ other_session = ShopifyAPI::Session.new(
525
+ domain: "http://testshop.myshopify.com",
526
+ token: "any-token",
527
+ api_version: '2019-01',
528
+ extra: { foo: "bar" }
529
+ )
530
+ different_session = ShopifyAPI::Session.new(
531
+ domain: "http://another_testshop.myshopify.com",
532
+ token: "any-token",
533
+ api_version: '2019-01',
534
+ extra: { foo: "bar" }
535
+ )
536
+
537
+ assert_equal([session, different_session], [session, other_session, different_session].uniq)
538
+ end
539
+
349
540
  private
350
541
 
351
542
  def make_sorted_params(params)
@@ -356,7 +547,7 @@ class SessionTest < Test::Unit::TestCase
356
547
 
357
548
  def generate_signature(params)
358
549
  params = make_sorted_params(params) if params.is_a?(Hash)
359
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, ShopifyAPI::Session.secret, params)
550
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA256'), ShopifyAPI::Session.secret, params)
360
551
  end
361
552
 
362
553
  def any_api_version