소스 검색

Fix issues with resources that have both direct and namespaced routes

Add a number of tests
John Duff 13 년 전
부모
커밋
a53e18acc2

+ 8 - 0
lib/active_resource/disable_prefix_check.rb

@@ -0,0 +1,8 @@
+module DisablePrefixCheck
+  extend ActiveSupport::Concern
+
+  module ClassMethods
+    def check_prefix_options(options)
+    end
+  end
+end

+ 1 - 0
lib/shopify_api.rb

@@ -8,6 +8,7 @@ require 'active_resource/connection_ext'
 require 'shopify_api/limits'
 require 'shopify_api/json_format'
 require 'active_resource/json_errors'
+require 'active_resource/disable_prefix_check'
 
 module ShopifyAPI
   include Limits

+ 2 - 0
lib/shopify_api/resources/asset.rb

@@ -32,6 +32,8 @@ module ShopifyAPI
   #     the value will be copied:
   #       asset.source_key = "assets/another_image.png"
   class Asset < Base
+    include DisablePrefixCheck
+
     self.primary_key = 'key'
     self.prefix = "/admin/themes/:theme_id/"
     

+ 2 - 0
lib/shopify_api/resources/event.rb

@@ -1,5 +1,7 @@
 module ShopifyAPI
   class Event < Base
+    include DisablePrefixCheck
+
     self.prefix = "/admin/:resource/:resource_id/"
     
     # Hack to allow both Shop and other Events in through the same AR class

+ 2 - 0
lib/shopify_api/resources/metafield.rb

@@ -1,5 +1,7 @@
 module ShopifyAPI
   class Metafield < Base
+    include DisablePrefixCheck
+
     self.prefix = "/admin/:resource/:resource_id/"
     
     # Hack to allow both Shop and other Metafields in through the same AR class

+ 1 - 0
lib/shopify_api/resources/variant.rb

@@ -1,6 +1,7 @@
 module ShopifyAPI
   class Variant < Base
     include Metafields
+    include DisablePrefixCheck
 
     self.prefix = "/admin/products/:product_id/"
     

+ 2 - 0
shopify_api.gemspec

@@ -27,7 +27,9 @@ Gem::Specification.new do |s|
   
   if s.respond_to?(:add_development_dependency)
     s.add_development_dependency("mocha", ">= 0.9.8")
+    s.add_development_dependency("fakeweb")
   else
     s.add_dependency("mocha", ">= 0.9.8")
+    s.add_dependency("fakeweb")
   end
 end

+ 19 - 0
test/asset_test.rb

@@ -0,0 +1,19 @@
+require 'test_helper'
+require 'uri'
+
+class AssetTest < Test::Unit::TestCase
+  def test_get_assetss
+    fake "themes/1/assets", :method => :get, :body => load_fixture('assets')
+    v = ShopifyAPI::Asset.find(:all, :params => {:theme_id => 1})
+  end
+
+  def test_get_asset_namespaced
+    fake "themes/1/assets.json?asset%5Bkey%5D=templates%2Findex.liquid&theme_id=1", :extension=> false, :method => :get, :body => load_fixture('asset')
+    v = ShopifyAPI::Asset.find('templates/index.liquid', :params => {:theme_id => 1})
+  end
+
+  def test_get_asset
+    fake "assets.json?asset%5Bkey%5D=templates%2Findex.liquid", :extension=> false, :method => :get, :body => load_fixture('asset')
+    v = ShopifyAPI::Asset.find('templates/index.liquid')
+  end
+end

+ 9 - 0
test/fixtures/asset.json

