imap-backup 2.1.1 → 2.2.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/.rubocop.yml +2 -0
- data/README.md +6 -2
- data/bin/imap-backup +1 -1
- data/lib/email/mboxrd/message.rb +0 -1
- data/lib/imap/backup/account/connection.rb +28 -21
- data/lib/imap/backup/account/folder.rb +0 -1
- data/lib/imap/backup/serializer/mbox_enumerator.rb +1 -1
- data/lib/imap/backup/uploader.rb +10 -1
- data/lib/imap/backup/version.rb +2 -2
- data/spec/features/restore_spec.rb +75 -27
- data/spec/features/support/email_server.rb +1 -3
- data/spec/features/support/shared/message_fixtures.rb +8 -0
- data/spec/unit/email/mboxrd/message_spec.rb +0 -6
- data/spec/unit/imap/backup/account/connection_spec.rb +58 -43
- data/spec/unit/imap/backup/account/folder_spec.rb +16 -20
- data/spec/unit/imap/backup/configuration/account_spec.rb +31 -25
- data/spec/unit/imap/backup/configuration/asker_spec.rb +20 -17
- data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +6 -10
- data/spec/unit/imap/backup/configuration/folder_chooser_spec.rb +16 -10
- data/spec/unit/imap/backup/configuration/list_spec.rb +6 -3
- data/spec/unit/imap/backup/configuration/setup_spec.rb +40 -25
- data/spec/unit/imap/backup/configuration/store_spec.rb +18 -16
- data/spec/unit/imap/backup/downloader_spec.rb +14 -14
- data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +6 -1
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +54 -40
- data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +49 -31
- data/spec/unit/imap/backup/uploader_spec.rb +20 -7
- data/spec/unit/imap/backup/utils_spec.rb +8 -9
- metadata +2 -2
@@ -28,7 +28,7 @@ describe Imap::Backup::Account::Folder do
|
|
28
28
|
describe "#uids" do
|
29
29
|
let(:uids) { [5678, 123] }
|
30
30
|
|
31
|
-
before { allow(imap).to receive(:uid_search)
|
31
|
+
before { allow(imap).to receive(:uid_search) { uids } }
|
32
32
|
|
33
33
|
it "lists available messages" do
|
34
34
|
expect(subject.uids).to eq(uids.reverse)
|
@@ -83,12 +83,6 @@ describe Imap::Backup::Account::Folder do
|
|
83
83
|
expect(subject.fetch(123)).to be_nil
|
84
84
|
end
|
85
85
|
end
|
86
|
-
|
87
|
-
it "sets the encoding on the message" do
|
88
|
-
subject.fetch(123)
|
89
|
-
|
90
|
-
expect(message_body).to have_received(:force_encoding).with("utf-8")
|
91
|
-
end
|
92
86
|
end
|
93
87
|
|
94
88
|
describe "#folder" do
|
@@ -117,21 +111,22 @@ describe Imap::Backup::Account::Folder do
|
|
117
111
|
|
118
112
|
describe "#create" do
|
119
113
|
context "when the folder exists" do
|
120
|
-
before { subject.create }
|
121
|
-
|
122
114
|
it "is does not create the folder" do
|
123
|
-
expect(imap).to_not
|
115
|
+
expect(imap).to_not receive(:create)
|
116
|
+
|
117
|
+
subject.create
|
124
118
|
end
|
125
119
|
end
|
126
120
|
|
127
121
|
context "when the folder doesn't exist" do
|
128
122
|
before do
|
129
123
|
allow(imap).to receive(:examine).and_raise(missing_mailbox_error)
|
130
|
-
subject.create
|
131
124
|
end
|
132
125
|
|
133
126
|
it "is does not create the folder" do
|
134
|
-
expect(imap).to
|
127
|
+
expect(imap).to receive(:create)
|
128
|
+
|
129
|
+
subject.create
|
135
130
|
end
|
136
131
|
end
|
137
132
|
end
|
@@ -168,26 +163,27 @@ describe Imap::Backup::Account::Folder do
|
|
168
163
|
let(:append_response) do
|
169
164
|
OpenStruct.new(data: OpenStruct.new(code: OpenStruct.new(data: "1 2")))
|
170
165
|
end
|
171
|
-
let(:result) { subject.append(message) }
|
172
|
-
|
173
|
-
before do
|
174
|
-
result
|
175
|
-
end
|
176
166
|
|
177
167
|
it "appends the message" do
|
178
|
-
expect(imap).to
|
168
|
+
expect(imap).to receive(:append)
|
169
|
+
|
170
|
+
subject.append(message)
|
179
171
|
end
|
180
172
|
|
181
173
|
it "sets the date and time" do
|
182
|
-
expect(imap).to
|
174
|
+
expect(imap).to receive(:append).
|
183
175
|
with(anything, anything, anything, message_date)
|
176
|
+
|
177
|
+
subject.append(message)
|
184
178
|
end
|
185
179
|
|
186
180
|
it "returns the new uid" do
|
187
|
-
expect(
|
181
|
+
expect(subject.append(message)).to eq(2)
|
188
182
|
end
|
189
183
|
|
190
184
|
it "set the new uid validity" do
|
185
|
+
subject.append(message)
|
186
|
+
|
191
187
|
expect(subject.uid_validity).to eq(1)
|
192
188
|
end
|
193
189
|
end
|
@@ -1,23 +1,6 @@
|
|
1
1
|
# rubocop:disable RSpec/NestedGroups
|
2
2
|
|
3
3
|
describe Imap::Backup::Configuration::Account do
|
4
|
-
class MockHighlineMenu
|
5
|
-
attr_reader :choices
|
6
|
-
attr_accessor :header
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@choices = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
def choice(name, &block)
|
13
|
-
choices[name] = block
|
14
|
-
end
|
15
|
-
|
16
|
-
def hidden(name, &block)
|
17
|
-
choices[name] = block
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
4
|
describe "#initialize" do
|
22
5
|
subject { described_class.new(store, account, highline) }
|
23
6
|
|
@@ -35,8 +18,27 @@ describe Imap::Backup::Configuration::Account do
|
|
35
18
|
describe "#run" do
|
36
19
|
subject { described_class.new(store, account, highline) }
|
37
20
|
|
21
|
+
let(:highline_menu_class) do
|
22
|
+
Class.new do
|
23
|
+
attr_reader :choices
|
24
|
+
attr_accessor :header
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@choices = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def choice(name, &block)
|
31
|
+
choices[name] = block
|
32
|
+
end
|
33
|
+
|
34
|
+
def hidden(name, &block)
|
35
|
+
choices[name] = block
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
38
40
|
let(:highline) { instance_double(HighLine) }
|
39
|
-
let(:menu) {
|
41
|
+
let(:menu) { highline_menu_class.new }
|
40
42
|
let(:store) do
|
41
43
|
instance_double(Imap::Backup::Configuration::Store, accounts: accounts)
|
42
44
|
end
|
@@ -73,15 +75,17 @@ describe Imap::Backup::Configuration::Account do
|
|
73
75
|
end
|
74
76
|
|
75
77
|
describe "preparation" do
|
76
|
-
before { subject.run }
|
77
|
-
|
78
78
|
it "clears the screen" do
|
79
|
-
expect(Kernel).to
|
79
|
+
expect(Kernel).to receive(:system).with("clear")
|
80
|
+
|
81
|
+
subject.run
|
80
82
|
end
|
81
83
|
|
82
84
|
describe "menu" do
|
83
85
|
it "shows the menu" do
|
84
|
-
expect(highline).to
|
86
|
+
expect(highline).to receive(:choose)
|
87
|
+
|
88
|
+
subject.run
|
85
89
|
end
|
86
90
|
end
|
87
91
|
end
|
@@ -240,8 +244,10 @@ describe Imap::Backup::Configuration::Account do
|
|
240
244
|
let(:server) { "server" }
|
241
245
|
|
242
246
|
before do
|
243
|
-
allow(highline).to receive(:ask).with("server: ")
|
247
|
+
allow(highline).to receive(:ask).with("server: ") { server }
|
248
|
+
|
244
249
|
subject.run
|
250
|
+
|
245
251
|
menu.choices["modify server"].call
|
246
252
|
end
|
247
253
|
|
@@ -310,7 +316,7 @@ describe Imap::Backup::Configuration::Account do
|
|
310
316
|
describe "connection test" do
|
311
317
|
before do
|
312
318
|
allow(Imap::Backup::Configuration::ConnectionTester).
|
313
|
-
to receive(:test)
|
319
|
+
to receive(:test) { "All fine" }
|
314
320
|
allow(highline).to receive(:ask)
|
315
321
|
subject.run
|
316
322
|
menu.choices["test connection"].call
|
@@ -326,7 +332,7 @@ describe Imap::Backup::Configuration::Account do
|
|
326
332
|
let(:confirmed) { true }
|
327
333
|
|
328
334
|
before do
|
329
|
-
allow(highline).to receive(:agree)
|
335
|
+
allow(highline).to receive(:agree) { confirmed }
|
330
336
|
subject.run
|
331
337
|
catch :done do
|
332
338
|
menu.choices["delete"].call
|
@@ -30,9 +30,9 @@ module Imap::Backup
|
|
30
30
|
].each do |method, params, prompt|
|
31
31
|
context ".#{method}" do
|
32
32
|
it "asks for input" do
|
33
|
-
|
33
|
+
expect(highline).to receive(:ask).with("#{prompt}: ")
|
34
34
|
|
35
|
-
|
35
|
+
described_class.send(method, *params)
|
36
36
|
end
|
37
37
|
|
38
38
|
it "returns the answer" do
|
@@ -56,16 +56,15 @@ module Imap::Backup
|
|
56
56
|
describe "#email" do
|
57
57
|
let(:email) { "email@example.com" }
|
58
58
|
let(:answer) { email }
|
59
|
-
let(:result) { subject.email }
|
60
|
-
|
61
|
-
before { result }
|
62
59
|
|
63
60
|
it "asks for an email" do
|
64
|
-
expect(highline).to
|
61
|
+
expect(highline).to receive(:ask).with(/email/)
|
62
|
+
|
63
|
+
subject.email
|
65
64
|
end
|
66
65
|
|
67
66
|
it "returns the address" do
|
68
|
-
expect(
|
67
|
+
expect(subject.email).to eq(email)
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
@@ -73,7 +72,6 @@ module Imap::Backup
|
|
73
72
|
let(:password1) { "password" }
|
74
73
|
let(:password2) { "password" }
|
75
74
|
let(:answers) { [true, false] }
|
76
|
-
let(:result) { subject.password }
|
77
75
|
|
78
76
|
before do
|
79
77
|
i = 0
|
@@ -84,27 +82,32 @@ module Imap::Backup
|
|
84
82
|
i += 1
|
85
83
|
answer
|
86
84
|
end
|
87
|
-
result
|
88
85
|
end
|
89
86
|
|
90
87
|
it "asks for a password" do
|
91
|
-
expect(highline).to
|
88
|
+
expect(highline).to receive(:ask).with("password: ")
|
89
|
+
|
90
|
+
subject.password
|
92
91
|
end
|
93
92
|
|
94
93
|
it "asks for confirmation" do
|
95
|
-
expect(highline).to
|
94
|
+
expect(highline).to receive(:ask).with("repeat password: ")
|
95
|
+
|
96
|
+
subject.password
|
96
97
|
end
|
97
98
|
|
98
99
|
it "returns the password" do
|
99
|
-
expect(
|
100
|
+
expect(subject.password).to eq(password1)
|
100
101
|
end
|
101
102
|
|
102
103
|
context "with different answers" do
|
103
104
|
let(:password2) { "secret" }
|
104
105
|
|
105
106
|
it "asks to continue" do
|
106
|
-
expect(highline).to
|
107
|
+
expect(highline).to receive(:agree).
|
107
108
|
at_least(:once).with(/Continue\?/)
|
109
|
+
|
110
|
+
subject.password
|
108
111
|
end
|
109
112
|
end
|
110
113
|
end
|
@@ -112,22 +115,22 @@ module Imap::Backup
|
|
112
115
|
describe "#backup_path" do
|
113
116
|
let(:path) { "/path" }
|
114
117
|
let(:answer) { path }
|
115
|
-
let(:result) { subject.backup_path("", //) }
|
116
118
|
|
117
119
|
before do
|
118
120
|
allow(highline).to receive(:ask) do |&b|
|
119
121
|
b.call query
|
120
122
|
path
|
121
123
|
end
|
122
|
-
result
|
123
124
|
end
|
124
125
|
|
125
126
|
it "asks for a directory" do
|
126
|
-
expect(highline).to
|
127
|
+
expect(highline).to receive(:ask).with(/directory/)
|
128
|
+
|
129
|
+
subject.backup_path("", //)
|
127
130
|
end
|
128
131
|
|
129
132
|
it "returns the path" do
|
130
|
-
expect(
|
133
|
+
expect(subject.backup_path("", //)).to eq(path)
|
131
134
|
end
|
132
135
|
end
|
133
136
|
end
|
@@ -3,32 +3,28 @@ describe Imap::Backup::Configuration::ConnectionTester do
|
|
3
3
|
let(:connection) do
|
4
4
|
instance_double(Imap::Backup::Account::Connection, imap: nil)
|
5
5
|
end
|
6
|
-
let(:result) { subject.test("foo") }
|
7
6
|
|
8
7
|
before do
|
9
8
|
allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
|
10
9
|
end
|
11
10
|
|
12
11
|
describe "call" do
|
13
|
-
before { result }
|
14
|
-
|
15
12
|
it "tries to connect" do
|
16
|
-
expect(connection).to
|
13
|
+
expect(connection).to receive(:imap)
|
14
|
+
|
15
|
+
subject.test("foo")
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
19
|
describe "success" do
|
21
|
-
before { result }
|
22
|
-
|
23
20
|
it "returns success" do
|
24
|
-
expect(
|
21
|
+
expect(subject.test("foo")).to match(/successful/)
|
25
22
|
end
|
26
23
|
end
|
27
24
|
|
28
25
|
describe "failure" do
|
29
26
|
before do
|
30
27
|
allow(connection).to receive(:imap).and_raise(error)
|
31
|
-
result
|
32
28
|
end
|
33
29
|
|
34
30
|
context "with no connection" do
|
@@ -39,7 +35,7 @@ describe Imap::Backup::Configuration::ConnectionTester do
|
|
39
35
|
end
|
40
36
|
|
41
37
|
it "returns error" do
|
42
|
-
expect(
|
38
|
+
expect(subject.test("foo")).to match(/no response/i)
|
43
39
|
end
|
44
40
|
end
|
45
41
|
|
@@ -47,7 +43,7 @@ describe Imap::Backup::Configuration::ConnectionTester do
|
|
47
43
|
let(:error) { "Error" }
|
48
44
|
|
49
45
|
it "returns error" do
|
50
|
-
expect(
|
46
|
+
expect(subject.test("foo")).to match(/unexpected error/i)
|
51
47
|
end
|
52
48
|
end
|
53
49
|
end
|
@@ -22,13 +22,15 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "display" do
|
25
|
-
before { subject.run }
|
26
|
-
|
27
25
|
it "clears the screen" do
|
28
|
-
expect(Kernel).to
|
26
|
+
expect(Kernel).to receive(:system).with("clear")
|
27
|
+
|
28
|
+
subject.run
|
29
29
|
end
|
30
30
|
|
31
31
|
it "shows the menu" do
|
32
|
+
subject.run
|
33
|
+
|
32
34
|
expect(output.string).to match %r{Add/remove folders}
|
33
35
|
end
|
34
36
|
end
|
@@ -114,13 +116,14 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
114
116
|
|
115
117
|
before do
|
116
118
|
allow(Imap::Backup::Configuration::Setup.highline).
|
117
|
-
to receive(:ask)
|
118
|
-
subject.run
|
119
|
+
to receive(:ask) { "q" }
|
119
120
|
end
|
120
121
|
|
121
122
|
it "asks to press a key" do
|
122
123
|
expect(Imap::Backup::Configuration::Setup.highline).
|
123
|
-
to
|
124
|
+
to receive(:ask).with("Press a key ")
|
125
|
+
|
126
|
+
subject.run
|
124
127
|
end
|
125
128
|
end
|
126
129
|
|
@@ -129,18 +132,21 @@ describe Imap::Backup::Configuration::FolderChooser do
|
|
129
132
|
allow(Imap::Backup::Account::Connection).
|
130
133
|
to receive(:new).with(account).and_raise("error")
|
131
134
|
allow(Imap::Backup::Configuration::Setup.highline).
|
132
|
-
to receive(:ask)
|
133
|
-
subject.run
|
135
|
+
to receive(:ask) { "q" }
|
134
136
|
end
|
135
137
|
|
136
138
|
it "prints an error message" do
|
137
139
|
expect(Imap::Backup.logger).
|
138
|
-
to
|
140
|
+
to receive(:warn).with("Connection failed")
|
141
|
+
|
142
|
+
subject.run
|
139
143
|
end
|
140
144
|
|
141
145
|
it "asks to continue" do
|
142
146
|
expect(Imap::Backup::Configuration::Setup.highline).
|
143
|
-
to
|
147
|
+
to receive(:ask).with("Press a key ")
|
148
|
+
|
149
|
+
subject.run
|
144
150
|
end
|
145
151
|
end
|
146
152
|
end
|
@@ -35,18 +35,21 @@ describe Imap::Backup::Configuration::List do
|
|
35
35
|
allow(Imap::Backup::Configuration::Store).
|
36
36
|
to receive(:exist?) { config_exists }
|
37
37
|
allow(Imap::Backup).to receive(:setup_logging)
|
38
|
-
subject.setup_logging
|
39
38
|
end
|
40
39
|
|
41
40
|
it "sets global logging level" do
|
42
|
-
expect(Imap::Backup).to
|
41
|
+
expect(Imap::Backup).to receive(:setup_logging).with(store)
|
42
|
+
|
43
|
+
subject.setup_logging
|
43
44
|
end
|
44
45
|
|
45
46
|
context "without a config" do
|
46
47
|
let(:config_exists) { false }
|
47
48
|
|
48
49
|
it "does nothing" do
|
49
|
-
expect(Imap::Backup).to_not
|
50
|
+
expect(Imap::Backup).to_not receive(:setup_logging).with(store)
|
51
|
+
|
52
|
+
subject.setup_logging
|
50
53
|
end
|
51
54
|
end
|
52
55
|
end
|
@@ -52,15 +52,15 @@ describe Imap::Backup::Configuration::Setup do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it "clears the screen" do
|
55
|
-
|
55
|
+
expect(Kernel).to receive(:system).with("clear")
|
56
56
|
|
57
|
-
|
57
|
+
subject.run
|
58
58
|
end
|
59
59
|
|
60
60
|
it "updates logging status" do
|
61
|
-
|
61
|
+
expect(Imap::Backup).to receive(:setup_logging)
|
62
62
|
|
63
|
-
|
63
|
+
subject.run
|
64
64
|
end
|
65
65
|
|
66
66
|
describe "listing" do
|
@@ -97,15 +97,15 @@ describe Imap::Backup::Configuration::Setup do
|
|
97
97
|
before do
|
98
98
|
allow(input).to receive(:gets).and_return("1\n", "exit\n")
|
99
99
|
allow(Imap::Backup::Configuration::Asker).to receive(:email).
|
100
|
-
with(no_args)
|
100
|
+
with(no_args) { "new@example.com" }
|
101
101
|
allow(Imap::Backup::Configuration::Account).to receive(:new).
|
102
|
-
with(store, normal, anything)
|
103
|
-
|
104
|
-
subject.run
|
102
|
+
with(store, normal, anything) { account }
|
105
103
|
end
|
106
104
|
|
107
105
|
it "edits the account" do
|
108
|
-
expect(account).to
|
106
|
+
expect(account).to receive(:run)
|
107
|
+
|
108
|
+
subject.run
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -125,9 +125,9 @@ describe Imap::Backup::Configuration::Setup do
|
|
125
125
|
before do
|
126
126
|
allow(input).to receive(:gets).and_return("add\n", "exit\n")
|
127
127
|
allow(Imap::Backup::Configuration::Asker).to receive(:email).
|
128
|
-
with(no_args)
|
128
|
+
with(no_args) { "new@example.com" }
|
129
129
|
allow(Imap::Backup::Configuration::Account).to receive(:new).
|
130
|
-
with(store, blank_account, anything)
|
130
|
+
with(store, blank_account, anything) { account }
|
131
131
|
|
132
132
|
subject.run
|
133
133
|
end
|
@@ -145,20 +145,25 @@ describe Imap::Backup::Configuration::Setup do
|
|
145
145
|
context "when debug logging is disabled" do
|
146
146
|
before do
|
147
147
|
allow(input).to receive(:gets).and_return("start\n", "exit\n")
|
148
|
-
subject.run
|
149
148
|
end
|
150
149
|
|
151
150
|
it "shows a menu item" do
|
151
|
+
subject.run
|
152
|
+
|
152
153
|
expect(output.string).to include("start logging")
|
153
154
|
end
|
154
155
|
|
155
156
|
context "when selected" do
|
156
157
|
it "sets the debug flag" do
|
157
|
-
expect(store).to
|
158
|
+
expect(store).to receive(:debug=).with(true)
|
159
|
+
|
160
|
+
subject.run
|
158
161
|
end
|
159
162
|
|
160
163
|
it "updates logging status" do
|
161
|
-
expect(Imap::Backup).to
|
164
|
+
expect(Imap::Backup).to receive(:setup_logging).twice
|
165
|
+
|
166
|
+
subject.run
|
162
167
|
end
|
163
168
|
end
|
164
169
|
end
|
@@ -168,10 +173,11 @@ describe Imap::Backup::Configuration::Setup do
|
|
168
173
|
|
169
174
|
before do
|
170
175
|
allow(input).to receive(:gets).and_return("stop\n", "exit\n")
|
171
|
-
subject.run
|
172
176
|
end
|
173
177
|
|
174
178
|
it "shows a menu item" do
|
179
|
+
subject.run
|
180
|
+
|
175
181
|
expect(output.string).to include("stop logging")
|
176
182
|
end
|
177
183
|
|
@@ -181,11 +187,15 @@ describe Imap::Backup::Configuration::Setup do
|
|
181
187
|
end
|
182
188
|
|
183
189
|
it "unsets the debug flag" do
|
184
|
-
expect(store).to
|
190
|
+
expect(store).to receive(:debug=).with(false)
|
191
|
+
|
192
|
+
subject.run
|
185
193
|
end
|
186
194
|
|
187
195
|
it "updates logging status" do
|
188
|
-
expect(Imap::Backup).to
|
196
|
+
expect(Imap::Backup).to receive(:setup_logging).twice
|
197
|
+
|
198
|
+
subject.run
|
189
199
|
end
|
190
200
|
end
|
191
201
|
end
|
@@ -193,41 +203,46 @@ describe Imap::Backup::Configuration::Setup do
|
|
193
203
|
|
194
204
|
context "when 'save' is selected" do
|
195
205
|
before do
|
196
|
-
allow(input).to receive(:gets)
|
197
|
-
subject.run
|
206
|
+
allow(input).to receive(:gets) { "save\n" }
|
198
207
|
end
|
199
208
|
|
200
209
|
it "exits" do
|
201
210
|
# N.B. this will hang forever if save does not cause an exit
|
211
|
+
subject.run
|
202
212
|
end
|
203
213
|
|
204
214
|
it "saves the configuration" do
|
205
|
-
expect(store).to
|
215
|
+
expect(store).to receive(:save)
|
216
|
+
|
217
|
+
subject.run
|
206
218
|
end
|
207
219
|
end
|
208
220
|
|
209
221
|
context "when 'exit without saving' is selected" do
|
210
222
|
before do
|
211
|
-
allow(input).to receive(:gets)
|
212
|
-
|
213
|
-
subject.run
|
223
|
+
allow(input).to receive(:gets) { "exit\n" }
|
214
224
|
end
|
215
225
|
|
216
226
|
it "exits" do
|
217
227
|
# N.B. this will hang forever if quit does not cause an exit
|
228
|
+
subject.run
|
218
229
|
end
|
219
230
|
|
220
231
|
context "when the configuration is modified" do
|
221
232
|
let(:modified) { true }
|
222
233
|
|
223
234
|
it "doesn't save the configuration" do
|
224
|
-
expect(store).to_not
|
235
|
+
expect(store).to_not receive(:save)
|
236
|
+
|
237
|
+
subject.run
|
225
238
|
end
|
226
239
|
end
|
227
240
|
|
228
241
|
context "when the configuration isn't modified" do
|
229
242
|
it "doesn't save the configuration" do
|
230
|
-
expect(store).to_not
|
243
|
+
expect(store).to_not receive(:save)
|
244
|
+
|
245
|
+
subject.run
|
231
246
|
end
|
232
247
|
end
|
233
248
|
end
|