imap-backup 5.2.0 → 6.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.
- checksums.yaml +4 -4
- data/README.md +9 -2
- data/docs/development.md +10 -4
- data/imap-backup.gemspec +5 -1
- data/lib/cli_coverage.rb +11 -11
- data/lib/email/provider/base.rb +2 -0
- data/lib/email/provider/unknown.rb +2 -0
- data/lib/email/provider.rb +2 -0
- data/lib/imap/backup/account/connection/backup_folders.rb +27 -0
- data/lib/imap/backup/account/connection/client_factory.rb +54 -0
- data/lib/imap/backup/account/connection/folder_names.rb +26 -0
- data/lib/imap/backup/account/connection.rb +17 -105
- data/lib/imap/backup/account/folder.rb +9 -6
- data/lib/imap/backup/account.rb +36 -16
- data/lib/imap/backup/cli/backup.rb +1 -3
- data/lib/imap/backup/cli/folders.rb +3 -3
- data/lib/imap/backup/cli/helpers.rb +24 -22
- data/lib/imap/backup/cli/local.rb +20 -13
- data/lib/imap/backup/cli/migrate.rb +5 -11
- data/lib/imap/backup/cli/restore.rb +8 -7
- data/lib/imap/backup/cli/setup.rb +10 -8
- data/lib/imap/backup/cli/stats.rb +78 -0
- data/lib/imap/backup/cli/status.rb +2 -2
- data/lib/imap/backup/cli/utils.rb +6 -8
- data/lib/imap/backup/cli.rb +24 -3
- data/lib/imap/backup/configuration.rb +9 -21
- data/lib/imap/backup/downloader.rb +56 -34
- data/lib/imap/backup/migrator.rb +5 -5
- data/lib/imap/backup/sanitizer.rb +3 -2
- data/lib/imap/backup/serializer/appender.rb +49 -0
- data/lib/imap/backup/serializer/directory.rb +37 -0
- data/lib/imap/backup/serializer/imap.rb +144 -0
- data/lib/imap/backup/serializer/mbox.rb +33 -88
- data/lib/imap/backup/serializer/mbox_enumerator.rb +2 -0
- data/lib/imap/backup/serializer/message_enumerator.rb +29 -0
- data/lib/imap/backup/serializer/unused_name_finder.rb +25 -0
- data/lib/imap/backup/serializer.rb +160 -3
- data/lib/imap/backup/setup/account/header.rb +75 -0
- data/lib/imap/backup/setup/account.rb +41 -95
- data/lib/imap/backup/setup/asker.rb +4 -15
- data/lib/imap/backup/setup/backup_path.rb +41 -0
- data/lib/imap/backup/setup/email.rb +45 -0
- data/lib/imap/backup/setup/folder_chooser.rb +3 -3
- data/lib/imap/backup/setup/helpers.rb +2 -2
- data/lib/imap/backup/setup.rb +5 -4
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +41 -22
- data/lib/imap/backup/uploader.rb +46 -8
- data/lib/imap/backup/utils.rb +1 -1
- data/lib/imap/backup/version.rb +3 -3
- data/lib/imap/backup.rb +0 -2
- metadata +31 -105
- data/lib/imap/backup/serializer/mbox_store.rb +0 -217
- data/spec/features/backup_spec.rb +0 -108
- data/spec/features/configuration/minimal_configuration.rb +0 -15
- data/spec/features/configuration/missing_configuration.rb +0 -14
- data/spec/features/folders_spec.rb +0 -36
- data/spec/features/helper.rb +0 -2
- data/spec/features/local/list_accounts_spec.rb +0 -12
- data/spec/features/local/list_emails_spec.rb +0 -21
- data/spec/features/local/list_folders_spec.rb +0 -21
- data/spec/features/local/show_an_email_spec.rb +0 -34
- data/spec/features/migrate_spec.rb +0 -35
- data/spec/features/remote/list_account_folders_spec.rb +0 -16
- data/spec/features/restore_spec.rb +0 -162
- data/spec/features/status_spec.rb +0 -43
- data/spec/features/support/aruba.rb +0 -77
- data/spec/features/support/backup_directory.rb +0 -43
- data/spec/features/support/email_server.rb +0 -110
- data/spec/features/support/shared/connection_context.rb +0 -14
- data/spec/features/support/shared/message_fixtures.rb +0 -16
- data/spec/fixtures/connection.yml +0 -7
- data/spec/spec_helper.rb +0 -15
- data/spec/support/fixtures.rb +0 -11
- data/spec/support/higline_test_helpers.rb +0 -8
- data/spec/support/silence_logging.rb +0 -7
- data/spec/unit/email/mboxrd/message_spec.rb +0 -177
- data/spec/unit/email/provider/apple_mail_spec.rb +0 -7
- data/spec/unit/email/provider/base_spec.rb +0 -11
- data/spec/unit/email/provider/fastmail_spec.rb +0 -7
- data/spec/unit/email/provider/gmail_spec.rb +0 -7
- data/spec/unit/email/provider_spec.rb +0 -27
- data/spec/unit/imap/backup/account/connection_spec.rb +0 -405
- data/spec/unit/imap/backup/account/folder_spec.rb +0 -251
- data/spec/unit/imap/backup/cli/accounts_spec.rb +0 -47
- data/spec/unit/imap/backup/cli/helpers_spec.rb +0 -87
- data/spec/unit/imap/backup/cli/local_spec.rb +0 -81
- data/spec/unit/imap/backup/cli/utils_spec.rb +0 -62
- data/spec/unit/imap/backup/client/default_spec.rb +0 -22
- data/spec/unit/imap/backup/configuration_spec.rb +0 -238
- data/spec/unit/imap/backup/downloader_spec.rb +0 -44
- data/spec/unit/imap/backup/logger_spec.rb +0 -48
- data/spec/unit/imap/backup/migrator_spec.rb +0 -58
- data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +0 -45
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +0 -222
- data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +0 -329
- data/spec/unit/imap/backup/setup/account_spec.rb +0 -366
- data/spec/unit/imap/backup/setup/asker_spec.rb +0 -137
- data/spec/unit/imap/backup/setup/connection_tester_spec.rb +0 -51
- data/spec/unit/imap/backup/setup/folder_chooser_spec.rb +0 -146
- data/spec/unit/imap/backup/setup_spec.rb +0 -301
- data/spec/unit/imap/backup/uploader_spec.rb +0 -54
- data/spec/unit/imap/backup/utils_spec.rb +0 -92
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
module Imap::Backup
|
|
2
|
-
describe Setup::Asker do
|
|
3
|
-
subject { described_class.new(highline) }
|
|
4
|
-
|
|
5
|
-
let(:highline) { double }
|
|
6
|
-
let(:query) do
|
|
7
|
-
instance_double(
|
|
8
|
-
HighLine::Question,
|
|
9
|
-
"default=": nil,
|
|
10
|
-
"readline=": nil,
|
|
11
|
-
"validate=": nil,
|
|
12
|
-
"responses": {},
|
|
13
|
-
"echo=": nil
|
|
14
|
-
)
|
|
15
|
-
end
|
|
16
|
-
let(:answer) { "foo" }
|
|
17
|
-
|
|
18
|
-
before do
|
|
19
|
-
allow(Setup).to receive(:highline) { highline }
|
|
20
|
-
allow(highline).to receive(:ask) do |&b|
|
|
21
|
-
b.call query
|
|
22
|
-
answer
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
[
|
|
27
|
-
[:email, [], "email address"],
|
|
28
|
-
[:password, [], "password"],
|
|
29
|
-
[:backup_path, %w(x y), "backup directory"]
|
|
30
|
-
].each do |method, params, prompt|
|
|
31
|
-
context ".#{method}" do
|
|
32
|
-
it "asks for input" do
|
|
33
|
-
expect(highline).to receive(:ask).with("#{prompt}: ")
|
|
34
|
-
|
|
35
|
-
described_class.send(method, *params)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "returns the answer" do
|
|
39
|
-
expect(described_class.send(method, *params)).to eq(answer)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
describe "#initialize" do
|
|
45
|
-
it "requires 1 parameter" do
|
|
46
|
-
expect do
|
|
47
|
-
described_class.new
|
|
48
|
-
end.to raise_error(ArgumentError, /wrong number/)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it "expects a higline" do
|
|
52
|
-
expect(subject.highline).to eq(highline)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
describe "#email" do
|
|
57
|
-
let(:email) { "email@example.com" }
|
|
58
|
-
let(:answer) { email }
|
|
59
|
-
|
|
60
|
-
it "asks for an email" do
|
|
61
|
-
expect(highline).to receive(:ask).with(/email/)
|
|
62
|
-
|
|
63
|
-
subject.email
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
it "returns the address" do
|
|
67
|
-
expect(subject.email).to eq(email)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
describe "#password" do
|
|
72
|
-
let(:password1) { "password" }
|
|
73
|
-
let(:password2) { "password" }
|
|
74
|
-
let(:answers) { [true, false] }
|
|
75
|
-
|
|
76
|
-
before do
|
|
77
|
-
i = 0
|
|
78
|
-
allow(highline).to receive(:ask).with("password: ") { password1 }
|
|
79
|
-
allow(highline).to receive(:ask).with("repeat password: ") { password2 }
|
|
80
|
-
allow(highline).to receive(:agree) do
|
|
81
|
-
answer = answers[i]
|
|
82
|
-
i += 1
|
|
83
|
-
answer
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it "asks for a password" do
|
|
88
|
-
expect(highline).to receive(:ask).with("password: ")
|
|
89
|
-
|
|
90
|
-
subject.password
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it "asks for confirmation" do
|
|
94
|
-
expect(highline).to receive(:ask).with("repeat password: ")
|
|
95
|
-
|
|
96
|
-
subject.password
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "returns the password" do
|
|
100
|
-
expect(subject.password).to eq(password1)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
context "with different answers" do
|
|
104
|
-
let(:password2) { "secret" }
|
|
105
|
-
|
|
106
|
-
it "asks to continue" do
|
|
107
|
-
expect(highline).to receive(:agree).
|
|
108
|
-
at_least(:once).with(/Continue\?/)
|
|
109
|
-
|
|
110
|
-
subject.password
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
describe "#backup_path" do
|
|
116
|
-
let(:path) { "/path" }
|
|
117
|
-
let(:answer) { path }
|
|
118
|
-
|
|
119
|
-
before do
|
|
120
|
-
allow(highline).to receive(:ask) do |&b|
|
|
121
|
-
b.call query
|
|
122
|
-
path
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
it "asks for a directory" do
|
|
127
|
-
expect(highline).to receive(:ask).with(/directory/)
|
|
128
|
-
|
|
129
|
-
subject.backup_path("", //)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
it "returns the path" do
|
|
133
|
-
expect(subject.backup_path("", //)).to eq(path)
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
describe Imap::Backup::Setup::ConnectionTester do
|
|
2
|
-
describe "#test" do
|
|
3
|
-
subject { described_class.new("foo") }
|
|
4
|
-
|
|
5
|
-
let(:connection) do
|
|
6
|
-
instance_double(Imap::Backup::Account::Connection, client: nil)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
before do
|
|
10
|
-
allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
it "tries to connect" do
|
|
14
|
-
expect(connection).to receive(:client)
|
|
15
|
-
|
|
16
|
-
subject.test
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe "success" do
|
|
20
|
-
it "returns success" do
|
|
21
|
-
expect(subject.test).to match(/successful/)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
describe "failure" do
|
|
26
|
-
before do
|
|
27
|
-
allow(connection).to receive(:client).and_raise(error)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
context "with no connection" do
|
|
31
|
-
let(:error) do
|
|
32
|
-
data = OpenStruct.new(text: "bar")
|
|
33
|
-
response = OpenStruct.new(data: data)
|
|
34
|
-
Net::IMAP::NoResponseError.new(response)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it "returns error" do
|
|
38
|
-
expect(subject.test).to match(/no response/i)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
context "when caused by other errors" do
|
|
43
|
-
let(:error) { "Error" }
|
|
44
|
-
|
|
45
|
-
it "returns error" do
|
|
46
|
-
expect(subject.test).to match(/unexpected error/i)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
describe Imap::Backup::Setup::FolderChooser do
|
|
2
|
-
include HighLineTestHelpers
|
|
3
|
-
|
|
4
|
-
describe "#run" do
|
|
5
|
-
subject { described_class.new(account) }
|
|
6
|
-
|
|
7
|
-
let(:connection) do
|
|
8
|
-
instance_double(
|
|
9
|
-
Imap::Backup::Account::Connection, folder_names: connection_folders
|
|
10
|
-
)
|
|
11
|
-
end
|
|
12
|
-
let(:account) do
|
|
13
|
-
instance_double(
|
|
14
|
-
Imap::Backup::Account,
|
|
15
|
-
folders: account_folders,
|
|
16
|
-
"folders=": nil
|
|
17
|
-
)
|
|
18
|
-
end
|
|
19
|
-
let(:account_folders) { [] }
|
|
20
|
-
let(:connection_folders) { [] }
|
|
21
|
-
let!(:highline_streams) { prepare_highline }
|
|
22
|
-
let(:input) { highline_streams[0] }
|
|
23
|
-
let(:output) { highline_streams[1] }
|
|
24
|
-
|
|
25
|
-
before do
|
|
26
|
-
allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
|
|
27
|
-
allow(Kernel).to receive(:system)
|
|
28
|
-
allow(Imap::Backup::Logger.logger).to receive(:warn)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
describe "display" do
|
|
32
|
-
it "clears the screen" do
|
|
33
|
-
expect(Kernel).to receive(:system).with("clear")
|
|
34
|
-
|
|
35
|
-
subject.run
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "shows the menu" do
|
|
39
|
-
subject.run
|
|
40
|
-
|
|
41
|
-
expect(output.string).to match %r{Add/remove folders}
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
describe "folder listing" do
|
|
46
|
-
let(:account_folders) { [{name: "my_folder"}]}
|
|
47
|
-
let(:connection_folders) do
|
|
48
|
-
# N.B. my_folder is already backed up
|
|
49
|
-
%w(my_folder another_folder)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
describe "display" do
|
|
53
|
-
before { subject.run }
|
|
54
|
-
|
|
55
|
-
it "shows folders which are being backed up" do
|
|
56
|
-
expect(output.string).to include("+ my_folder")
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it "shows folders which are not being backed up" do
|
|
60
|
-
expect(output.string).to include("- another_folder")
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
context "when adding folders" do
|
|
65
|
-
before do
|
|
66
|
-
allow(input).to receive(:gets).and_return("2\n", "q\n")
|
|
67
|
-
|
|
68
|
-
subject.run
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
specify "are added to the account" do
|
|
72
|
-
expect(account).to have_received(:"folders=").
|
|
73
|
-
with([{name: "my_folder"}, {name: "another_folder"}])
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
context "when removing folders" do
|
|
78
|
-
before do
|
|
79
|
-
allow(input).to receive(:gets).and_return("1\n", "q\n")
|
|
80
|
-
|
|
81
|
-
subject.run
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
specify "are removed from the account" do
|
|
85
|
-
expect(account).to have_received(:"folders=").with([])
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
context "with missing remote folders" do
|
|
91
|
-
let(:account_folders) do
|
|
92
|
-
[{name: "on_server"}, {name: "not_on_server"}]
|
|
93
|
-
end
|
|
94
|
-
let(:connection_folders) { ["on_server"] }
|
|
95
|
-
|
|
96
|
-
before do
|
|
97
|
-
allow(Kernel).to receive(:puts)
|
|
98
|
-
subject.run
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
specify "are removed from the account" do
|
|
102
|
-
expect(account).to have_received(:"folders=").
|
|
103
|
-
with([{name: "on_server"}])
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
context "when folders are not available" do
|
|
108
|
-
let(:connection_folders) { nil }
|
|
109
|
-
|
|
110
|
-
before do
|
|
111
|
-
allow(Imap::Backup::Setup.highline).
|
|
112
|
-
to receive(:ask) { "q" }
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
it "asks to press a key" do
|
|
116
|
-
expect(Imap::Backup::Setup.highline).
|
|
117
|
-
to receive(:ask).with("Press a key ")
|
|
118
|
-
|
|
119
|
-
subject.run
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
context "with connection errors" do
|
|
124
|
-
before do
|
|
125
|
-
allow(Imap::Backup::Account::Connection).
|
|
126
|
-
to receive(:new).with(account).and_raise("error")
|
|
127
|
-
allow(Imap::Backup::Setup.highline).
|
|
128
|
-
to receive(:ask) { "q" }
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
it "prints an error message" do
|
|
132
|
-
expect(Imap::Backup::Logger.logger).
|
|
133
|
-
to receive(:warn).with("Connection failed")
|
|
134
|
-
|
|
135
|
-
subject.run
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
it "asks to continue" do
|
|
139
|
-
expect(Imap::Backup::Setup.highline).
|
|
140
|
-
to receive(:ask).with("Press a key ")
|
|
141
|
-
|
|
142
|
-
subject.run
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
describe Imap::Backup::Setup do
|
|
2
|
-
include HighLineTestHelpers
|
|
3
|
-
|
|
4
|
-
subject { described_class.new }
|
|
5
|
-
|
|
6
|
-
let(:normal_account) do
|
|
7
|
-
instance_double(
|
|
8
|
-
Imap::Backup::Account,
|
|
9
|
-
username: "account@example.com",
|
|
10
|
-
marked_for_deletion?: false,
|
|
11
|
-
modified?: false
|
|
12
|
-
)
|
|
13
|
-
end
|
|
14
|
-
let(:modified_account) do
|
|
15
|
-
instance_double(
|
|
16
|
-
Imap::Backup::Account,
|
|
17
|
-
username: "modified@example.com",
|
|
18
|
-
marked_for_deletion?: false,
|
|
19
|
-
modified?: true
|
|
20
|
-
)
|
|
21
|
-
end
|
|
22
|
-
let(:deleted_account) do
|
|
23
|
-
instance_double(
|
|
24
|
-
Imap::Backup::Account,
|
|
25
|
-
username: "delete@example.com",
|
|
26
|
-
marked_for_deletion?: true,
|
|
27
|
-
modified?: false
|
|
28
|
-
)
|
|
29
|
-
end
|
|
30
|
-
let(:accounts) { [normal_account] }
|
|
31
|
-
let(:store) do
|
|
32
|
-
instance_double(
|
|
33
|
-
Imap::Backup::Configuration,
|
|
34
|
-
"accounts": accounts,
|
|
35
|
-
"path": "/base/path",
|
|
36
|
-
"save": nil,
|
|
37
|
-
"debug?": debug,
|
|
38
|
-
"debug=": nil,
|
|
39
|
-
"modified?": config_modified
|
|
40
|
-
)
|
|
41
|
-
end
|
|
42
|
-
let(:debug) { false }
|
|
43
|
-
let(:config_modified) { false }
|
|
44
|
-
let!(:highline_streams) { prepare_highline }
|
|
45
|
-
let(:input) { highline_streams[0] }
|
|
46
|
-
let(:output) { highline_streams[1] }
|
|
47
|
-
let(:gmail_imap_server) { "imap.gmail.com" }
|
|
48
|
-
|
|
49
|
-
describe "#initialize" do
|
|
50
|
-
context "without a config file" do
|
|
51
|
-
it "works" do
|
|
52
|
-
described_class.new
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
describe "#run" do
|
|
58
|
-
before do
|
|
59
|
-
allow(Imap::Backup::Configuration).to receive(:new) { store }
|
|
60
|
-
allow(Imap::Backup::Logger).to receive(:setup_logging)
|
|
61
|
-
allow(input).to receive(:eof?) { false }
|
|
62
|
-
allow(input).to receive(:gets) { "q\n" }
|
|
63
|
-
allow(Kernel).to receive(:system)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
describe "main menu" do
|
|
67
|
-
context "when changes have not been made" do
|
|
68
|
-
before { subject.run }
|
|
69
|
-
|
|
70
|
-
["add account", "quit"].each do |choice|
|
|
71
|
-
it "includes #{choice}" do
|
|
72
|
-
expect(output.string).to include(choice)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
context "when changes have been made" do
|
|
78
|
-
let(:config_modified) { true }
|
|
79
|
-
|
|
80
|
-
before do
|
|
81
|
-
allow(input).to receive(:gets) { "exit\n" }
|
|
82
|
-
subject.run
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
["save and exit", "exit without saving"].each do |choice|
|
|
86
|
-
it "includes '#{choice}'" do
|
|
87
|
-
expect(output.string).to include(choice)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it "clears the screen" do
|
|
94
|
-
expect(Kernel).to receive(:system).with("clear")
|
|
95
|
-
|
|
96
|
-
subject.run
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
describe "listing" do
|
|
100
|
-
let(:accounts) { [normal_account, modified_account, deleted_account] }
|
|
101
|
-
|
|
102
|
-
before { subject.run }
|
|
103
|
-
|
|
104
|
-
describe "normal accounts" do
|
|
105
|
-
it "are listed" do
|
|
106
|
-
expect(output.string).to match(/account@example.com/)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
describe "modified accounts" do
|
|
111
|
-
it "are flagged" do
|
|
112
|
-
expect(output.string).to match(/modified@example.com \*/)
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
describe "deleted accounts" do
|
|
117
|
-
it "are hidden" do
|
|
118
|
-
expect(output.string).to_not match(/delete@example.com/)
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
context "when editing accounts" do
|
|
124
|
-
let(:account) do
|
|
125
|
-
instance_double(Imap::Backup::Setup::Account, run: nil)
|
|
126
|
-
end
|
|
127
|
-
let(:config_modified) { true }
|
|
128
|
-
|
|
129
|
-
before do
|
|
130
|
-
allow(input).to receive(:gets).and_return("1\n", "exit\n")
|
|
131
|
-
allow(Imap::Backup::Setup::Asker).to receive(:email).
|
|
132
|
-
with(no_args) { "new@example.com" }
|
|
133
|
-
allow(Imap::Backup::Setup::Account).to receive(:new).
|
|
134
|
-
with(store, normal_account, anything) { account }
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
it "edits the account" do
|
|
138
|
-
expect(account).to receive(:run)
|
|
139
|
-
|
|
140
|
-
subject.run
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
context "when adding accounts" do
|
|
145
|
-
let(:blank_account) do
|
|
146
|
-
{
|
|
147
|
-
username: added_email,
|
|
148
|
-
password: "",
|
|
149
|
-
local_path: local_path,
|
|
150
|
-
folders: []
|
|
151
|
-
}
|
|
152
|
-
end
|
|
153
|
-
let(:account) do
|
|
154
|
-
instance_double(Imap::Backup::Setup::Account, run: nil)
|
|
155
|
-
end
|
|
156
|
-
let(:config_modified) { true }
|
|
157
|
-
let(:added_email) { "new@example.com" }
|
|
158
|
-
let(:local_path) { "/base/path/new_example.com" }
|
|
159
|
-
|
|
160
|
-
before do
|
|
161
|
-
allow(input).to receive(:gets).and_return("add\n", "exit\n")
|
|
162
|
-
allow(Imap::Backup::Setup::Asker).to receive(:email).
|
|
163
|
-
with(no_args) { added_email }
|
|
164
|
-
allow(Imap::Backup::Setup::Account).to receive(:new).
|
|
165
|
-
with(store, anything, anything) { account }
|
|
166
|
-
|
|
167
|
-
subject.run
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
it "sets username" do
|
|
171
|
-
expect(accounts[1].username).to eq(added_email)
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
it "sets blank password" do
|
|
175
|
-
expect(accounts[1].password).to eq("")
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
it "sets local_path" do
|
|
179
|
-
expect(accounts[1].local_path).to eq(local_path)
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
it "sets folders" do
|
|
183
|
-
expect(accounts[1].folders).to eq([])
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
context "when the account is a GMail account" do
|
|
187
|
-
let(:added_email) { "new@gmail.com" }
|
|
188
|
-
let(:local_path) { "/base/path/new_gmail.com" }
|
|
189
|
-
|
|
190
|
-
it "sets the server" do
|
|
191
|
-
expect(accounts[1].server).to eq(gmail_imap_server)
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
it "doesn't flag the unedited account as modified" do
|
|
196
|
-
expect(accounts[1].modified?).to be_falsey
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
describe "logging" do
|
|
201
|
-
context "when debug logging is disabled" do
|
|
202
|
-
let(:config_modified) { true }
|
|
203
|
-
|
|
204
|
-
before do
|
|
205
|
-
allow(input).to receive(:gets).and_return("start\n", "exit\n")
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
it "shows a menu item" do
|
|
209
|
-
subject.run
|
|
210
|
-
|
|
211
|
-
expect(output.string).to include("start logging")
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
context "when selected" do
|
|
215
|
-
it "sets the debug flag" do
|
|
216
|
-
expect(store).to receive(:debug=).with(true)
|
|
217
|
-
|
|
218
|
-
subject.run
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
it "updates logging status" do
|
|
222
|
-
expect(Imap::Backup::Logger).to receive(:setup_logging)
|
|
223
|
-
|
|
224
|
-
subject.run
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
context "when debug logging is enabled" do
|
|
230
|
-
let(:debug) { true }
|
|
231
|
-
let(:config_modified) { true }
|
|
232
|
-
|
|
233
|
-
before do
|
|
234
|
-
allow(input).to receive(:gets).and_return("stop\n", "exit\n")
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
it "shows a menu item" do
|
|
238
|
-
subject.run
|
|
239
|
-
|
|
240
|
-
expect(output.string).to include("stop logging")
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
context "when selected" do
|
|
244
|
-
before do
|
|
245
|
-
allow(input).to receive(:gets).and_return("stop\n", "exit\n")
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
it "unsets the debug flag" do
|
|
249
|
-
expect(store).to receive(:debug=).with(false)
|
|
250
|
-
|
|
251
|
-
subject.run
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
it "updates logging status" do
|
|
255
|
-
expect(Imap::Backup::Logger).to receive(:setup_logging)
|
|
256
|
-
|
|
257
|
-
subject.run
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
context "when 'save' is selected" do
|
|
264
|
-
let(:config_modified) { true }
|
|
265
|
-
|
|
266
|
-
before do
|
|
267
|
-
allow(input).to receive(:gets) { "save\n" }
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
it "exits" do
|
|
271
|
-
# N.B. this will hang forever if save does not cause an exit
|
|
272
|
-
subject.run
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
it "saves the configuration" do
|
|
276
|
-
expect(store).to receive(:save)
|
|
277
|
-
|
|
278
|
-
subject.run
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
context "when 'exit without saving' is selected" do
|
|
283
|
-
let(:config_modified) { true }
|
|
284
|
-
|
|
285
|
-
before do
|
|
286
|
-
allow(input).to receive(:gets) { "exit\n" }
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
it "exits" do
|
|
290
|
-
# N.B. this will hang forever if quit does not cause an exit
|
|
291
|
-
subject.run
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
it "doesn't save the configuration" do
|
|
295
|
-
expect(store).to_not receive(:save)
|
|
296
|
-
|
|
297
|
-
subject.run
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
describe Imap::Backup::Uploader do
|
|
2
|
-
subject { described_class.new(folder, serializer) }
|
|
3
|
-
|
|
4
|
-
let(:folder) do
|
|
5
|
-
instance_double(
|
|
6
|
-
Imap::Backup::Account::Folder, uids: [2, 3], append: 99, name: "foo"
|
|
7
|
-
)
|
|
8
|
-
end
|
|
9
|
-
let(:serializer) do
|
|
10
|
-
instance_double(
|
|
11
|
-
Imap::Backup::Serializer::Mbox,
|
|
12
|
-
uids: [1, 2],
|
|
13
|
-
update_uid: nil
|
|
14
|
-
)
|
|
15
|
-
end
|
|
16
|
-
let(:missing_message) do
|
|
17
|
-
instance_double(Email::Mboxrd::Message, supplied_body: "missing message")
|
|
18
|
-
end
|
|
19
|
-
let(:existing_message) do
|
|
20
|
-
instance_double(Email::Mboxrd::Message, supplied_body: "existing message")
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def message_enumerator
|
|
24
|
-
yield [1, missing_message]
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
describe "#run" do
|
|
28
|
-
before do
|
|
29
|
-
allow(serializer).to receive(:each_message).and_return(enum_for(:message_enumerator))
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
context "with messages that are missing" do
|
|
33
|
-
it "restores them" do
|
|
34
|
-
expect(folder).to receive(:append).with(missing_message)
|
|
35
|
-
|
|
36
|
-
subject.run
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "updates the local message id" do
|
|
40
|
-
expect(serializer).to receive(:update_uid).with(1, 99)
|
|
41
|
-
|
|
42
|
-
subject.run
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
context "with messages that are present on server" do
|
|
47
|
-
it "does nothing" do
|
|
48
|
-
expect(folder).to_not receive(:append).with(existing_message)
|
|
49
|
-
|
|
50
|
-
subject.run
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|