googlecontacts 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +10 -0
- data/LICENSE +20 -0
- data/README.md +41 -0
- data/README.rdoc +17 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/google_contacts.rb +15 -0
- data/lib/google_contacts/auth.rb +28 -0
- data/lib/google_contacts/base.rb +163 -0
- data/lib/google_contacts/contact.rb +32 -0
- data/lib/google_contacts/group.rb +9 -0
- data/lib/google_contacts/proxies/array.rb +46 -0
- data/lib/google_contacts/proxies/emails.rb +125 -0
- data/lib/google_contacts/proxies/hash.rb +41 -0
- data/lib/google_contacts/wrapper.rb +126 -0
- data/spec/assets/contacts_full.xml +60 -0
- data/spec/assets/groups_full.xml +58 -0
- data/spec/base_spec.rb +78 -0
- data/spec/contact_spec.rb +80 -0
- data/spec/group_spec.rb +18 -0
- data/spec/proxies/array_spec.rb +105 -0
- data/spec/proxies/emails_spec.rb +161 -0
- data/spec/proxies/hash_spec.rb +78 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/wrapper_spec.rb +75 -0
- metadata +129 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Contact do
|
4
|
+
describe "when loaded" do
|
5
|
+
before(:each) do
|
6
|
+
entries = parsed_asset('contacts_full').search('feed > entry')
|
7
|
+
@contacts = entries.map { |entry| Contact.new(wrapper, entry) }
|
8
|
+
@contact = @contacts.first
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should know its id" do
|
12
|
+
@contact.id.should == 'http://www.google.com/m8/feeds/contacts/liz%40gmail.com/base/c9012de'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should know when it was updated" do
|
16
|
+
@contact.updated_at.should == Time.utc(2008, 12, 10, 04, 45, 03, 331000)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should initialize with groups from xml" do
|
20
|
+
@contact.groups.should have(1).group
|
21
|
+
@contact.groups[0].should == 'http://www.google.com/m8/feeds/groups/liz%40gmail.com/base/270f'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should initialize extended properties" do
|
25
|
+
@contact[:pet].should == 'hamster'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not be changed? initially" do
|
29
|
+
@contact.changed?.should be_false
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "urls" do
|
33
|
+
it "should know its self url" do
|
34
|
+
@contact.url(:self).should == 'http://www.google.com/m8/feeds/contacts/liz%40gmail.com/full/c9012de'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should know its edit url" do
|
38
|
+
@contact.url(:edit).should == 'http://www.google.com/m8/feeds/contacts/liz%40gmail.com/full/c9012de'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should know its photo url" do
|
42
|
+
@contact.url(:photo).should == 'http://www.google.com/m8/feeds/photos/media/liz%40gmail.com/c9012de'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "initializing" do
|
48
|
+
before(:each) do
|
49
|
+
@contact = Contact.new(wrapper)
|
50
|
+
@root = @contact.xml.document.root
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should create a new xml root node" do
|
54
|
+
@root.name.should == 'entry'
|
55
|
+
@root.namespace.href.should == 'http://www.w3.org/2005/Atom'
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should set the right category term" do
|
59
|
+
@root.at_xpath('./category')['term'].should == 'http://schemas.google.com/contact/2008#contact'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should not have an id" do
|
63
|
+
@contact.id.should be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not have an updated entry" do
|
67
|
+
@contact.updated_at.should be_nil
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should always be changed" do
|
71
|
+
@contact.changed?.should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be possible to set the default email address" do
|
75
|
+
@contact.email = 'foo@bar.com'
|
76
|
+
@contact.emails['foo@bar.com'].should be_primary
|
77
|
+
@contact.emails.size.should == 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/spec/group_spec.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Group do
|
4
|
+
before(:each) do
|
5
|
+
entries = parsed_asset('groups_full').search('feed > entry')
|
6
|
+
@groups = entries.map { |entry| Group.new(wrapper, entry) }
|
7
|
+
@group = @groups.first
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should know its id" do
|
11
|
+
@group.id.should == 'http://www.google.com/m8/feeds/groups/jo%40gmail.com/base/6'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should know when it is a system group" do
|
15
|
+
@groups[0].system_group?.should be_true
|
16
|
+
@groups[1].system_group?.should be_false
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Proxies::Array do
|
4
|
+
describe "with existing entries" do
|
5
|
+
before(:each) do
|
6
|
+
create_proxy_from_xml %{<entry><group href="http://some.group" /></entry>}
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should initialize on creation" do
|
10
|
+
@proxy.size.should == 1
|
11
|
+
@proxy[0].should == 'http://some.group'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "without existing entries" do
|
16
|
+
before(:each) do
|
17
|
+
create_proxy_from_xml "<entry></entry>"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow pushing a plain value" do
|
21
|
+
@proxy << 'http://foo'
|
22
|
+
@proxy.should have(1).group
|
23
|
+
@proxy[0].should == 'http://foo'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should allow pushing an object that responds to href" do
|
27
|
+
@proxy << mock('Group', :href => 'http://foo')
|
28
|
+
@proxy.should have(1).group
|
29
|
+
@proxy[0].should == 'http://foo'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should filter duplicates" do
|
33
|
+
@proxy << 'http://foo'
|
34
|
+
@proxy << 'http://foo'
|
35
|
+
@proxy.should have(1).group
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should filter nils" do
|
39
|
+
@proxy << nil
|
40
|
+
@proxy.should have(:no).groups
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should allow clearing" do
|
44
|
+
@proxy << 'http://foo'
|
45
|
+
@proxy.clear
|
46
|
+
@proxy.should have(:no).groups
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "knows when it is changed" do
|
51
|
+
before(:each) do
|
52
|
+
create_proxy_from_xml <<-XML
|
53
|
+
<entry>
|
54
|
+
<group href="http://some.group" />
|
55
|
+
<group href="http://another.group" />
|
56
|
+
</entry>
|
57
|
+
XML
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should work after pushing a new entry" do
|
61
|
+
lambda {
|
62
|
+
@proxy << 'http://foo'
|
63
|
+
}.should change(@proxy, :changed?).from(false).to(true)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not be changed when a duplicate is added" do
|
67
|
+
lambda {
|
68
|
+
@proxy << 'http://some.group'
|
69
|
+
}.should_not change(@proxy, :changed?).from(false)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should not be changed when nils are added" do
|
73
|
+
lambda {
|
74
|
+
@proxy.concat [nil, nil]
|
75
|
+
}.should_not change(@proxy, :changed?).from(false)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should not be influenced by order" do
|
79
|
+
lambda {
|
80
|
+
@proxy.replace ['http://another.group', 'http://some.group']
|
81
|
+
}.should_not change(@proxy, :changed?).from(false)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "synchronize to xml document" do
|
86
|
+
before(:each) do
|
87
|
+
create_proxy_from_xml "<entry></entry>"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should update the group entries" do
|
91
|
+
@proxy << 'http://another.group'
|
92
|
+
@proxy << 'http://some.group'
|
93
|
+
@parent.expects(:remove_xml).with('./group')
|
94
|
+
@parent.expects(:insert_xml).with('group', { 'href' => 'http://another.group' })
|
95
|
+
@parent.expects(:insert_xml).with('group', { 'href' => 'http://some.group' })
|
96
|
+
@proxy.synchronize
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_proxy_from_xml(str)
|
101
|
+
@parent = mock('parent', :xml => Nokogiri::XML.parse(str).root)
|
102
|
+
@proxy = Proxies::Array.new(@parent, :tag => 'group', :attr => 'href')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Proxies::Emails do
|
4
|
+
describe "with existing entries" do
|
5
|
+
before(:each) do
|
6
|
+
create_proxy_from_xml <<-XML
|
7
|
+
<entry xmlns:gd="http://schemas.google.com/g/2005">
|
8
|
+
<gd:email label="Personal" displayName="Foo Bar"
|
9
|
+
address="foo@bar.example.com" />
|
10
|
+
<gd:email rel="http://schemas.google.com/g/2005#home"
|
11
|
+
address="fubar@gmail.com" primary="true"/>
|
12
|
+
</entry>
|
13
|
+
XML
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should initialize on creation" do
|
17
|
+
@proxy['foo@bar.example.com'].address .should == 'foo@bar.example.com'
|
18
|
+
@proxy['foo@bar.example.com'].name .should == 'Foo Bar'
|
19
|
+
@proxy['foo@bar.example.com'].label .should == 'Personal'
|
20
|
+
@proxy['foo@bar.example.com'].rel .should be_nil
|
21
|
+
@proxy['foo@bar.example.com'] .should_not be_primary
|
22
|
+
|
23
|
+
@proxy['fubar@gmail.com' ].address .should == 'fubar@gmail.com'
|
24
|
+
@proxy['fubar@gmail.com' ].name .should be_nil
|
25
|
+
@proxy['fubar@gmail.com' ].label .should be_nil
|
26
|
+
@proxy['fubar@gmail.com' ].rel .should == 'http://schemas.google.com/g/2005#home'
|
27
|
+
@proxy['fubar@gmail.com' ] .should be_primary
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should initially be unchanged" do
|
31
|
+
@proxy.changed?.should be_false
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "should be changed" do
|
35
|
+
after(:each) do
|
36
|
+
@proxy.changed?.should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "when switching primary" do
|
40
|
+
@proxy['foo@bar.example.com'].primary!
|
41
|
+
end
|
42
|
+
|
43
|
+
it "when modifying name" do
|
44
|
+
@proxy['foo@bar.example.com'].name = 'Quux'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "when modifying rel" do
|
48
|
+
@proxy['foo@bar.example.com'].rel = 'http://some.rel'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "when adding a new address" do
|
52
|
+
@proxy << 'john@doe.com'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "when removing an address" do
|
56
|
+
@proxy.delete 'foo@bar.example.com'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "without existing entries" do
|
62
|
+
before(:each) do
|
63
|
+
create_proxy_from_xml <<-XML
|
64
|
+
<entry xmlns:gd="http://schemas.google.com/g/2005">
|
65
|
+
</entry>
|
66
|
+
XML
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should be possible to add email address" do
|
70
|
+
lambda {
|
71
|
+
@proxy['foo@bar.com']
|
72
|
+
}.should change(@proxy, :size).by(1)
|
73
|
+
|
74
|
+
lambda {
|
75
|
+
@proxy << 'quux@bar.com'
|
76
|
+
}.should change(@proxy, :size).by(1)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should raise when adding a duplicate" do
|
80
|
+
@proxy << 'quux@bar.com'
|
81
|
+
lambda {
|
82
|
+
@proxy << 'quux@bar.com'
|
83
|
+
}.should raise_error
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should provide sensible defaults for new addresses" do
|
87
|
+
@proxy['john@doe.com'].address.should == 'john@doe.com'
|
88
|
+
@proxy['john@doe.com'].rel.should == 'http://schemas.google.com/g/2005#home'
|
89
|
+
@proxy['john@doe.com'].label.should be_nil
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should set the first created entry to be primary" do
|
93
|
+
@proxy['john@doe.com'].should be_primary
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should only allow one entry to be primary" do
|
97
|
+
@proxy['john@doe.com'].should be_primary
|
98
|
+
@proxy['jane@doe.com'].should_not be_primary
|
99
|
+
@proxy['jane@doe.com'].primary!
|
100
|
+
@proxy['john@doe.com'].should_not be_primary
|
101
|
+
@proxy['jane@doe.com'].should be_primary
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should only allow either rel or label to be set" do
|
105
|
+
@proxy['john@doe.com'].rel = 'foo'
|
106
|
+
@proxy['john@doe.com'].label = 'foo'
|
107
|
+
@proxy['john@doe.com'].rel.should be_nil
|
108
|
+
|
109
|
+
@proxy['john@doe.com'].label = 'foo'
|
110
|
+
@proxy['john@doe.com'].rel = 'foo'
|
111
|
+
@proxy['john@doe.com'].label.should be_nil
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should raise when attempting to modify the address" do
|
115
|
+
lambda {
|
116
|
+
@proxy['john@doe.com'].address = 'foo'
|
117
|
+
}.should raise_error(/cannot modify/i)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should allow email addresses to be removed" do
|
121
|
+
@proxy << 'john@doe.com'
|
122
|
+
lambda {
|
123
|
+
@proxy.delete('john@doe.com')
|
124
|
+
}.should change(@proxy, :size).from(1).to(0)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "synchronize to xml document" do
|
129
|
+
before(:each) do
|
130
|
+
create_proxy_from_xml <<-XML
|
131
|
+
<entry xmlns:gd="http://schemas.google.com/g/2005">
|
132
|
+
</entry>
|
133
|
+
XML
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should clear existing email tags" do
|
137
|
+
@proxy << 'john@doe.com'
|
138
|
+
@parent.expects(:remove_xml).with('./gd:email')
|
139
|
+
@parent.stubs(:insert_xml)
|
140
|
+
@proxy.synchronize
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should add every email address" do
|
144
|
+
@proxy << 'john@doe.com'
|
145
|
+
@proxy << 'jane@doe.com'
|
146
|
+
|
147
|
+
@parent.stubs(:remove_xml)
|
148
|
+
@parent.expects(:insert_xml).with('gd:email', has_entries(
|
149
|
+
'address' => 'john@doe.com',
|
150
|
+
'primary' => 'true'))
|
151
|
+
@parent.expects(:insert_xml).with('gd:email', has_entries(
|
152
|
+
'address' => 'jane@doe.com'))
|
153
|
+
@proxy.synchronize
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def create_proxy_from_xml(str)
|
158
|
+
@parent = stub('parent', :xml => Nokogiri::XML.parse(str).root)
|
159
|
+
@proxy = Proxies::Emails.new(@parent)
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Proxies::Hash do
|
4
|
+
describe "with existing entries" do
|
5
|
+
before(:each) do
|
6
|
+
create_proxy_from_xml <<-XML
|
7
|
+
<entry>
|
8
|
+
<prop name="foo" value="bar" />
|
9
|
+
</entry>
|
10
|
+
XML
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should initialize on creation" do
|
14
|
+
@proxy[:foo].should == 'bar'
|
15
|
+
@proxy.should have(1).entry
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "without existing entries" do
|
20
|
+
before(:each) do
|
21
|
+
create_proxy_from_xml "<entry></entry>"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should allow setting a value" do
|
25
|
+
@proxy[:foo] = 'bar'
|
26
|
+
@proxy.should have(1).entry
|
27
|
+
@proxy[:foo].should == 'bar'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should allow clearing" do
|
31
|
+
@proxy[:foo] = 'bar'
|
32
|
+
@proxy.clear
|
33
|
+
@proxy.should have(:no).entries
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "knows when it is changed" do
|
38
|
+
before(:each) do
|
39
|
+
create_proxy_from_xml <<-XML
|
40
|
+
<entry>
|
41
|
+
<prop name="foo" value="foo" />
|
42
|
+
</entry>
|
43
|
+
XML
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should work when a new value was set" do
|
47
|
+
lambda {
|
48
|
+
@proxy[:foo] = 'quux'
|
49
|
+
}.should change(@proxy, :changed?).from(false).to(true)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should not be changed when the new value equals the old one" do
|
53
|
+
lambda {
|
54
|
+
@proxy[:foo] = 'foo'
|
55
|
+
}.should_not change(@proxy, :changed?).from(false)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "synchronize to xml document" do
|
60
|
+
before(:each) do
|
61
|
+
create_proxy_from_xml "<entry></entry>"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should update the group entries" do
|
65
|
+
@proxy[:foo] = 'quux'
|
66
|
+
@proxy[:baz] = 'bar'
|
67
|
+
@parent.expects(:remove_xml).with('./prop')
|
68
|
+
@parent.expects(:insert_xml).with('prop', { 'name' => 'foo', 'value' => 'quux' })
|
69
|
+
@parent.expects(:insert_xml).with('prop', { 'name' => 'baz', 'value' => 'bar' })
|
70
|
+
@proxy.synchronize
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_proxy_from_xml(str)
|
75
|
+
@parent = stub('parent', :xml => Nokogiri::XML.parse(str).root)
|
76
|
+
@proxy = Proxies::Hash.new(@parent, :tag => 'prop', :key => 'name', :value => 'value')
|
77
|
+
end
|
78
|
+
end
|
data/spec/spec.opts
ADDED