context-io 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +129 -0
- data/Rakefile +121 -0
- data/SPEC.md +49 -0
- data/context-io.gemspec +96 -0
- data/lib/context-io.rb +14 -0
- data/lib/context-io/account.rb +254 -0
- data/lib/context-io/authentication.rb +23 -0
- data/lib/context-io/config.rb +103 -0
- data/lib/context-io/connection.rb +45 -0
- data/lib/context-io/core_ext/hash.rb +31 -0
- data/lib/context-io/error.rb +24 -0
- data/lib/context-io/error/bad_request.rb +12 -0
- data/lib/context-io/error/client_error.rb +10 -0
- data/lib/context-io/error/forbidden.rb +12 -0
- data/lib/context-io/error/internal_server_error.rb +10 -0
- data/lib/context-io/error/not_found.rb +12 -0
- data/lib/context-io/error/payment_required.rb +13 -0
- data/lib/context-io/error/server_error.rb +10 -0
- data/lib/context-io/error/service_unavailable.rb +13 -0
- data/lib/context-io/error/unauthorized.rb +12 -0
- data/lib/context-io/file.rb +234 -0
- data/lib/context-io/folder.rb +90 -0
- data/lib/context-io/message.rb +160 -0
- data/lib/context-io/oauth_provider.rb +84 -0
- data/lib/context-io/request.rb +70 -0
- data/lib/context-io/request/oauth.rb +44 -0
- data/lib/context-io/resource.rb +16 -0
- data/lib/context-io/response.rb +5 -0
- data/lib/context-io/response/parse_json.rb +30 -0
- data/lib/context-io/response/raise_client_error.rb +59 -0
- data/lib/context-io/response/raise_server_error.rb +32 -0
- data/lib/context-io/source.rb +193 -0
- data/lib/context-io/version.rb +7 -0
- data/spec/account_spec.rb +247 -0
- data/spec/contextio_spec.rb +45 -0
- data/spec/file_spec.rb +101 -0
- data/spec/fixtures/accounts.json +21 -0
- data/spec/fixtures/files.json +41 -0
- data/spec/fixtures/files_group.json +47 -0
- data/spec/fixtures/folders.json +1 -0
- data/spec/fixtures/messages.json +1 -0
- data/spec/fixtures/oauth_providers.json +12 -0
- data/spec/fixtures/sources.json +1 -0
- data/spec/folder_spec.rb +48 -0
- data/spec/message_spec.rb +294 -0
- data/spec/oauth_provider_spec.rb +88 -0
- data/spec/source_spec.rb +248 -0
- data/spec/spec_helper.rb +4 -0
- metadata +214 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ContextIO do
|
4
|
+
after do
|
5
|
+
ContextIO.reset
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.adapter' do
|
9
|
+
it 'should return the default adapter' do
|
10
|
+
ContextIO.adapter.should == ContextIO::Config::DEFAULT_ADAPTER
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.adapter=' do
|
15
|
+
it 'should set the adapter' do
|
16
|
+
ContextIO.adapter = :typhoeus
|
17
|
+
ContextIO.adapter.should == :typhoeus
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.user_agent' do
|
22
|
+
it 'should return the default user agent' do
|
23
|
+
ContextIO.user_agent.should == ContextIO::Config::DEFAULT_USER_AGENT
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.user_agent=' do
|
28
|
+
it 'should set the user agent' do
|
29
|
+
ContextIO.user_agent = 'Custom User Agent'
|
30
|
+
ContextIO.user_agent.should == 'Custom User Agent'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.configure' do
|
35
|
+
ContextIO::Config::VALID_OPTIONS_KEYS.each do |key|
|
36
|
+
it "should set the #{key}" do
|
37
|
+
ContextIO.configure do |config|
|
38
|
+
config.send("#{key}=", key)
|
39
|
+
ContextIO.send(key).should == key
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
data/spec/file_spec.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ContextIO::File do
|
4
|
+
before(:each) do
|
5
|
+
@fixtures_path = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
|
6
|
+
account_id = 'abcdef1234567890'
|
7
|
+
@account = ContextIO::Account.new
|
8
|
+
@account.instance_eval do
|
9
|
+
# TODO: Tests shouldn't rely on internal state...
|
10
|
+
@id = account_id
|
11
|
+
end
|
12
|
+
@files_url = "https://api.context.io/2.0/accounts/#{account_id}/files"
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.all' do
|
16
|
+
before(:each) do
|
17
|
+
json_files = File.read(File.join(@fixtures_path, 'files.json'))
|
18
|
+
@request = stub_request(:get, @files_url).to_return(:body => json_files)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns an array of File objects' do
|
22
|
+
ContextIO::File.all(@account).first.should be_a(ContextIO::File)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'calls the API request' do
|
26
|
+
ContextIO::File.all(@account)
|
27
|
+
|
28
|
+
@request.should have_been_requested
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'sends a query if one is given' do
|
32
|
+
@request.with(:query => { :email => 'me@example.com'})
|
33
|
+
|
34
|
+
ContextIO::File.all(@account, :email => 'me@example.com')
|
35
|
+
|
36
|
+
@request.should have_been_requested
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'supports searching for a filename with a regexp' do
|
40
|
+
@request.with(:query => { :file_name => '/\.pdf$/'})
|
41
|
+
|
42
|
+
ContextIO::File.all(@account, :file_name => /\.pdf$/)
|
43
|
+
|
44
|
+
@request.should have_been_requested
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'converts Time objects to integer timestamps' do
|
48
|
+
time = Time.now
|
49
|
+
@request.with(:query => { :date_before => time.to_i.to_s })
|
50
|
+
|
51
|
+
ContextIO::File.all(@account, :date_before => time)
|
52
|
+
|
53
|
+
@request.should have_been_requested
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'group_by_revisions' do
|
57
|
+
before(:each) do
|
58
|
+
json_files = File.read(File.join(@fixtures_path, 'files_group.json'))
|
59
|
+
@request = stub_request(:get, @files_url).
|
60
|
+
with(:query => { :group_by_revisions => '1' }).
|
61
|
+
to_return(:body => json_files)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'converts occurences to File objects' do
|
65
|
+
files = ContextIO::File.all(@account, :group_by_revisions => true)
|
66
|
+
files.first[:occurences].first.should be_a(ContextIO::File)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'converts latest_date to a Time object' do
|
70
|
+
files = ContextIO::File.all(@account, :group_by_revisions => true)
|
71
|
+
files.first[:latest_date].should be_a(Time)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#content' do
|
77
|
+
before(:each) do
|
78
|
+
json_files = MultiJson.decode(File.read(File.join(@fixtures_path, 'files.json')))
|
79
|
+
file = json_files.first
|
80
|
+
@file_url = "#@files_url/#{file['file_id']}"
|
81
|
+
@request = stub_request(:get, @file_url).to_return(:body => MultiJson.encode(file))
|
82
|
+
@file = ContextIO::File.from_json(@account.id, file)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'calls the API request' do
|
86
|
+
request = stub_request(:get, "#@file_url/content")
|
87
|
+
|
88
|
+
@file.content
|
89
|
+
|
90
|
+
request.should have_been_requested
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'does not parse the response' do
|
94
|
+
content = '{ "foo": "bar" }'
|
95
|
+
request = stub_request(:get, "#@file_url/content").
|
96
|
+
to_return(:body => content)
|
97
|
+
|
98
|
+
@file.content.should == content
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
[{"id": "abcdef0123456789",
|
2
|
+
"username": "me.example.com_1234567890abcdef",
|
3
|
+
"created": 1234567890,
|
4
|
+
"suspended": 0,
|
5
|
+
"email_addresses": [ "me@example.com" ],
|
6
|
+
"first_name": "John",
|
7
|
+
"last_name": "Doe",
|
8
|
+
"password_expired": 0,
|
9
|
+
"sources": [{
|
10
|
+
"server": "mail.example.com",
|
11
|
+
"label": "me::mail.example.com",
|
12
|
+
"username": "me",
|
13
|
+
"port": 993,
|
14
|
+
"authentication_type": "password",
|
15
|
+
"use_ssl": true,
|
16
|
+
"sync_period": "1d",
|
17
|
+
"status": "OK",
|
18
|
+
"service_level": "pro",
|
19
|
+
"type": "imap"
|
20
|
+
}]
|
21
|
+
}]
|
@@ -0,0 +1,41 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"size": 123456,
|
4
|
+
"type": "application/octet-stream",
|
5
|
+
"subject": "A subject",
|
6
|
+
"date": 1234567890,
|
7
|
+
"addresses": {
|
8
|
+
"from": {
|
9
|
+
"email": "you@example.com"
|
10
|
+
},
|
11
|
+
"to": [{
|
12
|
+
"email": "me@example.com"
|
13
|
+
}]
|
14
|
+
},
|
15
|
+
"file_name": "a_file.pdf",
|
16
|
+
"body_section": 3,
|
17
|
+
"file_id": "0987654321abcdef",
|
18
|
+
"supports_preview": true,
|
19
|
+
"message_id": "0987654321fedcba",
|
20
|
+
"date_indexed": 1234567900,
|
21
|
+
"email_message_id": "<0192837465ABCDEFABCDEF@ABCDEFGHIJK>",
|
22
|
+
"person_info": {
|
23
|
+
"you@example.com": {
|
24
|
+
"thumbnail": "http://example.com/you.png"
|
25
|
+
},
|
26
|
+
"me@example.com": {
|
27
|
+
"thumbnail": "http://example.com/me.com"
|
28
|
+
}
|
29
|
+
},
|
30
|
+
"file_name_structure": [
|
31
|
+
[
|
32
|
+
"a_file",
|
33
|
+
"main"
|
34
|
+
],
|
35
|
+
[
|
36
|
+
".pdf",
|
37
|
+
"ext"
|
38
|
+
]
|
39
|
+
]
|
40
|
+
}
|
41
|
+
]
|
@@ -0,0 +1,47 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"occurences": [
|
4
|
+
{
|
5
|
+
"size": 123456,
|
6
|
+
"type": "application/octet-stream",
|
7
|
+
"subject": "A subject",
|
8
|
+
"date": 1234567890,
|
9
|
+
"addresses": {
|
10
|
+
"from": {
|
11
|
+
"email": "you@example.com"
|
12
|
+
},
|
13
|
+
"to": [{
|
14
|
+
"email": "me@example.com"
|
15
|
+
}]
|
16
|
+
},
|
17
|
+
"file_name": "a_file.pdf",
|
18
|
+
"body_section": 3,
|
19
|
+
"file_id": "0987654321abcdef",
|
20
|
+
"supports_preview": true,
|
21
|
+
"message_id": "0987654321fedcba",
|
22
|
+
"date_indexed": 1234567900,
|
23
|
+
"email_message_id": "<0192837465ABCDEFABCDEF@ABCDEFGHIJK>",
|
24
|
+
"person_info": {
|
25
|
+
"you@example.com": {
|
26
|
+
"thumbnail": "http://example.com/you.png"
|
27
|
+
},
|
28
|
+
"me@example.com": {
|
29
|
+
"thumbnail": "http://example.com/me.com"
|
30
|
+
}
|
31
|
+
},
|
32
|
+
"file_name_structure": [
|
33
|
+
[
|
34
|
+
"a_file",
|
35
|
+
"main"
|
36
|
+
],
|
37
|
+
[
|
38
|
+
".pdf",
|
39
|
+
"ext"
|
40
|
+
]
|
41
|
+
]
|
42
|
+
}
|
43
|
+
],
|
44
|
+
"file_name": "a_file.pdf",
|
45
|
+
"latest_date": 1234567890
|
46
|
+
}
|
47
|
+
]
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"name":"Follow up","nb_messages":"0","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/"},{"name":"INBOX","nb_messages":"15","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/"},{"name":"Misc","nb_messages":"0","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/"},{"name":"Priority","nb_messages":"0","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/"},{"name":"[Gmail]/All Mail","nb_messages":20,"delim":"/","symbolic_name":"\\AllMail","included_in_sync":true},{"name":"[Gmail]/Drafts","nb_messages":"0","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/","symbolic_name":"\\Drafts"},{"name":"[Gmail]/Important","nb_messages":"3","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/","symbolic_name":"\\Important"},{"name":"[Gmail]/Sent Mail","nb_messages":"1","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/","symbolic_name":"\\Sent"},{"name":"[Gmail]/Starred","nb_messages":"0","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":false,"Noselect":false,"HasNoChildren":true},"delim":"/","symbolic_name":"\\Starred"},{"name":"[Gmail]/Trash","nb_messages":"1","attributes":{"Noinferiors":false,"Marked":false,"HasChildren":true,"Noselect":false,"HasNoChildren":true},"delim":"/","symbolic_name":"\\Trash"}]
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"date_indexed":1326390355,"person_info":{"james@example.com":{"thumbnail":"https://secure.gravatar.com/avatar/da027b7f882991709b63a08e7e300221?s=50&d=https%3A%2F%2Fapp.dokdok.com%2Findex.php%3Fdo%3Dusrgetimg%26id%3D-1"},"mail-noreply@google.com":{"thumbnail":"https://secure.gravatar.com/avatar/eee980fd43816c612e888a1b63907aef?s=50&d=https%3A%2F%2Fapp.dokdok.com%2Findex.php%3Fdo%3Dusrgetimg%26id%3D-1"}},"gmail_message_id":"1339e889bae8fff8","email_message_id":"<CA+him2-bVdNrrugkU7rkDtj-Wn-gk2d=bPiBBWk+iagtVV1csQ@mail.gmail.com>","addresses":{"from":{"name":"Gmail Team","email":"mail-noreply@google.com"},"to":[{"name":"James Dean","email":"james@example.com"}]},"subject":"Get Gmail on your mobile phone","date":1321214712,"gmail_thread_id":"1339e889bae8fff8","sources":[{"label":"james@example.com::imap.googlemail.com","resource_url":"https://api.context.io/2.0/accounts/4f0f1c4f3f757edc3b000002/sources/james%40example.com%3A%3Aimap.googlemail.com"}],"folders":["\\Inbox","INBOX"],"message_id":"4f0f1c533f757e0f3c00000b"},{"date_indexed":1326390355,"person_info":{"james@example.com":{"thumbnail":"https://secure.gravatar.com/avatar/da027b7f882991709b63a08e7e300221?s=50&d=https%3A%2F%2Fapp.dokdok.com%2Findex.php%3Fdo%3Dusrgetimg%26id%3D-1"},"mail-noreply@google.com":{"thumbnail":"https://secure.gravatar.com/avatar/eee980fd43816c612e888a1b63907aef?s=50&d=https%3A%2F%2Fapp.dokdok.com%2Findex.php%3Fdo%3Dusrgetimg%26id%3D-1"}},"gmail_message_id":"1339e889bcda5676","email_message_id":"<CA+him2_6bjYfmDmM9ai5N3bDovACCKUwb5XWCc1XRn=7LdTsQA@mail.gmail.com>","addresses":{"from":{"name":"Gmail Team","email":"mail-noreply@google.com"},"to":[{"name":"James Dean","email":"james@example.com"}]},"subject":"Customize Gmail with colors and themes","date":1321214712,"gmail_thread_id":"1339e889bcda5676","sources":[{"label":"james@example.com::imap.googlemail.com","resource_url":"https://api.context.io/2.0/accounts/4f0f1c4f3f757edc3b000002/sources/james%40example.com%3A%3Aimap.googlemail.com"}],"folders":["\\Inbox","INBOX"],"message_id":"4f0f1c533f757e0f3c00000c"}]
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"label":"bi@example.com::imap.example.com","authentication_type":"oauth","port":993,"service_level":"pro","username":"bi@example.com","server":"imap.example.com","type":"imap","sync_period":"1d","use_ssl":true,"status":"OK"}]
|
data/spec/folder_spec.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ContextIO::Folder do
|
4
|
+
before(:each) do
|
5
|
+
@fixtures_path = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
|
6
|
+
account_id = 'abcdef1234567890'
|
7
|
+
@account = ContextIO::Account.new
|
8
|
+
@account.instance_eval do
|
9
|
+
@id = account_id
|
10
|
+
end
|
11
|
+
source_label = 'me@example.com::imap.example.com'
|
12
|
+
@source = ContextIO::Source.new(account_id)
|
13
|
+
@source.instance_eval { @label = source_label }
|
14
|
+
|
15
|
+
@folders_url = "https://api.context.io/2.0/accounts/#{account_id}/sources/#{source_label}/folders"
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.all' do
|
19
|
+
before(:each) do
|
20
|
+
json_folders = File.read(File.join(@fixtures_path, 'folders.json'))
|
21
|
+
@response = stub_request(:get, @folders_url).
|
22
|
+
to_return(:body => json_folders)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'accepts a Source object as an argument' do
|
26
|
+
expect { ContextIO::Folder.all(@source) }.to_not raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'accepts an account ID and a source label as arguments' do
|
30
|
+
expect { ContextIO::Folder.all(@account.id, @source.label) }.to_not raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns an array of Folder objects' do
|
34
|
+
folders = ContextIO::Folder.all(@source)
|
35
|
+
folders.first.should be_a(ContextIO::Folder)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'calls the API method' do
|
39
|
+
ContextIO::Folder.all(@source)
|
40
|
+
@response.should have_been_requested
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'sets the name of Folder object' do
|
44
|
+
folder = ContextIO::Folder.all(@source).first
|
45
|
+
folder.name.should == 'Follow up'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,294 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ContextIO::Message do
|
4
|
+
before(:each) do
|
5
|
+
@fixtures_path = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
|
6
|
+
account_id = 'abcdef1234567890'
|
7
|
+
@account = ContextIO::Account.new
|
8
|
+
@account.instance_eval do
|
9
|
+
@id = account_id
|
10
|
+
end
|
11
|
+
@messages_url = "https://api.context.io/2.0/accounts/#{account_id}/messages"
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.all' do
|
16
|
+
before(:each) do
|
17
|
+
json_messages = File.read(File.join(@fixtures_path, 'messages.json'))
|
18
|
+
@response = stub_request(:get, @messages_url).
|
19
|
+
to_return(:body => json_messages)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns an array of Message objects for given account ID' do
|
23
|
+
messages = ContextIO::Message.all(@account.id)
|
24
|
+
messages.should be_a(Array)
|
25
|
+
messages.first.should be_a(ContextIO::Message)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns an array of Message objects for given Account object' do
|
29
|
+
messages = ContextIO::Message.all(@account)
|
30
|
+
messages.should be_a(Array)
|
31
|
+
messages.first.should be_a(ContextIO::Message)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns empty array when no account is given' do
|
35
|
+
messages = ContextIO::Message.all(nil)
|
36
|
+
messages.should be_a(Array)
|
37
|
+
messages.length.should == 0
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'calls the API method' do
|
41
|
+
ContextIO::Message.all(@account)
|
42
|
+
@response.should have_been_requested
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'sets attributes of Message object' do
|
46
|
+
msg = ContextIO::Message.all(@account).first
|
47
|
+
msg.message_id.should == '4f0f1c533f757e0f3c00000b'
|
48
|
+
msg.subject.should == 'Get Gmail on your mobile phone'
|
49
|
+
msg.from['name'].should == 'Gmail Team'
|
50
|
+
msg.to.length.should == 1
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'sends query' do
|
54
|
+
q = {
|
55
|
+
:subject => 'Some subject',
|
56
|
+
:email => 'james@example.net',
|
57
|
+
:to => 'james@example.com',
|
58
|
+
:limit => '30',
|
59
|
+
:offset => '30'
|
60
|
+
}
|
61
|
+
|
62
|
+
@response = @response.with(:query => q)
|
63
|
+
|
64
|
+
ContextIO::Message.all(@account, q)
|
65
|
+
@response.should have_been_requested
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'message flags' do
|
70
|
+
before(:each) do
|
71
|
+
@msg_id = '4f0f1c533f757e0f3c00000b'
|
72
|
+
json_messages = File.read(File.join(@fixtures_path, 'messages.json'))
|
73
|
+
@response = stub_request(:get, @messages_url).
|
74
|
+
to_return(:body => json_messages)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'retrieves flags' do
|
78
|
+
flags_response = stub_request(:get, "#{@messages_url}/#{@msg_id}/flags").
|
79
|
+
to_return(:body => '{"answered":false,"draft":false,"deleted":false,"seen":true,"flagged":false}')
|
80
|
+
flags = ContextIO::Message.all(@account).first.flags
|
81
|
+
flags.should be_a(Hash)
|
82
|
+
flags['seen'].should == true
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'sets read flag' do
|
86
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
87
|
+
with(:body => { "seen" => "true" }).
|
88
|
+
to_return(:body => '{"success":true}')
|
89
|
+
ContextIO::Message.all(@account).first.read!.should be_true
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'resets read flag' do
|
93
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
94
|
+
with(:body => { "seen" => "false" }).
|
95
|
+
to_return(:body => '{"success":true}')
|
96
|
+
ContextIO::Message.all(@account).first.unread!.should be_true
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'sets flagged flag' do
|
100
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
101
|
+
with(:body => { "flagged" => "true" }).
|
102
|
+
to_return(:body => '{"success":true}')
|
103
|
+
ContextIO::Message.all(@account).first.flagged!.should be_true
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'resets flagged flag' do
|
107
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
108
|
+
with(:body => { "flagged" => "false" }).
|
109
|
+
to_return(:body => '{"success":true}')
|
110
|
+
ContextIO::Message.all(@account).first.unflagged!.should be_true
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'sets answered flag' do
|
114
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
115
|
+
with(:body => { "answered" => "true" }).
|
116
|
+
to_return(:body => '{"success":true}')
|
117
|
+
ContextIO::Message.all(@account).first.answered!.should be_true
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'resets answered flag' do
|
121
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
122
|
+
with(:body => { "answered" => "false" }).
|
123
|
+
to_return(:body => '{"success":true}')
|
124
|
+
ContextIO::Message.all(@account).first.unanswered!.should be_true
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'sets draft flag' do
|
128
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
129
|
+
with(:body => { "draft" => "true" }).
|
130
|
+
to_return(:body => '{"success":true}')
|
131
|
+
ContextIO::Message.all(@account).first.draft!.should be_true
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'resets draft flag' do
|
135
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
136
|
+
with(:body => { "draft" => "false" }).
|
137
|
+
to_return(:body => '{"success":true}')
|
138
|
+
ContextIO::Message.all(@account).first.undraft!.should be_true
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'sets deleted flag' do
|
142
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
143
|
+
with(:body => { "deleted" => "true" }).
|
144
|
+
to_return(:body => '{"success":true}')
|
145
|
+
ContextIO::Message.all(@account).first.delete!.should be_true
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'resets deleted flag' do
|
149
|
+
flags_response = stub_request(:post, "#{@messages_url}/#{@msg_id}/flags").
|
150
|
+
with(:body => { "deleted" => "false" }).
|
151
|
+
to_return(:body => '{"success":true}')
|
152
|
+
ContextIO::Message.all(@account).first.undelete!.should be_true
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe 'thread' do
|
157
|
+
before(:each) do
|
158
|
+
json_messages = File.read(File.join(@fixtures_path, 'messages.json'))
|
159
|
+
thread_messages = "{\"messages\": #{json_messages}}"
|
160
|
+
stub_request(:get, @messages_url).to_return(:body => json_messages)
|
161
|
+
msg_id = '4f0f1c533f757e0f3c00000b'
|
162
|
+
@response = stub_request(:get, "#{@messages_url}/#{msg_id}/thread").
|
163
|
+
to_return(:body => thread_messages)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'returns array of Message objects' do
|
167
|
+
thread = ContextIO::Message.all(@account).first.thread
|
168
|
+
thread.should be_a(Array)
|
169
|
+
thread.first.should be_a(ContextIO::Message)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'calls API method' do
|
173
|
+
ContextIO::Message.all(@account).first.thread
|
174
|
+
@response.should have_been_requested
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe 'body and headers lazy loading' do
|
179
|
+
before(:each) do
|
180
|
+
msg_id = '4f0f1c533f757e0f3c00000b'
|
181
|
+
body = '[
|
182
|
+
{
|
183
|
+
"type": "text/plain",
|
184
|
+
"content":"Just a message"
|
185
|
+
},
|
186
|
+
{
|
187
|
+
"type": "text/html",
|
188
|
+
"content": "<html><p>Just a message</p></html>"
|
189
|
+
}]'
|
190
|
+
headers = '{"Received":"by 10.10.1.1"}'
|
191
|
+
json_messages = File.read(File.join(@fixtures_path, 'messages.json'))
|
192
|
+
stub_request(:get, @messages_url).
|
193
|
+
to_return(:body => json_messages)
|
194
|
+
@body_resp = stub_request(:get, "#{@messages_url}/#{msg_id}/body").
|
195
|
+
to_return(:body => body)
|
196
|
+
@headers_resp = stub_request(:get, "#{@messages_url}/#{msg_id}/headers").
|
197
|
+
to_return(:body => headers)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'requests body on first access' do
|
201
|
+
msg = ContextIO::Message.all(@account).first
|
202
|
+
msg.body.should == 'Just a message'
|
203
|
+
msg.body('html').start_with?('<html>').should be_true
|
204
|
+
@body_resp.should have_been_requested
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'does not request body on second request' do
|
208
|
+
msg = ContextIO::Message.all(@account).first
|
209
|
+
msg.body
|
210
|
+
msg.body
|
211
|
+
@body_resp.should have_been_made.once
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'requests headers' do
|
215
|
+
msg = ContextIO::Message.all(@account).first
|
216
|
+
msg.headers.should be_a(Hash)
|
217
|
+
msg.headers['Received'].should == 'by 10.10.1.1'
|
218
|
+
@headers_resp.should have_been_requested
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'does not request headers on second request' do
|
222
|
+
msg = ContextIO::Message.all(@account).first
|
223
|
+
msg.headers
|
224
|
+
msg.headers
|
225
|
+
@headers_resp.should have_been_made.once
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "copy" do
|
230
|
+
before(:each) do
|
231
|
+
msgs = MultiJson.decode(File.read(File.join(@fixtures_path, 'messages.json')))
|
232
|
+
@message = ContextIO::Message.from_json(@account.id, msgs.first)
|
233
|
+
copy_options = {:dst_folder => "Important", :move => '0'}
|
234
|
+
copy_to_source = {:dst_folder => "Important", :dst_source => "Other Source", :move => '0'}
|
235
|
+
@copy_response = stub_request(:post, "#{@messages_url}/#{@message.message_id}").
|
236
|
+
with(:body => copy_options)
|
237
|
+
@copy_to_source_response = stub_request(:post, "#{@messages_url}/#{@message.message_id}").
|
238
|
+
with(:body => copy_to_source)
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'raises ArgumentError for empty target folder' do
|
242
|
+
lambda { @message.copy(nil) }.should raise_error ArgumentError
|
243
|
+
end
|
244
|
+
|
245
|
+
it "copy calls API method with copy options" do
|
246
|
+
@message.copy("Important")
|
247
|
+
@copy_response.should have_been_requested
|
248
|
+
end
|
249
|
+
|
250
|
+
it "copy to source calls API method with source in post arguments" do
|
251
|
+
@message.copy("Important", "Other Source")
|
252
|
+
@copy_to_source_response.should have_been_requested
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe "move" do
|
257
|
+
before(:each) do
|
258
|
+
msgs = MultiJson.decode(File.read(File.join(@fixtures_path, 'messages.json')))
|
259
|
+
@message = ContextIO::Message.from_json(@account.id, msgs.first)
|
260
|
+
move_options = {:dst_folder => "Important", :move => '1'}
|
261
|
+
@move_response = stub_request(:post, "#{@messages_url}/#{@message.message_id}").
|
262
|
+
with(:body => move_options)
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'raises ArgumentError for empty target folder' do
|
266
|
+
lambda { @message.move(nil) }.should raise_error ArgumentError
|
267
|
+
end
|
268
|
+
|
269
|
+
it "move calls API method with move options" do
|
270
|
+
@message.move("Important")
|
271
|
+
@move_response.should have_been_requested
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe '.find' do
|
276
|
+
before(:each) do
|
277
|
+
@messages = MultiJson.decode(File.read(File.join(@fixtures_path, 'messages.json')))
|
278
|
+
@find_url = "#{@messages_url}/#{@messages.first['message_id']}"
|
279
|
+
@response = stub_request(:get, @find_url).
|
280
|
+
to_return(:body => MultiJson.encode(@messages.first))
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'calls API method' do
|
284
|
+
ContextIO::Message.find(@account, @messages.first['message_id'])
|
285
|
+
@response.should have_been_requested
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'returns single message for given ID' do
|
289
|
+
msg = ContextIO::Message.find(@account, @messages.first['message_id'])
|
290
|
+
msg.should be_a(ContextIO::Message)
|
291
|
+
msg.message_id.should == @messages.first['message_id']
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|