sucker 1.1.4 → 1.2.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.
- data/README.md +13 -19
- data/lib/sucker.rb +4 -4
- data/lib/sucker/parameters.rb +28 -0
- data/lib/sucker/request.rb +100 -88
- data/lib/sucker/response.rb +10 -0
- data/lib/sucker/version.rb +1 -1
- data/spec/fixtures/cassette_library/{unit → spec}/sucker/request.yml +4 -4
- data/spec/fixtures/cassette_library/spec/sucker/response.yml +26 -0
- data/spec/sucker/parameters_spec.rb +61 -0
- data/spec/sucker/request_spec.rb +276 -0
- data/spec/{unit/sucker → sucker}/response_spec.rb +39 -60
- data/spec/{unit/sucker_spec.rb → sucker_spec.rb} +0 -4
- data/spec/support/vcr.rb +0 -1
- metadata +69 -114
- data/spec/fixtures/cassette_library/integration/alternate_versions.yml +0 -26
- data/spec/fixtures/cassette_library/integration/errors.yml +0 -26
- data/spec/fixtures/cassette_library/integration/france.yml +0 -26
- data/spec/fixtures/cassette_library/integration/images.yml +0 -26
- data/spec/fixtures/cassette_library/integration/item_lookup/multiple.yml +0 -26
- data/spec/fixtures/cassette_library/integration/item_lookup/single.yml +0 -26
- data/spec/fixtures/cassette_library/integration/item_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/japan.yml +0 -26
- data/spec/fixtures/cassette_library/integration/keyword_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/kindle.yml +0 -26
- data/spec/fixtures/cassette_library/integration/kindle_2.yml +0 -26
- data/spec/fixtures/cassette_library/integration/multiple_locales.yml +0 -151
- data/spec/fixtures/cassette_library/integration/power_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/related_items/child.yml +0 -26
- data/spec/fixtures/cassette_library/integration/related_items/parent.yml +0 -26
- data/spec/fixtures/cassette_library/integration/seller_listings_search.yml +0 -26
- data/spec/fixtures/cassette_library/integration/twenty_items.yml +0 -26
- data/spec/fixtures/cassette_library/unit/sucker/response.yml +0 -26
- data/spec/integration/alternate_versions_spec.rb +0 -35
- data/spec/integration/errors_spec.rb +0 -40
- data/spec/integration/france_spec.rb +0 -42
- data/spec/integration/images_spec.rb +0 -41
- data/spec/integration/item_lookup_spec.rb +0 -71
- data/spec/integration/item_search_spec.rb +0 -41
- data/spec/integration/japan_spec.rb +0 -35
- data/spec/integration/keyword_search_spec.rb +0 -33
- data/spec/integration/kindle_spec.rb +0 -55
- data/spec/integration/multiple_locales_spec.rb +0 -70
- data/spec/integration/power_search_spec.rb +0 -41
- data/spec/integration/related_items_spec.rb +0 -53
- data/spec/integration/seller_listing_search_spec.rb +0 -32
- data/spec/integration/twenty_items_spec.rb +0 -49
- data/spec/unit/sucker/request_spec.rb +0 -282
| @@ -1,70 +0,0 @@ | |
| 1 | 
            -
            # encoding: utf-8
         | 
| 2 | 
            -
            require "spec_helper"
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            module Sucker
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              describe "Item lookup" do
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                use_vcr_cassette "integration/multiple_locales", :record => :new_episodes
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                context "when using Curl::Multi to search all locales simultaneously" do
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                  it "returns matches for all locales" do
         | 
| 13 | 
            -
                    worker = Sucker.new(
         | 
| 14 | 
            -
                      :key    => amazon["key"],
         | 
| 15 | 
            -
                      :secret => amazon["secret"])
         | 