@@ -0,0 +1,9 @@
+{
+  "asset": {
+    "created_at": "2010-07-12T15:31:50-04:00",
+    "updated_at": "2010-07-12T15:31:50-04:00",
+    "public_url": null,
+    "value": "<!-- LIST 3 PER ROW -->\n<h2>Featured Products</h2>\n<table id=\"products\" cellspacing=\"0\" cellpadding=\"0\">\n{% tablerow product in collections.frontpage.products cols:3  %}\n   <a href=\"{{product.url}}\">{{ product.featured_image | product_img_url: 'small' | img_tag }}</a>\n   <h3><a href=\"{{product.url}}\">{{product.title}}</a></h3>\n   <ul class=\"attributes\">\n     <li><span class=\"money\">{{product.price_min | money}}</span></li>\n   </ul>\n{% endtablerow %}\n</table>\n<!-- /LIST 3 PER ROW  -->\n\n  <div id=\"articles\">\n  \t{% assign article = pages.frontpage %}\n\n    <div class=\"article\">\n    {% if article.content != \"\" %}\n\t\t  <h3>{{ article.title }}</h3>\n      <div class=\"article-body textile\">\n  \t\t  {{ article.content }}\n  \t\t</div>\n  \t{% else %}\n      <div class=\"article-body textile\">\n  \t  In <em>Admin &gt; Blogs &amp; Pages</em>, create a page with the handle <strong><code>frontpage</code></strong> and it will show up here.<br />\n  \t  {{ \"Learn more about handles\" | link_to \"http://wiki.shopify.com/Handle\" }}\n      </div>\n  \t{% endif %}\n    </div>\n\n  </div>\n\n",
+    "key": "templates/index.liquid"
+  }
+}

+ 136 - 0
test/fixtures/assets.json

@@ -0,0 +1,136 @@
+{
+  "assets": [
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body-green.gif?1",
+      "key": "assets/bg-body-green.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body-orange.gif?1",
+      "key": "assets/bg-body-orange.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body-pink.gif?1",
+      "key": "assets/bg-body-pink.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body.gif?1",
+      "key": "assets/bg-body.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-content.gif?1",
+      "key": "assets/bg-content.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-footer.gif?1",
+      "key": "assets/bg-footer.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-main.gif?1",
+      "key": "assets/bg-main.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-sidebar.gif?1",
+      "key": "assets/bg-sidebar.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/shop.css?1",
+      "key": "assets/shop.css"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/shop.css.liquid?1",
+      "key": "assets/shop.css.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/shop.js?1",
+      "key": "assets/shop.js"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/sidebar-devider.gif?1",
+      "key": "assets/sidebar-devider.gif"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/sidebar-menu.jpg?1",
+      "key": "assets/sidebar-menu.jpg"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "config/settings.html"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "layout/theme.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "templates/article.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "templates/blog.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "templates/cart.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "templates/collection.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "templates/index.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "templates/page.liquid"
+    },
+    {
+      "created_at": "2010-07-12T15:31:50-04:00",
+      "updated_at": "2010-07-12T15:31:50-04:00",
+      "public_url": null,
+      "key": "templates/product.liquid"
+    }
+  ]
+}

+ 31 - 0
test/fixtures/events.json

@@ -0,0 +1,31 @@
+{
+  "events": [
+    {
+      "verb": "placed",
+      "created_at": "2008-01-10T11:00:00-05:00",
+      "body": null,
+      "subject_id": 450789469,
+      "id": 852065041,
+      "subject_type": "Order",
+      "message": "Order was placed"
+    },
+    {
+      "verb": "confirmed",
+      "created_at": "2008-01-10T11:00:00-05:00",
+      "body": null,
+      "subject_id": 450789469,
+      "id": 164748010,
+      "subject_type": "Order",
+      "message": "Received new order <a href=\"/admin/orders/show/450789469\">#1001</a> by Bob Norman"
+    },
+    {
+      "verb": "authorization_success",
+      "created_at": "2008-01-10T11:00:00-05:00",
+      "body": null,
+      "subject_id": 450789469,
+      "id": 103105390,
+      "subject_type": "Order",
+      "message": "<a href=\"/admin/orders/450789469/transactions/389404469\">The customer successfully authorized us to capture 210.94 USD</a>"
+    }
+  ]
+}

+ 12 - 0
test/fixtures/metafield.json

