shopify_api 9.2.0 → 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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +36 -0
- data/.github/workflows/build.yml +41 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +23 -3
- data/.rubocop_todo.yml +75 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +151 -0
- data/Gemfile_ar51 +1 -1
- data/README.md +40 -30
- data/RELEASING +10 -6
- data/Rakefile +10 -6
- data/docs/graphql.md +1 -1
- data/docs/index.md +1 -1
- data/lib/active_resource/connection_ext.rb +1 -0
- data/lib/active_resource/detailed_log_subscriber.rb +6 -7
- data/lib/active_resource/json_errors.rb +8 -2
- data/lib/shopify_api.rb +8 -1
- data/lib/shopify_api/api_access.rb +57 -0
- data/lib/shopify_api/api_version.rb +6 -5
- data/lib/shopify_api/connection.rb +1 -0
- data/lib/shopify_api/countable.rb +3 -2
- data/lib/shopify_api/disable_prefix_check.rb +2 -2
- data/lib/shopify_api/events.rb +2 -1
- data/lib/shopify_api/graphql.rb +8 -6
- data/lib/shopify_api/limits.rb +3 -2
- data/lib/shopify_api/message_enricher.rb +11 -9
- data/lib/shopify_api/meta.rb +0 -1
- data/lib/shopify_api/metafields.rb +5 -4
- data/lib/shopify_api/pagination_link_headers.rb +4 -3
- data/lib/shopify_api/resources.rb +1 -0
- data/lib/shopify_api/resources/access_scope.rb +1 -1
- data/lib/shopify_api/resources/access_token.rb +1 -0
- data/lib/shopify_api/resources/address.rb +1 -0
- data/lib/shopify_api/resources/announcement.rb +2 -1
- data/lib/shopify_api/resources/application_charge.rb +1 -0
- data/lib/shopify_api/resources/application_credit.rb +1 -0
- data/lib/shopify_api/resources/article.rb +3 -2
- data/lib/shopify_api/resources/asset.rb +6 -5
- data/lib/shopify_api/resources/assigned_fulfillment_order.rb +1 -1
- data/lib/shopify_api/resources/base.rb +11 -6
- data/lib/shopify_api/resources/billing_address.rb +1 -0
- data/lib/shopify_api/resources/blog.rb +2 -1
- data/lib/shopify_api/resources/carrier_service.rb +1 -0
- data/lib/shopify_api/resources/cart.rb +2 -1
- data/lib/shopify_api/resources/collect.rb +1 -0
- data/lib/shopify_api/resources/collection_listing.rb +1 -0
- data/lib/shopify_api/resources/comment.rb +20 -5
- data/lib/shopify_api/resources/country.rb +1 -0
- data/lib/shopify_api/resources/custom_collection.rb +4 -3
- data/lib/shopify_api/resources/customer.rb +2 -1
- data/lib/shopify_api/resources/customer_group.rb +1 -0
- data/lib/shopify_api/resources/customer_invite.rb +1 -0
- data/lib/shopify_api/resources/customer_saved_search.rb +2 -1
- data/lib/shopify_api/resources/discount_code.rb +1 -0
- data/lib/shopify_api/resources/discount_code_batch.rb +4 -2
- data/lib/shopify_api/resources/draft_order.rb +1 -0
- data/lib/shopify_api/resources/draft_order_invoice.rb +1 -0
- data/lib/shopify_api/resources/event.rb +1 -0
- data/lib/shopify_api/resources/fulfillment.rb +12 -3
- data/lib/shopify_api/resources/fulfillment_event.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_order.rb +30 -16
- data/lib/shopify_api/resources/fulfillment_order_locations_for_move.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_request.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_service.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_v2.rb +3 -2
- data/lib/shopify_api/resources/gift_card.rb +1 -0
- data/lib/shopify_api/resources/image.rb +2 -1
- data/lib/shopify_api/resources/inventory_level.rb +2 -3
- data/lib/shopify_api/resources/line_item.rb +4 -3
- data/lib/shopify_api/resources/location.rb +1 -1
- data/lib/shopify_api/resources/marketing_event.rb +1 -0
- data/lib/shopify_api/resources/metafield.rb +1 -0
- data/lib/shopify_api/resources/note_attribute.rb +1 -0
- data/lib/shopify_api/resources/option.rb +1 -0
- data/lib/shopify_api/resources/order.rb +2 -1
- data/lib/shopify_api/resources/order_risk.rb +1 -0
- data/lib/shopify_api/resources/page.rb +1 -0
- data/lib/shopify_api/resources/payment_details.rb +1 -0
- data/lib/shopify_api/resources/policy.rb +1 -0
- data/lib/shopify_api/resources/price_rule.rb +1 -1
- data/lib/shopify_api/resources/product.rb +14 -11
- data/lib/shopify_api/resources/product_listing.rb +1 -0
- data/lib/shopify_api/resources/province.rb +1 -0
- data/lib/shopify_api/resources/receipt.rb +1 -0
- data/lib/shopify_api/resources/recurring_application_charge.rb +4 -1
- data/lib/shopify_api/resources/redirect.rb +1 -0
- data/lib/shopify_api/resources/refund.rb +2 -1
- data/lib/shopify_api/resources/report.rb +1 -0
- data/lib/shopify_api/resources/resource_feedback.rb +1 -1
- data/lib/shopify_api/resources/rule.rb +1 -0
- data/lib/shopify_api/resources/script_tag.rb +1 -0
- data/lib/shopify_api/resources/shipping_address.rb +1 -0
- data/lib/shopify_api/resources/shipping_line.rb +1 -0
- data/lib/shopify_api/resources/shipping_zone.rb +1 -0
- data/lib/shopify_api/resources/shop.rb +2 -1
- data/lib/shopify_api/resources/smart_collection.rb +2 -2
- data/lib/shopify_api/resources/storefront_access_token.rb +1 -0
- data/lib/shopify_api/resources/tax_line.rb +1 -0
- data/lib/shopify_api/resources/tax_service.rb +1 -0
- data/lib/shopify_api/resources/theme.rb +1 -0
- data/lib/shopify_api/resources/transaction.rb +1 -0
- data/lib/shopify_api/resources/usage_charge.rb +1 -0
- data/lib/shopify_api/resources/user.rb +1 -0
- data/lib/shopify_api/resources/variant.rb +16 -18
- data/lib/shopify_api/resources/webhook.rb +1 -0
- data/lib/shopify_api/session.rb +28 -14
- data/lib/shopify_api/version.rb +2 -1
- data/lib/verify_docs.rb +1 -0
- data/service.yml +1 -1
- data/shopify_api.gemspec +10 -4
- data/test/access_token_test.rb +6 -5
- data/test/active_resource/json_errors_test.rb +6 -6
- data/test/api_access_test.rb +153 -0
- data/test/api_version_test.rb +3 -3
- data/test/application_charge_test.rb +30 -27
- data/test/application_credit_test.rb +10 -9
- data/test/article_test.rb +34 -35
- data/test/asset_test.rb +14 -6
- data/test/assigned_fulfillment_order_test.rb +5 -4
- data/test/base_test.rb +55 -56
- data/test/blog_test.rb +4 -3
- data/test/carrier_service_test.rb +7 -6
- data/test/cart_test.rb +2 -1
- data/test/collect_test.rb +4 -3
- data/test/collection_listing_test.rb +21 -16
- data/test/collection_publication_test.rb +8 -8
- data/test/collection_test.rb +20 -19
- data/test/countable_test.rb +3 -2
- data/test/currency_test.rb +5 -5
- data/test/custom_collection_test.rb +4 -3
- data/test/customer_saved_search_test.rb +18 -8
- data/test/customer_test.rb +22 -14
- data/test/detailed_log_subscriber_test.rb +15 -11
- data/test/discount_code_batch_test.rb +11 -10
- data/test/discount_code_test.rb +21 -15
- data/test/draft_order_test.rb +68 -52
- data/test/fixtures/assigned_fulfillment_orders.json +2 -0
- data/test/fixtures/fulfillment_order.json +1 -0
- data/test/fixtures/fulfillment_orders.json +2 -0
- data/test/fulfillment_event_test.rb +31 -26
- data/test/fulfillment_order_test.rb +215 -147
- data/test/fulfillment_order_test_helper.rb +1 -0
- data/test/fulfillment_request_test.rb +10 -8
- data/test/fulfillment_service_test.rb +13 -12
- data/test/fulfillment_test.rb +81 -66
- data/test/fulfillment_v2_test.rb +16 -12
- data/test/gift_card_test.rb +6 -4
- data/test/graphql_test.rb +27 -27
- data/test/image_test.rb +19 -17
- data/test/inventory_level_test.rb +24 -15
- data/test/lib/webmock_extensions/last_request.rb +1 -1
- data/test/limits_test.rb +2 -1
- data/test/location_test.rb +2 -1
- data/test/marketing_event_test.rb +20 -20
- data/test/message_enricher_test.rb +6 -6
- data/test/meta_test.rb +7 -9
- data/test/metafield_test.rb +30 -20
- data/test/order_risk_test.rb +17 -16
- data/test/order_test.rb +43 -28
- data/test/pagination_test.rb +89 -56
- data/test/policy_test.rb +6 -5
- data/test/price_rule_test.rb +20 -15
- data/test/product_listing_test.rb +20 -20
- data/test/product_publication_test.rb +8 -8
- data/test/product_test.rb +44 -32
- data/test/publication_test.rb +3 -3
- data/test/recurring_application_charge_test.rb +104 -42
- data/test/redirect_test.rb +4 -3
- data/test/refund_test.rb +22 -17
- data/test/report_test.rb +12 -10
- data/test/resource_feedback_test.rb +14 -13
- data/test/script_tag_test.rb +10 -9
- data/test/session_test.rb +137 -46
- data/test/shipping_zone_test.rb +4 -3
- data/test/shop_test.rb +47 -33
- data/test/smart_collection_test.rb +5 -4
- data/test/storefront_access_token_test.rb +13 -15
- data/test/tax_service_test.rb +7 -4
- data/test/tender_transaction_test.rb +3 -3
- data/test/test_helper.rb +13 -11
- data/test/transaction_test.rb +4 -3
- data/test/usage_charge_test.rb +12 -8
- data/test/user_test.rb +4 -3
- data/test/variant_test.rb +23 -54
- data/test/webhook_test.rb +10 -7
- metadata +14 -9
- data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
- data/.travis.yml +0 -28
data/test/redirect_test.rb
CHANGED
|
@@ -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
|
|
6
|
-
redirect = ShopifyAPI::Redirect.create(:
|
|
7
|
-
assert_equal
|
|
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
|
|
6
|
+
fake("orders/450789469/refunds", method: :post, status: 201, body: load_fixture('refund'))
|
|
7
7
|
refund = ShopifyAPI::Refund.create(
|
|
8
|
-
:
|
|
9
|
-
:
|
|
10
|
-
:
|
|
11
|
-
:
|
|
12
|
-
:
|
|
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
|
|
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
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
26
|
-
data = { :
|
|
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, :
|
|
29
|
-
assert_equal
|
|
30
|
-
assert_equal
|
|
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
|
|
6
|
+
fake('reports/987', method: :get, status: 200, body: load_fixture('report'))
|
|
6
7
|
|
|
7
8
|
report = ShopifyAPI::Report.find(987)
|
|
8
|
-
assert_equal
|
|
9
|
+
assert_equal(987, report.id)
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
test 'get all should get all reports' do
|
|
12
|
-
fake
|
|
13
|
+
fake('reports', method: :get, status: 200, body: load_fixture('reports'))
|
|
13
14
|
|
|
14
15
|
reports = ShopifyAPI::Report.all
|
|
15
|
-
assert_equal
|
|
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
|
|
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
|
|
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
|
|
27
|
+
assert_equal('custom_app_reports', report.category)
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
test 'delete should delete report' do
|
|
29
|
-
fake
|
|
30
|
-
fake
|
|
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
|
|
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: [
|
|
4
|
-
fake
|
|
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
|
|
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
|
|
12
|
+
fake('resource_feedback', method: :post, body: body)
|
|
12
13
|
ShopifyAPI::ResourceFeedback.new.save
|
|
13
|
-
assert_request_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: [
|
|
18
|
-
fake
|
|
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
|
|
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
|
|
26
|
+
fake('products/42/resource_feedback', method: :post, body: body)
|
|
26
27
|
ShopifyAPI::ResourceFeedback.new(product_id: 42).save
|
|
27
|
-
assert_request_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
|
|
33
|
+
fake('resource_feedback', method: :post, body: body)
|
|
33
34
|
resource_feedback = ShopifyAPI::ResourceFeedback.new
|
|
34
35
|
resource_feedback.save
|
|
35
|
-
assert_request_body
|
|
36
|
+
assert_request_body(body)
|
|
36
37
|
|
|
37
38
|
ShopifyAPI::ResourceFeedback.any_instance.expects(:persisted?).returns(true)
|
|
38
|
-
assert_raises
|
|
39
|
+
assert_raises(ShopifyAPI::ResourceFeedback::ExistingFeedbackSaved) do
|
|
39
40
|
resource_feedback.save
|
|
40
41
|
end
|
|
41
42
|
end
|
data/test/script_tag_test.rb
CHANGED
|
@@ -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
|
|
6
|
+
fake('script_tags', method: :get, status: 200, body: load_fixture('script_tags'))
|
|
6
7
|
script_tags = ShopifyAPI::ScriptTag.all
|
|
7
|
-
assert_equal
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
27
|
+
fake('script_tags/421379493', method: :put, status: 200, body: load_fixture('script_tag'))
|
|
27
28
|
script_tag.save
|
|
28
|
-
assert_equal
|
|
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,33 +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
|
|
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
|
|
20
|
+
assert_not(session.valid?)
|
|
19
21
|
end
|
|
20
22
|
|
|
21
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
|
|
25
|
+
assert_not(session.valid?)
|
|
24
26
|
|
|
25
|
-
session = ShopifyAPI::Session.new(
|
|
26
|
-
|
|
27
|
+
session = ShopifyAPI::Session.new(
|
|
28
|
+
domain: "testshop.myshopify.com", token: "any-token", api_version: ShopifyAPI::ApiVersion::NullVersion
|
|
29
|
+
)
|
|
30
|
+
assert_not(session.valid?)
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
test "default to base API version" do
|
|
30
34
|
session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: "any-token")
|
|
31
|
-
assert
|
|
32
|
-
assert_equal
|
|
35
|
+
assert(session.valid?)
|
|
36
|
+
assert_equal(session.api_version, ShopifyAPI::Base.api_version)
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
test "can override the base API version" do
|
|
36
40
|
different_api_version = '2020-01'
|
|
37
|
-
session = ShopifyAPI::Session.new(
|
|
38
|
-
|
|
39
|
-
|
|
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))
|
|
40
46
|
end
|
|
41
47
|
|
|
42
48
|
test "be valid with any token, any url and version" do
|
|
@@ -45,7 +51,40 @@ class SessionTest < Test::Unit::TestCase
|
|
|
45
51
|
token: "any-token",
|
|
46
52
|
api_version: any_api_version
|
|
47
53
|
)
|
|
48
|
-
assert
|
|
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?)
|
|
49
88
|
end
|
|
50
89
|
|
|
51
90
|
test "not raise error without params" do
|
|
@@ -78,17 +117,47 @@ class SessionTest < Test::Unit::TestCase
|
|
|
78
117
|
end
|
|
79
118
|
end
|
|
80
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
|
+
|
|
81
150
|
test "raise error if params passed but signature omitted" do
|
|
82
151
|
assert_raises(ShopifyAPI::ValidationException) do
|
|
83
152
|
session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
|
|
84
|
-
session.request_token({'code' => 'any-code'})
|
|
153
|
+
session.request_token({ 'code' => 'any-code' })
|
|
85
154
|
end
|
|
86
155
|
end
|
|
87
156
|
|
|
88
157
|
test "setup api_key and secret for all sessions" do
|
|
89
|
-
ShopifyAPI::Session.setup(:
|
|
90
|
-
assert_equal
|
|
91
|
-
assert_equal
|
|
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)
|
|
92
161
|
end
|
|
93
162
|
|
|
94
163
|
test "#temp reset ShopifyAPI::Base values to original value" do
|
|
@@ -168,7 +237,7 @@ class SessionTest < Test::Unit::TestCase
|
|
|
168
237
|
api_version: :unstable
|
|
169
238
|
)
|
|
170
239
|
|
|
171
|
-
assert_raises
|
|
240
|
+
assert_raises(StandardError) do
|
|
172
241
|
ShopifyAPI::Session.with_session(other_session) { raise StandardError, "" }
|
|
173
242
|
end
|
|
174
243
|
|
|
@@ -214,7 +283,11 @@ class SessionTest < Test::Unit::TestCase
|
|
|
214
283
|
)
|
|
215
284
|
scope = ["write_products"]
|
|
216
285
|
permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com")
|
|
217
|
-
assert_equal
|
|
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
|
+
)
|
|
218
291
|
end
|
|
219
292
|
|
|
220
293
|
test "create_permission_url returns correct url with dual scope" do
|
|
@@ -224,9 +297,13 @@ class SessionTest < Test::Unit::TestCase
|
|
|
224
297
|
token: 'any-token',
|
|
225
298
|
api_version: any_api_version
|
|
226
299
|
)
|
|
227
|
-
scope = ["write_products","write_customers"]
|
|
300
|
+
scope = ["write_products", "write_customers"]
|
|
228
301
|
permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com")
|
|
229
|
-
assert_equal
|
|
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
|
+
)
|
|
230
307
|
end
|
|
231
308
|
|
|
232
309
|
test "create_permission_url returns correct url with no scope" do
|
|
@@ -238,7 +315,11 @@ class SessionTest < Test::Unit::TestCase
|
|
|
238
315
|
)
|
|
239
316
|
scope = []
|
|
240
317
|
permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com")
|
|
241
|
-
assert_equal
|
|
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
|
+
)
|
|
242
323
|
end
|
|
243
324
|
|
|
244
325
|
test "create_permission_url returns correct url with state" do
|
|
@@ -250,11 +331,15 @@ class SessionTest < Test::Unit::TestCase
|
|
|
250
331
|
)
|
|
251
332
|
scope = []
|
|
252
333
|
permission_url = session.create_permission_url(scope, "http://my_redirect_uri.com", state: "My nonce")
|
|
253
|
-
assert_equal
|
|
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
|
+
)
|
|
254
339
|
end
|
|
255
340
|
|
|
256
341
|
test "raise exception if code invalid in request token" do
|
|
257
|
-
ShopifyAPI::Session.setup(:
|
|
342
|
+
ShopifyAPI::Session.setup(api_key: "My test key", secret: "My test secret")
|
|
258
343
|
session = ShopifyAPI::Session.new(
|
|
259
344
|
domain: 'http://localhost.myshopify.com',
|
|
260
345
|
token: nil,
|
|
@@ -270,7 +355,7 @@ class SessionTest < Test::Unit::TestCase
|
|
|
270
355
|
assert_raises(ShopifyAPI::ValidationException) do
|
|
271
356
|
session.request_token(code: "bad-code")
|
|
272
357
|
end
|
|
273
|
-
assert_equal
|
|
358
|
+
assert_equal(false, session.valid?)
|
|
274
359
|
end
|
|
275
360
|
|
|
276
361
|
test "return site for session" do
|
|
@@ -279,87 +364,93 @@ class SessionTest < Test::Unit::TestCase
|
|
|
279
364
|
token: "any-token",
|
|
280
365
|
api_version: any_api_version
|
|
281
366
|
)
|
|
282
|
-
assert_equal
|
|
367
|
+
assert_equal("https://testshop.myshopify.com", session.site)
|
|
283
368
|
end
|
|
284
369
|
|
|
285
370
|
test "return_token_if_signature_is_valid" do
|
|
286
371
|
api_version = any_api_version
|
|
287
|
-
fake
|
|
372
|
+
fake(
|
|
373
|
+
nil,
|
|
288
374
|
url: "https://testshop.myshopify.com/admin/oauth/access_token",
|
|
289
375
|
method: :post,
|
|
290
376
|
body: '{"access_token":"any-token"}'
|
|
377
|
+
)
|
|
291
378
|
session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
|
|
292
379
|
|
|
293
380
|
params = { code: 'any-code', timestamp: Time.now }
|
|
294
381
|
token = session.request_token(params.merge(hmac: generate_signature(params)))
|
|
295
382
|
|
|
296
|
-
assert_equal
|
|
297
|
-
assert_equal
|
|
383
|
+
assert_equal("any-token", token)
|
|
384
|
+
assert_equal("any-token", session.token)
|
|
298
385
|
end
|
|
299
386
|
|
|
300
387
|
test "extra parameters are stored in session" do
|
|
301
388
|
api_version = ShopifyAPI::ApiVersion.new(handle: :unstable)
|
|
302
|
-
fake
|
|
389
|
+
fake(
|
|
390
|
+
nil,
|
|
303
391
|
url: "https://testshop.myshopify.com/admin/oauth/access_token",
|
|
304
392
|
method: :post,
|
|
305
393
|
body: '{"access_token":"any-token","foo":"example"}'
|
|
394
|
+
)
|
|
306
395
|
session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
|
|
307
396
|
|
|
308
397
|
params = { code: 'any-code', timestamp: Time.now }
|
|
309
|
-
assert
|
|
398
|
+
assert(session.request_token(params.merge(hmac: generate_signature(params))))
|
|
310
399
|
|
|
311
|
-
assert_equal
|
|
400
|
+
assert_equal({ "foo" => "example" }, session.extra)
|
|
312
401
|
end
|
|
313
402
|
|
|
314
403
|
test "expires_in is automatically converted in expires_at" do
|
|
315
404
|
api_version = any_api_version
|
|
316
|
-
fake
|
|
405
|
+
fake(
|
|
406
|
+
nil,
|
|
317
407
|
url: "https://testshop.myshopify.com/admin/oauth/access_token",
|
|
318
408
|
method: :post,
|
|
319
409
|
body: '{"access_token":"any-token","expires_in":86393}'
|
|
410
|
+
)
|
|
320
411
|
session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: api_version)
|
|
321
412
|
|
|
322
413
|
Timecop.freeze do
|
|
323
414
|
params = { code: 'any-code', timestamp: Time.now }
|
|
324
|
-
assert
|
|
415
|
+
assert(session.request_token(params.merge(hmac: generate_signature(params))))
|
|
325
416
|
|
|
326
417
|
expires_at = Time.now.utc + 86393
|
|
327
|
-
assert_equal
|
|
328
|
-
assert
|
|
329
|
-
assert_equal
|
|
330
|
-
assert_equal
|
|
331
|
-
assert_equal
|
|
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?)
|
|
332
423
|
|
|
333
424
|
Timecop.travel(session.expires_at) do
|
|
334
|
-
assert_equal
|
|
425
|
+
assert_equal(true, session.expired?)
|
|
335
426
|
end
|
|
336
427
|
end
|
|
337
428
|
end
|
|
338
429
|
|
|
339
430
|
test "raise error if signature does not match expected" do
|
|
340
|
-
params = {:
|
|
431
|
+
params = { code: "any-code", timestamp: Time.now }
|
|
341
432
|
signature = generate_signature(params)
|
|
342
433
|
params[:foo] = 'world'
|
|
343
434
|
assert_raises(ShopifyAPI::ValidationException) do
|
|
344
435
|
session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
|
|
345
|
-
session.request_token(params.merge(:
|
|
436
|
+
session.request_token(params.merge(hmac: signature))
|
|
346
437
|
end
|
|
347
438
|
end
|
|
348
439
|
|
|
349
440
|
test "raise error if timestamp is too old" do
|
|
350
|
-
params = {:
|
|
441
|
+
params = { code: "any-code", timestamp: Time.now - 2 * SECONDS_IN_A_DAY }
|
|
351
442
|
signature = generate_signature(params)
|
|
352
443
|
params[:foo] = 'world'
|
|
353
444
|
assert_raises(ShopifyAPI::ValidationException) do
|
|
354
445
|
session = ShopifyAPI::Session.new(domain: "testshop.myshopify.com", token: nil, api_version: any_api_version)
|
|
355
|
-
session.request_token(params.merge(:
|
|
446
|
+
session.request_token(params.merge(hmac: signature))
|
|
356
447
|
end
|
|
357
448
|
end
|
|
358
449
|
|
|
359
450
|
test "return true when the signature is valid and the keys of params are strings" do
|
|
360
451
|
params = { 'code' => 'any-code', 'timestamp' => Time.now }
|
|
361
452
|
params[:hmac] = generate_signature(params)
|
|
362
|
-
assert_equal
|
|
453
|
+
assert_equal(true, ShopifyAPI::Session.validate_signature(params))
|
|
363
454
|
end
|
|
364
455
|
|
|
365
456
|
test "return true when validating signature of params with ampersand and equal sign characters" do
|
|
@@ -367,7 +458,7 @@ class SessionTest < Test::Unit::TestCase
|
|
|
367
458
|
params = { 'a' => '1&b=2', 'c=3&d' => '4' }
|
|
368
459
|
to_sign = 'a=1%26b=2&c%3D3%26d=4'
|
|
369
460
|
params[:hmac] = generate_signature(to_sign)
|
|
370
|
-
assert_equal
|
|
461
|
+
assert_equal(true, ShopifyAPI::Session.validate_signature(params))
|
|
371
462
|
end
|
|
372
463
|
|
|
373
464
|
test "return true when validating signature of params with percent sign characters" do
|
|
@@ -375,7 +466,7 @@ class SessionTest < Test::Unit::TestCase
|
|
|
375
466
|
params = { 'a%3D1%26b' => '2%26c%3D3' }
|
|
376
467
|
to_sign = 'a%253D1%2526b=2%2526c%253D3'
|
|
377
468
|
params[:hmac] = generate_signature(to_sign)
|
|
378
|
-
assert_equal
|
|
469
|
+
assert_equal(true, ShopifyAPI::Session.validate_signature(params))
|
|
379
470
|
end
|
|
380
471
|
|
|
381
472
|
test "url is aliased to domain to minimize the upgrade changes" do
|
|
@@ -519,7 +610,7 @@ class SessionTest < Test::Unit::TestCase
|
|
|
519
610
|
|
|
520
611
|
def generate_signature(params)
|
|
521
612
|
params = make_sorted_params(params) if params.is_a?(Hash)
|
|
522
|
-
OpenSSL::HMAC.hexdigest(OpenSSL::Digest
|
|
613
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA256'), ShopifyAPI::Session.secret, params)
|
|
523
614
|
end
|
|
524
615
|
|
|
525
616
|
def any_api_version
|