| 16 | 
            -
                    worker << {
         | 
| 17 | 
            -
                      "Operation"     => "ItemLookup",
         | 
| 18 | 
            -
                      "IdType"        => "ASIN",
         | 
| 19 | 
            -
                      "ResponseGroup" => "ItemAttributes",
         | 
| 20 | 
            -
                      "ItemId"        => "0816614024" }
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                    bindings = worker.get_all.map do |response|
         | 
| 23 | 
            -
                      item = response.find("Item").first
         | 
| 24 | 
            -
                      item["ItemAttributes"]["Binding"]
         | 
| 25 | 
            -
                    end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                    bindings.uniq.should =~ %w{ Paperback Taschenbuch Broché ペーパーバック }
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                context "when using threads to search all locales simultaneously" do
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  # Use this approach to be able to throttle requests individually.
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                  it "returns matches for all locales" do
         | 
| 38 | 
            -
                    locales = %w{us uk de ca fr jp}
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                    params = {
         | 
| 41 | 
            -
                      "Operation"     => "ItemLookup",
         | 
| 42 | 
            -
                      "IdType"        => "ASIN",
         | 
| 43 | 
            -
                      "ResponseGroup" => "ItemAttributes",
         | 
| 44 | 
            -
                      "ItemId"        => "0816614024" }
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                    threads = locales.map do |locale|
         | 
| 47 | 
            -
                      Thread.new do
         | 
| 48 | 
            -
                        worker = Sucker.new(
         | 
| 49 | 
            -
                          :locale => locale,
         | 
| 50 | 
            -
                          :key    => amazon["key"],
         | 
| 51 | 
            -
                          :secret => amazon["secret"])
         | 
| 52 | 
            -
                        worker << params
         | 
| 53 | 
            -
                        Thread.current[:response] = worker.get
         | 
| 54 | 
            -
                      end
         | 
| 55 | 
            -
                    end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                    bindings = threads.map do |thread|
         | 
| 58 | 
            -
                      thread.join
         | 
| 59 | 
            -
                      item = thread[:response].find("Item").first
         | 
| 60 | 
            -
                      item["ItemAttributes"]["Binding"]
         | 
| 61 | 
            -
                    end
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                    bindings.uniq.should =~ %w{ Paperback Taschenbuch Broché ペーパーバック }
         | 
| 64 | 
            -
                  end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
              end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
            end
         | 
| @@ -1,41 +0,0 @@ | |
| 1 | 
            -
            require "spec_helper"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            # http://docs.amazonwebservices.com/AWSECommerceService/2010-09-01/DG/index.html?PowerSearchSyntax.html
         | 
| 4 | 
            -
            #
         | 
| 5 | 
            -
            # author: ambrose and binding: (abridged or large print) and pubdate: after 11-1996
         | 
| 6 | 
            -
            # subject: history and (Spain or Mexico) and not military and language: Spanish
         | 
| 7 | 
            -
            # (subject: marketing and author: kotler) or (publisher: harper and subject: "high technology")
         | 
| 8 | 
            -
            # keywords: "high tech*" and not fiction and pubdate: during 1999
         | 
| 9 | 
            -
            # isbn: 0446394319 or 0306806819 or 1567993850
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            module Sucker
         | 
| 12 | 
            -
             | 
| 13 | 
            -
              describe "Power search" do
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                use_vcr_cassette "integration/power_search", :record => :new_episodes
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                let(:worker) do
         | 
| 18 | 
            -
                  worker = Sucker.new(
         | 
| 19 | 
            -
                    :locale => "us",
         | 
| 20 | 
            -
                    :key    => amazon["key"],
         | 
| 21 | 
            -
                    :secret => amazon["secret"])
         | 
| 22 | 
            -
                  worker << {
         | 
| 23 | 
            -
                    "Operation"   => "ItemSearch",
         | 
| 24 | 
            -
                    "SearchIndex" => "Books",
         | 
| 25 | 
            -
                    "Power"       => "author:lacan or deleuze and not fiction",
         | 
| 26 | 
            -
                    "Sort"        => "relevancerank" }
         | 