@@ -0,0 +1,12 @@
+{
+  "metafields": {
+    "created_at": "2011-10-20T14:05:13-04:00",
+    "updated_at": "2011-10-20T14:05:13-04:00",
+    "namespace": "contact",
+    "id": 721389482,
+    "value": "123@example.com",
+    "description": null,
+    "key": "email",
+    "value_type": "string"
+  }
+}

+ 24 - 0
test/fixtures/metafields.json

@@ -0,0 +1,24 @@
+{
+  "metafields": [
+    {
+      "created_at": "2011-10-20T14:05:13-04:00",
+      "updated_at": "2011-10-20T14:05:13-04:00",
+      "namespace": "affiliates",
+      "id": 721389482,
+      "value": "app_key",
+      "description": null,
+      "key": "app_key",
+      "value_type": "string"
+     },
+    {
+      "created_at": "2011-10-20T14:05:13-04:00",
+      "updated_at": "2011-10-20T14:05:13-04:00",
+      "namespace": "contact",
+      "id": 721389480,
+      "value": "1231231231",
+      "description": null,
+      "key": "phone",
+      "value_type": "string"
+    }
+  ]
+}

+ 112 - 0
test/fixtures/product.json

@@ -0,0 +1,112 @@
+{
+  "product": {
+    "product_type": "Cult Products",
+    "handle": "ipod-nano",
+    "created_at": "2011-10-20T14:05:13-04:00",
+    "body_html": "<p>It's the small iPod with one very big idea: Video. Now the world's most popular music player, available in 4GB and 8GB models, lets you enjoy TV shows, movies, video podcasts, and more. The larger, brighter display means amazing picture quality. In six eye-catching colors, iPod nano is stunning all around. And with models starting at just $149, little speaks volumes.</p>",
+    "title": "IPod Nano - 8GB",
+    "template_suffix": null,
+    "updated_at": "2011-10-20T14:05:13-04:00",
+    "id": 632910392,
+    "tags": "Emotive, Flash Memory, MP3, Music",
+    "images": [
+      {
+        "position": 1,
+        "created_at": "2011-10-20T14:05:13-04:00",
+        "product_id": 632910392,
+        "updated_at": "2011-10-20T14:05:13-04:00",
+        "src": "http://static.shopify.com/s/files/1/6909/3384/products/ipod-nano.png?0",
+        "id": 850703190
+      }
+    ],
+    "variants": [
+      {
+        "position": 1,
+        "price": "199.00",
+        "created_at": "2011-10-20T14:05:13-04:00",
+        "requires_shipping": true,
+        "title": "Pink",
+        "inventory_quantity": 10,
+        "compare_at_price": null,
+        "inventory_policy": "continue",
+        "updated_at": "2011-10-20T14:05:13-04:00",
+        "inventory_management": "shopify",
+        "id": 808950810,
+        "taxable": true,
+        "grams": 200,
+        "sku": "IPOD2008PINK",
+        "option1": "Pink",
+        "fulfillment_service": "manual",
+        "option2": null,
+        "option3": null
+      },
+      {
+        "position": 2,
+        "price": "199.00",
+        "created_at": "2011-10-20T14:05:13-04:00",
+        "requires_shipping": true,
+        "title": "Red",
+        "inventory_quantity": 20,
+        "compare_at_price": null,
+        "inventory_policy": "continue",
+        "updated_at": "2011-10-20T14:05:13-04:00",
+        "inventory_management": "shopify",
+        "id": 49148385,
+        "taxable": true,
+        "grams": 200,
+        "sku": "IPOD2008RED",
+        "option1": "Red",
+        "fulfillment_service": "manual",
+        "option2": null,
+        "option3": null
+      },
+      {
+        "position": 3,
+        "price": "199.00",
+        "created_at": "2011-10-20T14:05:13-04:00",
+        "requires_shipping": true,
+        "title": "Green",
+        "inventory_quantity": 30,
+        "compare_at_price": null,
+        "inventory_policy": "continue",
+        "updated_at": "2011-10-20T14:05:13-04:00",
+        "inventory_management": "shopify",
+        "id": 39072856,
+        "taxable": true,
+        "grams": 200,
+        "sku": "IPOD2008GREEN",
+        "option1": "Green",
+        "fulfillment_service": "manual",
+        "option2": null,
+        "option3": null
+      },
+      {
+        "position": 4,
+        "price": "199.00",
+        "created_at": "2011-10-20T14:05:13-04:00",
+        "requires_shipping": true,
+        "title": "Black",
+        "inventory_quantity": 40,
+        "compare_at_price": null,
+        "inventory_policy": "continue",
+        "updated_at": "2011-10-20T14:05:13-04:00",
+        "inventory_management": "shopify",
+        "id": 457924702,
+        "taxable": true,
+        "grams": 200,
+        "sku": "IPOD2008BLACK",
+        "option1": "Black",
+        "fulfillment_service": "manual",
+        "option2": null,
+        "option3": null
+      }
+    ],
+    "vendor": "Apple",
+    "published_at": "2007-12-31T19:00:00-05:00",
+    "options": [
+      {
+        "name": "Title"
+      }
+    ]
+  }
+}

