shopify_api 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/RELEASING CHANGED
@@ -1,7 +1,7 @@
1
1
  Releasing ShopifyAPI
2
2
 
3
3
  1. Check the Semantic Versioning page for info on how to version the new release: http://semver.org
4
- 2. Update the version of ShopifyAPI in shopify_api.gemspec
4
+ 2. Update the version of ShopifyAPI in lib/shopify_api/version.rb
5
5
  3. Add a CHANGELOG entry for the new release with the date
6
6
  4. Commit the changes with a commit message like "Packaging for release X.Y.Z"
7
7
  5. Tag the release with the version (Leave REV blank for HEAD or provide a SHA)
@@ -0,0 +1,14 @@
1
+ module ActiveResource
2
+ class Base
3
+ # Backported from ActiveResource master branch
4
+ def self.headers
5
+ @headers ||= {}
6
+
7
+ if superclass != Object && superclass.headers
8
+ @headers = superclass.headers.merge(@headers)
9
+ else
10
+ @headers
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/shopify_api.rb CHANGED
@@ -10,6 +10,7 @@ require 'shopify_api/limits'
10
10
  require 'shopify_api/json_format'
11
11
  require 'active_resource/json_errors'
12
12
  require 'active_resource/disable_prefix_check'
13
+ require 'active_resource/base_ext'
13
14
 
14
15
  module ShopifyAPI
15
16
  include Limits
@@ -25,6 +25,7 @@ module ShopifyAPI
25
25
  config = {'protocol' => 'https'}
26
26
  config['domain'] = ask("Domain? (leave blank for #{connection}.myshopify.com)")
27
27
  config['domain'] = "#{connection}.myshopify.com" if config['domain'].blank?
28
+ config['domain'] = "#{config['domain']}.myshopify.com" unless config['domain'].match(/[.:]/)
28
29
  puts "\nopen https://#{config['domain']}/admin/api in your browser to get API credentials\n"
29
30
  config['api_key'] = ask("API key?")
30
31
  config['password'] = ask("Password?")
@@ -5,6 +5,7 @@ require 'shopify_api/resources/article'
5
5
  require 'shopify_api/resources/asset'
6
6
  require 'shopify_api/resources/billing_address'
7
7
  require 'shopify_api/resources/blog'
8
+ require 'shopify_api/resources/cart'
8
9
  require 'shopify_api/resources/collect'
9
10
  require 'shopify_api/resources/comment'
10
11
  require 'shopify_api/resources/country'
@@ -1,7 +1,34 @@
1
+ require 'shopify_api/version'
2
+
1
3
  module ShopifyAPI
2
4
  class Base < ActiveResource::Base
3
5
  extend Countable
4
6
  self.include_root_in_json = false
7
+ self.headers['User-Agent'] = ["ShopifyAPI/#{ShopifyAPI::VERSION}",
8
+ "ActiveResource/#{ActiveResource::VERSION::STRING}",
9
+ "Ruby/#{RUBY_VERSION}"].join(' ')
10
+
11
+ class << self
12
+ def headers
13
+ if defined?(@headers)
14
+ @headers
15
+ elsif superclass != Object && superclass.headers
16
+ superclass.headers
17
+ else
18
+ @headers ||= {}
19
+ end
20
+ end
21
+
22
+ def activate_session(session)
23
+ self.site = session.site
24
+ self.headers.merge!('X-Shopify-Access-Token' => session.token)
25
+ end
26
+
27
+ def clear_session
28
+ self.site = nil
29
+ self.headers.delete('X-Shopify-Access-Token')
30
+ end
31
+ end
5
32
 
6
33
  private
7
34
  def only_id
@@ -0,0 +1,4 @@
1
+ module ShopifyAPI
2
+ class Cart < Base
3
+ end
4
+ end
@@ -1,84 +1,6 @@
1
+
1
2
  module ShopifyAPI