| 27 | 
            -
                  worker
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                it "returns matches" do
         | 
| 31 | 
            -
                  items  = worker.get.find("Item")
         | 
| 32 | 
            -
                  items.size.should > 0
         | 
| 33 | 
            -
                  items.each do |item|
         | 
| 34 | 
            -
                    item["ItemAttributes"]["Title"].should_not be_nil
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
              end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
            end
         | 
| @@ -1,53 +0,0 @@ | |
| 1 | 
            -
            require "spec_helper"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Sucker
         | 
| 4 | 
            -
             | 
| 5 | 
            -
              describe "Item lookup" do
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                context "when response group includes related items" do
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                  let(:worker) do
         | 
| 10 | 
            -
                    worker = Sucker.new(
         | 
| 11 | 
            -
                      :locale => "us",
         | 
| 12 | 
            -
                      :key    => amazon["key"],
         | 
| 13 | 
            -
                      :secret => amazon["secret"])
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                    worker << {
         | 
| 16 | 
            -
                      "Operation"         => "ItemLookup",
         | 
| 17 | 
            -
                      "IdType"            => "ASIN",
         | 
| 18 | 
            -
                      "ResponseGroup"     => ["RelatedItems"],
         | 
| 19 | 
            -
                      "RelationshipType"  => "AuthorityTitle" }
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                    worker
         | 
| 22 | 
            -
                  end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  context "when item is a child" do
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                    use_vcr_cassette "integration/related_items/child", :record => :new_episodes
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                    it "finds parent and related items" do
         | 
| 29 | 
            -
                      worker << { "ItemId" => "0415246334" }
         | 
| 30 | 
            -
                      response = worker.get
         | 
| 31 | 
            -
                      response.find("RelatedItem").size.should eql 1
         | 
| 32 | 
            -
                      parent_asin = response.find("RelatedItem").first["Item"]["ASIN"]
         | 
| 33 | 
            -
                    end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                  context "when item is a parent" do
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                    use_vcr_cassette "integration/related_items/parent", :record => :new_episodes
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                    it "finds related items" do
         | 
| 42 | 
            -
                      worker << { "ItemId" => "B000ASPUES" }
         | 
| 43 | 
            -
                      response = worker.get
         | 
| 44 | 
            -
                      response.find("RelatedItem").size.should > 1
         | 
| 45 | 
            -
                    end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                  end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
              end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
            end
         | 
| @@ -1,32 +0,0 @@ | |
| 1 | 
            -
            require "spec_helper"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Sucker
         | 
| 4 | 
            -
              describe "Seller listing search" do
         | 
| 5 | 
            -
             | 
| 6 | 
            -
                use_vcr_cassette "integration/seller_listings_search", :record => :new_episodes
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                let(:listings) do
         | 
| 9 | 
            -
                  worker = Sucker.new(
         | 
| 10 | 
            -
                    :locale => "us",
         | 
| 11 | 
            -
                    :key    => amazon["key"],
         | 
| 12 | 
            -
                    :secret => amazon["secret"])
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  worker << {
         | 
| 15 | 
            -
                    "Operation"   => "SellerListingSearch",
         | 
| 16 | 
            -
                    "SellerId"    => "A2JYSO6W6KEP83" }
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                  worker.get.find("SellerListings").first
         | 
| 19 | 
            -
                end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                it "returns page count" do
         | 
| 22 | 
            -
                  listings["TotalPages"].to_i.should be > 0
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                it "returns listings" do
         | 
| 26 | 
            -
                  listings["SellerListing"].size.should be > 0
         | 
| 27 | 
            -
                  listings["SellerListing"].first.has_key?("Price").should be_true
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
              end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            end
         | 
| @@ -1,49 +0,0 @@ | |
| 1 | 
            -
            require "spec_helper"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Sucker
         | 