+ 26 - 0
test/fixtures/shop.json

@@ -0,0 +1,26 @@
+{
+  "shop": {
+    "name": "Apple Computers",
+    "city": "Cupertino",
+    "address1": "1 Infinite Loop",
+    "zip": "95014",
+    "created_at": "2007-12-31T19:00:00-05:00",
+    "shop_owner": "Steve Jobs",
+    "plan_name": "enterprise",
+    "public": false,
+    "country": "US",
+    "money_with_currency_format": "$ {{amount}} USD",
+    "money_format": "$ {{amount}}",
+    "domain": "shop.apple.com",
+    "taxes_included": null,
+    "id": 690933842,
+    "timezone": "(GMT-05:00) Eastern Time (US & Canada)",
+    "tax_shipping": null,
+    "phone": null,
+    "currency": "USD",
+    "myshopify_domain": "apple.myshopify.com",
+    "source": null,
+    "province": "CA",
+    "email": "steve@apple.com"
+  }
+}

+ 22 - 0
test/fixtures/variant.json

@@ -0,0 +1,22 @@
+{
+  "variant": {
+    "price": "199.00",
+    "position": 1,
+    "created_at": "2011-10-20T14:05:13-04:00",
+    "title": "Pink",
+    "requires_shipping": true,
+    "updated_at": "2011-10-20T14:05:13-04:00",
+    "inventory_policy": "continue",
+    "compare_at_price": null,
+    "inventory_quantity": 10,
+    "inventory_management": "shopify",
+    "taxable": true,
+    "id": 808950810,
+    "grams": 200,
+    "sku": "IPOD2008PINK",
+    "option1": "Pink",
+    "option2": null,
+    "fulfillment_service": "manual",
+    "option3": null
+  }
+}

+ 84 - 0
test/fixtures/variants.json

