tmuxinator 0.6.11 → 0.7.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/bin/mux +6 -9
- data/bin/tmuxinator +6 -9
- data/lib/tmuxinator/assets/template.erb +6 -6
- data/lib/tmuxinator/assets/wemux_template.erb +1 -1
- data/lib/tmuxinator/cli.rb +111 -33
- data/lib/tmuxinator/config.rb +47 -35
- data/lib/tmuxinator/pane.rb +21 -5
- data/lib/tmuxinator/project.rb +94 -29
- data/lib/tmuxinator/version.rb +1 -1
- data/lib/tmuxinator/wemux_support.rb +4 -4
- data/lib/tmuxinator/window.rb +15 -5
- data/spec/factories/projects.rb +53 -11
- data/spec/fixtures/detach.yml +41 -0
- data/spec/fixtures/nameless_window.yml +5 -0
- data/spec/fixtures/nowindows.yml +3 -0
- data/spec/fixtures/sample.yml +1 -0
- data/spec/fixtures/sample_number_as_name.yml +5 -0
- data/spec/lib/tmuxinator/cli_spec.rb +191 -30
- data/spec/lib/tmuxinator/config_spec.rb +105 -8
- data/spec/lib/tmuxinator/project_spec.rb +172 -28
- data/spec/lib/tmuxinator/util_spec.rb +0 -1
- data/spec/lib/tmuxinator/wemux_support_spec.rb +47 -0
- data/spec/lib/tmuxinator/window_spec.rb +82 -21
- data/spec/spec_helper.rb +16 -15
- metadata +13 -3
@@ -20,11 +20,11 @@ describe Tmuxinator::Cli do
|
|
20
20
|
describe "#completions" do
|
21
21
|
before do
|
22
22
|
ARGV.replace(["completions", "start"])
|
23
|
-
allow(Tmuxinator::Config).to receive_messages(:
|
23
|
+
allow(Tmuxinator::Config).to receive_messages(configs: ["test.yml"])
|
24
24
|
end
|
25
25
|
|
26
26
|
it "gets completions" do
|
27
|
-
out,
|
27
|
+
out, _err = capture_io { cli.start }
|
28
28
|
expect(out).to include("test.yml")
|
29
29
|
end
|
30
30
|
end
|
@@ -35,16 +35,29 @@ describe Tmuxinator::Cli do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
it "lists the commands" do
|
38
|
-
out,
|
39
|
-
|
38
|
+
out, _err = capture_io { cli.start }
|
39
|
+
expected = %w(commands
|
40
|
+
completions
|
41
|
+
new
|
42
|
+
open
|
43
|
+
start
|
44
|
+
local
|
45
|
+
debug
|
46
|
+
copy
|
47
|
+
delete
|
48
|
+
implode
|
49
|
+
version
|
50
|
+
doctor
|
51
|
+
list)
|
52
|
+
expect(out).to eq "#{expected.join("\n")}\n"
|
40
53
|
end
|
41
54
|
end
|
42
55
|
|
43
56
|
describe "#start" do
|
44
57
|
before do
|
45
58
|
ARGV.replace(["start", "foo"])
|
46
|
-
allow(Tmuxinator::Config).to receive_messages(:
|
47
|
-
allow(Tmuxinator::Config).to receive_messages(:
|
59
|
+
allow(Tmuxinator::Config).to receive_messages(validate: project)
|
60
|
+
allow(Tmuxinator::Config).to receive_messages(version: 1.9)
|
48
61
|
allow(Kernel).to receive(:exec)
|
49
62
|
end
|
50
63
|
|
@@ -55,27 +68,74 @@ describe Tmuxinator::Cli do
|
|
55
68
|
expect(Kernel).to receive(:exec)
|
56
69
|
capture_io { cli.start }
|
57
70
|
end
|
71
|
+
|
72
|
+
it "accepts a flag for alternate name" do
|
73
|
+
ARGV.replace(["start", "foo" "--name=bar"])
|
74
|
+
|
75
|
+
expect(Kernel).to receive(:exec)
|
76
|
+
capture_io { cli.start }
|
77
|
+
end
|
78
|
+
|
79
|
+
it "accepts additional arguments" do
|
80
|
+
ARGV.replace(["start", "foo", "bar", "three=four"])
|
81
|
+
|
82
|
+
expect(Kernel).to receive(:exec)
|
83
|
+
capture_io { cli.start }
|
84
|
+
end
|
58
85
|
end
|
59
86
|
|
60
87
|
context "deprecations" do
|
61
88
|
before do
|
62
|
-
allow($stdin).to receive_messages(:
|
89
|
+
allow($stdin).to receive_messages(getc: "y")
|
63
90
|
end
|
64
91
|
|
65
92
|
let(:project) { FactoryGirl.build(:project_with_deprecations) }
|
66
93
|
|
67
94
|
it "prints the deprecations" do
|
68
|
-
out,
|
95
|
+
out, _err = capture_io { cli.start }
|
69
96
|
expect(out).to include "DEPRECATION"
|
70
97
|
end
|
71
98
|
end
|
72
99
|
end
|
73
100
|
|
101
|
+
describe "#local" do
|
102
|
+
shared_examples_for :local_project do
|
103
|
+
before do
|
104
|
+
allow(Tmuxinator::Config).to receive_messages(validate: project)
|
105
|
+
allow(Tmuxinator::Config).to receive_messages(version: 1.9)
|
106
|
+
allow(Kernel).to receive(:exec)
|
107
|
+
end
|
108
|
+
|
109
|
+
let(:project) { FactoryGirl.build(:project) }
|
110
|
+
|
111
|
+
it "starts the project" do
|
112
|
+
expect(Kernel).to receive(:exec)
|
113
|
+
out, err = capture_io { cli.start }
|
114
|
+
expect(err).to eq ""
|
115
|
+
expect(out).to eq ""
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "when the command used is 'local'" do
|
120
|
+
before do
|
121
|
+
ARGV.replace ["local"]
|
122
|
+
end
|
123
|
+
it_should_behave_like :local_project
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when the command used is '.'" do
|
127
|
+
before do
|
128
|
+
ARGV.replace ["."]
|
129
|
+
end
|
130
|
+
it_should_behave_like :local_project
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
74
134
|
describe "#start(custom_name)" do
|
75
135
|
before do
|
76
136
|
ARGV.replace(["start", "foo", "bar"])
|
77
|
-
allow(Tmuxinator::Config).to receive_messages(:
|
78
|
-
allow(Tmuxinator::Config).to receive_messages(:
|
137
|
+
allow(Tmuxinator::Config).to receive_messages(validate: project)
|
138
|
+
allow(Tmuxinator::Config).to receive_messages(version: 1.9)
|
79
139
|
allow(Kernel).to receive(:exec)
|
80
140
|
end
|
81
141
|
|
@@ -91,31 +151,70 @@ describe Tmuxinator::Cli do
|
|
91
151
|
|
92
152
|
describe "#new" do
|
93
153
|
let(:file) { StringIO.new }
|
154
|
+
let(:name) { "test" }
|
94
155
|
|
95
156
|
before do
|
96
|
-
ARGV.replace(["new", "test"])
|
97
157
|
allow(File).to receive(:open) { |&block| block.yield file }
|
98
158
|
end
|
99
159
|
|
100
|
-
context "
|
160
|
+
context "without the --local option" do
|
101
161
|
before do
|
102
|
-
|
162
|
+
ARGV.replace(["new", name])
|
103
163
|
end
|
104
164
|
|
105
|
-
|
106
|
-
|
107
|
-
|
165
|
+
context "existing project doesn't exist" do
|
166
|
+
before do
|
167
|
+
expect(Tmuxinator::Config).to receive_messages(exists?: false)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "creates a new tmuxinator project file" do
|
171
|
+
capture_io { cli.start }
|
172
|
+
expect(file.string).to_not be_empty
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "files exists" do
|
177
|
+
let(:command) { "#{ENV['HOME']}\/\.tmuxinator\/#{name}\.yml" }
|
178
|
+
|
179
|
+
before do
|
180
|
+
expect(Tmuxinator::Config).to receive_messages(exists?: true)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "just opens the file" do
|
184
|
+
expect(Kernel).to receive(:system).with(%r{#{command}})
|
185
|
+
capture_io { cli.start }
|
186
|
+
end
|
108
187
|
end
|
109
188
|
end
|
110
189
|
|
111
|
-
context "
|
190
|
+
context "with the --local option" do
|
112
191
|
before do
|
113
|
-
|
192
|
+
ARGV.replace ["new", name, "--local"]
|
114
193
|
end
|
115
194
|
|
116
|
-
|
117
|
-
|
118
|
-
|
195
|
+
context "existing project doesn't exist" do
|
196
|
+
before do
|
197
|
+
expect(Tmuxinator::Config).to receive(:exists?).at_least(:once) do
|
198
|
+
false
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
it "creates a new tmuxinator project file" do
|
203
|
+
capture_io { cli.start }
|
204
|
+
expect(file.string).to_not be_empty
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "files exists" do
|
209
|
+
let(:path) { Tmuxinator::Config::LOCAL_DEFAULT }
|
210
|
+
before do
|
211
|
+
expect(Tmuxinator::Config).to receive(:exists?).with(path) { true }
|
212
|
+
end
|
213
|
+
|
214
|
+
it "just opens the file" do
|
215
|
+
expect(Kernel).to receive(:system).with(%r{#{path}})
|
216
|
+
capture_io { cli.start }
|
217
|
+
end
|
119
218
|
end
|
120
219
|
end
|
121
220
|
end
|
@@ -128,7 +227,7 @@ describe Tmuxinator::Cli do
|
|
128
227
|
|
129
228
|
context "new project already exists" do
|
130
229
|
before do
|
131
|
-
allow(Thor::LineEditor).to receive_messages(:
|
230
|
+
allow(Thor::LineEditor).to receive_messages(readline: "y")
|
132
231
|
end
|
133
232
|
|
134
233
|
it "prompts user to confirm overwrite" do
|
@@ -150,20 +249,40 @@ describe Tmuxinator::Cli do
|
|
150
249
|
|
151
250
|
describe "#debug" do
|
152
251
|
let(:project) { FactoryGirl.build(:project) }
|
252
|
+
let(:project_with_force_attach) do
|
253
|
+
FactoryGirl.build(:project_with_force_attach)
|
254
|
+
end
|
255
|
+
let(:project_with_force_detach) do
|
256
|
+
FactoryGirl.build(:project_with_force_detach)
|
257
|
+
end
|
153
258
|
|
154
259
|
before do
|
155
|
-
|
156
|
-
|
260
|
+
allow(Tmuxinator::Config).to receive_messages(validate: project)
|
261
|
+
expect(project).to receive(:render)
|
157
262
|
end
|
158
263
|
|
159
264
|
it "renders the project" do
|
160
|
-
|
265
|
+
ARGV.replace(["debug", "foo"])
|
161
266
|
capture_io { cli.start }
|
162
267
|
end
|
163
268
|
|
269
|
+
it "force attach renders the project with attach code" do
|
270
|
+
ARGV.replace(["debug", "--attach=true", "sample"])
|
271
|
+
capture_io { cli.start }
|
272
|
+
# Currently no project is rendered at all,
|
273
|
+
# because the project file is not found
|
274
|
+
# expect(out).to include "attach-session"
|
275
|
+
end
|
276
|
+
|
277
|
+
it "force detach renders the project without attach code" do
|
278
|
+
ARGV.replace(["debug", "--attach=false", "sample"])
|
279
|
+
capture_io { cli.start }
|
280
|
+
# Currently no project is rendered at all
|
281
|
+
# expect(out).to_not include "attach-session"
|
282
|
+
end
|
283
|
+
|
164
284
|
it "renders the project with custom session" do
|
165
285
|
ARGV.replace(["debug", "sample", "bar"])
|
166
|
-
expect(project).to receive(:render)
|
167
286
|
capture_io { cli.start }
|
168
287
|
end
|
169
288
|
end
|
@@ -171,7 +290,7 @@ describe Tmuxinator::Cli do
|
|
171
290
|
describe "#delete" do
|
172
291
|
before do
|
173
292
|
ARGV.replace(["delete", "foo"])
|
174
|
-
allow(Thor::LineEditor).to receive_messages(:
|
293
|
+
allow(Thor::LineEditor).to receive_messages(readline: "y")
|
175
294
|
end
|
176
295
|
|
177
296
|
context "project exists" do
|
@@ -188,7 +307,7 @@ describe Tmuxinator::Cli do
|
|
188
307
|
context "project doesn't exist" do
|
189
308
|
before do
|
190
309
|
allow(Tmuxinator::Config).to receive(:exists?) { false }
|
191
|
-
allow(Thor::LineEditor).to receive_messages(:
|
310
|
+
allow(Thor::LineEditor).to receive_messages(readline: "y")
|
192
311
|
end
|
193
312
|
|
194
313
|
it "exits with error message" do
|
@@ -200,7 +319,7 @@ describe Tmuxinator::Cli do
|
|
200
319
|
describe "#implode" do
|
201
320
|
before do
|
202
321
|
ARGV.replace(["implode"])
|
203
|
-
allow(Thor::LineEditor).to receive_messages(:
|
322
|
+
allow(Thor::LineEditor).to receive_messages(readline: "y")
|
204
323
|
end
|
205
324
|
|
206
325
|
it "confirms deletion of all projects" do
|
@@ -231,7 +350,7 @@ describe Tmuxinator::Cli do
|
|
231
350
|
end
|
232
351
|
|
233
352
|
it "prints the current version" do
|
234
|
-
out,
|
353
|
+
out, _err = capture_io { cli.start }
|
235
354
|
expect(out).to eq "tmuxinator #{Tmuxinator::VERSION}\n"
|
236
355
|
end
|
237
356
|
end
|
@@ -248,4 +367,46 @@ describe Tmuxinator::Cli do
|
|
248
367
|
capture_io { cli.start }
|
249
368
|
end
|
250
369
|
end
|
370
|
+
|
371
|
+
describe "#create_project" do
|
372
|
+
shared_examples_for :a_proper_project do
|
373
|
+
it "should create a valid project" do
|
374
|
+
expect(subject).to be_a Tmuxinator::Project
|
375
|
+
expect(subject.name).to eq name
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
let(:name) { "sample" }
|
380
|
+
let(:custom_name) { nil }
|
381
|
+
let(:cli_options) { {} }
|
382
|
+
let(:path) { File.expand_path("../../../fixtures", __FILE__) }
|
383
|
+
|
384
|
+
context "when creating a traditional named project" do
|
385
|
+
let(:params) do
|
386
|
+
{
|
387
|
+
name: name,
|
388
|
+
custom_name: custom_name
|
389
|
+
}
|
390
|
+
end
|
391
|
+
subject { described_class.new.create_project(params) }
|
392
|
+
|
393
|
+
before do
|
394
|
+
allow(Tmuxinator::Config).to receive_messages(root: path)
|
395
|
+
end
|
396
|
+
|
397
|
+
it_should_behave_like :a_proper_project
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
context "exit status" do
|
402
|
+
before do
|
403
|
+
ARGV.replace(["non-existent-command"])
|
404
|
+
end
|
405
|
+
|
406
|
+
it "returns a non-zero status when an error occurs" do
|
407
|
+
expect { capture_io { cli.start } }.to raise_error(SystemExit) do |e|
|
408
|
+
expect(e.status).to eq 1
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
251
412
|
end
|
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe Tmuxinator::Config do
|
4
4
|
describe "#root" do
|
5
5
|
it "is ~/.tmuxintaor" do
|
6
|
-
expect(Tmuxinator::Config.root).to eq "#{ENV[
|
6
|
+
expect(Tmuxinator::Config.root).to eq "#{ENV['HOME']}/.tmuxinator"
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -43,10 +43,13 @@ describe Tmuxinator::Config do
|
|
43
43
|
|
44
44
|
describe "#default?" do
|
45
45
|
let(:root) { Tmuxinator::Config.root }
|
46
|
+
let(:local_default) { Tmuxinator::Config::LOCAL_DEFAULT }
|
47
|
+
let(:proj_default) { Tmuxinator::Config.default }
|
46
48
|
|
47
49
|
context "when the file exists" do
|
48
50
|
before do
|
49
|
-
allow(File).to receive(:exists?).with(
|
51
|
+
allow(File).to receive(:exists?).with(local_default) { false }
|
52
|
+
allow(File).to receive(:exists?).with(proj_default) { true }
|
50
53
|
end
|
51
54
|
|
52
55
|
it "returns true" do
|
@@ -56,7 +59,8 @@ describe Tmuxinator::Config do
|
|
56
59
|
|
57
60
|
context "when the file doesn't exist" do
|
58
61
|
before do
|
59
|
-
allow(File).to receive(:exists?).with(
|
62
|
+
allow(File).to receive(:exists?).with(local_default) { false }
|
63
|
+
allow(File).to receive(:exists?).with(proj_default) { false }
|
60
64
|
end
|
61
65
|
|
62
66
|
it "returns true" do
|
@@ -143,8 +147,8 @@ describe Tmuxinator::Config do
|
|
143
147
|
|
144
148
|
describe "#exists?" do
|
145
149
|
before do
|
146
|
-
allow(File).to receive_messages(
|
147
|
-
allow(Tmuxinator::Config).to receive_messages(:
|
150
|
+
allow(File).to receive_messages(exists?: true)
|
151
|
+
allow(Tmuxinator::Config).to receive_messages(project: "")
|
148
152
|
end
|
149
153
|
|
150
154
|
it "checks if the given project exists" do
|
@@ -152,23 +156,116 @@ describe Tmuxinator::Config do
|
|
152
156
|
end
|
153
157
|
end
|
154
158
|
|
155
|
-
describe "#
|
159
|
+
describe "#project_in_root" do
|
156
160
|
let(:root) { Tmuxinator::Config.root }
|
161
|
+
let(:base) { "#{root}/sample.yml" }
|
157
162
|
|
158
163
|
before do
|
159
164
|
path = File.expand_path("../../../fixtures/", __FILE__)
|
160
|
-
allow(Tmuxinator::Config).to receive_messages(:
|
165
|
+
allow(Tmuxinator::Config).to receive_messages(root: path)
|
161
166
|
end
|
162
167
|
|
163
168
|
context "with project yml" do
|
169
|
+
it "gets the project as path to the yml file" do
|
170
|
+
expect(Tmuxinator::Config.project_in_root("sample")).to eq base
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context "without project yml" do
|
175
|
+
it "gets the project as path to the yml file" do
|
176
|
+
expect(Tmuxinator::Config.project_in_root("new-project")).to be_nil
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#local?" do
|
182
|
+
it "checks if the given project exists" do
|
183
|
+
path = Tmuxinator::Config::LOCAL_DEFAULT
|
184
|
+
expect(File).to receive(:exists?).with(path) { true }
|
185
|
+
expect(Tmuxinator::Config.local?).to be_truthy
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#project_in_local" do
|
190
|
+
let(:default) { Tmuxinator::Config::LOCAL_DEFAULT }
|
191
|
+
|
192
|
+
context "with a project yml" do
|
193
|
+
it "gets the project as path to the yml file" do
|
194
|
+
expect(File).to receive(:exists?).with(default) { true }
|
195
|
+
expect(Tmuxinator::Config.project_in_local).to eq default
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context "without project yml" do
|
200
|
+
it "gets the project as path to the yml file" do
|
201
|
+
expect(Tmuxinator::Config.project_in_local).to be_nil
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#project" do
|
207
|
+
let(:root) { Tmuxinator::Config.root }
|
208
|
+
let(:path) { File.expand_path("../../../fixtures/", __FILE__) }
|
209
|
+
let(:default) { Tmuxinator::Config::LOCAL_DEFAULT }
|
210
|
+
|
211
|
+
context "with project yml in the root directory" do
|
212
|
+
before do
|
213
|
+
allow(Tmuxinator::Config).to receive_messages(root: path)
|
214
|
+
end
|
215
|
+
|
164
216
|
it "gets the project as path to the yml file" do
|
165
217
|
expect(Tmuxinator::Config.project("sample")).to eq "#{root}/sample.yml"
|
166
218
|
end
|
167
219
|
end
|
168
220
|
|
221
|
+
context "with a local project, but no project in root" do
|
222
|
+
it "gets the project as path to the yml file" do
|
223
|
+
expect(File).to receive(:exists?).with(default) { true }
|
224
|
+
expect(Tmuxinator::Config.project("sample")).to eq "./.tmuxinator.yml"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
169
228
|
context "without project yml" do
|
229
|
+
let(:expected) { "#{root}/new-project.yml" }
|
170
230
|
it "gets the project as path to the yml file" do
|
171
|
-
expect(Tmuxinator::Config.project("new-project")).to eq
|
231
|
+
expect(Tmuxinator::Config.project("new-project")).to eq expected
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "#validate" do
|
237
|
+
let(:path) { File.expand_path("../../../fixtures", __FILE__) }
|
238
|
+
let(:default) { Tmuxinator::Config::LOCAL_DEFAULT }
|
239
|
+
|
240
|
+
context "when a project name is provided" do
|
241
|
+
it "should raise if the project file can't be found" do
|
242
|
+
expect do
|
243
|
+
Tmuxinator::Config.validate(name: "sample")
|
244
|
+
end.to raise_error RuntimeError, %r{Project.+doesn't.exist}
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should load and validate the project" do
|
248
|
+
expect(Tmuxinator::Config).to receive_messages(root: path)
|
249
|
+
expect(Tmuxinator::Config.validate(name: "sample")).to \
|
250
|
+
be_a Tmuxinator::Project
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
context "when no project name is provided" do
|
255
|
+
it "should raise if the local project file doesn't exist" do
|
256
|
+
expect(File).to receive(:exists?).with(default) { false }
|
257
|
+
expect do
|
258
|
+
Tmuxinator::Config.validate
|
259
|
+
end.to raise_error RuntimeError, %r{Project.+doesn't.exist}
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should load and validate the project" do
|
263
|
+
content = File.read(File.join(path, "sample.yml"))
|
264
|
+
|
265
|
+
expect(File).to receive(:exists?).with(default).at_least(:once) { true }
|
266
|
+
expect(File).to receive(:read).with(default).and_return(content)
|
267
|
+
|
268
|
+
expect(Tmuxinator::Config.validate).to be_a Tmuxinator::Project
|
172
269
|
end
|
173
270
|
end
|
174
271
|
end
|