| 4 | 
            -
              describe "Item lookup" do
         | 
| 5 | 
            -
             | 
| 6 | 
            -
                context "when querying for twenty items" do
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                  use_vcr_cassette "integration/twenty_items", :record => :new_episodes
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  let(:asins) do
         | 
| 11 | 
            -
                    %w{
         | 
| 12 | 
            -
                      0816614024 0143105825 0485113600 0816616779 0942299078
         | 
| 13 | 
            -
                      0816614008 144006654X 0486400360 0486417670 087220474X
         | 
| 14 | 
            -
                      0486454398 0268018359 1604246014 184467598X 0312427182
         | 
| 15 | 
            -
                      1844674282 0745640974 0745646441 0826489540 1844672972 }
         | 
| 16 | 
            -
                  end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                  let(:items) do
         | 
| 19 | 
            -
                    worker = Sucker.new(
         | 
| 20 | 
            -
                      :locale => "us",
         | 
| 21 | 
            -
                      :key    => amazon["key"],
         | 
| 22 | 
            -
                      :secret => amazon["secret"])
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    # Prep worker
         | 
| 25 | 
            -
                    worker << {
         | 
| 26 | 
            -
                      "Operation"                       => "ItemLookup",
         | 
| 27 | 
            -
                      "ItemLookup.Shared.IdType"        => "ASIN",
         | 
| 28 | 
            -
                      "ItemLookup.Shared.Condition"     => "All",
         | 
| 29 | 
            -
                      "ItemLookup.Shared.MerchantId"    => "All",
         | 
| 30 | 
            -
                      "ItemLookup.Shared.ResponseGroup" => "OfferFull" }
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                    # Push twenty ASINs to worker
         | 
| 33 | 
            -
                    worker << {
         | 
| 34 | 
            -
                      "ItemLookup.1.ItemId" => asins[0, 10],
         | 
| 35 | 
            -
                      "ItemLookup.2.ItemId" => asins[10, 10] }
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                    worker.get.find("Item")
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                  it "returns all items" do
         | 
| 41 | 
            -
                    items.count.should eql 20
         | 
| 42 | 
            -
                    items.map { |item| item["ASIN"] }.should eql asins
         | 
| 43 | 
            -
                  end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
              end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
            end
         | 
| @@ -1,282 +0,0 @@ | |
| 1 | 
            -
            require "spec_helper"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Sucker
         | 
| 4 | 
            -
             | 
| 5 | 
            -
              describe Request do
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                use_vcr_cassette "unit/sucker/request", :record => :new_episodes
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                let(:worker) do
         | 
| 10 | 
            -
                  Sucker.new(
         | 
| 11 | 
            -
                    :locale => "us",
         | 
| 12 | 
            -
                    :key    => "key",
         | 
| 13 | 
            -
                    :secret => "secret")
         | 
| 14 | 
            -
                end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                describe ".new" do
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                  it "sets default parameters" do
         | 
| 19 | 
            -
                    default_parameters = {
         | 
| 20 | 
            -
                      "Service" => "AWSECommerceService",
         | 
| 21 | 
            -
                      "Version" => Sucker::CURRENT_AMAZON_API_VERSION }
         | 
| 22 | 
            -
                    worker.parameters.should include default_parameters
         | 
| 23 | 
            -
                  end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                describe "#<<" do
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  it "merges a hash into the parameters" do
         | 
| 30 | 
            -
                    worker << { "foo" => "bar" }
         | 
| 31 | 
            -
                    worker.parameters["foo"].should eql "bar"
         | 
| 32 | 
            -
                  end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                describe "#version=" do
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  it "sets the Amazon API version" do
         | 
| 39 | 
            -
                    worker.version = "foo"
         | 
| 40 | 
            -
                    worker.parameters["Version"].should eql "foo"
         | 
| 41 | 
            -
                  end
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                describe "#associate_tag" do
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                  it "returns the associate tag for the current locale" do
         | 