@@ -0,0 +1,84 @@
+{
+  "variants": [
+    {
+      "price": "199.00",
+      "position": 1,
+      "created_at": "2011-10-20T14:05:13-04:00",
+      "title": "Pink",
+      "requires_shipping": true,
+      "updated_at": "2011-10-20T14:05:13-04:00",
+      "inventory_policy": "continue",
+      "compare_at_price": null,
+      "inventory_quantity": 10,
+      "inventory_management": "shopify",
+      "taxable": true,
+      "id": 808950810,
+      "grams": 200,
+      "sku": "IPOD2008PINK",
+      "option1": "Pink",
+      "option2": null,
+      "fulfillment_service": "manual",
+      "option3": null
+    },
+    {
+      "price": "199.00",
+      "position": 2,
+      "created_at": "2011-10-20T14:05:13-04:00",
+      "title": "Red",
+      "requires_shipping": true,
+      "updated_at": "2011-10-20T14:05:13-04:00",
+      "inventory_policy": "continue",
+      "compare_at_price": null,
+      "inventory_quantity": 20,
+      "inventory_management": "shopify",
+      "taxable": true,
+      "id": 49148385,
+      "grams": 200,
+      "sku": "IPOD2008RED",
+      "option1": "Red",
+      "option2": null,
+      "fulfillment_service": "manual",
+      "option3": null
+    },
+    {
+      "price": "199.00",
+      "position": 3,
+      "created_at": "2011-10-20T14:05:13-04:00",
+      "title": "Green",
+      "requires_shipping": true,
+      "updated_at": "2011-10-20T14:05:13-04:00",
+      "inventory_policy": "continue",
+      "compare_at_price": null,
+      "inventory_quantity": 30,
+      "inventory_management": "shopify",
+      "taxable": true,
+      "id": 39072856,
+      "grams": 200,
+      "sku": "IPOD2008GREEN",
+      "option1": "Green",
+      "option2": null,
+      "fulfillment_service": "manual",
+      "option3": null
+    },
+    {
+      "price": "199.00",
+      "position": 4,
+      "created_at": "2011-10-20T14:05:13-04:00",
+      "title": "Black",
+      "requires_shipping": true,
+      "updated_at": "2011-10-20T14:05:13-04:00",
+      "inventory_policy": "continue",
+      "compare_at_price": null,
+      "inventory_quantity": 40,
+      "inventory_management": "shopify",
+      "taxable": true,
+      "id": 457924702,
+      "grams": 200,
+      "sku": "IPOD2008BLACK",
+      "option1": "Black",
+      "option2": null,
+      "fulfillment_service": "manual",
+      "option3": null
+    }
+  ]
+}

+ 30 - 0
test/product_test.rb

@@ -0,0 +1,30 @@
+require 'test_helper'
+
+class ProductTest < Test::Unit::TestCase
+  def setup
+    super
+
+    fake "products/632910392", :body => load_fixture('product')
+    @product = ShopifyAPI::Product.find(632910392)
+  end
+
+  def test_add_metafields_to_product
+    fake "products/632910392/metafields", :method => :post, :status => 201, :body => load_fixture('metafield')
+
+    field = @product.add_metafield(ShopifyAPI::Metafield.new(:namespace => "contact", :key => "email", :value => "123@example.com", :value_type => "string"))
+
+    assert !field.new_record?
+    assert_equal "contact", field.namespace
+    assert_equal "email", field.key
+    assert_equal "123@example.com", field.value
+  end
+
+  def test_get_metafields_for_product
+    fake "products/632910392/metafields", :body => load_fixture('metafields')
+
+    metafields = @product.metafields
+
+    assert_equal 2, metafields.length
+    assert metafields.all?{|m| m.is_a?(ShopifyAPI::Metafield)}
+  end
+end

+ 10 - 0
test/session_test.rb

@@ -51,5 +51,15 @@ class SessionTest < Test::Unit::TestCase
       assert_equal 'https://key:e56d5793b869753d87cf03ceb6bb5dfc@testshop.myshopify.com/admin', assigned_site.to_s
       assert_equal 'http://www.original.com', ShopifyAPI::Base.site.to_s
     end
+
+    should "return permissions url" do
+      session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
+      assert_equal "http://testshop.myshopify.com/admin/api/auth?api_key=key", session.create_permission_url
+    end
+
+    should "return site for session" do
+      session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
+      assert_equal "https://key:e56d5793b869753d87cf03ceb6bb5dfc@testshop.myshopify.com/admin", session.site
+    end
   end
 end

+ 47 - 0
test/shop_test.rb

