context-io 0.0.1
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.
- 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
|