| 48 | 
            -
                    worker.instance_variable_set(:@associate_tags, { :us => 'foo-bar'})
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                    worker.associate_tag.should eql 'foo-bar'
         | 
| 51 | 
            -
                  end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                  it "returns nil if an associate tag is not set for the current locale" do
         | 
| 54 | 
            -
                    worker.associate_tag.should eql nil
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                describe "#associate_tag=" do
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  it "sets the associate tag for the current locale" do
         | 
| 62 | 
            -
                    worker.associate_tag = "foo-bar"
         | 
| 63 | 
            -
                    associate_tags = worker.instance_variable_get(:@associate_tags)
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                    associate_tags.keys.size.should eql 1
         | 
| 66 | 
            -
                    associate_tags[:us].should eql 'foo-bar'
         | 
| 67 | 
            -
                    worker.associate_tag.should eql 'foo-bar'
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                describe "#associate_tags=" do
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                  it "sets associate tags for the locales" do
         | 
| 75 | 
            -
                    tags = {
         | 
| 76 | 
            -
                      :us => 'foo',
         | 
| 77 | 
            -
                      :uk => 'bar',
         | 
| 78 | 
            -
                      :de => 'baz',
         | 
| 79 | 
            -
                      :ca => 'foo',
         | 
| 80 | 
            -
                      :fr => 'bar',
         | 
| 81 | 
            -
                      :jp => 'baz' }
         | 
| 82 | 
            -
                    worker.associate_tags = tags
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                    worker.instance_variable_get(:@associate_tags).should eql tags
         | 
| 85 | 
            -
                  end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                describe "#curl_opts" do
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                  it "returns options for curl" do
         | 
| 92 | 
            -
                    worker.curl_opts.should be_an_instance_of Hash
         | 
| 93 | 
            -
                  end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                  context "when given a block" do
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                    it "yields options for curl" do
         | 
| 98 | 
            -
                      worker.curl_opts { |c| c.interface = "eth1" }
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                      worker.curl_opts[:interface].should eql "eth1"
         | 
| 101 | 
            -
                    end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                  end
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                end
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                describe "#get" do
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                  it "returns a response" do
         | 
| 110 | 
            -
                    worker.get.class.ancestors.should include Response
         | 
| 111 | 
            -
                  end
         | 
| 112 | 
            -
             | 
| 113 | 
            -
                  it "raises an argument error if no key is provided" do
         | 
| 114 | 
            -
                    worker.key = nil
         | 
| 115 | 
            -
                    expect do
         | 
| 116 | 
            -
                      worker.get
         | 
| 117 | 
            -
                    end.to raise_error(/AWS access key missing/)
         | 
| 118 | 
            -
                  end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                  it "raises an argument error if no locale is provided" do
         | 
| 121 | 
            -
                    worker.locale = nil
         | 
| 122 | 
            -
                    expect do
         | 
| 123 | 
            -
                      worker.get
         | 
| 124 | 
            -
                    end.to raise_error(/Locale missing/)
         | 
| 125 | 
            -
                  end
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                  it "sets options on curl" do
         | 
| 128 | 
            -
                    easy = mock
         | 
| 129 | 
            -
                    easy.should_receive(:interface=).once.with("eth1")
         | 
| 130 | 
            -
                    Curl::Easy.stub!(:perform).and_yield(easy)
         | 
| 131 | 
            -
                    Response.should_receive(:new).once
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                    worker.curl_opts { |c| c.interface = 'eth1' }
         | 
| 134 | 
            -
                    worker.get
         | 
| 135 | 
            -
                  end
         | 
| 136 | 
            -
             | 
| 137 | 
            -
                end
         | 
| 138 | 
            -
             | 
| 139 | 
            -
                describe "#get_all" do
         | 
| 140 | 
            -
             | 
| 141 | 
            -
                  it "returns an array of responses" do
         | 
