gmail-britta 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +5 -8
- data/.yardopts +2 -1
- data/Gemfile +3 -2
- data/Gemfile.lock +66 -21
- data/README.md +3 -1
- data/THANKS.md +15 -0
- data/TODO.org +6 -0
- data/VERSION +1 -1
- data/examples/Gemfile.lock +2 -2
- data/examples/asf.rb +29 -2
- data/gmail-britta.gemspec +14 -11
- data/lib/gmail-britta.rb +2 -0
- data/lib/gmail-britta/chaining_filter.rb +82 -0
- data/lib/gmail-britta/filter.rb +117 -62
- data/lib/gmail-britta/filter_set.rb +5 -2
- data/lib/gmail-britta/single_write_accessors.rb +54 -21
- data/test/test_gmail-britta.rb +249 -21
- metadata +24 -39
data/test/test_gmail-britta.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "codeclimate-test-reporter"
|
2
|
+
CodeClimate::TestReporter.start
|
3
|
+
|
1
4
|
require 'bundler/setup'
|
2
5
|
require 'minitest/unit'
|
3
6
|
require 'nokogiri'
|
@@ -6,15 +9,6 @@ require 'minitest/autorun'
|
|
6
9
|
require 'gmail-britta'
|
7
10
|
|
8
11
|
describe GmailBritta do
|
9
|
-
def simple_filterset
|
10
|
-
fs = GmailBritta.filterset() do
|
11
|
-
filter {
|
12
|
-
has %w{to:asf@boinkor.net}
|
13
|
-
label 'ohai'
|
14
|
-
}.archive_unless_directed
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
12
|
def dom(filterset)
|
19
13
|
text = filterset.generate
|
20
14
|
#puts text
|
@@ -29,33 +23,267 @@ describe GmailBritta do
|
|
29
23
|
end
|
30
24
|
|
31
25
|
it "runs" do
|
32
|
-
|
26
|
+
fs = GmailBritta.filterset() do
|
27
|
+
filter {
|
28
|
+
has 'to:asf@boinkor.net'
|
29
|
+
label 'ohai'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
filters = fs.generate
|
33
33
|
assert(filters, "Should generate something")
|
34
34
|
assert(filters.is_a?(String), "Generated filters should be a string")
|
35
35
|
end
|
36
36
|
|
37
|
-
it "generates
|
38
|
-
|
37
|
+
it "generates 'label' properties" do
|
38
|
+
fs = GmailBritta.filterset() do
|
39
|
+
filter {
|
40
|
+
has 'to:asf@boinkor.net'
|
41
|
+
label 'ohai'
|
42
|
+
}
|
43
|
+
end
|
39
44
|
|
40
|
-
|
41
|
-
assert_equal(
|
45
|
+
filters = dom(fs)
|
46
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="label"]',ns).length, "Should have exactly one 'label' property")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "also generates 'smartLabelToApply' properties" do
|
50
|
+
groups = {
|
51
|
+
'forums' => :group,
|
52
|
+
'Forums' => :group,
|
53
|
+
'notifications' => :notification,
|
54
|
+
'Notifications' => :notification,
|
55
|
+
'updates' => :notification,
|
56
|
+
'Updates' => :notification,
|
57
|
+
'promotions' => :promo,
|
58
|
+
'Promotions' => :promo,
|
59
|
+
'social' => :social,
|
60
|
+
'Social' => :social
|
61
|
+
}
|
62
|
+
|
63
|
+
groups.each do |key, value|
|
64
|
+
fs = GmailBritta.filterset() do
|
65
|
+
filter {
|
66
|
+
has 'to:asf@boinkor.net'
|
67
|
+
label 'ohai'
|
68
|
+
smart_label key
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
filters = dom(fs)
|
73
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="label"]',ns).length, "Should have exactly one 'label' property")
|
74
|
+
|
75
|
+
smart_labels = filters.xpath('/a:feed/a:entry/apps:property[@name="smartLabelToApply"]',ns)
|
76
|
+
assert_equal(1, smart_labels.length, "Should have exactly one 'smartLabelToApply' property")
|
77
|
+
smart_label_value = smart_labels.first['value']
|
78
|
+
assert_equal("^smartlabel_#{value}", smart_label_value, "Should use the smartlabel_ value")
|
79
|
+
end
|
80
|
+
|
81
|
+
err = assert_raises RuntimeError do
|
82
|
+
fs = GmailBritta.filterset() do
|
83
|
+
filter {
|
84
|
+
has 'to:asf@boinkor.net'
|
85
|
+
label 'ohai'
|
86
|
+
smart_label 'Foobar'
|
87
|
+
}
|
88
|
+
end
|
89
|
+
dom(fs)
|
90
|
+
end
|
91
|
+
assert_equal('invalid category "Foobar"', err.message)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "generates simple 'has' condition xml" do
|
95
|
+
filters = dom(
|
96
|
+
GmailBritta.filterset() do
|
97
|
+
filter {
|
98
|
+
has %w{to:asf@boinkor.net}
|
99
|
+
label 'ohai'
|
100
|
+
archive
|
101
|
+
}
|
102
|
+
end
|
103
|
+
)
|
104
|
+
|
105
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry',ns).length, "Should have exactly one filter entry")
|
106
|
+
assert_equal(3, filters.xpath('/a:feed/a:entry/apps:property',ns).length, "Should have two properties")
|
107
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="label"]',ns).length, "Should have exactly one 'label' property")
|
108
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="shouldArchive"]',ns).length, "Should have exactly one 'shouldArchive' property")
|
109
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="hasTheWord"]',ns).length, "Should have exactly one 'has' property")
|
110
|
+
end
|
111
|
+
|
112
|
+
it "generates simple 'has_not' condition xml" do
|
113
|
+
filters = dom(
|
114
|
+
GmailBritta.filterset() do
|
115
|
+
filter {
|
116
|
+
has_not %w{to:asf@boinkor.net}
|
117
|
+
label 'ohai'
|
118
|
+
archive
|
119
|
+
}
|
120
|
+
end
|
121
|
+
)
|
122
|
+
|
123
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry',ns).length, "Should have exactly one filter entry")
|
124
|
+
assert_equal(3, filters.xpath('/a:feed/a:entry/apps:property',ns).length, "Should have two properties")
|
42
125
|
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="label"]',ns).length, "Should have exactly one 'label' property")
|
43
126
|
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="shouldArchive"]',ns).length, "Should have exactly one 'shouldArchive' property")
|
44
|
-
assert_equal(
|
127
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="doesNotHaveTheWord"]',ns).length, "Should have exactly one 'has_not' property")
|
45
128
|
end
|
46
129
|
|
47
|
-
|
48
|
-
|
130
|
+
it "generates simple 'from' condition xml" do
|
131
|
+
filters = dom(
|
132
|
+
GmailBritta.filterset() do
|
133
|
+
filter {
|
134
|
+
from %w{asf@boinkor.net}
|
135
|
+
label 'ohai'
|
136
|
+
}
|
137
|
+
end
|
138
|
+
)
|
139
|
+
|
140
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="from"]',ns).length, "Should have exactly one 'from' property")
|
141
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@value="asf@boinkor.net"]',ns).length, "Should have exactly one 'from' value")
|
142
|
+
end
|
143
|
+
|
144
|
+
it "generates an error for multiple accessors" do
|
145
|
+
err = assert_raises RuntimeError do
|
146
|
+
GmailBritta.filterset() do
|
147
|
+
filter {
|
148
|
+
from %w{asf@boinkor.net}
|
149
|
+
from %w{asf@boinkor.net}
|
150
|
+
label 'ohai'
|
151
|
+
}
|
152
|
+
end
|
153
|
+
end
|
154
|
+
assert_equal('Only one use of from is permitted per filter', err.message)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "generates an error for multiple boolean accessors" do
|
158
|
+
err = assert_raises RuntimeError do
|
159
|
+
GmailBritta.filterset() do
|
160
|
+
filter {
|
161
|
+
from %w{asf@boinkor.net}
|
162
|
+
archive
|
163
|
+
archive
|
164
|
+
}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
assert_equal('Only one use of archive is permitted per filter', err.message)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "generates multiple 'from' condition xml" do
|
171
|
+
filters = dom(
|
172
|
+
GmailBritta.filterset() do
|
173
|
+
filter {
|
174
|
+
from ['asf@boinkor.net', 'abc@boinkor.net']
|
175
|
+
label 'ohai'
|
176
|
+
}
|
177
|
+
end
|
178
|
+
)
|
179
|
+
|
180
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="from"]',ns).length, "Should have exactly one 'from' property")
|
181
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@value="asf@boinkor.net abc@boinkor.net"]',ns).length, "Should have both addresses in 'from' property")
|
182
|
+
end
|
183
|
+
|
184
|
+
it "uses .otherwise for single 'from' condition" do
|
185
|
+
filters = dom(
|
186
|
+
GmailBritta.filterset() do
|
187
|
+
filter {
|
188
|
+
from %w{asf@boinkor.net}
|
189
|
+
label 'ohai'
|
190
|
+
}.otherwise {
|
191
|
+
label 'bai'
|
192
|
+
}
|
193
|
+
end
|
194
|
+
)
|
195
|
+
|
196
|
+
assert_equal(2, filters.xpath('/a:feed/a:entry/apps:property[@name="from"]',ns).length, "Should have two 'from' properties")
|
197
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@value="asf@boinkor.net"]',ns).length, "Should have the address positively exactly once")
|
198
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@value="-asf@boinkor.net"]',ns).length, "Should have the address negatively exactly once")
|
199
|
+
end
|
200
|
+
|
201
|
+
it "uses .also for single 'to' condition" do
|
202
|
+
filters = dom(
|
203
|
+
GmailBritta.filterset() do
|
204
|
+
filter {
|
205
|
+
from %w{from@boinkor.net}
|
206
|
+
label 'ohai'
|
207
|
+
}.also {
|
208
|
+
to %w{to@boinkor.net}
|
209
|
+
}
|
210
|
+
end
|
211
|
+
)
|
212
|
+
|
213
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="from"][@value="from@boinkor.net"]',ns).length, "Should have the from address")
|
214
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="to"][@value="to@boinkor.net"]',ns).length, "Should have the to address")
|
215
|
+
end
|
216
|
+
|
217
|
+
it "understands me" do
|
218
|
+
fs = GmailBritta.filterset(:me => ['thisisme@my-private.org', 'this-is-me@bigco.example.com']) do
|
219
|
+
filter {
|
220
|
+
to_me = me.map {|address| "to:#{address}"}
|
221
|
+
has [{:or => to_me}]
|
222
|
+
}
|
223
|
+
end
|
224
|
+
filters = dom(fs)
|
225
|
+
|
226
|
+
filter_text = filters.xpath('/a:feed/a:entry/apps:property[@name="hasTheWord"]',ns).first['value']
|
227
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@name="hasTheWord"]',ns).length, "Should have exactly one 'has' property")
|
228
|
+
assert_equal('(to:thisisme@my-private.org OR to:this-is-me@bigco.example.com)', filter_text, "Should have exactly one 'has' property")
|
229
|
+
end
|
230
|
+
|
231
|
+
it "doesn't fail issue #4 - correctly-parenthesised nested ANDs" do
|
232
|
+
fs = GmailBritta.filterset do
|
233
|
+
filter {
|
234
|
+
has :or => [['subject:whee', 'from:zot@spammer.com'], 'from:bob@bob.com', 'from:foo@foo.com']
|
235
|
+
label 'yay'
|
236
|
+
}
|
237
|
+
end
|
238
|
+
filters = dom(fs)
|
239
|
+
|
240
|
+
filter_text = filters.xpath('/a:feed/a:entry/apps:property[@name="hasTheWord"]',ns).first['value']
|
241
|
+
assert_equal('(subject:whee from:zot@spammer.com) OR from:bob@bob.com OR from:foo@foo.com', filter_text)
|
242
|
+
end
|
243
|
+
|
244
|
+
it "uses .otherwise for multiple 'from' condition" do
|
245
|
+
filters = dom(
|
246
|
+
GmailBritta.filterset() do
|
247
|
+
filter {
|
248
|
+
from ['asf@boinkor.net', 'abc@boinkor.net']
|
249
|
+
label 'ohai'
|
250
|
+
}.otherwise {
|
251
|
+
label 'bai'
|
252
|
+
}
|
253
|
+
end
|
254
|
+
)
|
255
|
+
|
256
|
+
assert_equal(2, filters.xpath('/a:feed/a:entry/apps:property[@name="from"]',ns).length, "Should have two 'from' properties")
|
257
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@value="asf@boinkor.net abc@boinkor.net"]',ns).length, "Should have both addresses positively in one 'from' property")
|
258
|
+
assert_equal(1, filters.xpath('/a:feed/a:entry/apps:property[@value="-asf@boinkor.net -abc@boinkor.net"]',ns).length, "Should have both addresses negated in one 'from' property")
|
259
|
+
end
|
260
|
+
|
261
|
+
describe "subject" do
|
262
|
+
it "works with single subject" do
|
49
263
|
fs = GmailBritta.filterset do
|
50
264
|
filter {
|
51
|
-
|
52
|
-
label '
|
265
|
+
subject 'SPAM: '
|
266
|
+
label 'important'
|
53
267
|
}
|
54
268
|
end
|
269
|
+
|
270
|
+
filters = dom(fs)
|
271
|
+
|
272
|
+
filter_text = filters.xpath('//apps:property[@name="subject"]', ns).first['value']
|
273
|
+
assert_equal('SPAM: ', filter_text)
|
274
|
+
end
|
275
|
+
|
276
|
+
it "works with hash of subjects" do
|
277
|
+
fs = GmailBritta.filterset do
|
278
|
+
filter {
|
279
|
+
subject :or => ['SPAM', 'HAM']
|
280
|
+
}
|
281
|
+
end
|
282
|
+
|
55
283
|
filters = dom(fs)
|
56
284
|
|
57
|
-
filter_text = filters.xpath('
|
58
|
-
assert_equal('
|
285
|
+
filter_text = filters.xpath('//apps:property[@name="subject"]', ns).first['value']
|
286
|
+
assert_equal('SPAM OR HAM', filter_text)
|
59
287
|
end
|
60
288
|
end
|
61
289
|
end
|
metadata
CHANGED
@@ -1,110 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gmail-britta
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.7
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Andreas Fuchs
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-01-29 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: haml
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 3.1.6
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 3.1.6
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: 0.9.2
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: 0.9.2
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: shoulda
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: bundler
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - ">="
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: 1.2.0
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - ">="
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: 1.2.0
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: minitest
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - ">="
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: nokogiri
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - ">="
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - ">="
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
description: This gem helps create large (>50) gmail filter chains by writing xml
|
@@ -116,14 +103,15 @@ extra_rdoc_files:
|
|
116
103
|
- LICENSE.txt
|
117
104
|
- README.md
|
118
105
|
files:
|
119
|
-
- .document
|
120
|
-
- .travis.yml
|
121
|
-
- .yardopts
|
106
|
+
- ".document"
|
107
|
+
- ".travis.yml"
|
108
|
+
- ".yardopts"
|
122
109
|
- Gemfile
|
123
110
|
- Gemfile.lock
|
124
111
|
- LICENSE.txt
|
125
112
|
- README.md
|
126
113
|
- Rakefile
|
114
|
+
- THANKS.md
|
127
115
|
- TODO.org
|
128
116
|
- VERSION
|
129
117
|
- examples/Gemfile
|
@@ -132,6 +120,7 @@ files:
|
|
132
120
|
- examples/asf.rb
|
133
121
|
- gmail-britta.gemspec
|
134
122
|
- lib/gmail-britta.rb
|
123
|
+
- lib/gmail-britta/chaining_filter.rb
|
135
124
|
- lib/gmail-britta/filter.rb
|
136
125
|
- lib/gmail-britta/filter_set.rb
|
137
126
|
- lib/gmail-britta/single_write_accessors.rb
|
@@ -139,29 +128,25 @@ files:
|
|
139
128
|
homepage: http://github.com/antifuchs/gmail-britta
|
140
129
|
licenses:
|
141
130
|
- MIT
|
131
|
+
metadata: {}
|
142
132
|
post_install_message:
|
143
133
|
rdoc_options: []
|
144
134
|
require_paths:
|
145
135
|
- lib
|
146
136
|
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
-
none: false
|
148
137
|
requirements:
|
149
|
-
- -
|
138
|
+
- - ">="
|
150
139
|
- !ruby/object:Gem::Version
|
151
140
|
version: '0'
|
152
|
-
segments:
|
153
|
-
- 0
|
154
|
-
hash: -4216942302698371957
|
155
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
-
none: false
|
157
142
|
requirements:
|
158
|
-
- -
|
143
|
+
- - ">="
|
159
144
|
- !ruby/object:Gem::Version
|
160
145
|
version: '0'
|
161
146
|
requirements: []
|
162
147
|
rubyforge_project:
|
163
|
-
rubygems_version:
|
148
|
+
rubygems_version: 2.2.5
|
164
149
|
signing_key:
|
165
|
-
specification_version:
|
150
|
+
specification_version: 4
|
166
151
|
summary: Create complex gmail filtersets with a ruby DSL.
|
167
152
|
test_files: []
|