gmail 0.4.0 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +26 -25
- data/.rspec +2 -0
- data/CHANGELOG.md +82 -82
- data/Gemfile +3 -0
- data/LICENSE +21 -21
- data/README.md +271 -251
- data/Rakefile +35 -45
- data/TODO.md +12 -7
- data/gmail.gemspec +34 -23
- data/lib/gmail.rb +65 -82
- data/lib/gmail/client.rb +30 -22
- data/lib/gmail/client/base.rb +225 -220
- data/lib/gmail/client/imap_extensions.rb +54 -0
- data/lib/gmail/client/plain.rb +20 -18
- data/lib/gmail/client/xoauth.rb +51 -49
- data/lib/gmail/labels.rb +62 -48
- data/lib/gmail/mailbox.rb +117 -117
- data/lib/gmail/message.rb +166 -164
- data/lib/gmail/version.rb +3 -12
- data/spec/account.yml.example +1 -1
- data/spec/client_spec.rb +178 -173
- data/spec/gmail_spec.rb +39 -38
- data/spec/mailbox_spec.rb +47 -49
- data/spec/message_spec.rb +51 -51
- data/spec/spec_helper.rb +28 -28
- metadata +109 -110
data/lib/gmail/message.rb
CHANGED
@@ -1,164 +1,166 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
when :
|
36
|
-
when :
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
#
|
99
|
-
#
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
#
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
return true
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
1
|
+
module Gmail
|
2
|
+
class Message
|
3
|
+
# Raised when given label doesn't exists.
|
4
|
+
class NoLabelError < Exception; end
|
5
|
+
|
6
|
+
attr_reader :uid
|
7
|
+
|
8
|
+
def initialize(mailbox, uid)
|
9
|
+
@uid = uid
|
10
|
+
@mailbox = mailbox
|
11
|
+
@gmail = mailbox.instance_variable_get("@gmail") if mailbox
|
12
|
+
end
|
13
|
+
|
14
|
+
def labels
|
15
|
+
@gmail.conn.uid_fetch(uid, "X-GM-LABELS")[0].attr["X-GM-LABELS"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def uid
|
19
|
+
@uid ||= @gmail.conn.uid_search(['HEADER', 'Message-ID', message_id])[0]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Mark message with given flag.
|
23
|
+
def flag(name)
|
24
|
+
!!@gmail.mailbox(@mailbox.name) { @gmail.conn.uid_store(uid, "+FLAGS", [name]) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Unmark message.
|
28
|
+
def unflag(name)
|
29
|
+
!!@gmail.mailbox(@mailbox.name) { @gmail.conn.uid_store(uid, "-FLAGS", [name]) }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Do commonly used operations on message.
|
33
|
+
def mark(flag)
|
34
|
+
case flag
|
35
|
+
when :read then read!
|
36
|
+
when :unread then unread!
|
37
|
+
when :deleted then delete!
|
38
|
+
when :spam then spam!
|
39
|
+
else
|
40
|
+
flag(flag)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Mark this message as a spam.
|
45
|
+
def spam!
|
46
|
+
move_to('[Gmail]/Spam')
|
47
|
+
end
|
48
|
+
|
49
|
+
# Mark as read.
|
50
|
+
def read!
|
51
|
+
flag(:Seen)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Mark as unread.
|
55
|
+
def unread!
|
56
|
+
unflag(:Seen)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Mark message with star.
|
60
|
+
def star!
|
61
|
+
flag('[Gmail]/Starred')
|
62
|
+
end
|
63
|
+
|
64
|
+
# Remove message from list of starred.
|
65
|
+
def unstar!
|
66
|
+
unflag('[Gmail]/Starred')
|
67
|
+
end
|
68
|
+
|
69
|
+
# Move to trash / bin.
|
70
|
+
def delete!
|
71
|
+
@mailbox.messages.delete(uid)
|
72
|
+
flag(:deleted)
|
73
|
+
|
74
|
+
# For some, it's called "Trash", for others, it's called "Bin". Support both.
|
75
|
+
trash = @gmail.labels.exist?('[Gmail]/Bin') ? '[Gmail]/Bin' : '[Gmail]/Trash'
|
76
|
+
move_to(trash) unless %w[[Gmail]/Spam [Gmail]/Bin [Gmail]/Trash].include?(@mailbox.name)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Archive this message.
|
80
|
+
def archive!
|
81
|
+
move_to('[Gmail]/All Mail')
|
82
|
+
end
|
83
|
+
|
84
|
+
# Move to given box and delete from others.
|
85
|
+
def move_to(name, from=nil)
|
86
|
+
label(name, from)
|
87
|
+
delete! if !%w[[Gmail]/Bin [Gmail]/Trash].include?(name)
|
88
|
+
end
|
89
|
+
alias :move :move_to
|
90
|
+
|
91
|
+
# Move message to given and delete from others. When given mailbox doesn't
|
92
|
+
# exist then it will be automaticaly created.
|
93
|
+
def move_to!(name, from=nil)
|
94
|
+
label!(name, from) && delete!
|
95
|
+
end
|
96
|
+
alias :move! :move_to!
|
97
|
+
|
98
|
+
# Mark this message with given label. When given label doesn't exist then
|
99
|
+
# it will raise <tt>NoLabelError</tt>.
|
100
|
+
#
|
101
|
+
# See also <tt>Gmail::Message#label!</tt>.
|
102
|
+
def label(name, from=nil)
|
103
|
+
@gmail.mailbox(Net::IMAP.encode_utf7(from || @mailbox.external_name)) { @gmail.conn.uid_copy(uid, Net::IMAP.encode_utf7(name)) }
|
104
|
+
rescue Net::IMAP::NoResponseError
|
105
|
+
raise NoLabelError, "Label '#{name}' doesn't exist!"
|
106
|
+
end
|
107
|
+
|
108
|
+
# Mark this message with given label. When given label doesn't exist then
|
109
|
+
# it will be automaticaly created.
|
110
|
+
#
|
111
|
+
# See also <tt>Gmail::Message#label</tt>.
|
112
|
+
def label!(name, from=nil)
|
113
|
+
label(name, from)
|
114
|
+
rescue NoLabelError
|
115
|
+
@gmail.labels.add(Net::IMAP.encode_utf7(name))
|
116
|
+
label(name, from)
|
117
|
+
end
|
118
|
+
alias :add_label :label!
|
119
|
+
alias :add_label! :label!
|
120
|
+
|
121
|
+
# Remove given label from this message.
|
122
|
+
def remove_label!(name)
|
123
|
+
move_to('[Gmail]/All Mail', name)
|
124
|
+
end
|
125
|
+
alias :delete_label! :remove_label!
|
126
|
+
|
127
|
+
def inspect
|
128
|
+
"#<Gmail::Message#{'0x%04x' % (object_id << 1)} mailbox=#{@mailbox.external_name}#{' uid='+@uid.to_s if @uid}#{' message_id='+@message_id.to_s if @message_id}>"
|
129
|
+
end
|
130
|
+
|
131
|
+
def method_missing(meth, *args, &block)
|
132
|
+
# Delegate rest directly to the message.
|
133
|
+
if envelope.respond_to?(meth)
|
134
|
+
envelope.send(meth, *args, &block)
|
135
|
+
elsif message.respond_to?(meth)
|
136
|
+
message.send(meth, *args, &block)
|
137
|
+
else
|
138
|
+
super(meth, *args, &block)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def respond_to?(meth, *args, &block)
|
143
|
+
if envelope.respond_to?(meth)
|
144
|
+
return true
|
145
|
+
elsif message.respond_to?(meth)
|
146
|
+
return true
|
147
|
+
else
|
148
|
+
super(meth, *args, &block)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def envelope
|
153
|
+
@envelope ||= @gmail.mailbox(@mailbox.name) {
|
154
|
+
@gmail.conn.uid_fetch(uid, "ENVELOPE")[0].attr["ENVELOPE"]
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
158
|
+
def message
|
159
|
+
@message ||= Mail.new(@gmail.mailbox(@mailbox.name) {
|
160
|
+
@gmail.conn.uid_fetch(uid, "RFC822")[0].attr["RFC822"] # RFC822
|
161
|
+
})
|
162
|
+
end
|
163
|
+
alias_method :raw_message, :message
|
164
|
+
|
165
|
+
end # Message
|
166
|
+
end # Gmail
|
data/lib/gmail/version.rb
CHANGED
@@ -1,12 +1,3 @@
|
|
1
|
-
module Gmail
|
2
|
-
|
3
|
-
|
4
|
-
MINOR = 4
|
5
|
-
PATCH = 0
|
6
|
-
STRING = [MAJOR, MINOR, PATCH].join('.')
|
7
|
-
end # Version
|
8
|
-
|
9
|
-
def self.version # :nodoc:
|
10
|
-
Version::STRING
|
11
|
-
end
|
12
|
-
end # Gmail
|
1
|
+
module Gmail
|
2
|
+
VERSION = "0.4.2"
|
3
|
+
end # Gmail
|
data/spec/account.yml.example
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
- "test@gmail.com"
|
1
|
+
- "test@gmail.com"
|
2
2
|
- "test"
|
data/spec/client_spec.rb
CHANGED
@@ -1,173 +1,178 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Gmail client (Plain)" do
|
4
|
-
subject { Gmail::Client::Plain }
|
5
|
-
|
6
|
-
context "on initialize" do
|
7
|
-
it "should set username, password and options" do
|
8
|
-
client = subject.new("test@gmail.com", "pass", :foo => :bar)
|
9
|
-
client.username.should == "test@gmail.com"
|
10
|
-
client.password.should == "pass"
|
11
|
-
client.options[:foo].should == :bar
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should convert simple name to gmail email" do
|
15
|
-
client = subject.new("test", "pass")
|
16
|
-
client.username.should == "test@gmail.com"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context "instance" do
|
21
|
-
def mock_client(&block)
|
22
|
-
client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
|
23
|
-
if block_given?
|
24
|
-
client.connect
|
25
|
-
yield client
|
26
|
-
client.logout
|
27
|
-
end
|
28
|
-
client
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should connect to GMail IMAP service" do
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
client
|
40
|
-
client.
|
41
|
-
client.
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
client
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
client
|
57
|
-
client.
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
client
|
64
|
-
client.
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
mail
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
mail
|
90
|
-
mail.
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
mail
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
mock_client
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
labels
|
148
|
-
|
149
|
-
|
150
|
-
it "should
|
151
|
-
labels = subject
|
152
|
-
labels.
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
labels
|
158
|
-
labels.
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
labels
|
166
|
-
labels.
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Gmail client (Plain)" do
|
4
|
+
subject { Gmail::Client::Plain }
|
5
|
+
|
6
|
+
context "on initialize" do
|
7
|
+
it "should set username, password and options" do
|
8
|
+
client = subject.new("test@gmail.com", "pass", :foo => :bar)
|
9
|
+
client.username.should == "test@gmail.com"
|
10
|
+
client.password.should == "pass"
|
11
|
+
client.options[:foo].should == :bar
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should convert simple name to gmail email" do
|
15
|
+
client = subject.new("test", "pass")
|
16
|
+
client.username.should == "test@gmail.com"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "instance" do
|
21
|
+
def mock_client(&block)
|
22
|
+
client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
|
23
|
+
if block_given?
|
24
|
+
client.connect
|
25
|
+
yield client
|
26
|
+
client.logout
|
27
|
+
end
|
28
|
+
client
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should connect to GMail IMAP service" do
|
32
|
+
client = mock_client
|
33
|
+
client.connect!.should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should properly login to valid GMail account" do
|
37
|
+
client = mock_client
|
38
|
+
client.connect.should be_true
|
39
|
+
client.login.should be_true
|
40
|
+
client.should be_logged_in
|
41
|
+
client.logout
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should raise error when given GMail account is invalid and errors enabled" do
|
45
|
+
lambda {
|
46
|
+
client = Gmail::Client::Plain.new("foo", "bar")
|
47
|
+
client.connect.should be_true
|
48
|
+
client.login!.should_not be_nil
|
49
|
+
}.should raise_error
|
50
|
+
### FIX: can someone dig to the bottom of this? We are getting NoMethodError instead of Gmail::Client::AuthorizationError in 1.9
|
51
|
+
end
|
52
|
+
|
53
|
+
it "shouldn't raise error even though GMail account is invalid" do
|
54
|
+
lambda {
|
55
|
+
client = Gmail::Client::Plain.new("foo", "bar")
|
56
|
+
client.connect.should be_true
|
57
|
+
expect(client.login).to_not be_true
|
58
|
+
}.should_not raise_error
|
59
|
+
end
|
60
|
+
|
61
|
+
it "shouldn't login when given GMail account is invalid" do
|
62
|
+
client = Gmail::Client::Plain.new("foo", "bar")
|
63
|
+
client.connect.should be_true
|
64
|
+
client.login.should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should properly logout from GMail" do
|
68
|
+
client = mock_client
|
69
|
+
client.connect
|
70
|
+
client.login.should be_true
|
71
|
+
client.logout.should be_true
|
72
|
+
client.should_not be_logged_in
|
73
|
+
end
|
74
|
+
|
75
|
+
it "#connection should automatically log in to GMail account when it's called" do
|
76
|
+
mock_client do |client|
|
77
|
+
client.expects(:login).once.returns(false)
|
78
|
+
client.connection.should_not be_nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should properly compose message" do
|
83
|
+
mail = mock_client.compose do
|
84
|
+
from "test@gmail.com"
|
85
|
+
to "friend@gmail.com"
|
86
|
+
subject "Hello world!"
|
87
|
+
end
|
88
|
+
mail.from.should == ["test@gmail.com"]
|
89
|
+
mail.to.should == ["friend@gmail.com"]
|
90
|
+
mail.subject.should == "Hello world!"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "#compose should automatically add `from` header when it is not specified" do
|
94
|
+
mail = mock_client.compose
|
95
|
+
mail.from.should == [TEST_ACCOUNT[0]]
|
96
|
+
mail = mock_client.compose(Mail.new)
|
97
|
+
mail.from.should == [TEST_ACCOUNT[0]]
|
98
|
+
mail = mock_client.compose {}
|
99
|
+
mail.from.should == [TEST_ACCOUNT[0]]
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should deliver inline composed email" do
|
103
|
+
mock_client do |client|
|
104
|
+
client.deliver do
|
105
|
+
to TEST_ACCOUNT[0]
|
106
|
+
subject "Hello world!"
|
107
|
+
body "Yeah, hello there!"
|
108
|
+
end.should be_true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should not raise error when mail can't be delivered and errors are disabled" do
|
113
|
+
lambda {
|
114
|
+
client = mock_client
|
115
|
+
client.deliver(Mail.new {}).should be_false
|
116
|
+
}.should_not raise_error
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should raise error when mail can't be delivered and errors are disabled" do
|
120
|
+
lambda {
|
121
|
+
client = mock_client
|
122
|
+
client.deliver!(Mail.new {})
|
123
|
+
}.should raise_error(Gmail::Client::DeliveryError)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should properly switch to given mailbox" do
|
127
|
+
mock_client do |client|
|
128
|
+
mailbox = client.mailbox("INBOX")
|
129
|
+
mailbox.should be_kind_of(Gmail::Mailbox)
|
130
|
+
mailbox.name.should == "INBOX"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should properly switch to given mailbox using block style" do
|
135
|
+
mock_client do |client|
|
136
|
+
client.mailbox("INBOX") do |mailbox|
|
137
|
+
mailbox.should be_kind_of(Gmail::Mailbox)
|
138
|
+
mailbox.name.should == "INBOX"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "labels" do
|
144
|
+
subject {
|
145
|
+
client = Gmail::Client::Plain.new(*TEST_ACCOUNT)
|
146
|
+
client.connect
|
147
|
+
client.labels
|
148
|
+
}
|
149
|
+
|
150
|
+
it "should get list of all available labels" do
|
151
|
+
labels = subject
|
152
|
+
labels.all.should include("INBOX")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should be able to check if there is given label defined" do
|
156
|
+
labels = subject
|
157
|
+
labels.exists?("INBOX").should be_true
|
158
|
+
labels.exists?("FOOBAR").should be_false
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should be able to create given label" do
|
162
|
+
labels = subject
|
163
|
+
labels.create("MYLABEL")
|
164
|
+
labels.exists?("MYLABEL").should be_true
|
165
|
+
labels.create("MYLABEL").should be_false
|
166
|
+
labels.delete("MYLABEL")
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should be able to remove existing label" do
|
170
|
+
labels = subject
|
171
|
+
labels.create("MYLABEL")
|
172
|
+
labels.delete("MYLABEL").should be_true
|
173
|
+
labels.exists?("MYLABEL").should be_false
|
174
|
+
labels.delete("MYLABEL").should be_false
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|