google_r 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +26 -0
- data/.github/workflows/gempush.yml +28 -0
- data/.gitignore +7 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +4 -0
- data/LICENSE +201 -0
- data/README.md +18 -0
- data/Rakefile +1 -0
- data/google_r.gemspec +27 -0
- data/lib/google_r.rb +201 -0
- data/lib/google_r/calendar.rb +58 -0
- data/lib/google_r/contact.rb +241 -0
- data/lib/google_r/event.rb +99 -0
- data/lib/google_r/exceptions.rb +16 -0
- data/lib/google_r/group.rb +88 -0
- data/lib/google_r/token.rb +44 -0
- data/lib/google_r/version.rb +3 -0
- data/spec/fixtures/contact_list.xml +98 -0
- data/spec/fixtures/no_contacts.xml +20 -0
- data/spec/fixtures/single_contact.xml +75 -0
- data/spec/fixtures/single_group.xml +14 -0
- data/spec/google_api_spec.rb +90 -0
- data/spec/google_contact_spec.rb +428 -0
- data/spec/google_event_spec.rb +33 -0
- data/spec/google_group_spec.rb +46 -0
- data/spec/spec_helper.rb +7 -0
- metadata +156 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
class GoogleR::Token
|
4
|
+
attr_accessor :issued_to, :audience, :scopes, :expires_at, :access_type, :token
|
5
|
+
|
6
|
+
def initialize(token)
|
7
|
+
self.token = token
|
8
|
+
self.scopes = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.url
|
12
|
+
"https://www.googleapis.com"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.api_headers
|
16
|
+
{}
|
17
|
+
end
|
18
|
+
|
19
|
+
def path
|
20
|
+
"/oauth2/v2/tokeninfo"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.from_json(json, *attrs)
|
24
|
+
token = self.new(*attrs)
|
25
|
+
token.issued_to = json["issued_to"]
|
26
|
+
token.audience = json["audience"]
|
27
|
+
token.scopes = json["scope"].split(" ")
|
28
|
+
token.expires_at = Time.at(Time.now.to_i + json["expires_in"])
|
29
|
+
token.access_type = json["access_type"]
|
30
|
+
token
|
31
|
+
end
|
32
|
+
|
33
|
+
def expires_in
|
34
|
+
expires_at.to_i - Time.now.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_google(yajl_opts = {})
|
38
|
+
Yajl::Encoder.encode({}, yajl_opts)
|
39
|
+
end
|
40
|
+
|
41
|
+
def new?
|
42
|
+
self.token.nil?
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/"CEAGSHw9cSt7I2A9WhVSGEU."">
|
3
|
+
<id>michal@futuresimple.com</id>
|
4
|
+
<updated>2012-03-16T07:25:29.269Z</updated>
|
5
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
|
6
|
+
<title>Michal Bugno's Contacts</title>
|
7
|
+
<link rel="alternate" type="text/html" href="http://www.google.com/"/>
|
8
|
+
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full"/>
|
9
|
+
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full"/>
|
10
|
+
<link rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/batch"/>
|
11
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full?max-results=3"/>
|
12
|
+
<link rel="next" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full?start-index=4&max-results=3"/>
|
13
|
+
<author>
|
14
|
+
<name>Michal Bugno</name>
|
15
|
+
<email>michal@futuresimple.com</email>
|
16
|
+
</author>
|
17
|
+
<generator version="1.0" uri="http://www.google.com/m8/feeds">Contacts</generator>
|
18
|
+
<openSearch:totalResults>34</openSearch:totalResults>
|
19
|
+
<openSearch:startIndex>1</openSearch:startIndex>
|
20
|
+
<openSearch:itemsPerPage>3</openSearch:itemsPerPage>
|
21
|
+
<entry gd:etag=""Q3o6cDVSLit7I2A9WhVSGEkOQgI."">
|
22
|
+
<id>http://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/base/2f30e7d8bf01953</id>
|
23
|
+
<updated>2012-03-15T20:49:22.418Z</updated>
|
24
|
+
<app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-15T20:49:22.418Z</app:edited>
|
25
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
|
26
|
+
<title>Sir Bartek Maciej Niemtur III</title>
|
27
|
+
<content>moje notatki</content>
|
28
|
+
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/michal%40futuresimple.com/2f30e7d8bf01953"/>
|
29
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/2f30e7d8bf01953"/>
|
30
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/2f30e7d8bf01953"/>
|
31
|
+
<gd:name>
|
32
|
+
<gd:fullName>Sir Bartek Maciej Niemtur III</gd:fullName>
|
33
|
+
<gd:namePrefix>Sir</gd:namePrefix>
|
34
|
+
<gd:givenName yomi="Namtir">Bartek</gd:givenName>
|
35
|
+
<gd:additionalName>Maciej</gd:additionalName>
|
36
|
+
<gd:familyName yomi="Bortik">Niemtur</gd:familyName>
|
37
|
+
<gd:nameSuffix>III</gd:nameSuffix>
|
38
|
+
</gd:name>
|
39
|
+
<gContact:nickname>barti</gContact:nickname>
|
40
|
+
<gd:organization rel="http://schemas.google.com/g/2005#other">
|
41
|
+
<gd:orgName>Applicake</gd:orgName>
|
42
|
+
<gd:orgTitle>Klepacz</gd:orgTitle>
|
43
|
+
</gd:organization>
|
44
|
+
<gd:email rel="http://schemas.google.com/g/2005#home" address="lol@lol.home.com" primary="true"/>
|
45
|
+
<gd:email rel="http://schemas.google.com/g/2005#work" address="bart@work.com"/>
|
46
|
+
<gd:email rel="http://schemas.google.com/g/2005#other" address="mike@mike.com"/>
|
47
|
+
<gd:email label="Niestandardowy2" address="bart@bart.com"/>
|
48
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">komorkowy</gd:phoneNumber>
|
49
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">sluzbowy</gd:phoneNumber>
|
50
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#home">domowy</gd:phoneNumber>
|
51
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#main">glowny</gd:phoneNumber>
|
52
|
+
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
|
53
|
+
<gd:formattedAddress>ulica
|
54
|
+
skrytka
|
55
|
+
okolica, miasto, wojewodztwo kod
|
56
|
+
kraj</gd:formattedAddress>
|
57
|
+
<gd:street>ulica</gd:street>
|
58
|
+
<gd:neighborhood>okolica</gd:neighborhood>
|
59
|
+
<gd:pobox>skrytka</gd:pobox>
|
60
|
+
<gd:postcode>kod</gd:postcode>
|
61
|
+
<gd:city>miasto</gd:city>
|
62
|
+
<gd:region>wojewodztwo</gd:region>
|
63
|
+
<gd:country>kraj</gd:country>
|
64
|
+
</gd:structuredPostalAddress>
|
65
|
+
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work">
|
66
|
+
<gd:formattedAddress>ulica2
|
67
|
+
skrytka2
|
68
|
+
okolica2, miasto2, woj2 kod2
|
69
|
+
kraj2</gd:formattedAddress>
|
70
|
+
<gd:street>ulica2</gd:street>
|
71
|
+
<gd:neighborhood>okolica2</gd:neighborhood>
|
72
|
+
<gd:pobox>skrytka2</gd:pobox>
|
73
|
+
<gd:postcode>kod2</gd:postcode>
|
74
|
+
<gd:city>miasto2</gd:city>
|
75
|
+
<gd:region>woj2</gd:region>
|
76
|
+
<gd:country>kraj2</gd:country>
|
77
|
+
</gd:structuredPostalAddress>
|
78
|
+
<gContact:userDefinedField key="wlasne1" value="wlasnawartosc"/>
|
79
|
+
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/6"/>
|
80
|
+
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/5747930b8e7844f6"/>
|
81
|
+
</entry>
|
82
|
+
<entry gd:etag=""Qnc4fzVSLit7I2A9WhVTGUgJTwA."">
|
83
|
+
<id>http://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/base/8c7c7c80d9dcaf7</id>
|
84
|
+
<updated>2012-03-05T13:24:03.937Z</updated>
|
85
|
+
<app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-05T13:24:03.937Z</app:edited>
|
86
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
|
87
|
+
<title>Awangarda druga</title>
|
88
|
+
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/michal%40futuresimple.com/8c7c7c80d9dcaf7"/>
|
89
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/8c7c7c80d9dcaf7"/>
|
90
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/8c7c7c80d9dcaf7"/>
|
91
|
+
<gd:name>
|
92
|
+
<gd:fullName>Awangarda druga</gd:fullName>
|
93
|
+
<gd:givenName>Awangarda</gd:givenName>
|
94
|
+
<gd:familyName>druga</gd:familyName>
|
95
|
+
</gd:name>
|
96
|
+
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/6"/>
|
97
|
+
</entry>
|
98
|
+
</feed>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/"D0EFSX8_cCt7I2A9WhVSGEQ."">
|
3
|
+
<id>michal@futuresimple.com</id>
|
4
|
+
<updated>2012-03-16T11:00:18.148Z</updated>
|
5
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
|
6
|
+
<title>Michal Bugno's Contacts</title>
|
7
|
+
<link rel="alternate" type="text/html" href="http://www.google.com/"/>
|
8
|
+
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full"/>
|
9
|
+
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full"/>
|
10
|
+
<link rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/batch"/>
|
11
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full?max-results=0"/>
|
12
|
+
<author>
|
13
|
+
<name>Michal Bugno</name>
|
14
|
+
<email>michal@futuresimple.com</email>
|
15
|
+
</author>
|
16
|
+
<generator version="1.0" uri="http://www.google.com/m8/feeds">Contacts</generator>
|
17
|
+
<openSearch:totalResults>34</openSearch:totalResults>
|
18
|
+
<openSearch:startIndex>1</openSearch:startIndex>
|
19
|
+
<openSearch:itemsPerPage>0</openSearch:itemsPerPage>
|
20
|
+
</feed>
|
@@ -0,0 +1,75 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag=""Q3o6cDVSLit7I2A9WhVSGEkOQgI."">
|
3
|
+
<id>http://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/base/2f30e7d8bf01953</id>
|
4
|
+
<updated>2012-03-15T20:49:22.418Z</updated>
|
5
|
+
<app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-15T20:49:22.418Z</app:edited>
|
6
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"/>
|
7
|
+
<title>Sir Mike Thomas Bugno XI</title>
|
8
|
+
<content>Notes about Mike</content>
|
9
|
+
|
10
|
+
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/michal%40futuresimple.com/2f30e7d8bf01953"/>
|
11
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/2f30e7d8bf01953"/>
|
12
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/full/2f30e7d8bf01953"/>
|
13
|
+
|
14
|
+
<gd:name>
|
15
|
+
<gd:fullName>Sir Mike Thomas Bugno XI</gd:fullName>
|
16
|
+
<gd:namePrefix>Sir</gd:namePrefix>
|
17
|
+
<gd:givenName yomi="Maik">Mike</gd:givenName>
|
18
|
+
<gd:additionalName>Thomas</gd:additionalName>
|
19
|
+
<gd:familyName yomi="Boogno">Bugno</gd:familyName>
|
20
|
+
<gd:nameSuffix>XI</gd:nameSuffix>
|
21
|
+
</gd:name>
|
22
|
+
|
23
|
+
<gContact:nickname>Majki</gContact:nickname>
|
24
|
+
|
25
|
+
<gd:organization rel="http://schemas.google.com/g/2005#other">
|
26
|
+
<gd:orgName>FutureSimple</gd:orgName>
|
27
|
+
<gd:orgTitle>Coder</gd:orgTitle>
|
28
|
+
</gd:organization>
|
29
|
+
|
30
|
+
<gd:email rel="http://schemas.google.com/g/2005#home" address="home@example.com" primary="true"/>
|
31
|
+
<gd:email rel="http://schemas.google.com/g/2005#work" address="work@example.com"/>
|
32
|
+
<gd:email rel="http://schemas.google.com/g/2005#other" address="other@example.com"/>
|
33
|
+
<gd:email label="Non standard" address="nonstandard@example.com"/>
|
34
|
+
|
35
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#mobile">43-mobile</gd:phoneNumber>
|
36
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">023-office</gd:phoneNumber>
|
37
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#home">444-home</gd:phoneNumber>
|
38
|
+
<gd:phoneNumber rel="http://schemas.google.com/g/2005#main">888-main</gd:phoneNumber>
|
39
|
+
|
40
|
+
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
|
41
|
+
<gd:formattedAddress>ulica
|
42
|
+
skrytka
|
43
|
+
okolica, miasto, wojewodztwo kod
|
44
|
+
kraj</gd:formattedAddress>
|
45
|
+
<gd:street>ulica</gd:street>
|
46
|
+
<gd:neighborhood>okolica</gd:neighborhood>
|
47
|
+
<gd:pobox>skrytka</gd:pobox>
|
48
|
+
<gd:postcode>kod</gd:postcode>
|
49
|
+
<gd:city>miasto</gd:city>
|
50
|
+
<gd:region>wojewodztwo</gd:region>
|
51
|
+
<gd:country>kraj</gd:country>
|
52
|
+
</gd:structuredPostalAddress>
|
53
|
+
|
54
|
+
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#work">
|
55
|
+
<gd:formattedAddress>ulica2
|
56
|
+
skrytka2
|
57
|
+
okolica2, miasto2, wojedwodztwo2 kod2
|
58
|
+
kraj2</gd:formattedAddress>
|
59
|
+
<gd:street>ulica2</gd:street>
|
60
|
+
<gd:neighborhood>okolica2</gd:neighborhood>
|
61
|
+
<gd:pobox>skrytka2</gd:pobox>
|
62
|
+
<gd:postcode>kod2</gd:postcode>
|
63
|
+
<gd:city>miasto2</gd:city>
|
64
|
+
<gd:region>wojewodztwo2</gd:region>
|
65
|
+
<gd:country>kraj2</gd:country>
|
66
|
+
</gd:structuredPostalAddress>
|
67
|
+
|
68
|
+
<gContact:userDefinedField key="own key" value="Own value"/>
|
69
|
+
|
70
|
+
<gContact:website href="glowna.com" rel="home-page"/>
|
71
|
+
<gContact:website href="sluzbowy.com" rel="work"/>
|
72
|
+
|
73
|
+
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/6"/>
|
74
|
+
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/5747930b8e7844f6"/>
|
75
|
+
</entry>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag=""Qnw-eTVSLit7I2A9WhVREUgNQQ0."">
|
3
|
+
<id>http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/5e8cb5e00cc22016</id>
|
4
|
+
<updated>2012-03-19T11:48:13.251Z</updated>
|
5
|
+
<app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-19T11:48:13.251Z</app:edited>
|
6
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#group"/>
|
7
|
+
<title>Grupa 52</title>
|
8
|
+
<content>Grupa 52</content>
|
9
|
+
<extendedProperty name="Grupa 55">
|
10
|
+
<info>To jest grupa</info>
|
11
|
+
</extendedProperty>
|
12
|
+
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/groups/michal%40futuresimple.com/full/5e8cb5e00cc22016"/>
|
13
|
+
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/groups/michal%40futuresimple.com/full/5e8cb5e00cc22016"/>
|
14
|
+
</entry>
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GoogleR do
|
4
|
+
|
5
|
+
let(:api) { GoogleR.new("token") }
|
6
|
+
|
7
|
+
it "should process contacts" do
|
8
|
+
google_contacts = File.read('spec/fixtures/contact_list.xml');
|
9
|
+
connection_get_answer = double(:body => google_contacts,
|
10
|
+
:status => 200,
|
11
|
+
:headers => {"Content-Type" => "xml"})
|
12
|
+
allow(api).to receive_message_chain(:connection, :get).and_return(connection_get_answer)
|
13
|
+
|
14
|
+
data = api.contacts
|
15
|
+
expect(data.size).to eq(2)
|
16
|
+
|
17
|
+
contact_1 = data.find { |e| e.full_name == "Awangarda druga" }
|
18
|
+
expect(contact_1).not_to be_nil
|
19
|
+
|
20
|
+
contact_2 = data.find { |e| e.full_name == "Sir Bartek Maciej Niemtur III" }
|
21
|
+
expect(contact_2).not_to be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should process groups"
|
25
|
+
|
26
|
+
it "should process events"
|
27
|
+
|
28
|
+
it "should handle accounts which have 0 contacts" do
|
29
|
+
no_contacts = File.read('spec/fixtures/no_contacts.xml')
|
30
|
+
connection_get_answer = double(:body => no_contacts,
|
31
|
+
:status => 200,
|
32
|
+
:headers => {"Content-Type" => "xml"})
|
33
|
+
allow_any_instance_of(GoogleR).to receive_message_chain(:connection, :get).and_return(connection_get_answer)
|
34
|
+
|
35
|
+
expect(api.connection(GoogleR::Contact)).to receive(:get)
|
36
|
+
expect(api.contacts).to be_empty
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should raise error if request fails" do
|
40
|
+
connection_get_answer = double(:body => "Failed :(",
|
41
|
+
:status => 400)
|
42
|
+
allow_any_instance_of(GoogleR).to receive_message_chain(:connection, :get).and_return(connection_get_answer)
|
43
|
+
ex = nil
|
44
|
+
begin
|
45
|
+
api.contacts
|
46
|
+
rescue GoogleR::Error => e
|
47
|
+
ex = e
|
48
|
+
end
|
49
|
+
expect(ex.class).to eq(GoogleR::Error)
|
50
|
+
expect(ex.message).to include("400")
|
51
|
+
expect(ex.message).to include("Failed :(")
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "test_access" do
|
55
|
+
context "when test response is 200" do
|
56
|
+
before do
|
57
|
+
response = double(:status => 200)
|
58
|
+
expect(api).to receive(:make_request).and_return(response)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns true" do
|
62
|
+
expect(api.test_access).to eq(true)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when test response is 401" do
|
67
|
+
before do
|
68
|
+
response = double(:status => 401)
|
69
|
+
expect(api).to receive(:make_request).and_return(response)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns true" do
|
73
|
+
expect(api.test_access).to eq(false)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when test response is somethig else" do
|
78
|
+
before do
|
79
|
+
response = double(:status => 500, :body => "Server error")
|
80
|
+
expect(api).to receive(:make_request).and_return(response)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "raises GoogleR::Error" do
|
84
|
+
expect {
|
85
|
+
api.test_access
|
86
|
+
}.to raise_error(GoogleR::Error)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,428 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GoogleR::Contact do
|
4
|
+
before do
|
5
|
+
single_contact_path = "spec/fixtures/single_contact.xml"
|
6
|
+
doc = Nokogiri::XML.parse(File.read(single_contact_path))
|
7
|
+
doc.remove_namespaces!
|
8
|
+
@doc_root = doc.root
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:contact) { GoogleR::Contact.from_xml(@doc_root) }
|
12
|
+
subject { contact }
|
13
|
+
|
14
|
+
context "should load id and etag from xml" do
|
15
|
+
describe '#google_id' do
|
16
|
+
subject { super().google_id }
|
17
|
+
it { is_expected.to eq("http://www.google.com/m8/feeds/contacts/michal%40futuresimple.com/base/2f30e7d8bf01953") }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#etag' do
|
21
|
+
subject { super().etag }
|
22
|
+
it { is_expected.to eq("\"Q3o6cDVSLit7I2A9WhVSGEkOQgI.\"") }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "should load emails from xml" do
|
27
|
+
let (:emails) { GoogleR::Contact.from_xml(@doc_root).emails }
|
28
|
+
subject { emails }
|
29
|
+
|
30
|
+
describe '#size' do
|
31
|
+
subject { super().size }
|
32
|
+
it { is_expected.to eq(4) }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "home_email" do
|
36
|
+
subject { emails.find { |e| e.rel == "http://schemas.google.com/g/2005#home" } }
|
37
|
+
|
38
|
+
describe '#address' do
|
39
|
+
subject { super().address }
|
40
|
+
it { is_expected.to eq("home@example.com") }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#label' do
|
44
|
+
subject { super().label }
|
45
|
+
it { is_expected.to be_nil }
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#primary' do
|
49
|
+
subject { super().primary }
|
50
|
+
it { is_expected.to be_truthy }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "work_email" do
|
55
|
+
subject { emails.find { |e| e.rel == "http://schemas.google.com/g/2005#work" } }
|
56
|
+
|
57
|
+
describe '#address' do
|
58
|
+
subject { super().address }
|
59
|
+
it { is_expected.to eq("work@example.com") }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#label' do
|
63
|
+
subject { super().label }
|
64
|
+
it { is_expected.to be_nil }
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#primary' do
|
68
|
+
subject { super().primary }
|
69
|
+
it { is_expected.to be_falsey }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "other_email" do
|
74
|
+
subject { emails.find { |e| e.rel == "http://schemas.google.com/g/2005#other" } }
|
75
|
+
|
76
|
+
describe '#address' do
|
77
|
+
subject { super().address }
|
78
|
+
it { is_expected.to eq("other@example.com") }
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#label' do
|
82
|
+
subject { super().label }
|
83
|
+
it { is_expected.to be_nil }
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#primary' do
|
87
|
+
subject { super().primary }
|
88
|
+
it { is_expected.to be_falsey }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "custom_email" do
|
93
|
+
subject { emails.find { |e| e.rel.nil? } }
|
94
|
+
|
95
|
+
describe '#address' do
|
96
|
+
subject { super().address }
|
97
|
+
it { is_expected.to eq("nonstandard@example.com") }
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#label' do
|
101
|
+
subject { super().label }
|
102
|
+
it { is_expected.to eq("Non standard") }
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#primary' do
|
106
|
+
subject { super().primary }
|
107
|
+
it { is_expected.to be_falsey }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
context "should load phones from xml" do
|
114
|
+
let (:phones) { GoogleR::Contact.from_xml(@doc_root).phones }
|
115
|
+
subject { phones }
|
116
|
+
|
117
|
+
describe '#size' do
|
118
|
+
subject { super().size }
|
119
|
+
it { is_expected.to eq(4) }
|
120
|
+
end
|
121
|
+
|
122
|
+
context "home_phone" do
|
123
|
+
subject { phones.find { |e| e.rel == "http://schemas.google.com/g/2005#home" } }
|
124
|
+
|
125
|
+
describe '#text' do
|
126
|
+
subject { super().text }
|
127
|
+
it { is_expected.to eq("444-home") }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "work_phone" do
|
132
|
+
subject { phones.find { |e| e.rel == "http://schemas.google.com/g/2005#work" } }
|
133
|
+
|
134
|
+
describe '#text' do
|
135
|
+
subject { super().text }
|
136
|
+
it { is_expected.to eq("023-office") }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "mobile_phone" do
|
141
|
+
subject { phones.find { |e| e.rel == "http://schemas.google.com/g/2005#mobile" } }
|
142
|
+
|
143
|
+
describe '#text' do
|
144
|
+
subject { super().text }
|
145
|
+
it { is_expected.to eq("43-mobile") }
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "main_phone" do
|
150
|
+
subject { phones.find { |e| e.rel == "http://schemas.google.com/g/2005#main" } }
|
151
|
+
|
152
|
+
describe '#text' do
|
153
|
+
subject { super().text }
|
154
|
+
it { is_expected.to eq("888-main") }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "should load name from xml" do
|
160
|
+
describe '#name_prefix' do
|
161
|
+
subject { super().name_prefix }
|
162
|
+
it { is_expected.to eq("Sir") }
|
163
|
+
end
|
164
|
+
|
165
|
+
describe '#given_name' do
|
166
|
+
subject { super().given_name }
|
167
|
+
it { is_expected.to eq("Mike") }
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#additional_name' do
|
171
|
+
subject { super().additional_name }
|
172
|
+
it { is_expected.to eq("Thomas") }
|
173
|
+
end
|
174
|
+
|
175
|
+
describe '#family_name' do
|
176
|
+
subject { super().family_name }
|
177
|
+
it { is_expected.to eq("Bugno") }
|
178
|
+
end
|
179
|
+
|
180
|
+
describe '#name_suffix' do
|
181
|
+
subject { super().name_suffix }
|
182
|
+
it { is_expected.to eq("XI") }
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#full_name' do
|
186
|
+
subject { super().full_name }
|
187
|
+
it { is_expected.to eq("Sir Mike Thomas Bugno XI") }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "should load content from xml" do
|
192
|
+
describe '#content' do
|
193
|
+
subject { super().content }
|
194
|
+
it { is_expected.to eq("Notes about Mike") }
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "should load updated from xml" do
|
199
|
+
describe '#updated' do
|
200
|
+
subject { super().updated }
|
201
|
+
it { is_expected.to eq(Time.parse("2012-03-15T20:49:22.418Z")) }
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context "should load organisations from xml" do
|
206
|
+
let (:organizations) { GoogleR::Contact.from_xml(@doc_root).organizations }
|
207
|
+
subject { organizations }
|
208
|
+
|
209
|
+
describe '#size' do
|
210
|
+
subject { super().size }
|
211
|
+
it { is_expected.to eq(1) }
|
212
|
+
end
|
213
|
+
|
214
|
+
context "single organization" do
|
215
|
+
let (:organization) { GoogleR::Contact.from_xml(@doc_root).organizations.first }
|
216
|
+
subject { organization }
|
217
|
+
|
218
|
+
describe '#rel' do
|
219
|
+
subject { super().rel }
|
220
|
+
it { is_expected.to eq("http://schemas.google.com/g/2005#other") }
|
221
|
+
end
|
222
|
+
|
223
|
+
describe '#name' do
|
224
|
+
subject { super().name }
|
225
|
+
it { is_expected.to eq("FutureSimple") }
|
226
|
+
end
|
227
|
+
|
228
|
+
describe '#title' do
|
229
|
+
subject { super().title }
|
230
|
+
it { is_expected.to eq("Coder") }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context "should load user nickname from xml" do
|
236
|
+
describe '#nickname' do
|
237
|
+
subject { super().nickname }
|
238
|
+
it { should = "Majki"}
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context "should load addresses from xml" do
|
243
|
+
let (:addresses) { GoogleR::Contact.from_xml(@doc_root).addresses }
|
244
|
+
subject { addresses }
|
245
|
+
|
246
|
+
describe '#size' do
|
247
|
+
subject { super().size }
|
248
|
+
it { is_expected.to eq(2) }
|
249
|
+
end
|
250
|
+
|
251
|
+
context "home" do
|
252
|
+
subject { addresses.find { |e| e.rel == "http://schemas.google.com/g/2005#home" } }
|
253
|
+
|
254
|
+
describe '#street' do
|
255
|
+
subject { super().street }
|
256
|
+
it { is_expected.to eq("ulica") }
|
257
|
+
end
|
258
|
+
|
259
|
+
describe '#neighborhood' do
|
260
|
+
subject { super().neighborhood }
|
261
|
+
it { is_expected.to eq("okolica") }
|
262
|
+
end
|
263
|
+
|
264
|
+
describe '#pobox' do
|
265
|
+
subject { super().pobox }
|
266
|
+
it { is_expected.to eq("skrytka") }
|
267
|
+
end
|
268
|
+
|
269
|
+
describe '#postcode' do
|
270
|
+
subject { super().postcode }
|
271
|
+
it { is_expected.to eq("kod") }
|
272
|
+
end
|
273
|
+
|
274
|
+
describe '#city' do
|
275
|
+
subject { super().city }
|
276
|
+
it { is_expected.to eq("miasto") }
|
277
|
+
end
|
278
|
+
|
279
|
+
describe '#region' do
|
280
|
+
subject { super().region }
|
281
|
+
it { is_expected.to eq("wojewodztwo") }
|
282
|
+
end
|
283
|
+
|
284
|
+
describe '#country' do
|
285
|
+
subject { super().country }
|
286
|
+
it { is_expected.to eq("kraj") }
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
context "work" do
|
291
|
+
subject { addresses.find { |e| e.rel == "http://schemas.google.com/g/2005#work" } }
|
292
|
+
|
293
|
+
describe '#street' do
|
294
|
+
subject { super().street }
|
295
|
+
it { is_expected.to eq("ulica2") }
|
296
|
+
end
|
297
|
+
|
298
|
+
describe '#neighborhood' do
|
299
|
+
subject { super().neighborhood }
|
300
|
+
it { is_expected.to eq("okolica2") }
|
301
|
+
end
|
302
|
+
|
303
|
+
describe '#pobox' do
|
304
|
+
subject { super().pobox }
|
305
|
+
it { is_expected.to eq("skrytka2") }
|
306
|
+
end
|
307
|
+
|
308
|
+
describe '#postcode' do
|
309
|
+
subject { super().postcode }
|
310
|
+
it { is_expected.to eq("kod2") }
|
311
|
+
end
|
312
|
+
|
313
|
+
describe '#city' do
|
314
|
+
subject { super().city }
|
315
|
+
it { is_expected.to eq("miasto2") }
|
316
|
+
end
|
317
|
+
|
318
|
+
describe '#region' do
|
319
|
+
subject { super().region }
|
320
|
+
it { is_expected.to eq("wojewodztwo2") }
|
321
|
+
end
|
322
|
+
|
323
|
+
describe '#country' do
|
324
|
+
subject { super().country }
|
325
|
+
it { is_expected.to eq("kraj2") }
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
context "should load group membership from xml" do
|
332
|
+
let (:groups) { GoogleR::Contact.from_xml(@doc_root).groups }
|
333
|
+
subject { groups }
|
334
|
+
|
335
|
+
describe '#size' do
|
336
|
+
subject { super().size }
|
337
|
+
it { is_expected.to eq(2) }
|
338
|
+
end
|
339
|
+
|
340
|
+
context "first" do
|
341
|
+
google_id = "http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/6"
|
342
|
+
subject { groups.find { |e| e.google_id == google_id } }
|
343
|
+
it { is_expected.not_to be_nil }
|
344
|
+
end
|
345
|
+
|
346
|
+
context "last" do
|
347
|
+
google_id = "http://www.google.com/m8/feeds/groups/michal%40futuresimple.com/base/5747930b8e7844f6"
|
348
|
+
subject { groups.find { |e| e.google_id == google_id } }
|
349
|
+
it { is_expected.not_to be_nil }
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context "should treat contact without google_id as new?" do
|
354
|
+
subject { GoogleR::Contact.new }
|
355
|
+
it { is_expected.to be_new }
|
356
|
+
end
|
357
|
+
|
358
|
+
context "should treat contact with google_id as !new?" do
|
359
|
+
it { is_expected.not_to be_new }
|
360
|
+
end
|
361
|
+
|
362
|
+
context "should load user fields from xml" do
|
363
|
+
describe '#user_fields' do
|
364
|
+
subject { super().user_fields }
|
365
|
+
it { is_expected.to eq({"own key" => "Own value"}) }
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
it "should load websites from xml" do
|
370
|
+
expect(contact.websites.map { |e| e.href }.sort).to eq(["glowna.com", "sluzbowy.com"].sort)
|
371
|
+
expect(contact.websites.map { |e| e.rel }.sort).to eq(["work", "home-page"].sort)
|
372
|
+
end
|
373
|
+
|
374
|
+
it "should generate valid xml" do
|
375
|
+
xml = contact.to_google
|
376
|
+
c = Nokogiri::XML.parse(xml)
|
377
|
+
c = c.root
|
378
|
+
|
379
|
+
expect(c.name).to eq("entry")
|
380
|
+
expect(c.namespace.prefix).to eq("atom")
|
381
|
+
|
382
|
+
expect(c.search("id").size).to eq(1)
|
383
|
+
|
384
|
+
expect(c.search("./gd:name/gd:givenName").size).to eq(1)
|
385
|
+
expect(c.search("./gd:name/gd:givenName").inner_text).to eq("Mike")
|
386
|
+
expect(c.search("./gd:name/gd:additionalName").size).to eq(1)
|
387
|
+
expect(c.search("./gd:name/gd:additionalName").inner_text).to eq("Thomas")
|
388
|
+
expect(c.search("./gd:name/gd:familyName").size).to eq(1)
|
389
|
+
expect(c.search("./gd:name/gd:familyName").inner_text).to eq("Bugno")
|
390
|
+
expect(c.search("./gd:name/gd:namePrefix").size).to eq(1)
|
391
|
+
expect(c.search("./gd:name/gd:namePrefix").inner_text).to eq("Sir")
|
392
|
+
expect(c.search("./gd:name/gd:nameSuffix").size).to eq(1)
|
393
|
+
expect(c.search("./gd:name/gd:nameSuffix").inner_text).to eq("XI")
|
394
|
+
|
395
|
+
expect(c.search("./atom:content").inner_text).to eq("Notes about Mike")
|
396
|
+
|
397
|
+
expect(c.search("./gContact:nickname").inner_text).to eq("Majki")
|
398
|
+
|
399
|
+
expect(c.search("./gd:phoneNumber").map { |e| e.inner_text }.sort).to eq(["43-mobile", "023-office", "444-home", "888-main"].sort)
|
400
|
+
|
401
|
+
expect(c.search("./gd:email").map { |e| e[:address] }).to eq(["home@example.com", "work@example.com", "other@example.com", "nonstandard@example.com"])
|
402
|
+
expect(c.search("./gd:email").map { |e| e[:primary] }).to eq(["true", "false", "false", "false"])
|
403
|
+
|
404
|
+
expect(c.search("./gd:organization/gd:orgName").size).to eq(1)
|
405
|
+
expect(c.search("./gd:organization/gd:orgName").inner_text).to eq("FutureSimple")
|
406
|
+
expect(c.search("./gd:organization/gd:orgTitle").size).to eq(1)
|
407
|
+
expect(c.search("./gd:organization/gd:orgTitle").inner_text).to eq("Coder")
|
408
|
+
|
409
|
+
expect(c.search("./gContact:groupMembershipInfo").size).to eq(2)
|
410
|
+
expect(c.search("./gContact:groupMembershipInfo").map { |e| e[:deleted] }).to eq(["false", "false"])
|
411
|
+
|
412
|
+
expect(c.search("./gContact:userDefinedField").size).to eq(1)
|
413
|
+
expect(c.search("./gContact:userDefinedField")[0][:key]).to eq("own key")
|
414
|
+
expect(c.search("./gContact:userDefinedField")[0][:value]).to eq("Own value")
|
415
|
+
|
416
|
+
websites = c.search("./gContact:website")
|
417
|
+
expect(websites.map { |e| e[:href] }.sort).to eq(["glowna.com", "sluzbowy.com"].sort)
|
418
|
+
expect(websites.map { |e| e[:rel] }.sort).to eq(["work", "home-page"].sort)
|
419
|
+
end
|
420
|
+
|
421
|
+
context "google api expectations" do
|
422
|
+
it "should send application/xml+atom content type for contacts" do
|
423
|
+
headers = GoogleR::Contact.api_headers
|
424
|
+
expect(headers).to have_key("Content-Type")
|
425
|
+
expect(headers["Content-Type"]).to eq("application/atom+xml")
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|