shopify_api 9.0.3 → 9.4.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 (197) 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 +36 -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 +41 -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 +4 -2
  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 +12 -9
  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 +15 -11
  113. data/lib/shopify_api/resources/webhook.rb +1 -0
  114. data/lib/shopify_api/session.rb +50 -15
  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 +11 -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 +11 -10
  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/fulfillment_order.json +1 -0
  147. data/test/fixtures/fulfillment_orders.json +2 -0
  148. data/test/fulfillment_event_test.rb +31 -26
  149. data/test/fulfillment_order_test.rb +215 -147
  150. data/test/fulfillment_order_test_helper.rb +1 -0
  151. data/test/fulfillment_request_test.rb +10 -8
  152. data/test/fulfillment_service_test.rb +13 -12
  153. data/test/fulfillment_test.rb +81 -66
  154. data/test/fulfillment_v2_test.rb +16 -12
  155. data/test/gift_card_test.rb +6 -4
  156. data/test/graphql_test.rb +55 -23
  157. data/test/image_test.rb +19 -17
  158. data/test/inventory_level_test.rb +24 -15
  159. data/test/lib/webmock_extensions/last_request.rb +1 -1
  160. data/test/limits_test.rb +2 -1
  161. data/test/location_test.rb +2 -1
  162. data/test/marketing_event_test.rb +20 -20
  163. data/test/message_enricher_test.rb +6 -6
  164. data/test/meta_test.rb +7 -9
  165. data/test/metafield_test.rb +30 -20
  166. data/test/order_risk_test.rb +17 -16
  167. data/test/order_test.rb +43 -28
  168. data/test/pagination_test.rb +89 -56
  169. data/test/policy_test.rb +6 -5
  170. data/test/price_rule_test.rb +20 -15
  171. data/test/product_listing_test.rb +20 -20
  172. data/test/product_publication_test.rb +8 -8
  173. data/test/product_test.rb +44 -32
  174. data/test/publication_test.rb +3 -3
  175. data/test/recurring_application_charge_test.rb +104 -42
  176. data/test/redirect_test.rb +4 -3
  177. data/test/refund_test.rb +22 -17
  178. data/test/report_test.rb +12 -10
  179. data/test/resource_feedback_test.rb +14 -13
  180. data/test/script_tag_test.rb +10 -9
  181. data/test/session_test.rb +297 -43
  182. data/test/shipping_zone_test.rb +4 -3
  183. data/test/shop_test.rb +47 -33
  184. data/test/smart_collection_test.rb +5 -29
  185. data/test/storefront_access_token_test.rb +13 -15
  186. data/test/tax_service_test.rb +7 -4
  187. data/test/tender_transaction_test.rb +3 -3
  188. data/test/test_helper.rb +15 -13
  189. data/test/transaction_test.rb +4 -3
  190. data/test/usage_charge_test.rb +12 -8
  191. data/test/user_test.rb +4 -3
  192. data/test/variant_test.rb +29 -91
  193. data/test/webhook_test.rb +10 -7
  194. metadata +24 -14
  195. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
  196. data/.travis.yml +0 -23
  197. 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