2
- #
3
- # The Shopify API authenticates each call via HTTP Authentication, using
4
- # * the application's API key as the username, and
5
- # * a hex digest of the application's shared secret and an
6
- # authentication token as the password.
7
- #
8
- # Generation & acquisition of the beforementioned looks like this:
9
- #
10
- # 0. Developer (that's you) registers Application (and provides a
11
- # callback url) and receives an API key and a shared secret
12
- #
13
- # 1. User visits Application and are told they need to authenticate the
14
- # application first for read/write permission to their data (needs to
15
- # happen only once). User is asked for their shop url.
16
- #
17
- # 2. Application redirects to Shopify : GET <user's shop url>/admin/api/auth?api_key=<API key>
18
- # (See Session#create_permission_url)
19
- #
20
- # 3. User logs-in to Shopify, approves application permission request
21
- #
22
- # 4. Shopify redirects to the Application's callback url (provided during
23
- # registration), including the shop's name, and an authentication token in the parameters:
24
- # GET client.com/customers?shop=snake-oil.myshopify.com&t=a94a110d86d2452eb3e2af4cfb8a3828
25
- #
26
- # 5. Authentication password computed using the shared secret and the
27
- # authentication token (see Session#computed_password)
28
- #
29
- # 6. Profit!
30
- # (API calls can now authenticate through HTTP using the API key, and
31
- # computed password)
32
- #
33
- # LoginController and ShopifyLoginProtection use the Session class to set Shopify::Base.site
34
- # so that all API calls are authorized transparently and end up just looking like this:
35
- #
36
- # # get 3 products
37
- # @products = ShopifyAPI::Product.find(:all, :params => {:limit => 3})
38
- #
39
- # # get latest 3 orders
40
- # @orders = ShopifyAPI::Order.find(:all, :params => {:limit => 3, :order => "created_at DESC" })
41
- #
42
- # As an example of what your LoginController should look like, take a look
43
- # at the following:
44
- #
45
- # class LoginController < ApplicationController
46
- # def index
47
- # # Ask user for their #{shop}.myshopify.com address
48
- # end
49
- #
50
- # def authenticate
51
- # redirect_to ShopifyAPI::Session.new(params[:shop]).create_permission_url
52
- # end
53
- #
54
- # # Shopify redirects the logged-in user back to this action along with
55
- # # the authorization token t.
56
- # #
57
- # # This token is later combined with the developer's shared secret to form
58
- # # the password used to call API methods.
59
- # def finalize
60
- # shopify_session = ShopifyAPI::Session.new(params[:shop], params[:t])
61
- # if shopify_session.valid?
62
- # session[:shopify] = shopify_session
63
- # flash[:notice] = "Logged in to shopify store."
64
- #
65
- # return_address = session[:return_to] || '/home'
66
- # session[:return_to] = nil
67
- # redirect_to return_address
68
- # else
69
- # flash[:error] = "Could not log in to Shopify store."
70
- # redirect_to :action => 'index'
71
- # end
72
- # end
73
- #
74
- # def logout
75
- # session[:shopify] = nil
76
- # flash[:notice] = "Successfully logged out."
77
- #
78
- # redirect_to :action => 'index'
79
- # end
80
- # end
81
- #
3
+
82
4
  class Session
83
5
  cattr_accessor :api_key
84
6
  cattr_accessor :secret
@@ -95,13 +17,18 @@ module ShopifyAPI
95
17
 
96
18
  def temp(domain, token, &block)
97
19
  session = new(domain, token)
20
+ begin
21
+ original_domain = URI.parse(ShopifyAPI::Base.site.to_s).host
22
+ rescue URI::InvalidURIError
23
+ end
24
+ original_token = ShopifyAPI::Base.headers['X-Shopify-Access-Token']
25
+ original_session = new(original_domain, original_token)
98
26
 
99
- original_site = ShopifyAPI::Base.site
100
27
  begin
101
- ShopifyAPI::Base.site = session.site
28
+ ShopifyAPI::Base.activate_session(session)
102
29
  yield
103
30
  ensure
104
- ShopifyAPI::Base.site = original_site
31
+ ShopifyAPI::Base.activate_session(original_session)
105
32
  end
106
33
  end
107
34
 
