shopify_api 8.1.0 → 9.0.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +22 -10
  4. data/docs/graphql.md +191 -0
  5. data/lib/shopify_api.rb +2 -0
  6. data/lib/shopify_api/api_version.rb +1 -1
  7. data/lib/shopify_api/graphql.rb +79 -0
  8. data/lib/shopify_api/graphql/http_client.rb +22 -0
  9. data/lib/shopify_api/graphql/railtie.rb +17 -0
  10. data/lib/shopify_api/graphql/task.rake +100 -0
  11. data/lib/shopify_api/resources/assigned_fulfillment_order.rb +16 -0
  12. data/lib/shopify_api/resources/base.rb +8 -0
  13. data/lib/shopify_api/resources/fulfillment.rb +34 -0
  14. data/lib/shopify_api/resources/fulfillment_order.rb +137 -0
  15. data/lib/shopify_api/resources/fulfillment_order_locations_for_move.rb +4 -0
  16. data/lib/shopify_api/resources/fulfillment_v2.rb +20 -0
  17. data/lib/shopify_api/resources/order.rb +7 -0
  18. data/lib/shopify_api/session.rb +3 -3
  19. data/lib/shopify_api/version.rb +1 -1
  20. data/test/assigned_fulfillment_order_test.rb +77 -0
  21. data/test/base_test.rb +14 -0
  22. data/test/fixtures/assigned_fulfillment_orders.json +78 -0
  23. data/test/fixtures/fulfillment_order.json +38 -0
  24. data/test/fixtures/fulfillment_order_locations_for_move.json +18 -0
  25. data/test/fixtures/fulfillment_orders.json +78 -0
  26. data/test/fixtures/fulfillments.json +53 -0
  27. data/test/fixtures/graphql/2019-10.json +1083 -0
  28. data/test/fixtures/graphql/dummy_schema.rb +16 -0
  29. data/test/fixtures/graphql/unstable.json +1083 -0
  30. data/test/fulfillment_order_test.rb +462 -0
  31. data/test/fulfillment_order_test_helper.rb +7 -0
  32. data/test/fulfillment_test.rb +164 -1
  33. data/test/fulfillment_v2_test.rb +62 -0
  34. data/test/graphql/http_client_test.rb +26 -0
  35. data/test/graphql_test.rb +147 -0
  36. data/test/order_test.rb +50 -0
  37. data/test/session_test.rb +26 -13
  38. data/test/test_helper.rb +4 -1
  39. metadata +25 -3
  40. data/lib/shopify_api/resources/graphql.rb +0 -22
@@ -0,0 +1,7 @@
1
+ module FulfillmentOrderTestHelper
2
+ def url_prefix_for_activated_session_for(version)
3
+ available_version = ShopifyAPI::Session.new(domain: 'shop2.myshopify.com', token: 'token2', api_version: version)
4
+ ShopifyAPI::Base.activate_session(available_version)
5
+ "https://shop2.myshopify.com/admin/api/#{version}"
6
+ end
7
+ end
@@ -1,6 +1,9 @@
1
1
  require 'test_helper'
2
+ require 'fulfillment_order_test_helper'
2
3
 
3
4
  class FulFillmentTest < Test::Unit::TestCase
5
+ include FulfillmentOrderTestHelper
6
+
4
7
  def setup
5
8
  super
6
9
  fake "orders/450789469/fulfillments/255858046", :method => :get, :body => load_fixture('fulfillment')
@@ -56,6 +59,166 @@ class FulFillmentTest < Test::Unit::TestCase
56
59
  assert_equal 450789469, fulfillment.order_id
57
60
  end
58
61
  end
59
- end
60
62
 