| 142 | 
            -
                    responses = worker.get_all
         | 
| 143 | 
            -
             | 
| 144 | 
            -
                    responses.should be_an_instance_of Array
         | 
| 145 | 
            -
                    responses.each { |resp| resp.should be_an_instance_of Response }
         | 
| 146 | 
            -
                  end
         | 
| 147 | 
            -
             | 
| 148 | 
            -
                  context "when given a block" do
         | 
| 149 | 
            -
             | 
| 150 | 
            -
                    it "yields responses" do
         | 
| 151 | 
            -
                      count = 0
         | 
| 152 | 
            -
                      worker.get_all do |resp|
         | 
| 153 | 
            -
                        resp.should be_an_instance_of Response
         | 
| 154 | 
            -
                        count += 1
         | 
| 155 | 
            -
                      end
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                      count.should eql Request::HOSTS.size
         | 
| 158 | 
            -
                    end
         | 
| 159 | 
            -
             | 
| 160 | 
            -
                  end
         | 
| 161 | 
            -
             | 
| 162 | 
            -
                end
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                describe "#key" do
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                  it "returns the Amazon AWS access key for the current locale" do
         | 
| 167 | 
            -
                    worker.instance_variable_set(:@keys, { :us => 'foo' })
         | 
| 168 | 
            -
             | 
| 169 | 
            -
                    worker.key.should eql 'foo'
         | 
| 170 | 
            -
                  end
         | 
| 171 | 
            -
             | 
| 172 | 
            -
                end
         | 
| 173 | 
            -
             | 
| 174 | 
            -
                describe "#key=" do
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                  it "sets a global Amazon AWS access key" do
         | 
| 177 | 
            -
                    worker.key = "foo"
         | 
| 178 | 
            -
                    keys = worker.instance_variable_get(:@keys)
         | 
| 179 | 
            -
             | 
| 180 | 
            -
                    keys.size.should eql Request::HOSTS.size
         | 
| 181 | 
            -
                    keys.values.uniq.should eql ["foo"]
         | 
| 182 | 
            -
                  end
         | 
| 183 | 
            -
             | 
| 184 | 
            -
                end
         | 
| 185 | 
            -
             | 
| 186 | 
            -
                describe "#keys=" do
         | 
| 187 | 
            -
             | 
| 188 | 
            -
                  it "sets distinct Amazon AWS access keys for the locales" do
         | 
| 189 | 
            -
                    keys = {
         | 
| 190 | 
            -
                      :us => 'foo',
         | 
| 191 | 
            -
                      :uk => 'bar',
         | 
| 192 | 
            -
                      :de => 'baz',
         | 
| 193 | 
            -
                      :ca => 'foo',
         | 
| 194 | 
            -
                      :fr => 'bar',
         | 
| 195 | 
            -
                      :jp => 'baz' }
         | 
| 196 | 
            -
                    worker.keys = keys
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                    worker.instance_variable_get(:@keys).should eql keys
         | 
| 199 | 
            -
                  end
         | 
| 200 | 
            -
             | 
| 201 | 
            -
                end
         | 
| 202 | 
            -
             | 
| 203 | 
            -
                context "private methods" do
         | 
| 204 | 
            -
             | 
| 205 | 
            -
                  describe "#build_query" do
         | 
| 206 | 
            -
             | 
| 207 | 
            -
                    let(:query) { worker.send(:build_query) }
         | 
| 208 | 
            -
             | 
| 209 | 
            -
                    it "canonicalizes parameters" do
         | 
| 210 | 
            -
                      query.should match /Service=([^&]+)&Timestamp=([^&]+)&Version=([^&]+)/
         | 
| 211 | 
            -
                    end
         | 
| 212 | 
            -
             | 
| 213 | 
            -
                    it "includes the key for the current locale" do
         | 
| 214 | 
            -
                      worker.instance_variable_set(:@keys, { :us => 'foo' })
         | 