data/test/refund_test.rb CHANGED
@@ -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
data/test/report_test.rb CHANGED
@@ -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
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
@@ -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(
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(
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(
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,15 @@ 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(
335
+ "https://localhost.myshopify.com/admin/oauth/authorize?client_id=My_test_key&" \
336
+ "scope=&redirect_uri=http://my_redirect_uri.com&state=My%20nonce",
337
+ permission_url
338
+ )
212
339
  end
213
340
 
214
341
  test "raise exception if code invalid in request token" do
215
- ShopifyAPI::Session.setup(:api_key => "My test key", :secret => "My test secret")
342
+ ShopifyAPI::Session.setup(api_key: "My test key", secret: "My test secret")
216
343
  session = ShopifyAPI::Session.new(
217
344
  domain: 'http://localhost.myshopify.com',
218
345
  token: nil,
@@ -228,7 +355,7 @@ class SessionTest < Test::Unit::TestCase
228
355
  assert_raises(ShopifyAPI::ValidationException) do
229
356
  session.request_token(code: "bad-code")
230
357
  end
231
- assert_equal false, session.valid?
358
+ assert_equal(false, session.valid?)
232
359
  end
233
360
 
234
361
  test "return site for session" do
@@ -237,87 +364,93 @@ class SessionTest < Test::Unit::TestCase
237
364
  token: "any-token",
238
365
  api_version: any_api_version
239
366
  )
240
- assert_equal "https://testshop.myshopify.com", session.site
367
+ assert_equal("https://testshop.myshopify.com", session.site)
241
368
  end
242
369
 
243
370
  test "return_token_if_signature_is_valid" do
244
371
  api_version = any_api_version
245
- fake nil,
372
+ fake(
373
+ nil,
246
374
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
247
375
  method: :post,
248
376
  body: '{"access_token":"any-token"}'
377
+ )
249
378
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
250
379
 
251
380
  params = { code: 'any-code', timestamp: Time.now }
252
381
  token = session.request_token(params.merge(hmac: generate_signature(params)))
253
382
 
254
- assert_equal "any-token", token
255
- assert_equal "any-token", session.token
383
+ assert_equal("any-token", token)
384
+ assert_equal("any-token", session.token)
256
385
  end
257
386
 
258
387
  test "extra parameters are stored in session" do
259
388
  api_version = ShopifyAPI::ApiVersion.new(handle: :unstable)
260
- fake nil,
389
+ fake(
390
+ nil,
261
391
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
262
392
  method: :post,
263
393
  body: '{"access_token":"any-token","foo":"example"}'
394
+ )
264
395
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
265
396
 
266
397
  params = { code: 'any-code', timestamp: Time.now }
267
- assert session.request_token(params.merge(hmac: generate_signature(params)))
398
+ assert(session.request_token(params.merge(hmac: generate_signature(params))))
268
399
 
269
- assert_equal ({ "foo" => "example" }), session.extra
400
+ assert_equal({ "foo" => "example" }, session.extra)
270
401
  end
271
402
 
272
403
  test "expires_in is automatically converted in expires_at" do
273
404
  api_version = any_api_version
274
- fake nil,
405
+ fake(
406
+ nil,
275
407
  url: "https://testshop.myshopify.com/admin/oauth/access_token",
276
408
  method: :post,
277
409
  body: '{"access_token":"any-token","expires_in":86393}'
410
+ )
278
411
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
279
412
 
280
413
  Timecop.freeze do
281
414
  params = { code: 'any-code', timestamp: Time.now }
282
- assert session.request_token(params.merge(hmac: generate_signature(params)))
415
+ assert(session.request_token(params.merge(hmac: generate_signature(params))))
283
416
 
284
417
  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?
418
+ assert_equal({ "expires_at" => expires_at.to_i }, session.extra)
419
+ assert(session.expires_at.is_a?(Time))
420
+ assert_equal(expires_at.to_i, session.expires_at.to_i)
421
+ assert_equal(86393, session.expires_in)
422
+ assert_equal(false, session.expired?)
290
423
 
291
424
  Timecop.travel(session.expires_at) do
292
- assert_equal true, session.expired?
425
+ assert_equal(true, session.expired?)
293
426
  end
294
427
  end
295
428
  end
296
429
 
297
430
  test "raise error if signature does not match expected" do
298
- params = {:code => "any-code", :timestamp => Time.now}
431
+ params = { code: "any-code", timestamp: Time.now }
299
432
  signature = generate_signature(params)
300
433
  params[:foo] = 'world'
301
434
  assert_raises(ShopifyAPI::ValidationException) do
302
435
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
303
- session.request_token(params.merge(:hmac => signature))
436
+ session.request_token(params.merge(hmac: signature))
304
437
  end
305
438
  end
306
439
 
307
440
  test "raise error if timestamp is too old" do
308
- params = {:code => "any-code", :timestamp => Time.now - 2.days}
441
+ params = { code: "any-code", timestamp: Time.now - 2 * SECONDS_IN_A_DAY }
309
442
  signature = generate_signature(params)
310
443
  params[:foo] = 'world'
311
444
  assert_raises(ShopifyAPI::ValidationException) do
312
445
  session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
313
- session.request_token(params.merge(:hmac => signature))
446
+ session.request_token(params.merge(hmac: signature))
314
447
  end
315
448
  end
316
449
 
317
450
  test "return true when the signature is valid and the keys of params are strings" do
318
451
  params = { 'code' => 'any-code', 'timestamp' => Time.now }
319
452
  params[:hmac] = generate_signature(params)
320
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
453
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
321
454
  end
322
455
 
323
456
  test "return true when validating signature of params with ampersand and equal sign characters" do
@@ -325,7 +458,7 @@ class SessionTest < Test::Unit::TestCase
325
458
  params = { 'a' => '1&b=2', 'c=3&d' => '4' }
326
459
  to_sign = 'a=1%26b=2&c%3D3%26d=4'
327
460
  params[:hmac] = generate_signature(to_sign)
328
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
461
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
329
462
  end
330
463
 
331
464
  test "return true when validating signature of params with percent sign characters" do
@@ -333,7 +466,7 @@ class SessionTest < Test::Unit::TestCase
333
466
  params = { 'a%3D1%26b' => '2%26c%3D3' }
334
467
  to_sign = 'a%253D1%2526b=2%2526c%253D3'
335
468
  params[:hmac] = generate_signature(to_sign)
336
- assert_equal true, ShopifyAPI::Session.validate_signature(params)
469
+ assert_equal(true, ShopifyAPI::Session.validate_signature(params))
337
470
  end
338
471
 
339
472
  test "url is aliased to domain to minimize the upgrade changes" do
@@ -346,6 +479,127 @@ class SessionTest < Test::Unit::TestCase
346
479
  assert_equal('testshop.myshopify.com', session.url)
347
480
  end
348
481
 
482
+ test "#hash returns the same value for equal Sessions" do
483
+ session = ShopifyAPI::Session.new(
484
+ domain: "http://testshop.myshopify.com",
485
+ token: "any-token",
486
+ api_version: '2019-01',
487
+ extra: { foo: "bar" }
488
+ )
489
+ other_session = ShopifyAPI::Session.new(
490
+ domain: "http://testshop.myshopify.com",
491
+ token: "any-token",
492
+ api_version: '2019-01',
493
+ extra: { foo: "bar" }
494
+ )
495
+ assert_equal(session.hash, other_session.hash)
496
+ end
497
+
498
+ test "equality verifies domain" 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
+ different_session = ShopifyAPI::Session.new(
512
+ domain: "http://another_testshop.myshopify.com",
513
+ token: "any-token",
514
+ api_version: '2019-01',
515
+ extra: { foo: "bar" }
516
+ )
517
+ assert_equal(session, other_session)
518
+ refute_equal(session, different_session)
519
+ end
520
+
521
+ test "equality verifies token" do
522
+ session = ShopifyAPI::Session.new(
523
+ domain: "http://testshop.myshopify.com",
524
+ token: "any-token",
525
+ api_version: '2019-01',
526
+ extra: { foo: "bar" }
527
+ )
528
+ different_session = ShopifyAPI::Session.new(
529
+ domain: "http://testshop.myshopify.com",
530
+ token: "very-different-token",
531
+ api_version: '2019-01',
532
+ extra: { foo: "bar" }
533
+ )
534
+ refute_equal(session, different_session)
535
+ end
536
+
537
+ test "equality verifies api_version" 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: "any-token",
547
+ api_version: :unstable,
548
+ extra: { foo: "bar" }
549
+ )
550
+ refute_equal(session, different_session)
551
+ end
552
+
553
+ test "equality verifies extra" 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: '2019-01',
564
+ extra: { bar: "other-bar" }
565
+ )
566
+ refute_equal(session, different_session)
567
+ end
568
+
569
+ test "equality verifies other is a Session" 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 = nil
577
+ refute_equal(session, different_session)
578
+ end
579
+
580
+ test "#eql? and #hash are implemented" do
581
+ session = ShopifyAPI::Session.new(
582
+ domain: "http://testshop.myshopify.com",
583
+ token: "any-token",
584
+ api_version: '2019-01',
585
+ extra: { foo: "bar" }
586
+ )
587
+ other_session = ShopifyAPI::Session.new(
588
+ domain: "http://testshop.myshopify.com",
589
+ token: "any-token",
590
+ api_version: '2019-01',
591
+ extra: { foo: "bar" }
592
+ )
593
+ different_session = ShopifyAPI::Session.new(
594
+ domain: "http://another_testshop.myshopify.com",
595
+ token: "any-token",
596
+ api_version: '2019-01',
597
+ extra: { foo: "bar" }
598
+ )
599
+
600
+ assert_equal([session, different_session], [session, other_session, different_session].uniq)
601
+ end
602
+
349
603
  private
350
604
 
351
605
  def make_sorted_params(params)
@@ -356,7 +610,7 @@ class SessionTest < Test::Unit::TestCase
356
610
 
357
611
  def generate_signature(params)
358
612
  params = make_sorted_params(params) if params.is_a?(Hash)
359
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, ShopifyAPI::Session.secret, params)
613
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA256'), ShopifyAPI::Session.secret, params)
360
614
  end
361
615
 
362
616
  def any_api_version