@@ -110,56 +37,38 @@ module ShopifyAPI
110
37
  url.gsub!(/https?:\/\//, '') # remove http:// or https://
111
38
  url.concat(".myshopify.com") unless url.include?('.') # extend url to myshopify.com if no host is given
112
39
  end
113
-
40
+
114
41
  def validate_signature(params)
115
42
  return false unless signature = params[:signature]
116
43
 
117
44
  sorted_params = params.except(:signature, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join
118
45
  Digest::MD5.hexdigest(secret + sorted_params) == signature
119
46
  end
120
-
47
+
121
48
  end
122
49
 
123
50
  def initialize(url, token = nil, params = nil)
124
51
  self.url, self.token = url, token
52
+ self.class.prepare_url(self.url)
125
53
 
126
54
  if params
127
55
  unless self.class.validate_signature(params) && params[:timestamp].to_i > 24.hours.ago.utc.to_i
128
56
  raise "Invalid Signature: Possible malicious login"
129
57
  end
130
58
  end
131
-
132
- self.class.prepare_url(self.url)
133
59
  end
134
60
 
135
61
  def shop
136
62
  Shop.current
137
63
  end
138
-
139
- def create_permission_url
140
- return nil if url.blank? || api_key.blank?
141
- "http://#{url}/admin/api/auth?api_key=#{api_key}"
142
- end
143
64
 
144
- # Used by ActiveResource::Base to make all non-authentication API calls
145
- #
146
- # (ShopifyAPI::Base.site set in ShopifyLoginProtection#shopify_session)
147
65
  def site
148
- "#{protocol}://#{api_key}:#{computed_password}@#{url}/admin"
66
+ "#{protocol}://#{url}/admin"
149
67
  end
150
68
 
151
69
  def valid?
152
70
  url.present? && token.present?
153
71
  end
154
-
155
- private
156
-
157
- # The secret is computed by taking the shared_secret which we got when
158
- # registring this third party application and concating the request_to it,
159
- # and then calculating a MD5 hexdigest.
160
- def computed_password
161
- Digest::MD5.hexdigest(secret + token.to_s)
162
- end
163
-
72
+
164
73
  end
165
74
  end
@@ -0,0 +1,3 @@
1
+ module ShopifyAPI
2
+ VERSION = "3.0.0"
3
+ end
data/shopify_api.gemspec CHANGED
@@ -1,8 +1,10 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "shopify_api/version"
2
4
 
3
5
  Gem::Specification.new do |s|
4
6
  s.name = %q{shopify_api}
5
- s.version = "2.3.0"
7
+ s.version = ShopifyAPI::VERSION
6
8
  s.author = "Shopify"
7
9
 
8
10
  s.summary = %q{The Shopify API gem is a lightweight gem for accessing the Shopify admin REST web services}
data/test/base_test.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+
4
+ class BaseTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @session1 = ShopifyAPI::Session.new('shop1.myshopify.com', 'token1')
8
+ @session2 = ShopifyAPI::Session.new('shop2.myshopify.com', 'token2')
9
+ end
10
+
11
+ test '#activate_session should set site and headers for given session' do
12
+ ShopifyAPI::Base.activate_session @session1
13
+
14
+ assert_nil ActiveResource::Base.site
15
+ assert_equal 'https://shop1.myshopify.com/admin', ShopifyAPI::Base.site.to_s
16
+ assert_equal 'https://shop1.myshopify.com/admin', ShopifyAPI::Shop.site.to_s
17
+
18
+ assert_nil ActiveResource::Base.headers['X-Shopify-Access-Token']
19
+ assert_equal 'token1', ShopifyAPI::Base.headers['X-Shopify-Access-Token']
20
+ assert_equal 'token1', ShopifyAPI::Shop.headers['X-Shopify-Access-Token']
21
+ end
22
+
23
+ test '#clear_session should clear site and headers from Base' do
24
+ ShopifyAPI::Base.activate_session @session1
25
+ ShopifyAPI::Base.clear_session
26
+
27
+ assert_nil ActiveResource::Base.site
28
+ assert_nil ShopifyAPI::Base.site
29
+ assert_nil ShopifyAPI::Shop.site
30
+
31
+ assert_nil ActiveResource::Base.headers['X-Shopify-Access-Token']
32
+ assert_nil ShopifyAPI::Base.headers['X-Shopify-Access-Token']
33
+ assert_nil ShopifyAPI::Shop.headers['X-Shopify-Access-Token']
34
+ end
35
+
36
+ test '#activate_session with one session, then clearing and activating with another session should send request to correct shop' do
37
+ ShopifyAPI::Base.activate_session @session1
38
+ ShopifyAPI::Base.clear_session
39
+ ShopifyAPI::Base.activate_session @session2
40
+
41
+ assert_nil ActiveResource::Base.site
42
+ assert_equal 'https://shop2.myshopify.com/admin', ShopifyAPI::Base.site.to_s
43
+ assert_equal 'https://shop2.myshopify.com/admin', ShopifyAPI::Shop.site.to_s
44
+
45
+ assert_nil ActiveResource::Base.headers['X-Shopify-Access-Token']
46
+ assert_equal 'token2', ShopifyAPI::Base.headers['X-Shopify-Access-Token']
47
+ assert_equal 'token2', ShopifyAPI::Shop.headers['X-Shopify-Access-Token']
48
+ end
49
+
50
+ end
data/test/cart_test.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'test_helper'
2
+
3
+ class CartTest < Test::Unit::TestCase
4
+ test 'all should return all carts' do
5
+ fake 'carts'
6
+ carts = ShopifyAPI::Cart.all
7
+ assert_equal carts.size, 2
8
+ assert_equal 2, carts.first.id
9
+ assert_equal "3eed8183d4281db6ea82ee2b8f23e9cc", carts.first.token
10
+ assert_equal 1, carts.first.line_items.size
11
+ assert_equal 'test', carts.first.line_items.first.title
12
+ end
13
+ end
@@ -7,6 +7,7 @@ class LogSubscriberTest < Test::Unit::TestCase
7
7
  def setup
8
8
  super
9
9
  @page = { :page => { :id => 1, :title => 'Shopify API' } }.to_json
10
+ @ua_header = "\"User-Agent\"=>\"ShopifyAPI/#{ShopifyAPI::VERSION} ActiveResource/#{ActiveResource::VERSION::STRING} Ruby/#{RUBY_VERSION}\""
10
11
 
11
12
  ShopifyAPI::Base.site = "http://localhost/admin"
12
13
 
@@ -26,7 +27,7 @@ class LogSubscriberTest < Test::Unit::TestCase
26
27
  assert_equal 4, @logger.logged(:info).size
27
28
  assert_equal "GET http://localhost:80/admin/pages/1.json", @logger.logged(:info)[0]
28
29
  assert_match /\-\-\> 200/, @logger.logged(:info)[1]
29
- assert_equal "Headers: {\"Accept\"=>\"application/json\"}", @logger.logged(:info)[2]
30
+ assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}}", @logger.logged(:info)[2]
30
31
  assert_match /Response:\n\{\"page\"\:\{((\"id\"\:1)|(\"title\"\:\"Shopify API\")),((\"id\"\:1)|(\"title\"\:\"Shopify API\"))\}\}/, @logger.logged(:info)[3]
31
32
 
32
33
  end
@@ -41,7 +42,7 @@ class LogSubscriberTest < Test::Unit::TestCase
41
42
  assert_equal 4, @logger.logged(:info).size
42
43
  assert_equal "GET http://localhost:80/admin/pages/2.json", @logger.logged(:info)[0]
43
44
  assert_match /\-\-\> 404/, @logger.logged(:info)[1]
44
- assert_equal "Headers: {\"Accept\"=>\"application/json\"}", @logger.logged(:info)[2]
45
+ assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}}", @logger.logged(:info)[2]
45
46
  assert_equal "Response:", @logger.logged(:info)[3]