63
+ context "#create" do
64
+ should "create a fulfillment with line_items_by_fulfillment_order" do
65
+ create_fulfillment_attributes = {
66
+ message: "The message for this FO fulfillment",
67
+ notify_customer: true,
68
+ tracking_info: {
69
+ number: "XSDFHYR23475",
70
+ url: "https://tracking.example.com/XSDFHYR23475",
71
+ company: "TFTC - the fulfillment/tracking company"
72
+ },
73
+ line_items_by_fulfillment_order: [
74
+ {
75
+ fulfillment_order_id: 3,
76
+ fulfillment_order_line_items: [{ id: 2, quantity: 1 }]
77
+ }
78
+ ]
79
+ }
80
+ request_body = { fulfillment: create_fulfillment_attributes }
81
+ response_body = { fulfillment: create_fulfillment_attributes.merge(id: 346743624) }
82
+ url_prefix = url_prefix_for_activated_session_for('2020-01')
83
+ fake 'fulfillments',
84
+ url: "#{url_prefix}/fulfillments.json",
85
+ :method => :post,
86
+ request_body: ActiveSupport::JSON.encode(request_body),
87
+ body: ActiveSupport::JSON.encode(response_body)
88
+
89
+ fulfillment = ShopifyAPI::Fulfillment.create(create_fulfillment_attributes)
90
+ assert fulfillment.is_a?(ShopifyAPI::Fulfillment)
91
+ assert fulfillment.persisted?
92
+ assert_equal 346743624, fulfillment.id
93
+ end
94
+
95
+ should "raise NotImplementedError when api_version is older than 2020-01" do
96
+ create_fulfillment_attributes = {
97
+ message: "The message for this FO fulfillment",
98
+ notify_customer: true,
99
+ tracking_info: {
100
+ number: "XSDFHYR23475",
101
+ url: "https://tracking.example.com/XSDFHYR23475",
102
+ company: "TFTC - the fulfillment/tracking company"
103
+ },
104
+ line_items_by_fulfillment_order: [
105
+ {
106
+ fulfillment_order_id: 3,
107
+ fulfillment_order_line_items: [{ id: 2, quantity: 1 }]
108
+ }
109
+ ]
110
+ }
111
+ request_body = { fulfillment: create_fulfillment_attributes }
112
+ response_body = { fulfillment: create_fulfillment_attributes.merge(id: 346743624) }
113
+ url_prefix = url_prefix_for_activated_session_for('2019-10')
114
+ fake 'fulfillments',
115
+ url: "#{url_prefix}/fulfillments.json",
116
+ :method => :post,
117
+ request_body: ActiveSupport::JSON.encode(request_body),
118
+ body: ActiveSupport::JSON.encode(response_body)
119
+
120
+ assert_raises NotImplementedError do
121
+ ShopifyAPI::Fulfillment.create(create_fulfillment_attributes)
122
+ end
123
+ end
124
+ end
125
+
126
+ context "#save" do
127
+ should "save a fulfillment with line_items_by_fulfillment_order" do
128
+ create_fulfillment_attributes = {
129
+ message: "The message for this FO fulfillment",
130
+ notify_customer: true,
131
+ tracking_info: {
132
+ number: "XSDFHYR23475",
133
+ url: "https://tracking.example.com/XSDFHYR23475",
134
+ company: "TFTC - the fulfillment/tracking company"
135
+ },
136
+ line_items_by_fulfillment_order: [
137
+ {
138
+ fulfillment_order_id: 3,
139
+ fulfillment_order_line_items: [{ id: 2, quantity: 1 }]
140
+ }
141
+ ]
142
+ }
143
+ request_body = { fulfillment: create_fulfillment_attributes }
144
+ response_body = { fulfillment: create_fulfillment_attributes.merge(id: 346743624) }
145
+ url_prefix = url_prefix_for_activated_session_for('2020-01')
146
+ fake 'fulfillments',
147
+ url: "#{url_prefix}/fulfillments.json",
148
+ :method => :post,
149
+ request_body: ActiveSupport::JSON.encode(request_body),
150
+ body: ActiveSupport::JSON.encode(response_body)
151
+
152
+ fulfillment = ShopifyAPI::Fulfillment.new(create_fulfillment_attributes)
153
+ assert fulfillment.save
154
+ assert fulfillment.is_a?(ShopifyAPI::Fulfillment)
155
+ assert fulfillment.persisted?
156
+ assert_equal 346743624, fulfillment.id
157
+ end
158
+
159
+ should "save a fulfillment without line_items_by_fulfillment_order" do
160
+ order_id = 8
161
+ create_fulfillment_attributes = {
162
+ message: "The message for this FO fulfillment",
163
+ notify_customer: true,
164
+ tracking_info: {
165
+ number: "XSDFHYR23475",
166
+ url: "https://tracking.example.com/XSDFHYR23475",
167
+ company: "TFTC - the fulfillment/tracking company"
168
+ }
169
+ }
170
+ request_body = { fulfillment: create_fulfillment_attributes }
171
+ response_body = { fulfillment: create_fulfillment_attributes.merge(id: 346743624) }
172
+ fake "orders/#{order_id}/fulfillments", :method => :post,
173
+ request_body: ActiveSupport::JSON.encode(request_body),
174
+ body: ActiveSupport::JSON.encode(response_body)
175
+
176
+ fulfillment = ShopifyAPI::Fulfillment.new(create_fulfillment_attributes)
177
+ fulfillment.prefix_options[:order_id] = order_id
178
+
179
+ assert fulfillment.save
180
+ assert fulfillment.is_a?(ShopifyAPI::Fulfillment)
181
+ assert fulfillment.persisted?
182
+ assert_equal 346743624, fulfillment.id
183
+ end
184
+ end
185
+
186
+ context "#update_tracking" do
187
+ should "be able to update tracking info for a fulfillment" do
188
+ tracking_info = {
189
+ number: 'JSDHFHAG',
190
+ url: 'https://example.com/fulfillment_tracking/JSDHFHAG',
191
+ company: 'ACME co',
192
+ }
193
+ fake_fulfillment = ActiveSupport::JSON.decode(load_fixture('fulfillment'))['fulfillment']
194
+ fake_fulfillment['tracking_number'] = tracking_info[:number]
195
+ fake_fulfillment['tracking_numbers'] = [tracking_info[:number]]
196
+ fake_fulfillment['tracking_url'] = tracking_info[:url]
197
+ fake_fulfillment['tracking_urls'] = [tracking_info[:url]]
198
+ fake_fulfillment['tracking_company'] = tracking_info[:company]
199
+
200
+ request_body = {
201
+ fulfillment: {
202
+ tracking_info: tracking_info,
203
+ notify_customer: true
204
+ }
205
+ }
206
+ url_prefix = url_prefix_for_activated_session_for('2020-01')
207
+ fake 'fulfillments',
208
+ url: "#{url_prefix}/fulfillments/#{fake_fulfillment['id']}/update_tracking.json",
209
+ method: :post,
210
+ request_body: ActiveSupport::JSON.encode(request_body),
211
+ body: ActiveSupport::JSON.encode(fulfillment: fake_fulfillment)
212
+
213
+ fulfillment = ShopifyAPI::Fulfillment.new(id: fake_fulfillment['id'])
214
+ assert fulfillment.update_tracking(tracking_info: tracking_info, notify_customer: true)
215
+
216
+ assert_equal tracking_info[:number], fulfillment.tracking_number
217
+ assert_equal [tracking_info[:number]], fulfillment.tracking_numbers
218
+ assert_equal tracking_info[:url], fulfillment.tracking_url
219
+ assert_equal [tracking_info[:url]], fulfillment.tracking_urls
220
+ assert_equal tracking_info[:company], fulfillment.tracking_company
221
+ end
222
+ end
223
+ end
61
224
  end
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+ require 'fulfillment_order_test_helper'
3
+
4
+ class FulfillmentV2Test < Test::Unit::TestCase
5
+ include FulfillmentOrderTestHelper
6
+
7
+ def setup
8
+ super
9
+ @tracking_info = {
10
+ number: 'JSDHFHAG',
11
+ url: 'https://example.com/fulfillment_tracking/JSDHFHAG',
12
+ company: 'ACME co',
13
+ }
14
+ @fake_fulfillment = ActiveSupport::JSON.decode(load_fixture('fulfillment'))['fulfillment']
15
+ @fake_fulfillment['tracking_number'] = @tracking_info[:number]
16
+ @fake_fulfillment['tracking_numbers'] = [@tracking_info[:number]]
17
+ @fake_fulfillment['tracking_url'] = @tracking_info[:url]
18
+ @fake_fulfillment['tracking_urls'] = [@tracking_info[:url]]
19
+ @fake_fulfillment['tracking_company'] = @tracking_info[:company]
20
+
21
+ @request_body = {
22
+ fulfillment: {
23
+ tracking_info: @tracking_info,
24
+ notify_customer: true
25
+ }
26
+ }
27
+ @url_prefix = url_prefix_for_activated_session_for('2020-01')
28
+ fake 'fulfillments',
29
+ url: "#{@url_prefix}/fulfillments/#{@fake_fulfillment['id']}/update_tracking.json",
30
+ method: :post,
31
+ request_body: ActiveSupport::JSON.encode(@request_body),
32
+ body: ActiveSupport::JSON.encode(fulfillment: @fake_fulfillment)
33
+ end
34
+
35
+ context "FulfillmentV2" do
36
+ context "#update_tracking" do
37
+ should "be able to update tracking info for a fulfillment" do
38
+ fulfillment = ShopifyAPI::FulfillmentV2.new(id: @fake_fulfillment['id'])
39
+ assert fulfillment.update_tracking(tracking_info: @tracking_info, notify_customer: true)
40
+
41
+ assert_equal @tracking_info[:number], fulfillment.tracking_number
42
+ assert_equal [@tracking_info[:number]], fulfillment.tracking_numbers
43
+ assert_equal @tracking_info[:url], fulfillment.tracking_url
44
+ assert_equal [@tracking_info[:url]], fulfillment.tracking_urls
45
+ assert_equal @tracking_info[:company], fulfillment.tracking_company
46
+ end
47
+
48
+ should "raise NotImplementedError when api_version is older than 2020-01" do
49
+ @url_prefix = url_prefix_for_activated_session_for('2019-10')
50
+ fake 'fulfillments',
51
+ url: "#{@url_prefix}/fulfillments/#{@fake_fulfillment['id']}/update_tracking.json",
52
+ method: :post,
53
+ request_body: ActiveSupport::JSON.encode(@request_body),
54
+ body: ActiveSupport::JSON.encode(fulfillment: @fake_fulfillment)
55
+
56
+ assert_raises NotImplementedError do
57
+ ShopifyAPI::FulfillmentV2.new(id: @fake_fulfillment['id'])
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ module GraphQL
5
+ class HTTPClientTest < Test::Unit::TestCase
6
+ test '#headers uses the Base headers' do
7
+ ShopifyAPI::Base.headers['X-Custom'] = 'abc'
8
+
9
+ client = ShopifyAPI::GraphQL::HTTPClient.new('2019-07')
10
+
11
+ assert_equal 'abc', client.headers({})['X-Custom']
12
+
13
+ ShopifyAPI::Base.headers.delete('X-Custom')
14
+ end
15
+
16
+ test '#uri uses the Base site and the API version' do
17
+ ShopifyAPI::Base.site = 'https://foo:bar@www.zombo.com'
18
+ api_version = ShopifyAPI::ApiVersion.new(handle: '2019-07')
19
+
20
+ client = ShopifyAPI::GraphQL::HTTPClient.new(api_version)
21
+ expected_uri = URI('https://foo:bar@www.zombo.com/admin/api/2019-07/graphql.json')
22
+
23
+ assert_equal expected_uri, client.uri
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+ require_relative 'fixtures/graphql/dummy_schema'
4
+
5
+ class GraphQLTest < Test::Unit::TestCase
6
+ def setup
7
+ ShopifyAPI::ApiVersion.version_lookup_mode = :define_on_unknown
8
+ @fixture_location = Pathname('test/fixtures/graphql')
9
+ @site = 'https://this-is-my-test-shop.myshopify.com'
10
+ ShopifyAPI::Base.site = @site
11
+ end
12
+
13
+ def teardown
14
+ ShopifyAPI::GraphQL.clear_clients
15
+ end
16
+
17
+ test '#initialize_clients creates a GraphQL::Client from local schema file' do
18
+ version_fixtures('unstable') do |dir|
19
+ ShopifyAPI::GraphQL.initialize_clients
20
+
21
+ assert ShopifyAPI::GraphQL.client('unstable')
22
+ end
23
+ end
24
+
25
+ test '#initialize_clients handles multiple schema files' do
26
+ version_fixtures('unstable', '2019-10') do |dir|
27
+ ShopifyAPI::GraphQL.initialize_clients
28
+
29
+ assert ShopifyAPI::GraphQL.client('unstable')
30
+ assert ShopifyAPI::GraphQL.client('2019-10')
31
+ end
32
+ end
33
+
34
+ test '#initialize_clients ignores non JSON schema files' do
35
+ version_fixtures('unstable', '2019-10') do |dir|
36
+ FileUtils.touch(ShopifyAPI::GraphQL.schema_location.join('nope.txt'))
37
+
38
+ ShopifyAPI::GraphQL.initialize_clients
39
+
40
+ assert ShopifyAPI::GraphQL.client('unstable')
41
+ assert ShopifyAPI::GraphQL.client('2019-10')
42
+ end
43
+ end
44
+
45
+ test '#initialize_clients raises if a JSON schema file is not named after a version' do
46
+ version_fixtures do |dir|
47
+ ShopifyAPI::GraphQL.schema_location = dir
48
+ FileUtils.touch(ShopifyAPI::GraphQL.schema_location.join('nope.json'))
49
+
50
+ assert_raises ShopifyAPI::GraphQL::InvalidSchema do
51
+ ShopifyAPI::GraphQL.initialize_clients
52
+ end
53
+ end
54
+ end
55
+
56
+ test '#client returns default schema if only one exists' do
57
+ version_fixtures('unstable') do |dir|
58
+ ShopifyAPI::Base.api_version = 'unstable'
59
+
60
+ ShopifyAPI::GraphQL.initialize_clients
61
+
62
+ assert_instance_of ::GraphQL::Client, ShopifyAPI::GraphQL.client
63
+ end
64
+ end
65
+
66
+ test '#client accepts optional api_version parameter' do
67
+ version_fixtures('unstable') do |dir|
68
+ ShopifyAPI::Base.api_version = 'unstable'
69
+
70
+ ShopifyAPI::GraphQL.initialize_clients
71
+
72
+ assert_instance_of ::GraphQL::Client, ShopifyAPI::GraphQL.client('unstable')
73
+ end
74
+ end
75
+
76
+ test '#client executes queries on specified API version' do
77
+ version_fixtures('unstable', '2019-10') do |dir|
78
+ ShopifyAPI::Base.api_version = 'unstable'
79
+
80
+ ShopifyAPI::GraphQL.initialize_clients
81
+ ShopifyAPI::Base.site = 'https://this-is-my-test-shop.myshopify.com'
82
+
83
+ client = ShopifyAPI::GraphQL.client('2019-10')
84
+
85
+ assert_instance_of ::GraphQL::Client, client
86
+
87
+ query = client.parse <<~GRAPHQL
88
+ {
89
+ product {
90
+ name
91
+ }
92
+ }
93
+ GRAPHQL
94
+
95
+ path = ShopifyAPI::ApiVersion.new('2019-10').construct_graphql_path
96
+ stub_request(:post, "#{@site}#{path}").to_return(body: { product: { name: 'Shirt' } }.to_json)
97
+
98
+ client.query(query)
99
+ end
100
+ end
101
+
102
+ test '#client raises exception for version that does not exist' do
103
+ version_fixtures('unstable') do |dir|
104
+ ShopifyAPI::Base.api_version = '2019-10'
105
+
106
+ ShopifyAPI::GraphQL.initialize_clients
107
+
108
+ assert_raises ShopifyAPI::GraphQL::InvalidClient do
109
+ ShopifyAPI::GraphQL.client('2019-10')
110
+ end
111
+ end
112
+ end
113
+
114
+ test '#client lazily initializes clients' do
115
+ version_fixtures('unstable') do |dir|
116
+ ShopifyAPI::Base.api_version = 'unstable'
117
+
118
+ assert_raises ShopifyAPI::GraphQL::InvalidClient do
119
+ ShopifyAPI::GraphQL.client('2019-10')
120
+ end
121
+ end
122
+ end
123
+
124
+ test '#client caches lookups' do
125
+ version_fixtures('unstable') do |dir|
126
+ ShopifyAPI::Base.api_version = 'unstable'
127
+
128
+ client1 = ShopifyAPI::GraphQL.client
129
+ client2 = ShopifyAPI::GraphQL.client('unstable')
130
+
131
+ assert_equal client1, client2
132
+ end
133
+ end
134
+
135
+ private
136
+
137
+ def version_fixtures(*versions)
138
+ Dir.mktmpdir do |dir|
139
+ versions.each do |version|
140
+ FileUtils.cp(@fixture_location.join("#{version}.json"), dir)
141
+ end
142
+
143
+ ShopifyAPI::GraphQL.schema_location = dir
144
+ yield(dir)
145
+ end
146
+ end
147
+ end
data/test/order_test.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'test_helper'
2
+ require 'fulfillment_order_test_helper'
2
3
 
