require 'spec_helper' require 'contacts/google' describe Contacts::Google do before :each do @gmail = create end def create Contacts::Google.new('dummytoken') end after :each do FakeWeb.clean_registry end describe 'fetches contacts feed via HTTP GET' do it 'with defaults' do FakeWeb::register_uri(:get, 'www.google.com/m8/feeds/contacts/default/thin', :string => 'thin results', :verify => lambda { |req| req['Authorization'].should == %(AuthSub token="dummytoken") req['Accept-Encoding'].should == 'gzip' req['User-Agent'].should == "Ruby Contacts v#{Contacts::VERSION::STRING} (gzip)" } ) response = @gmail.get({}) response.body.should == 'thin results' end it 'with explicit user ID and full projection' do @gmail = Contacts::Google.new('dummytoken', 'person@example.com') @gmail.projection = 'full' FakeWeb::register_uri(:get, 'www.google.com/m8/feeds/contacts/person%40example.com/full', :string => 'full results' ) response = @gmail.get({}) response.body.should == 'full results' end end it 'handles a normal response body' do response = mock('HTTP response') @gmail.expects(:get).returns(response) response.expects(:'[]').with('Content-Encoding').returns(nil) response.expects(:body).returns('') @gmail.expects(:parse_contacts).with('') @gmail.contacts end it 'handles gzipped response' do response = mock('HTTP response') @gmail.expects(:get).returns(response) gzipped = StringIO.new gzwriter = Zlib::GzipWriter.new gzipped gzwriter.write(('a'..'z').to_a.join) gzwriter.close response.expects(:'[]').with('Content-Encoding').returns('gzip') response.expects(:body).returns gzipped.string @gmail.expects(:parse_contacts).with('abcdefghijklmnopqrstuvwxyz') @gmail.contacts end it 'raises a fetching error when something goes awry' do FakeWeb::register_uri(:get, 'www.google.com/m8/feeds/contacts/default/thin', :status => [404, 'YOU FAIL'] ) lambda { @gmail.get({}) }.should raise_error(Net::HTTPServerException) end it 'parses the resulting feed into name/email pairs' do @gmail.stubs(:get) @gmail.expects(:response_body).returns(sample_xml('google-single')) found = @gmail.contacts found.size.should == 1 contact = found.first contact.name.should == 'Fitzgerald' contact.emails.should == ['fubar@gmail.com'] end it 'parses a complex feed into name/email pairs' do @gmail.stubs(:get) @gmail.expects(:response_body).returns(sample_xml('google-many')) found = @gmail.contacts found.size.should == 3 found[0].name.should == 'Elizabeth Bennet' found[0].emails.should == ['liz@gmail.com', 'liz@example.org'] found[1].name.should == 'William Paginate' found[1].emails.should == ['will_paginate@googlegroups.com'] found[2].name.should be_nil found[2].emails.should == ['anonymous@example.com'] end it 'makes modification time available after parsing' do @gmail.updated_at.should be_nil @gmail.stubs(:get) @gmail.expects(:response_body).returns(sample_xml('google-single')) @gmail.contacts u = @gmail.updated_at u.year.should == 2008 u.day.should == 5 @gmail.updated_at_string.should == '2008-03-05T12:36:38.836Z' end describe 'GET query parameter handling' do before :each do @gmail = create @gmail.stubs(:response_body) @gmail.stubs(:parse_contacts) end it 'abstracts ugly parameters behind nicer ones' do expect_params 'max-results' => '25', 'orderby' => 'lastmodified', 'sortorder' => 'ascending', 'start-index' => '11', 'updated-min' => 'datetime' @gmail.contacts :limit => 25, :offset => 10, :order => 'lastmodified', :descending => false, :updated_after => 'datetime' end it 'should have implicit :descending with :order' do expect_params 'orderby' => 'lastmodified', 'sortorder' => 'descending', 'max-results' => '200' @gmail.contacts :order => 'lastmodified' end it 'should have default :limit of 200' do expect_params 'max-results' => '200' @gmail.contacts end it 'should skip nil values in parameters' do expect_params 'start-index' => '1' @gmail.contacts :limit => nil, :offset => 0 end def expect_params(params) query_string = Contacts::Google.query_string(params) FakeWeb::register_uri(:get, "www.google.com/m8/feeds/contacts/default/thin?#{query_string}") end end describe 'Retrieving all contacts (in chunks)' do before :each do @gmail = create end it 'should make only one API call when no more is needed' do @gmail.expects(:contacts).with(instance_of(Hash)).once.returns((0..8).to_a) @gmail.all_contacts({}, 10).should == (0..8).to_a end it 'should make multiple calls to :contacts when needed' do @gmail.expects(:contacts).with(has_entries(:offset => 0 , :limit => 10)).returns(( 0..9 ).to_a) @gmail.expects(:contacts).with(has_entries(:offset => 10, :limit => 10)).returns((10..19).to_a) @gmail.expects(:contacts).with(has_entries(:offset => 20, :limit => 10)).returns((20..24).to_a) @gmail.all_contacts({}, 10).should == (0..24).to_a end it 'should make one extra API call when not sure whether there are more contacts' do @gmail.expects(:contacts).with(has_entries(:offset => 0 , :limit => 10)).returns((0..9).to_a) @gmail.expects(:contacts).with(has_entries(:offset => 10, :limit => 10)).returns([]) @gmail.all_contacts({}, 10).should == (0..9).to_a end end end