bitsa 0.20 → 0.30
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.
- checksums.yaml +7 -0
- data/Gemfile.lock +26 -20
- data/HISTORY +11 -1
- data/README.rdoc +11 -2
- data/bin/bitsa +0 -1
- data/bitsa.gemspec +4 -4
- data/lib/bitsa.rb +24 -14
- data/lib/bitsa/args_processor.rb +7 -3
- data/lib/bitsa/contacts_cache.rb +8 -7
- data/lib/bitsa/gmail_contacts_loader.rb +19 -13
- data/lib/bitsa/settings.rb +8 -0
- data/lib/bitsa/version.rb +1 -1
- data/rvmrc +1 -0
- data/spec/helper.rb +5 -1
- data/spec/lib/bitsa/args_processor_spec.rb +123 -0
- data/spec/lib/bitsa/confg_file_spec.rb +34 -0
- data/spec/lib/bitsa/contacts_cache_spec.rb +331 -0
- data/spec/lib/bitsa/gmail_contacts_loader_spec.rb +203 -0
- data/spec/lib/bitsa/settings_spec.rb +50 -0
- data/spec/lib/bitsa_spec.rb +2 -0
- data/tasks/spec.rake +5 -5
- metadata +64 -46
- data/spec/args_processor_spec.rb +0 -66
- data/spec/confg_file_spec.rb +0 -32
- data/spec/contacts_cache_spec.rb +0 -294
- data/spec/gmail_contacts_loader_spec.rb +0 -89
- data/spec/settings_spec.rb +0 -34
@@ -0,0 +1,34 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
require "helper"
|
3
|
+
require "bitsa/config_file"
|
4
|
+
|
5
|
+
describe Bitsa::ConfigFile do
|
6
|
+
context "An existing configuration file should load from disk" do
|
7
|
+
let(:config) { Bitsa::ConfigFile.new("spec/data/config.yml")}
|
8
|
+
context :login do
|
9
|
+
specify { expect(config.data[:login]).to eq("test@gmail.com") }
|
10
|
+
end
|
11
|
+
context :password do
|
12
|
+
specify { expect(config.data[:password]).to eq("myPassword") }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "data from a non-existent configuration files" do
|
17
|
+
let(:config) { Bitsa::ConfigFile.new("/tmp/i-dont-exist") }
|
18
|
+
specify { expect(config.data).to eq({}) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "that I have no rights to" do
|
22
|
+
let(:tmp_file) {
|
23
|
+
tmp_file = Tempfile.open("cache")
|
24
|
+
FileUtils.cp("spec/data/config.yml", tmp_file.path)
|
25
|
+
FileUtils.chmod(0000, tmp_file.path)
|
26
|
+
tmp_file
|
27
|
+
}
|
28
|
+
|
29
|
+
context "reading" do
|
30
|
+
specify { expect { Bitsa::ConfigFile.new(tmp_file.path) }.to raise_error(Errno::EACCES) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,331 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "tempfile"
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
require "helper"
|
6
|
+
|
7
|
+
require "bitsa/contacts_cache"
|
8
|
+
|
9
|
+
def create_empty_temp_file
|
10
|
+
tmp_file = Tempfile.open("cache")
|
11
|
+
File.open(tmp_file.path, "w") do |f|
|
12
|
+
f.write('')
|
13
|
+
end
|
14
|
+
tmp_file
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_test_data
|
18
|
+
# 4 users, 5 email addresses
|
19
|
+
YAML::load_file("spec/data/bitsa_cache.yml")[1].values.flatten(1).sort
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_cache(last_modified = nil, lifespan_days = 1)
|
23
|
+
source_last_modified, addresses = YAML::load_file("spec/data/bitsa_cache.yml")
|
24
|
+
source_last_modified = last_modified.to_s if last_modified
|
25
|
+
|
26
|
+
tmp_file = Tempfile.open("cache")
|
27
|
+
File.open(tmp_file.path, "w") do |f|
|
28
|
+
f.write(YAML::dump([source_last_modified, addresses]))
|
29
|
+
end
|
30
|
+
[Bitsa::ContactsCache.new(tmp_file.path, lifespan_days), tmp_file]
|
31
|
+
end
|
32
|
+
|
33
|
+
RSpec.shared_examples_for "an empty cache" do |c|
|
34
|
+
specify { expect(c).not_to be_nil}
|
35
|
+
context :size do
|
36
|
+
specify { expect(c.size).to eq(0) }
|
37
|
+
end
|
38
|
+
context "last modified date" do
|
39
|
+
specify { expect(c.source_last_modified).to be_nil }
|
40
|
+
end
|
41
|
+
context :stale do
|
42
|
+
specify { expect(c.stale?).to be_truthy }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
RSpec.shared_examples "a full resultset" do |results|
|
47
|
+
specify "should return all entries" do
|
48
|
+
expect(results.size).to eq(5)
|
49
|
+
expect(results.flatten(0).sort).to eq(read_test_data)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe Bitsa::ContactsCache do
|
54
|
+
context "empty cache file" do
|
55
|
+
cache = Bitsa::ContactsCache.new(create_empty_temp_file.path, 1)
|
56
|
+
it_behaves_like "an empty cache", cache
|
57
|
+
end
|
58
|
+
|
59
|
+
context "cache file does not exist" do
|
60
|
+
cache = Bitsa::ContactsCache.new("/tmp/idonotexististhatoky", 1)
|
61
|
+
it_behaves_like "an empty cache", cache
|
62
|
+
end
|
63
|
+
|
64
|
+
context "user not authorised to read cache file" do
|
65
|
+
let(:tmp_file) do
|
66
|
+
tmp_file = create_empty_temp_file
|
67
|
+
FileUtils.chmod(0222, tmp_file.path)
|
68
|
+
tmp_file
|
69
|
+
end
|
70
|
+
|
71
|
+
specify {
|
72
|
+
expect {Bitsa::ContactsCache.new(tmp_file.path, 1)}.to raise_error(Errno::EACCES)
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
context "last updated today and lifespan is 1 day" do
|
77
|
+
context :stale do
|
78
|
+
specify {expect(create_cache(DateTime.now, 1)[0].stale?).to be_falsey}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "last updated yesterday and lifespan is 1 day" do
|
83
|
+
context :stale do
|
84
|
+
specify {expect(create_cache(DateTime.now-1, 1)[0].stale?).to be_truthy}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "last updated yesterday and lifespan is 2 days" do
|
89
|
+
context :stale do
|
90
|
+
specify {expect(create_cache(DateTime.now-1, 2)[0].stale?).to be_falsey}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "last updated 3 days ago and lifespan is 0 days" do
|
95
|
+
context :stale do
|
96
|
+
specify {expect(create_cache(DateTime.now-3, 0)[0].stale?).to be_falsey}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "last updated 3 days ago and lifespan is -1 days" do
|
101
|
+
context :stale do
|
102
|
+
specify {expect(create_cache(DateTime.now-3, -1)[0].stale?).to be_falsey}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "after clearing the cache" do
|
107
|
+
before(:each) do
|
108
|
+
expect(cache.size).to be >= 1
|
109
|
+
expect(cache.empty?).to be false
|
110
|
+
cache.clear!
|
111
|
+
end
|
112
|
+
let(:cache) { create_cache[0] }
|
113
|
+
|
114
|
+
context :size do
|
115
|
+
specify {expect(cache.size).to eq(0)}
|
116
|
+
end
|
117
|
+
|
118
|
+
context "empty?" do
|
119
|
+
specify {expect(cache.empty?).to be true}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "searching the test data" do
|
124
|
+
|
125
|
+
specify "should have read the correct number of contacts" do
|
126
|
+
expect(create_cache[0].size).to eq(4)
|
127
|
+
end
|
128
|
+
|
129
|
+
context "with an empty string" do
|
130
|
+
it_behaves_like "a full resultset", create_cache[0].search("")
|
131
|
+
end
|
132
|
+
|
133
|
+
context "with a nil string" do
|
134
|
+
it_behaves_like "a full resultset", create_cache[0].search(nil)
|
135
|
+
end
|
136
|
+
|
137
|
+
context "searching by start of email address" do
|
138
|
+
context "returning a single result" do
|
139
|
+
let(:expected) { [["test1@example.com", "My Tester"]] }
|
140
|
+
|
141
|
+
specify {expect(create_cache[0].search('test1')).to match_array expected}
|
142
|
+
end
|
143
|
+
|
144
|
+
context "returning multiple results" do
|
145
|
+
let(:expected) {
|
146
|
+
[["john_smith@here.org", ""],
|
147
|
+
["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]]
|
148
|
+
}
|
149
|
+
|
150
|
+
specify {expect(create_cache[0].search("jo")).to match_array expected}
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "searching by end of email address" do
|
155
|
+
let (:expected) {[["john_smith@here.org", ""]]}
|
156
|
+
|
157
|
+
specify {expect(create_cache[0].search('org')).to match_array expected}
|
158
|
+
end
|
159
|
+
|
160
|
+
context "searching by middle of email address" do
|
161
|
+
let (:expected) {[["john_smith@here.org", ""]]}
|
162
|
+
|
163
|
+
specify {expect(create_cache[0].search('n_s')).to match_array expected}
|
164
|
+
end
|
165
|
+
|
166
|
+
context "searching email using a different case to the actual data" do
|
167
|
+
let (:expected) {[["john_smith@here.org", ""]]}
|
168
|
+
|
169
|
+
specify {expect(create_cache[0].search('N_sMI')).to match_array expected}
|
170
|
+
end
|
171
|
+
|
172
|
+
context "searching by start of name" do
|
173
|
+
let(:expected) { [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]] }
|
174
|
+
|
175
|
+
specify {expect(create_cache[0].search('Joan Blo')).to match_array expected}
|
176
|
+
end
|
177
|
+
|
178
|
+
context "searching by end of name" do
|
179
|
+
let(:expected) { [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]] }
|
180
|
+
|
181
|
+
specify {expect(create_cache[0].search('ggshere')).to match_array expected}
|
182
|
+
end
|
183
|
+
|
184
|
+
context "searching by middle of name" do
|
185
|
+
let(:expected) { [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]] }
|
186
|
+
|
187
|
+
specify {expect(create_cache[0].search('n Bl')).to match_array expected}
|
188
|
+
end
|
189
|
+
|
190
|
+
context "searching by middle of name" do
|
191
|
+
let(:expected) { [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]] }
|
192
|
+
|
193
|
+
specify {expect(create_cache[0].search('n Bl')).to match_array expected}
|
194
|
+
end
|
195
|
+
|
196
|
+
context "searching name using a different case to the actual data" do
|
197
|
+
let(:expected) { [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]] }
|
198
|
+
|
199
|
+
specify {expect(create_cache[0].search('N BL')).to match_array expected}
|
200
|
+
end
|
201
|
+
|
202
|
+
context "search with no results" do
|
203
|
+
context :size do
|
204
|
+
specify {expect(create_cache[0].search('nothing is here').size).to eq(0)}
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "search on one contact with two email addresses" do
|
209
|
+
let(:expected) {
|
210
|
+
[["email2@somewhere.com", "Mr Multiple"], ["email1@somewhere.com", "Mr Multiple"]]
|
211
|
+
}
|
212
|
+
|
213
|
+
specify {expect(create_cache[0].search('multip')).to match_array expected}
|
214
|
+
end
|
215
|
+
|
216
|
+
context "searching a contact with multiple email addresses where only 1 email address matches" do
|
217
|
+
let(:expected) {[["email1@somewhere.com", "Mr Multiple"]]}
|
218
|
+
|
219
|
+
specify {expect(create_cache[0].search('email1')).to match_array expected}
|
220
|
+
end
|
221
|
+
|
222
|
+
context "find by ID" do
|
223
|
+
let(:id) {"http://www.google.com/m8/feeds/contacts/person%40example.org/base/685e301a549c176e"}
|
224
|
+
let(:expected) {[["email1@somewhere.com", "Mr Multiple"],
|
225
|
+
["email2@somewhere.com", "Mr Multiple"]]}
|
226
|
+
|
227
|
+
specify {expect(create_cache[0].get(id)).to match_array expected}
|
228
|
+
end
|
229
|
+
|
230
|
+
context "find by a non-existent ID" do
|
231
|
+
let(:id) {"http://www.google.com/m8/feeds/contacts/person%40example.org/base/4783783783"}
|
232
|
+
|
233
|
+
specify {expect(create_cache[0].get(id)).to be_nil}
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context "updating the test data" do
|
238
|
+
let(:cache) { create_cache[0] }
|
239
|
+
let(:id) {"http://www.google.com/m8/feeds/contacts/person%40example.org/base/637e301a549c176e"}
|
240
|
+
|
241
|
+
specify "should change the data" do
|
242
|
+
expect(cache.get(id)).to match_array [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]]
|
243
|
+
cache.update(id, "Tammy Smith", ["tammy5@example.com"])
|
244
|
+
expect(cache.get(id)).to match_array [["tammy5@example.com", "Tammy Smith"]]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context "updating with two email addresses" do
|
249
|
+
let(:cache) { create_cache[0] }
|
250
|
+
let(:id) {"http://www.google.com/m8/feeds/contacts/person%40example.org/base/637e301a549c176e"}
|
251
|
+
|
252
|
+
specify "should update the data" do
|
253
|
+
expected = [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]]
|
254
|
+
expect(cache.get(id)).to match_array expected
|
255
|
+
|
256
|
+
cache.update(id, "Tammy Smith", ["tammy5@example.com", "smithtammy@exampel.org"])
|
257
|
+
|
258
|
+
expected = [["smithtammy@exampel.org", "Tammy Smith"], ["tammy5@example.com", "Tammy Smith"]]
|
259
|
+
expect(cache.get(id)).to match_array expected
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context "deleting a non-existent entry" do
|
264
|
+
let(:cache) { create_cache[0] }
|
265
|
+
|
266
|
+
specify "should return nil" do
|
267
|
+
expect(cache.delete("NONEXISTENT")).to be_nil
|
268
|
+
end
|
269
|
+
|
270
|
+
specify do
|
271
|
+
expect {
|
272
|
+
cache.delete("NONEXISTENT")
|
273
|
+
}.to_not change(cache, :size)
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|
277
|
+
|
278
|
+
context "deleting an existing entry" do
|
279
|
+
let(:cache) { create_cache[0] }
|
280
|
+
let(:id) { "http://www.google.com/m8/feeds/contacts/person%40example.org/base/637e301a549c176e" }
|
281
|
+
|
282
|
+
specify {expect { cache.delete(id) }.to change(cache, :size).by(-1)}
|
283
|
+
|
284
|
+
specify "should return the deleted entry" do
|
285
|
+
expect(cache.delete(id)).to match_array [["Joan.bloggs@somewhere.com.au", "Joan Bloggshere"]]
|
286
|
+
end
|
287
|
+
|
288
|
+
context "the cache" do
|
289
|
+
specify "should no longer contain the deleted entry" do
|
290
|
+
cache.delete(id)
|
291
|
+
expect(cache.get(id)).to be_nil
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
context "saving" do
|
297
|
+
let(:data) { create_cache }
|
298
|
+
let(:cache) { data[0] }
|
299
|
+
let(:cache_file) { data[1] }
|
300
|
+
|
301
|
+
context "changes to existing contacts" do
|
302
|
+
specify {
|
303
|
+
id = "http://www.google.com/m8/feeds/contacts/person%40example.org/base/637e301a549c176e"
|
304
|
+
cache.update(id, "The Changed Name", ["change1@somewhere.org"])
|
305
|
+
cache.save
|
306
|
+
new_cache = Bitsa::ContactsCache.new(cache_file.path, 1)
|
307
|
+
expected = [["change1@somewhere.org", "The Changed Name"]]
|
308
|
+
expect(new_cache.get(id)).to match_array expected
|
309
|
+
}
|
310
|
+
end
|
311
|
+
|
312
|
+
context "adding new entries" do
|
313
|
+
specify {
|
314
|
+
id = "NONEXISTENT"
|
315
|
+
cache.update(id, "The Changed Name", ["change1@somewhere.org"])
|
316
|
+
cache.save
|
317
|
+
new_cache = Bitsa::ContactsCache.new(cache_file.path, 1)
|
318
|
+
expected = [["change1@somewhere.org", "The Changed Name"]]
|
319
|
+
expect(new_cache.get(id)).to match_array expected
|
320
|
+
}
|
321
|
+
end
|
322
|
+
|
323
|
+
context "to a file that I have no write rights to" do
|
324
|
+
before(:each) { FileUtils.chmod(0444, cache_file.path) }
|
325
|
+
|
326
|
+
specify { expect { cache.save }.to raise_error(Errno::EACCES) }
|
327
|
+
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
require 'fakeweb'
|
4
|
+
|
5
|
+
require "bitsa/contacts_cache"
|
6
|
+
require "bitsa/gmail_contacts_loader"
|
7
|
+
|
8
|
+
describe Bitsa::GmailContactsLoader do
|
9
|
+
context "Bitsa::GmailContactsLoader" do
|
10
|
+
before(:each) do
|
11
|
+
FakeWeb.allow_net_connect = false
|
12
|
+
|
13
|
+
# Start session.
|
14
|
+
FakeWeb.register_uri(:post, "https://www.google.com/accounts/ClientLogin",
|
15
|
+
:body => "SID=DQAAAGgA...7Zg8CTN\nLSID=DQAAAGsA...lk8BBbG\nAuth=DQAAAGgA...dk3fA5N")
|
16
|
+
|
17
|
+
# First chunk of contacts
|
18
|
+
FakeWeb.register_uri(:get, "https://www.google.com/m8/feeds/contacts/test/thin?orderby=lastmodified&showdeleted=true&max-results=15&start-index=1",
|
19
|
+
:body => <<eos
|
20
|
+
<feed gd:etag='W/"AkANQXo7eCp7ImA9WxFTGUo."' xmlns:gContact='http://schemas.google.com/contact/2008' xmlns:gd='http://schemas.google.com/g/2005' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns='http://www.w3.org/2005/Atom'>
|
21
|
+
<id>
|
22
|
+
somebody@example.com
|
23
|
+
</id>
|
24
|
+
<updated>
|
25
|
+
2010-04-11T09:39:50.400Z
|
26
|
+
</updated>
|
27
|
+
<category term='http://schemas.google.com/contact/2008#contact' scheme='http://schemas.google.com/g/2005#kind'/>
|
28
|
+
<title>
|
29
|
+
Somebodys's Contacts
|
30
|
+
</title>
|
31
|
+
<link href='http://www.google.com/' rel='alternate' type='text/html'/>
|
32
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin' rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'/>
|
33
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin' rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'/>
|
34
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin/batch' rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml'/>
|
35
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin?max-results=15' rel='self' type='application/atom+xml'/>
|
36
|
+
<author>
|
37
|
+
<name>
|
38
|
+
Somebody
|
39
|
+
</name>
|
40
|
+
<email>
|
41
|
+
somebody@example.com
|
42
|
+
</email>
|
43
|
+
</author>
|
44
|
+
<generator uri='http://www.google.com/m8/feeds' version='1.0'>
|
45
|
+
Contacts
|
46
|
+
</generator>
|
47
|
+
<openSearch:totalResults>
|
48
|
+
1
|
49
|
+
</openSearch:totalResults>
|
50
|
+
<openSearch:startIndex>
|
51
|
+
1
|
52
|
+
</openSearch:startIndex>
|
53
|
+
<openSearch:itemsPerPage>
|
54
|
+
15
|
55
|
+
</openSearch:itemsPerPage>
|
56
|
+
<entry gd:etag='"SHc-fTVSLyp7ImA9WxBaEkwIQAU."'>
|
57
|
+
<id>
|
58
|
+
http://www.google.com/m8/feeds/contacts/somebody%40example.com/base/0
|
59
|
+
</id>
|
60
|
+
<updated>
|
61
|
+
2010-03-21T23:05:19.955Z
|
62
|
+
</updated>
|
63
|
+
<app:edited xmlns:app='http://www.w3.org/2007/app'>
|
64
|
+
2010-03-21T23:05:19.955Z
|
65
|
+
</app:edited>
|
66
|
+
<category term='http://schemas.google.com/contact/2008#contact' scheme='http://schemas.google.com/g/2005#kind'/>
|
67
|
+
<title>
|
68
|
+
Jpe Bloggs
|
69
|
+
</title>
|
70
|
+
<link href='http://www.google.com/m8/feeds/photos/media/somebody%40example.com/0' gd:etag='"bwR-YldFbCp7ImBIGHMMbBALQAwWIFMBVVc."' rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/*'/>
|
71
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin/0' rel='self' type='application/atom+xml'/>
|
72
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin/0' rel='edit' type='application/atom+xml'/>
|
73
|
+
<gd:email address='jbloggs@example.com' rel='http://schemas.google.com/g/2005#other' primary='true'/>
|
74
|
+
<gd:email address='another@example.com' rel='http://schemas.google.com/g/2005#work'/>
|
75
|
+
<gContact:groupMembershipInfo href='http://www.google.com/m8/feeds/groups/somebody%40example.com/base/6' deleted='false'/>
|
76
|
+
</entry>
|
77
|
+
</feed>
|
78
|
+
eos
|
79
|
+
)
|
80
|
+
|
81
|
+
# Second chunk of contacts
|
82
|
+
FakeWeb.register_uri(:get, "https://www.google.com/m8/feeds/contacts/test/thin?orderby=lastmodified&showdeleted=true&max-results=15&start-index=16",
|
83
|
+
:body => <<eos
|
84
|
+
<feed gd:etag='W/"AkANQXo7eCp7ImA9WxFTGUo."' xmlns:gContact='http://schemas.google.com/contact/2008' xmlns:gd='http://schemas.google.com/g/2005' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns='http://www.w3.org/2005/Atom'>
|
85
|
+
<id>
|
86
|
+
somebody@example.com
|
87
|
+
</id>
|
88
|
+
<updated>
|
89
|
+
2010-04-11T09:39:50.400Z
|
90
|
+
</updated>
|
91
|
+
<category term='http://schemas.google.com/contact/2008#contact' scheme='http://schemas.google.com/g/2005#kind'/>
|
92
|
+
<title>
|
93
|
+
Somebodys's Contacts
|
94
|
+
</title>
|
95
|
+
<link href='http://www.google.com/' rel='alternate' type='text/html'/>
|
96
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin' rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'/>
|
97
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin' rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'/>
|
98
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin/batch' rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml'/>
|
99
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin?max-results=15' rel='self' type='application/atom+xml'/>
|
100
|
+
<author>
|
101
|
+
<name>
|
102
|
+
Somebody
|
103
|
+
</name>
|
104
|
+
<email>
|
105
|
+
somebody@example.com
|
106
|
+
</email>
|
107
|
+
</author>
|
108
|
+
<generator uri='http://www.google.com/m8/feeds' version='1.0'>
|
109
|
+
Contacts
|
110
|
+
</generator>
|
111
|
+
<openSearch:totalResults>
|
112
|
+
1
|
113
|
+
</openSearch:totalResults>
|
114
|
+
<openSearch:startIndex>
|
115
|
+
1
|
116
|
+
</openSearch:startIndex>
|
117
|
+
<openSearch:itemsPerPage>
|
118
|
+
15
|
119
|
+
</openSearch:itemsPerPage>
|
120
|
+
<entry gd:etag='"SHc-fTVSLyp7ImA9WxBaEkwIQAU."'>
|
121
|
+
<id>
|
122
|
+
http://www.google.com/m8/feeds/contacts/somebody%40example.com/base/0
|
123
|
+
</id>
|
124
|
+
<gd:deleted/>
|
125
|
+
<updated>
|
126
|
+
2010-03-21T23:05:19.955Z
|
127
|
+
</updated>
|
128
|
+
<app:edited xmlns:app='http://www.w3.org/2007/app'>
|
129
|
+
2010-03-21T23:05:19.955Z
|
130
|
+
</app:edited>
|
131
|
+
<category term='http://schemas.google.com/contact/2008#contact' scheme='http://schemas.google.com/g/2005#kind'/>
|
132
|
+
<title>
|
133
|
+
Jpe Bloggs
|
134
|
+
</title>
|
135
|
+
<link href='http://www.google.com/m8/feeds/photos/media/somebody%40example.com/0' gd:etag='"bwR-YldFbCp7ImBIGHMMbBALQAwWIFMBVVc."' rel='http://schemas.google.com/contacts/2008/rel#photo' type='image/*'/>
|
136
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin/0' rel='self' type='application/atom+xml'/>
|
137
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin/0' rel='edit' type='application/atom+xml'/>
|
138
|
+
<gd:email address='jbloggs@example.com' rel='http://schemas.google.com/g/2005#other' primary='true'/>
|
139
|
+
<gd:email address='another@example.com' rel='http://schemas.google.com/g/2005#work'/>
|
140
|
+
<gContact:groupMembershipInfo href='http://www.google.com/m8/feeds/groups/somebody%40example.com/base/6' deleted='false'/>
|
141
|
+
</entry>
|
142
|
+
</feed>
|
143
|
+
eos
|
144
|
+
)
|
145
|
+
|
146
|
+
# Third chunk - empty
|
147
|
+
FakeWeb.register_uri(:get, "https://www.google.com/m8/feeds/contacts/test/thin?orderby=lastmodified&showdeleted=true&max-results=15&start-index=31",
|
148
|
+
:body => <<eos
|
149
|
+
<feed gd:etag='W/"AkANQXo7eCp7ImA9WxFTGUo."' xmlns:gContact='http://schemas.google.com/contact/2008' xmlns:gd='http://schemas.google.com/g/2005' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns='http://www.w3.org/2005/Atom'>
|
150
|
+
<id>
|
151
|
+
somebody@example.com
|
152
|
+
</id>
|
153
|
+
<updated>
|
154
|
+
2010-04-11T09:39:50.400Z
|
155
|
+
</updated>
|
156
|
+
<category term='http://schemas.google.com/contact/2008#contact' scheme='http://schemas.google.com/g/2005#kind'/>
|
157
|
+
<title>
|
158
|
+
Somebodys's Contacts
|
159
|
+
</title>
|
160
|
+
<link href='http://www.google.com/' rel='alternate' type='text/html'/>
|
161
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin' rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml'/>
|
162
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin' rel='http://schemas.google.com/g/2005#post' type='application/atom+xml'/>
|
163
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin/batch' rel='http://schemas.google.com/g/2005#batch' type='application/atom+xml'/>
|
164
|
+
<link href='http://www.google.com/m8/feeds/contacts/somebody%40example.com/thin?max-results=15' rel='self' type='application/atom+xml'/>
|
165
|
+
<author>
|
166
|
+
<name>
|
167
|
+
Somebody
|
168
|
+
</name>
|
169
|
+
<email>
|
170
|
+
somebody@example.com
|
171
|
+
</email>
|
172
|
+
</author>
|
173
|
+
<generator uri='http://www.google.com/m8/feeds' version='1.0'>
|
174
|
+
Contacts
|
175
|
+
</generator>
|
176
|
+
<openSearch:totalResults>
|
177
|
+
0
|
178
|
+
</openSearch:totalResults>
|
179
|
+
<openSearch:startIndex>
|
180
|
+
0
|
181
|
+
</openSearch:startIndex>
|
182
|
+
<openSearch:itemsPerPage>
|
183
|
+
15
|
184
|
+
</openSearch:itemsPerPage>
|
185
|
+
</feed>
|
186
|
+
eos
|
187
|
+
)
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should update cache" do
|
192
|
+
cache = double('Bitsa::ContactsCache')
|
193
|
+
gcl = Bitsa::GmailContactsLoader.new('test', 'pw', 15)
|
194
|
+
expect(cache).to receive(:update).once
|
195
|
+
expect(cache).to receive(:source_last_modified=).once
|
196
|
+
expect(cache).to receive(:source_last_modified).exactly(3)
|
197
|
+
expect(cache).to receive(:save).once
|
198
|
+
expect(cache).to receive(:delete).once
|
199
|
+
gcl.update_cache(cache)
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|