3
4
  class OrderTest < Test::Unit::TestCase
5
+ include FulfillmentOrderTestHelper
4
6
 
5
7
  test "create should create order" do
6
8
  fake 'orders', :method => :post, :status => 201, :body => load_fixture('order')
@@ -72,4 +74,52 @@ class OrderTest < Test::Unit::TestCase
72
74
  },
73
75
  }.to_json)
74
76
  end
77
+
78
+ test "fulfillment_orders should get fulfillment orders for an order with 2020-01 version" do
79
+ url_prefix = url_prefix_for_activated_session_for('2020-01')
80
+
81
+ fake(
82
+ 'orders',
83
+ url: "#{url_prefix}/orders/450789469.json",
84
+ method: :get,
85
+ status: 200,
86
+ body: load_fixture('order'),
87
+ extension: false
88
+ )
89
+ order = ShopifyAPI::Order.find(450789469)
90
+
91
+ fake(
92
+ 'orders',
93
+ url: "#{url_prefix}/orders/450789469/fulfillment_orders.json",
94
+ method: :get,
95
+ status: 200,
96
+ body: load_fixture('fulfillment_orders'),
97
+ extension: false
98
+ )
99
+ fulfillment_orders = order.fulfillment_orders
100
+
101
+ assert_equal [519788021, 519788022], fulfillment_orders.map(&:id).sort
102
+ fulfillment_orders.each do |fulfillment_order|
103
+ assert fulfillment_order.is_a?(ShopifyAPI::FulfillmentOrder)
104
+ assert_equal 450789469, fulfillment_order.order_id
105
+ end
106
+ end
107
+
108
+ test "fulfillment_orders raises NotImplementedError when api_version is older than 2020-01" do
109
+ url_prefix = url_prefix_for_activated_session_for('2019-10')
110
+
111
+ fake(
112
+ 'orders',
113
+ url: "#{url_prefix}/orders/450789469.json",
114
+ method: :get,
115
+ status: 200,
116
+ body: load_fixture('order'),
117
+ extension: false
118
+ )
119
+ order = ShopifyAPI::Order.find(450789469)
120
+
121
+ assert_raises NotImplementedError do
122
+ order.fulfillment_orders
123
+ end
124
+ end
75
125
  end