| 215 | 
            -
                      query.should include 'AWSAccessKeyId=foo'
         | 
| 216 | 
            -
                    end
         | 
| 217 | 
            -
             | 
| 218 | 
            -
                    it "includes a timestamp" do
         | 
| 219 | 
            -
                      query.should include 'Timestamp='
         | 
| 220 | 
            -
                    end
         | 
| 221 | 
            -
             | 
| 222 | 
            -
                    it "sorts parameters" do
         | 
| 223 | 
            -
                      worker.parameters["AAA"] = "foo"
         | 
| 224 | 
            -
                      query.should match /^AAA=foo/
         | 
| 225 | 
            -
                    end
         | 
| 226 | 
            -
             | 
| 227 | 
            -
                    it "converts a parameter whose value is an array to a string" do
         | 
| 228 | 
            -
                      worker.parameters["Foo"] = ["bar", "baz"]
         | 
| 229 | 
            -
                      query.should match /Foo=bar%2Cbaz/
         | 
| 230 | 
            -
                    end
         | 
| 231 | 
            -
             | 
| 232 | 
            -
                    it "handles integer parameter values" do
         | 
| 233 | 
            -
                      worker.parameters["Foo"] = 1
         | 
| 234 | 
            -
                      query.should match /Foo=1/
         | 
| 235 | 
            -
                    end
         | 
| 236 | 
            -
             | 
| 237 | 
            -
                    it "handles floating-point parameter values" do
         | 
| 238 | 
            -
                      worker.parameters["Foo"] = 1.0
         | 
| 239 | 
            -
                      query.should match /Foo=1/
         | 
| 240 | 
            -
                    end
         | 
| 241 | 
            -
             | 
| 242 | 
            -
                  end
         | 
| 243 | 
            -
             | 
| 244 | 
            -
                  describe "#host" do
         | 
| 245 | 
            -
             | 
| 246 | 
            -
                    it "returns a host" do
         | 
| 247 | 
            -
                      worker.locale = "fr"
         | 
| 248 | 
            -
                      worker.send(:host).should eql "ecs.amazonaws.fr"
         | 
| 249 | 
            -
                    end
         | 
| 250 | 
            -
             | 
| 251 | 
            -
                  end
         | 
| 252 | 
            -
             | 
| 253 | 
            -
                  describe "#build_signed_query" do
         | 
| 254 | 
            -
             | 
| 255 | 
            -
                    it "returns a signed query string" do
         | 
| 256 | 
            -
                      query = worker.send :build_signed_query
         | 
| 257 | 
            -
                      query.should match /&Signature=.*/
         | 
| 258 | 
            -
                    end
         | 
| 259 | 
            -
             | 
| 260 | 
            -
                  end
         | 
| 261 | 
            -
             | 
| 262 | 
            -
                  describe "#timestamp" do
         | 
| 263 | 
            -
             | 
| 264 | 
            -
                    it "returns a timestamp" do
         | 
| 265 | 
            -
                      worker.send(:timestamp)["Timestamp"].should match /^\d+-\d+-\d+T\d+:\d+:\d+Z$/
         | 
| 266 | 
            -
                    end
         | 
| 267 | 
            -
             | 
| 268 | 
            -
                  end
         | 
| 269 | 
            -
             | 
| 270 | 
            -
                  describe "#uri" do
         | 
| 271 | 
            -
             | 
| 272 | 
            -
                    it "returns the URI with which to query Amazon" do
         | 
| 273 | 
            -
                      worker.send(:uri).should be_an_instance_of URI::HTTP
         | 
| 274 | 
            -
                    end
         | 
| 275 | 
            -
             | 
| 276 | 
            -
                  end
         | 
| 277 | 
            -
             | 
| 278 | 
            -
                end
         | 
| 279 | 
            -
             | 
| 280 | 
            -
              end
         | 
| 281 | 
            -
             | 
| 282 | 
            -
            end
         |