46
47
  end
47
48
  end
@@ -0,0 +1,43 @@
1
+ {
2
+ "carts": [
3
+ {
4
+ "id": 2,
5
+ "note": null,
6
+ "token": "3eed8183d4281db6ea82ee2b8f23e9cc",
7
+ "updated_at": "2012-02-13T14:39:37-05:00",
8
+ "line_items":
9
+ [
10
+ {
11
+ "id": 1,
12
+ "title": "test",
13
+ "price": "1.00",
14
+ "line_price": "1.00",
15
+ "quantity": 1,
16
+ "sku": "",
17
+ "grams": 1000,
18
+ "vendor": "test",
19
+ "variant_id": 1
20
+ }
21
+ ]
22
+ },
23
+ {
24
+ "id": 1,
25
+ "note": "",
26
+ "token": "49801807939c296be1e9a4bf6783a705",
27
+ "updated_at": "2012-02-13T14:39:12-05:00",
28
+ "line_items":[
29
+ {
30
+ "id": 1,
31
+ "title": "test",
32
+ "price": "1.00",
33
+ "line_price": "1.00",
34
+ "quantity": 1,
35
+ "sku": "",
36
+ "grams": 1000,
37
+ "vendor": "test",
38
+ "variant_id": 1
39
+ }
40
+ ]
41
+ }
42
+ ]
43
+ }
data/test/session_test.rb CHANGED
@@ -23,7 +23,7 @@ class SessionTest < Test::Unit::TestCase
23
23
  session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
24
24
  end
25
25
  end
26
-
26
+
27
27
  should "raise error if params passed but signature omitted" do
28
28
  assert_raises(RuntimeError) do
29
29
  session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token", {'foo' => 'bar'})
@@ -41,25 +41,30 @@ class SessionTest < Test::Unit::TestCase
41
41
  end
42
42
 
43
43
  should "#temp reset ShopifyAPI::Base.site to original value" do
44
- ShopifyAPI::Base.site = 'http://www.original.com'
45
-
44
+
46
45
  ShopifyAPI::Session.setup(:api_key => "key", :secret => "secret")
