imapcli 1.0.5 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.devcontainer/devcontainer.json +22 -0
- data/.github/dependabot.yml +12 -0
- data/.github/workflows/ci.yml +57 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +53 -0
- data/.vscode/launch.json +59 -0
- data/CHANGELOG.md +71 -0
- data/Dockerfile +8 -5
- data/Gemfile +13 -4
- data/Gemfile.lock +189 -67
- data/Guardfile +8 -6
- data/README.md +68 -101
- data/Rakefile +5 -7
- data/bin/bundle +109 -0
- data/bin/rspec +27 -0
- data/bin/rubocop +27 -0
- data/exe/imapcli +8 -0
- data/imapcli.gemspec +26 -19
- data/lib/imapcli/cli.rb +180 -0
- data/lib/imapcli/client.rb +32 -32
- data/lib/imapcli/command.rb +44 -44
- data/lib/imapcli/mailbox.rb +34 -38
- data/lib/imapcli/option_validator.rb +6 -6
- data/lib/imapcli/stats.rb +9 -11
- data/lib/imapcli/version.rb +3 -1
- data/lib/imapcli.rb +20 -6
- data/spec/lib/imapcli/client_spec.rb +34 -22
- data/spec/lib/imapcli/command_spec.rb +35 -31
- data/spec/lib/imapcli/mailbox_spec.rb +36 -23
- data/spec/lib/imapcli/stats_spec.rb +18 -16
- data/spec/spec_helper.rb +22 -70
- metadata +64 -44
- data/.rspec +0 -1
- data/NEWS +0 -12
- data/bin/imapcli +0 -164
- data/spec/lib/imapcli/option_validator_spec.rb +0 -4
data/lib/imapcli/stats.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Imapcli
|
2
4
|
# Handles mailbox statistics.
|
3
5
|
#
|
@@ -11,6 +13,7 @@ module Imapcli
|
|
11
13
|
# Adds other statistics.
|
12
14
|
def add(other_stats)
|
13
15
|
return unless other_stats
|
16
|
+
|
14
17
|
@message_sizes += other_stats.message_sizes
|
15
18
|
invalidate
|
16
19
|
end
|
@@ -20,27 +23,27 @@ module Imapcli
|
|
20
23
|
end
|
21
24
|
|
22
25
|
def total_size
|
23
|
-
@total_size ||=
|
26
|
+
@total_size ||= @message_sizes.sum
|
24
27
|
end
|
25
28
|
|
26
29
|
def min_size
|
27
|
-
@
|
30
|
+
@min_size ||= @message_sizes.min
|
28
31
|
end
|
29
32
|
|
30
33
|
def quartile_1_size
|
31
|
-
@
|
34
|
+
@quartile_1_size ||= @message_sizes.percentile(25)
|
32
35
|
end
|
33
36
|
|
34
37
|
def median_size
|
35
|
-
@
|
38
|
+
@median_size ||= @message_sizes.median
|
36
39
|
end
|
37
40
|
|
38
41
|
def quartile_3_size
|
39
|
-
@
|
42
|
+
@quartile_3_size ||= @message_sizes.percentile(75)
|
40
43
|
end
|
41
44
|
|
42
45
|
def max_size
|
43
|
-
@
|
46
|
+
@max_size ||= @message_sizes.max
|
44
47
|
end
|
45
48
|
|
46
49
|
protected
|
@@ -49,11 +52,6 @@ module Imapcli
|
|
49
52
|
|
50
53
|
private
|
51
54
|
|
52
|
-
# Converts a number of bytes to kiB.
|
53
|
-
def convert_bytes(bytes)
|
54
|
-
bytes.fdiv(1024).round if bytes
|
55
|
-
end
|
56
|
-
|
57
55
|
def invalidate
|
58
56
|
@count, @total_size, @min, @max, @q1, @q3, @median = nil # sets others to nil too
|
59
57
|
end
|
data/lib/imapcli/version.rb
CHANGED
data/lib/imapcli.rb
CHANGED
@@ -1,6 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require '
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'csv'
|
5
|
+
require 'descriptive_statistics'
|
6
|
+
require 'dotenv'
|
7
|
+
require 'gli'
|
8
|
+
require 'net/imap'
|
9
|
+
require 'tty-progressbar'
|
10
|
+
require 'tty-prompt'
|
11
|
+
require 'tty-table'
|
12
|
+
require 'zeitwerk'
|
13
|
+
|
14
|
+
# load zeitwerk
|
15
|
+
Zeitwerk::Loader.for_gem.tap do |loader|
|
16
|
+
loader.setup
|
17
|
+
end
|
18
|
+
|
19
|
+
module Imapcli # rubocop:disable Style/Documentation
|
20
|
+
end
|
@@ -1,69 +1,81 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
3
4
|
|
4
5
|
RSpec.describe Imapcli::Client do
|
5
6
|
|
6
7
|
context 'with mock credentials for a nonexistent server' do
|
7
|
-
let(:client) {
|
8
|
+
let(:client) { described_class.new('imap.example.com', 'username', 'password') }
|
9
|
+
|
8
10
|
it 'knows when a server name is invalid' do
|
9
11
|
client.server = 'i n v a l i d'
|
10
|
-
expect(client.server_valid?).to
|
12
|
+
expect(client.server_valid?).to be false
|
11
13
|
end
|
14
|
+
|
12
15
|
it 'knows when a server name is valid' do
|
13
16
|
client.server = 'imap.gmail.com'
|
14
|
-
expect(client.server_valid?).to
|
17
|
+
expect(client.server_valid?).to be true
|
15
18
|
end
|
19
|
+
|
16
20
|
it 'knows when a user name is invalid' do
|
17
21
|
client.user = ''
|
18
|
-
expect(client.user_valid?).to
|
22
|
+
expect(client.user_valid?).to be false
|
19
23
|
end
|
24
|
+
|
20
25
|
it 'knows when a user name is valid' do
|
21
26
|
client.user = 'bovender@example.com'
|
22
|
-
expect(client.user_valid?).to
|
27
|
+
expect(client.user_valid?).to be true
|
23
28
|
end
|
29
|
+
|
24
30
|
it 'uses port 993 by default' do
|
25
31
|
expect(client.port).to eq 993
|
26
32
|
end
|
33
|
+
|
27
34
|
it 'extracts a port from the server info' do
|
28
35
|
client.server = 'imap.example.com:143'
|
29
36
|
expect(client.port).to eq 143
|
30
37
|
end
|
38
|
+
|
31
39
|
it 'extracts a server from the server string when a port is appended' do
|
32
40
|
client.server = 'imap.example.com:143'
|
33
41
|
expect(client.server).to eq 'imap.example.com'
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
37
|
-
context 'with valid credentials for an actual server', network
|
38
|
-
before
|
39
|
-
Dotenv.load
|
40
|
-
end
|
45
|
+
context 'with valid credentials for an actual server', :network do
|
46
|
+
before { Dotenv.load }
|
41
47
|
|
42
|
-
let(:client)
|
48
|
+
let(:client) do
|
49
|
+
described_class.new(ENV.fetch('IMAP_SERVER', nil), ENV.fetch('IMAP_USER', nil), ENV.fetch('IMAP_PASS', nil))
|
50
|
+
end
|
43
51
|
|
44
52
|
it 'the IMAP_SERVER variable must be set' do
|
45
|
-
expect(ENV
|
53
|
+
expect(ENV.fetch('IMAP_SERVER', nil)).to_not be_nil
|
46
54
|
end
|
55
|
+
|
47
56
|
it 'the IMAP_USER variable must be set' do
|
48
|
-
expect(ENV
|
57
|
+
expect(ENV.fetch('IMAP_USER', nil)).to_not be_nil
|
49
58
|
end
|
59
|
+
|
50
60
|
it 'the IMAP_PASS variable must be set' do
|
51
|
-
expect(ENV
|
61
|
+
expect(ENV.fetch('IMAP_PASS', nil)).to_not be_nil
|
52
62
|
end
|
63
|
+
|
53
64
|
it 'successfully logs in to the server' do
|
54
|
-
expect(client.login).to
|
65
|
+
expect(client.login).to be true
|
55
66
|
end
|
56
67
|
end
|
57
68
|
|
58
|
-
context 'with invalid credentials for an actual server', network
|
59
|
-
before
|
60
|
-
Dotenv.load
|
61
|
-
end
|
69
|
+
context 'with invalid credentials for an actual server', :network do
|
70
|
+
before { Dotenv.load }
|
62
71
|
|
63
|
-
let(:client)
|
72
|
+
let(:client) do
|
73
|
+
described_class.new(ENV.fetch('IMAP_SERVER', nil), ENV.fetch('IMAP_USER', nil),
|
74
|
+
"#{ENV.fetch('IMAP_PASS', nil)}invalid")
|
75
|
+
end
|
64
76
|
|
65
77
|
it 'cannot log in to the server' do
|
66
|
-
expect(client.login).to
|
78
|
+
expect(client.login).to be false
|
67
79
|
end
|
68
80
|
end
|
69
81
|
|
@@ -1,10 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
2
4
|
|
3
5
|
RSpec.describe Imapcli::Command do
|
4
6
|
|
5
7
|
context 'without a client' do
|
6
8
|
it 'cannot be instantiated' do
|
7
|
-
expect {
|
9
|
+
expect { described_class.new('foobar') }.to raise_error(ArgumentError)
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
@@ -14,32 +16,29 @@ RSpec.describe Imapcli::Command do
|
|
14
16
|
allow(client).to receive(:login).and_return(true)
|
15
17
|
client
|
16
18
|
end
|
17
|
-
let(:command) {
|
19
|
+
let(:command) { described_class.new(client) }
|
18
20
|
let(:mailbox_root) do
|
19
21
|
Imapcli::Mailbox.new([
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox'),
|
23
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Foo'),
|
24
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Foo/Sub'),
|
25
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Bar'),
|
26
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Bar/Sub'),
|
27
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Bar/Sub/Subsub'),
|
28
|
+
])
|
27
29
|
end
|
28
30
|
|
29
31
|
it 'can be instantiated' do
|
30
|
-
expect {
|
32
|
+
expect { described_class.new(client) }.to_not raise_error
|
31
33
|
end
|
32
34
|
|
33
35
|
it 'logs in' do
|
34
|
-
expect(command.check).to
|
36
|
+
expect(command.check).to be true
|
35
37
|
end
|
36
38
|
|
37
39
|
it 'collects information about the server' do
|
38
|
-
allow(client).to
|
39
|
-
|
40
|
-
allow(client).to receive(:separator).and_return '/'
|
41
|
-
allow(client).to receive(:supports_quota).and_return true
|
42
|
-
allow(client).to receive(:quota).and_return [ '1024', '2048', 50.00 ]
|
40
|
+
allow(client).to receive_messages(greeting: 'hello', capability: %w[lots of capabilities], separator: '/',
|
41
|
+
supports_quota: true, quota: ['1024', '2048', 50.00])
|
43
42
|
output = command.info
|
44
43
|
expect(output).to be_a Array
|
45
44
|
expect(output[0]).to eq 'greeting: hello'
|
@@ -52,10 +51,9 @@ RSpec.describe Imapcli::Command do
|
|
52
51
|
expect(output[0]).to eq '- Inbox'
|
53
52
|
end
|
54
53
|
|
55
|
-
context 'collecting statistics' do
|
56
|
-
before
|
57
|
-
allow(client).to
|
58
|
-
allow(client).to receive(:separator).and_return '/'
|
54
|
+
context 'when collecting statistics' do
|
55
|
+
before do
|
56
|
+
allow(client).to receive_messages(mailbox_root: mailbox_root, separator: '/')
|
59
57
|
allow(client).to receive(:message_sizes) do |mailbox|
|
60
58
|
case mailbox
|
61
59
|
when 'Inbox'
|
@@ -67,8 +65,8 @@ RSpec.describe Imapcli::Command do
|
|
67
65
|
when 'Inbox/Bar'
|
68
66
|
(1..2).map { |i| 1024 * i }
|
69
67
|
when 'Inbox/Bar/Sub'
|
70
|
-
[
|
71
|
-
when 'Inbox/Bar/Sub/Subsub'
|
68
|
+
[1, 1024 * 20]
|
69
|
+
when 'Inbox/Bar/Sub/Subsub' # rubocop:disable Lint/DuplicateBranch
|
72
70
|
(1..4).map { |i| 1024 * i }
|
73
71
|
else
|
74
72
|
[1024, 2048, 4096, 8192]
|
@@ -77,42 +75,48 @@ RSpec.describe Imapcli::Command do
|
|
77
75
|
end
|
78
76
|
|
79
77
|
it 'for all folders' do
|
80
|
-
output = command.stats
|
78
|
+
output = command.stats
|
81
79
|
expect(output).to be_a Array
|
82
|
-
expect(output.length).to eq
|
80
|
+
expect(output.length).to eq 7
|
83
81
|
expect(output[0][0]).to eq 'Inbox'
|
84
82
|
expect(output[0][1]).to eq 4
|
85
83
|
end
|
84
|
+
|
86
85
|
it 'for a given folder' do
|
87
86
|
output = command.stats('Inbox/Foo')
|
88
87
|
expect(output).to be_a Array
|
89
|
-
expect(output.length).to eq
|
88
|
+
expect(output.length).to eq 1
|
90
89
|
expect(output[0][0]).to eq 'Inbox/Foo'
|
91
90
|
expect(output[0][1]).to eq 8 # depends on message_sizes stub (see above)
|
92
91
|
end
|
92
|
+
|
93
93
|
it 'for a given folder and subfolders' do
|
94
94
|
output = command.stats('Inbox/Foo', depth: -1)
|
95
95
|
expect(output).to be_a Array
|
96
|
-
expect(output.length).to eq
|
96
|
+
expect(output.length).to eq 3
|
97
97
|
expect(output[1][0]).to eq 'Inbox/Foo/Sub'
|
98
98
|
end
|
99
|
+
|
99
100
|
it 'sorts by number of messages' do
|
100
|
-
output = command.stats('Inbox', depth: -1, sort: :count,
|
101
|
+
output = command.stats('Inbox', depth: -1, sort: :count, reverse: true)
|
101
102
|
expect(output).to be_a Array
|
102
103
|
expect(output[0][0]).to eq 'Inbox/Foo/Sub'
|
103
104
|
end
|
105
|
+
|
104
106
|
it 'sorts by total message size' do
|
105
|
-
output = command.stats('Inbox', depth: -1, sort: :total_size,
|
107
|
+
output = command.stats('Inbox', depth: -1, sort: :total_size, reverse: true)
|
106
108
|
expect(output).to be_a Array
|
107
109
|
expect(output[0][0]).to eq 'Inbox/Foo'
|
108
110
|
end
|
111
|
+
|
109
112
|
it 'sorts by largest message' do
|
110
|
-
output = command.stats('Inbox', depth: -1, sort: :max_size,
|
113
|
+
output = command.stats('Inbox', depth: -1, sort: :max_size, reverse: true)
|
111
114
|
expect(output).to be_a Array
|
112
115
|
expect(output[0][0]).to eq 'Inbox/Bar/Sub'
|
113
116
|
end
|
117
|
+
|
114
118
|
it 'sorts by smallest message' do
|
115
|
-
output = command.stats('Inbox', depth: -1, sort: :min_size,
|
119
|
+
output = command.stats('Inbox', depth: -1, sort: :min_size, reverse: true)
|
116
120
|
expect(output).to be_a Array
|
117
121
|
# binding.pry
|
118
122
|
expect(output[0][0]).to eq 'Inbox/Foo'
|
@@ -1,41 +1,49 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
3
4
|
|
4
5
|
RSpec.describe Imapcli::Mailbox do
|
6
|
+
|
5
7
|
let(:mailbox) do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
described_class.new([
|
9
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox'),
|
10
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Foo'),
|
11
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Foo/Sub'),
|
12
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Bar'),
|
13
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Bar/Sub'),
|
14
|
+
Net::IMAP::MailboxList.new(nil, '/', 'Inbox/Bar/Sub/Subsub'),
|
15
|
+
])
|
14
16
|
end
|
17
|
+
|
15
18
|
# it 'parses a mailbox list' do
|
16
19
|
# mailbox_list = Net::IMAP::MailboxList.new(attr: nil, delim: '/', name: 'Root/Subfolder')
|
17
20
|
# mailbox_root = Imapcli::MailboxTree.new(mailbox_list)
|
18
21
|
# expect(mailbox_root.tree.length).to eq 1
|
19
22
|
# end
|
23
|
+
|
20
24
|
it 'returns nil if a given sub mailbox does not exist' do
|
21
|
-
expect(mailbox.find_sub_mailbox('INBOX.does.not.exist', '.')).to
|
25
|
+
expect(mailbox.find_sub_mailbox('INBOX.does.not.exist', '.')).to be_nil
|
22
26
|
end
|
27
|
+
|
23
28
|
it 'adds and retrieves an existing sub mailbox' do
|
24
29
|
name = 'Root/Subfolder/Subsubfolder'
|
25
30
|
imap_mailbox_list = Net::IMAP::MailboxList.new(nil, '/', name)
|
26
|
-
mailbox =
|
31
|
+
mailbox = described_class.new
|
27
32
|
mailbox.add_mailbox(imap_mailbox_list)
|
28
33
|
expect(mailbox.find_sub_mailbox(name, '/').imap_mailbox_list).to eq imap_mailbox_list
|
29
34
|
end
|
35
|
+
|
30
36
|
it 'counts the number of mailboxes' do
|
31
37
|
expect(mailbox.count).to eq 7 # includes virtual root mailbox
|
32
38
|
end
|
39
|
+
|
33
40
|
it 'determines the maximum level in the subtree' do
|
34
|
-
expect(mailbox.
|
41
|
+
expect(mailbox.max_level).to eq 3
|
35
42
|
end
|
36
|
-
|
43
|
+
|
44
|
+
it 'converts a tree to a list' do # rubocop:disable RSpec/ExampleLength
|
37
45
|
list = mailbox.to_list
|
38
|
-
list_names = list.map
|
46
|
+
list_names = list.map(&:full_name)
|
39
47
|
expect(list_names).to eq [
|
40
48
|
'Inbox',
|
41
49
|
'Inbox/Bar',
|
@@ -45,34 +53,39 @@ RSpec.describe Imapcli::Mailbox do
|
|
45
53
|
'Inbox/Foo/Sub',
|
46
54
|
]
|
47
55
|
end
|
48
|
-
|
56
|
+
|
57
|
+
it 'converts a tree to a list up to a certain level' do # rubocop:disable RSpec/ExampleLength
|
49
58
|
list = mailbox.to_list(1)
|
50
|
-
list_names = list.map
|
59
|
+
list_names = list.map(&:full_name)
|
51
60
|
expect(list_names).to eq [
|
52
61
|
'Inbox',
|
53
62
|
'Inbox/Bar',
|
54
|
-
'Inbox/Foo'
|
63
|
+
'Inbox/Foo',
|
55
64
|
]
|
56
65
|
end
|
57
66
|
|
58
|
-
context 'identification and consolidation' do
|
67
|
+
context 'with identification and consolidation' do
|
59
68
|
let(:parent) { mailbox.find_sub_mailbox('Inbox', '/') }
|
60
69
|
let(:child) { mailbox.find_sub_mailbox('Inbox/Bar/Sub/Subsub', '/') }
|
61
70
|
|
62
71
|
it 'knows if it is contains another mailbox' do
|
63
|
-
expect(parent.contains?
|
72
|
+
expect(parent.contains?(child)).to be true
|
64
73
|
end
|
74
|
+
|
65
75
|
it 'knows if it is does not contain another mailbox' do
|
66
|
-
expect(child.contains?
|
76
|
+
expect(child.contains?(mailbox)).to be false
|
67
77
|
end
|
78
|
+
|
68
79
|
# it 'consolidates several of the same mailboxes' do
|
69
80
|
# expect(Imapcli::Mailbox.consolidate([parent, parent])).to eq [ parent ]
|
70
81
|
# end
|
82
|
+
|
71
83
|
it 'consolidates several of the same mailbox' do
|
72
|
-
|
84
|
+
expect(described_class.consolidate([child, child])).to eq [child]
|
73
85
|
end
|
86
|
+
|
74
87
|
it 'consolidates several different mailboxes' do
|
75
|
-
|
88
|
+
expect(described_class.consolidate([child, parent])).to eq [parent]
|
76
89
|
end
|
77
90
|
|
78
91
|
end
|
@@ -1,41 +1,44 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
2
4
|
|
3
5
|
RSpec.describe Imapcli::Stats do
|
6
|
+
|
4
7
|
let(:array) { (1..12).map { |i| i * 1024 } }
|
5
8
|
let(:other_array) { (13..24).map { |i| i * 1024 } }
|
6
|
-
let(:stats) {
|
7
|
-
let(:other_stats) {
|
9
|
+
let(:stats) { described_class.new(array) }
|
10
|
+
let(:other_stats) { described_class.new(other_array) }
|
8
11
|
|
9
12
|
it 'knows the number of items' do
|
10
13
|
expect(stats.count).to eq 12
|
11
14
|
end
|
12
15
|
|
13
16
|
it 'computes the minimum' do
|
14
|
-
expect(stats.min_size).to eq 1
|
17
|
+
expect(stats.min_size).to eq 1 * 1024
|
15
18
|
end
|
16
19
|
|
17
20
|
it 'computes the maximum' do
|
18
|
-
expect(stats.max_size).to eq 12
|
21
|
+
expect(stats.max_size).to eq 12 * 1024
|
19
22
|
end
|
20
23
|
|
21
24
|
it 'computes the median' do
|
22
|
-
expect(stats.median_size).to eq
|
25
|
+
expect(stats.median_size).to eq 6656
|
23
26
|
end
|
24
27
|
|
25
28
|
it 'computes the first quartile' do
|
26
|
-
expect(stats.quartile_1_size).to eq
|
29
|
+
expect(stats.quartile_1_size).to eq 3840
|
27
30
|
end
|
28
31
|
|
29
32
|
it 'computes the third quartile' do
|
30
|
-
expect(stats.quartile_3_size).to eq
|
33
|
+
expect(stats.quartile_3_size).to eq 9472
|
31
34
|
end
|
32
35
|
|
33
36
|
it 'adds nothing if other stats are nil' do
|
34
37
|
expect { stats.add nil }.to_not raise_error
|
35
38
|
end
|
36
39
|
|
37
|
-
context 'adding other stats' do
|
38
|
-
before
|
40
|
+
context 'when adding other stats' do
|
41
|
+
before do
|
39
42
|
stats.add other_stats
|
40
43
|
end
|
41
44
|
|
@@ -44,25 +47,24 @@ RSpec.describe Imapcli::Stats do
|
|
44
47
|
end
|
45
48
|
|
46
49
|
it 'computes the minimum' do
|
47
|
-
expect(stats.min_size).to eq 1
|
50
|
+
expect(stats.min_size).to eq 1 * 1024
|
48
51
|
end
|
49
52
|
|
50
53
|
it 'computes the maximum' do
|
51
|
-
expect(stats.max_size).to eq 24
|
54
|
+
expect(stats.max_size).to eq 24 * 1024
|
52
55
|
end
|
53
56
|
|
54
57
|
it 'computes the median' do
|
55
|
-
expect(stats.median_size).to eq
|
58
|
+
expect(stats.median_size).to eq 12800
|
56
59
|
end
|
57
60
|
|
58
61
|
it 'computes the first quartile' do
|
59
|
-
expect(stats.quartile_1_size).to eq
|
62
|
+
expect(stats.quartile_1_size).to eq 6912
|
60
63
|
end
|
61
64
|
|
62
65
|
it 'computes the third quartile' do
|
63
|
-
expect(stats.quartile_3_size).to eq
|
66
|
+
expect(stats.quartile_3_size).to eq 18688
|
64
67
|
end
|
65
68
|
|
66
69
|
end
|
67
|
-
|
68
70
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# files.
|
6
|
-
#
|
7
|
-
# Given that it is always loaded, you are encouraged to keep this file as
|
8
|
-
# light-weight as possible. Requiring heavyweight dependencies from this file
|
9
|
-
# will add to the boot time of your test suite on EVERY test run, even for an
|
10
|
-
# individual file that may not need all of that loaded. Instead, consider making
|
11
|
-
# a separate helper file that requires the additional dependencies and performs
|
12
|
-
# the additional setup, and require it from the spec files that actually need
|
13
|
-
# it.
|
14
|
-
#
|
15
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
require 'rspec'
|
16
5
|
require 'pry'
|
17
6
|
|
7
|
+
# Start SimpleCov
|
8
|
+
SimpleCov.start do
|
9
|
+
add_filter 'spec/'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Configure RSpec
|
18
13
|
RSpec.configure do |config|
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
config.color = true
|
15
|
+
config.fail_fast = false
|
16
|
+
|
17
|
+
config.order = :random
|
18
|
+
Kernel.srand config.seed
|
19
|
+
|
22
20
|
config.expect_with :rspec do |expectations|
|
21
|
+
expectations.syntax = :expect
|
22
|
+
|
23
23
|
# This option will default to `true` in RSpec 4. It makes the `description`
|
24
24
|
# and `failure_message` of custom matchers include text for helper methods
|
25
25
|
# defined using `chain`, e.g.:
|
@@ -48,57 +48,9 @@ RSpec.configure do |config|
|
|
48
48
|
|
49
49
|
config.filter_run_excluding network: true
|
50
50
|
|
51
|
-
#
|
52
|
-
#
|
53
|
-
=begin
|
54
|
-
# This allows you to limit a spec run to individual examples or groups
|
55
|
-
# you care about by tagging them with `:focus` metadata. When nothing
|
56
|
-
# is tagged with `:focus`, all examples get run. RSpec also provides
|
57
|
-
# aliases for `it`, `describe`, and `context` that include `:focus`
|
58
|
-
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
59
|
-
config.filter_run_when_matching :focus
|
60
|
-
|
61
|
-
# Allows RSpec to persist some state between runs in order to support
|
62
|
-
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
63
|
-
# you configure your source control system to ignore this file.
|
64
|
-
config.example_status_persistence_file_path = "spec/examples.txt"
|
65
|
-
|
66
|
-
# Limits the available syntax to the non-monkey patched syntax that is
|
67
|
-
# recommended. For more details, see:
|
68
|
-
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
|
69
|
-
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
70
|
-
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
|
51
|
+
# disable monkey patching
|
52
|
+
# see: https://relishapp.com/rspec/rspec-core/v/3-8/docs/configuration/zero-monkey-patching-mode
|
71
53
|
config.disable_monkey_patching!
|
72
|
-
|
73
|
-
# This setting enables warnings. It's recommended, but in some cases may
|
74
|
-
# be too noisy due to issues in dependencies.
|
75
|
-
config.warnings = true
|
76
|
-
|
77
|
-
# Many RSpec users commonly either run the entire suite or an individual
|
78
|
-
# file, and it's useful to allow more verbose output when running an
|
79
|
-
# individual spec file.
|
80
|
-
if config.files_to_run.one?
|
81
|
-
# Use the documentation formatter for detailed output,
|
82
|
-
# unless a formatter has already been configured
|
83
|
-
# (e.g. via a command-line flag).
|
84
|
-
config.default_formatter = "doc"
|
85
|
-
end
|
86
|
-
|
87
|
-
# Print the 10 slowest examples and example groups at the
|
88
|
-
# end of the spec run, to help surface which specs are running
|
89
|
-
# particularly slow.
|
90
|
-
config.profile_examples = 10
|
91
|
-
|
92
|
-
# Run specs in random order to surface order dependencies. If you find an
|
93
|
-
# order dependency and want to debug it, you can fix the order by providing
|
94
|
-
# the seed, which is printed after each run.
|
95
|
-
# --seed 1234
|
96
|
-
config.order = :random
|
97
|
-
|
98
|
-
# Seed global randomization in this process using the `--seed` CLI option.
|
99
|
-
# Setting this allows you to use `--seed` to deterministically reproduce
|
100
|
-
# test failures related to randomization by passing the same `--seed` value
|
101
|
-
# as the one that triggered the failure.
|
102
|
-
Kernel.srand config.seed
|
103
|
-
=end
|
104
54
|
end
|
55
|
+
|
56
|
+
require 'imapcli'
|