@@ -0,0 +1,47 @@
+require 'test_helper'
+
+class ShopTest < Test::Unit::TestCase
+  def setup
+    super
+    fake "shop"
+    @shop = ShopifyAPI::Shop.current
+  end
+
+  def test_current_should_return_current_shop
+    assert @shop.is_a?(ShopifyAPI::Shop)
+    assert_equal "Apple Computers", @shop.name
+    assert_equal "apple.myshopify.com", @shop.myshopify_domain
+    assert_equal 690933842, @shop.id
+    assert_equal "2007-12-31T19:00:00-05:00", @shop.created_at
+    assert_nil @shop.tax_shipping
+  end
+
+  def test_get_metafields_for_shop
+    fake "metafields"
+
+    metafields = @shop.metafields
+
+    assert_equal 2, metafields.length
+    assert metafields.all?{|m| m.is_a?(ShopifyAPI::Metafield)}
+  end
+
+  def test_add_metafield
+    fake "metafields", :method => :post, :status => 201, :body =>load_fixture('metafield')
+
+    field = @shop.add_metafield(ShopifyAPI::Metafield.new(:namespace => "contact", :key => "email", :value => "123@example.com", :value_type => "string"))
+
+    assert !field.new_record?
+    assert_equal "contact", field.namespace
+    assert_equal "email", field.key
+    assert_equal "123@example.com", field.value
+  end
+
+  def test_events
+    fake "events"
+
+    events = @shop.events
+
+    assert_equal 3, events.length
+    assert events.all?{|m| m.is_a?(ShopifyAPI::Event)}
+  end
+end

+ 33 - 2
test/test_helper.rb

@@ -1,13 +1,15 @@
 require 'rubygems'
 require 'test/unit'
+require 'fakeweb'
 require 'mocha'
 
 $LOAD_PATH.unshift(File.dirname(__FILE__))
 $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
 require 'shopify_api'
 
+FakeWeb.allow_net_connect = false
+
 # setup ShopifyAPI with fake api_key and secret
-ShopifyAPI::Session.setup(:api_key => "API Test key", :secret => "API Test secret")
 
 class Test::Unit::TestCase
   def self.test(string, &block)
@@ -21,9 +23,38 @@ class Test::Unit::TestCase
   def self.context(string)
     yield
   end
+
+  def setup
+    ActiveResource::Base.format = :json
+    ShopifyAPI.constants.each do |const|
+      begin
+        const = "ShopifyAPI::#{const}".constantize
+        const.format = :json if const.respond_to?(:format=)
+      rescue NameError
+      end
+    end
+
+    ShopifyAPI::Base.site = "http://localhost/admin"
+    ShopifyAPI::Base.password = nil
+    ShopifyAPI::Base.user = nil
+  end
   
   # Custom Assertions
   def assert_not(expression)
     assert_block("Expected <#{expression}> to be false!") { not expression }
-  end  
+  end
+
+  def load_fixture(name, format=:json)
+    File.read(File.dirname(__FILE__) + "/fixtures/#{name}.#{format}")
+  end
+
+  def fake(endpoint, options={})
+    body = options.delete(:body) || load_fixture(endpoint)
+    format = options.delete(:format) || :json
+    method = options.delete(:method) || :get
+    extension = ".#{options.delete(:extension)||'json'}" unless options[:extension]==false
+
+    url = "http://localhost/admin/#{endpoint}#{extension}"
+    FakeWeb.register_uri(method, url, {:body => body, :status => 200, :content_type => "text/#{format}", :content_length => 1}.merge(options))
+  end
 end

+ 22 - 0
test/variant_test.rb

@@ -0,0 +1,22 @@
+require 'test_helper'
+
+class VariantTest < Test::Unit::TestCase
+
+  def test_get_variants
+    fake "products/632910392/variants", :method => :get, :body => load_fixture('variants')
+
+    v = ShopifyAPI::Variant.find(:all, :params => {:product_id => 632910392})
+  end
+
+  def test_get_variant_namespaced
+    fake "products/632910392/variants/808950810", :method => :get, :body => load_fixture('variant')
+
+    v = ShopifyAPI::Variant.find(808950810)
+  end
+
+  def test_get_variant
+    fake "variants/808950810", :method => :get, :body => load_fixture('variant')
+
+    v = ShopifyAPI::Variant.find(808950810)
+  end
+end