Browse Source

Fix issues with resources that have both direct and namespaced routes

Add a number of tests
John Duff 13 years ago
parent
commit
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