47
- assigned_site = nil
46
+ session1 = ShopifyAPI::Session.new('fakeshop.myshopify.com', 'token1')
47
+ ShopifyAPI::Base.activate_session(session1)
48
+
48
49
  ShopifyAPI::Session.temp("testshop.myshopify.com", "any-token") {
49
- assigned_site = ShopifyAPI::Base.site
50
+ @assigned_site = ShopifyAPI::Base.site
50
51
  }
51
- assert_equal 'https://key:e56d5793b869753d87cf03ceb6bb5dfc@testshop.myshopify.com/admin', assigned_site.to_s
52
- assert_equal 'http://www.original.com', ShopifyAPI::Base.site.to_s
52
+ assert_equal 'https://testshop.myshopify.com/admin', @assigned_site.to_s
53
+ assert_equal 'https://fakeshop.myshopify.com/admin', ShopifyAPI::Base.site.to_s
53
54
  end
54
55
 
55
- should "return permissions url" do
56
+ should "return site for session" do
56
57
  session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
57
- assert_equal "http://testshop.myshopify.com/admin/api/auth?api_key=key", session.create_permission_url
58
+ assert_equal "https://testshop.myshopify.com/admin", session.site
58
59
  end
59
60
 
60
- should "return site for session" do
61
- session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
62
- assert_equal "https://key:e56d5793b869753d87cf03ceb6bb5dfc@testshop.myshopify.com/admin", session.site
61
+ should "raise error if signature does not match expected" do
62
+ ShopifyAPI::Session.secret = 'secret'
63
+ params = {:foo => 'hello', :foo => 'world', :timestamp => Time.now}
64
+ sorted_params = params.except(:signature, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join
65
+ signature = Digest::MD5.hexdigest(ShopifyAPI::Session.secret + sorted_params)
66
+
67
+ session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token", params.merge(:signature => signature))
63
68
  end
64
69
  end
65
70
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-13 00:00:00.000000000 Z
12
+ date: 2012-04-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activeresource
16
- requirement: &2152625980 !ruby/object:Gem::Requirement
16
+ requirement: &70215153027780 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2152625980
24
+ version_requirements: *70215153027780
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: thor
27
- requirement: &2152625260 !ruby/object:Gem::Requirement
27
+ requirement: &70215153026900 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.14.4
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2152625260
35
+ version_requirements: *70215153026900
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: mocha
38
- requirement: &2152624800 !ruby/object:Gem::Requirement
38
+ requirement: &70215153026040 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.8
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2152624800
46
+ version_requirements: *70215153026040
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: fakeweb
49
- requirement: &2152624420 !ruby/object:Gem::Requirement
49
+ requirement: &70215153062680 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2152624420
57
+ version_requirements: *70215153062680
58
58
  description: The Shopify API gem allows Ruby developers to programmatically access
59
59
  the admin section of Shopify stores. The API is implemented as JSON or XML over
60
60
  HTTP using all four verbs (GET/POST/PUT/DELETE). Each resource, like Order, Product,
@@ -76,6 +76,7 @@ files:
76
76
  - RELEASING
77
77
  - Rakefile
78
78
  - bin/shopify
79
+ - lib/active_resource/base_ext.rb
79
80
  - lib/active_resource/connection_ext.rb
80
81
  - lib/active_resource/detailed_log_subscriber.rb
81
82
  - lib/active_resource/disable_prefix_check.rb
@@ -95,6 +96,7 @@ files:
95
96
  - lib/shopify_api/resources/base.rb
96
97
  - lib/shopify_api/resources/billing_address.rb
97
98
  - lib/shopify_api/resources/blog.rb
99
+ - lib/shopify_api/resources/cart.rb
98
100
  - lib/shopify_api/resources/collect.rb
99
101
  - lib/shopify_api/resources/comment.rb
100
102
  - lib/shopify_api/resources/country.rb
@@ -129,14 +131,18 @@ files:
129
131
  - lib/shopify_api/resources/variant.rb
130
132
  - lib/shopify_api/resources/webhook.rb
131
133
  - lib/shopify_api/session.rb
134
+ - lib/shopify_api/version.rb
132
135
  - shopify_api.gemspec
133
136
  - test/asset_test.rb
137
+ - test/base_test.rb
134
138
  - test/blog_test.rb
139
+ - test/cart_test.rb
135
140
  - test/cli_test.rb
136
141
  - test/detailed_log_subscriber_test.rb
137
142
  - test/fixtures/asset.json
138
143
  - test/fixtures/assets.json
139
144
  - test/fixtures/blogs.json
145
+ - test/fixtures/carts.json
140
146
  - test/fixtures/events.json
141
147
  - test/fixtures/metafield.json
142
148
  - test/fixtures/metafields.json