knapsack_pro 6.0.4 → 7.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +80 -19
  3. data/.github/pull_request_template.md +22 -0
  4. data/.gitignore +4 -0
  5. data/CHANGELOG.md +95 -0
  6. data/Gemfile +9 -0
  7. data/README.md +7 -9
  8. data/knapsack_pro.gemspec +2 -1
  9. data/lib/knapsack_pro/adapters/base_adapter.rb +7 -2
  10. data/lib/knapsack_pro/adapters/cucumber_adapter.rb +1 -3
  11. data/lib/knapsack_pro/adapters/rspec_adapter.rb +24 -9
  12. data/lib/knapsack_pro/config/env.rb +1 -9
  13. data/lib/knapsack_pro/extensions/rspec_extension.rb +137 -0
  14. data/lib/knapsack_pro/formatters/time_tracker.rb +10 -26
  15. data/lib/knapsack_pro/formatters/time_tracker_fetcher.rb +6 -0
  16. data/lib/knapsack_pro/presenter.rb +1 -1
  17. data/lib/knapsack_pro/pure/queue/rspec_pure.rb +100 -0
  18. data/lib/knapsack_pro/runners/queue/base_runner.rb +6 -1
  19. data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +6 -6
  20. data/lib/knapsack_pro/runners/queue/minitest_runner.rb +6 -6
  21. data/lib/knapsack_pro/runners/queue/rspec_runner.rb +127 -173
  22. data/lib/knapsack_pro/urls.rb +2 -0
  23. data/lib/knapsack_pro/version.rb +1 -1
  24. data/lib/knapsack_pro.rb +1 -0
  25. data/spec/integration/runners/queue/rspec_runner.rb +80 -0
  26. data/spec/integration/runners/queue/rspec_runner_spec.rb +2405 -0
  27. data/spec/knapsack_pro/adapters/base_adapter_spec.rb +17 -11
  28. data/spec/knapsack_pro/adapters/cucumber_adapter_spec.rb +2 -5
  29. data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +56 -24
  30. data/spec/knapsack_pro/config/env_spec.rb +1 -35
  31. data/spec/knapsack_pro/formatters/time_tracker_fetcher_spec.rb +30 -0
  32. data/spec/knapsack_pro/formatters/time_tracker_specs.rb +8 -37
  33. data/spec/knapsack_pro/hooks/queue_spec.rb +2 -2
  34. data/spec/knapsack_pro/presenter_spec.rb +1 -1
  35. data/spec/knapsack_pro/pure/queue/rspec_pure_spec.rb +248 -0
  36. data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +16 -16
  37. data/spec/knapsack_pro/runners/queue/minitest_runner_spec.rb +14 -14
  38. data/spec/knapsack_pro_spec.rb +3 -3
  39. metadata +19 -12
  40. data/lib/knapsack_pro/formatters/rspec_queue_profile_formatter_extension.rb +0 -58
  41. data/lib/knapsack_pro/formatters/rspec_queue_summary_formatter.rb +0 -145
  42. data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +0 -536
@@ -159,7 +159,7 @@ describe KnapsackPro::Adapters::BaseAdapter do
159
159
  it do
160
160
  logger = instance_double(Logger)
161
161
  expect(KnapsackPro).to receive(:logger).and_return(logger)
162
- expect(logger).to receive(:debug).with('Test suite time execution recording enabled.')
162
+ expect(logger).to receive(:debug).with('Regular Mode enabled.')
163
163
  end
164
164
  it { expect(subject).to receive(:bind_time_tracker) }
165
165
  it { expect(subject).to receive(:bind_save_report) }
@@ -168,24 +168,22 @@ describe KnapsackPro::Adapters::BaseAdapter do
168
168
  context 'when queue recording enabled' do
169
169
  let(:queue_recording_enabled?) { true }
170
170
 
171
- before do
172
- allow(subject).to receive(:bind_before_queue_hook)
173
- allow(subject).to receive(:bind_time_tracker)
174
- end
175
-
176
- it do
171
+ it 'calls queue hooks in proper order before binding time tracker' do
177
172
  logger = instance_double(Logger)
178
173
  expect(KnapsackPro).to receive(:logger).and_return(logger)
179
- expect(logger).to receive(:debug).with('Test suite time execution queue recording enabled.')
174
+ expect(logger).to receive(:debug).with('Queue Mode enabled.')
175
+
176
+ expect(subject).to receive(:bind_before_queue_hook).ordered
177
+ expect(subject).to receive(:bind_after_queue_hook).ordered
178
+ expect(subject).to receive(:bind_time_tracker).ordered
180
179
  end
181
- it { expect(subject).to receive(:bind_before_queue_hook) }
182
- it { expect(subject).to receive(:bind_time_tracker) }
183
180
  end
184
181
 
185
182
  context 'when recording disabled' do
186
- it { expect(subject).not_to receive(:bind_time_tracker) }
187
183
  it { expect(subject).not_to receive(:bind_save_report) }
188
184
  it { expect(subject).not_to receive(:bind_before_queue_hook) }
185
+ it { expect(subject).not_to receive(:bind_after_queue_hook) }
186
+ it { expect(subject).not_to receive(:bind_time_tracker) }
189
187
  end
190
188
  end
191
189
 
@@ -212,4 +210,12 @@ describe KnapsackPro::Adapters::BaseAdapter do
212
210
  }.to raise_error(NotImplementedError)
213
211
  end
214
212
  end
213
+
214
+ describe '#bind_after_queue_hook' do
215
+ it do
216
+ expect {
217
+ subject.bind_after_queue_hook
218
+ }.to raise_error(NotImplementedError)
219
+ end
220
+ end
215
221
  end
@@ -203,16 +203,13 @@ describe KnapsackPro::Adapters::CucumberAdapter do
203
203
  end
204
204
  end
205
205
 
206
- describe '#bind_queue_mode' do
206
+ describe '#bind_after_queue_hook' do
207
207
  it do
208
- expect(subject).to receive(:bind_before_queue_hook)
209
- expect(subject).to receive(:bind_time_tracker)
210
-
211
208
  expect(::Kernel).to receive(:at_exit).and_yield
212
209
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
213
210
  expect(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
214
211
 
215
- subject.bind_queue_mode
212
+ subject.bind_after_queue_hook
216
213
  end
217
214
  end
218
215
  end
@@ -187,6 +187,60 @@ describe KnapsackPro::Adapters::RSpecAdapter do
187
187
  end
188
188
  end
189
189
 
190
+ describe '.has_require_rails_helper_option?' do
191
+ subject { described_class.has_require_rails_helper_option?(cli_args) }
192
+
193
+ context 'when require option is provided as -r' do
194
+ let(:cli_args) { ['-r', 'rails_helper'] }
195
+
196
+ it { expect(subject).to be true }
197
+ end
198
+
199
+ context 'when require option is provided as --require' do
200
+ let(:cli_args) { ['--require', 'rails_helper'] }
201
+
202
+ it { expect(subject).to be true }
203
+ end
204
+
205
+ context 'when require option is provided without delimiter' do
206
+ let(:cli_args) { ['-rrails_helper'] }
207
+
208
+ it { expect(subject).to be true }
209
+ end
210
+
211
+ context 'when require option is not provided' do
212
+ let(:cli_args) { ['--fake', 'value'] }
213
+
214
+ it { expect(subject).to be false }
215
+ end
216
+ end
217
+
218
+ describe '.rails_helper_exists?' do
219
+ subject { described_class.rails_helper_exists?(test_dir) }
220
+
221
+ let(:test_dir) { 'spec_fake' }
222
+
223
+ context 'when rails_helper exists' do
224
+ before do
225
+ File.open("#{test_dir}/rails_helper.rb", 'w')
226
+ end
227
+
228
+ after do
229
+ FileUtils.rm("#{test_dir}/rails_helper.rb")
230
+ end
231
+
232
+ it { expect(subject).to be true }
233
+ end
234
+
235
+ context 'when rails_helper does not exist' do
236
+ before do
237
+ FileUtils.rm_f("#{test_dir}/rails_helper.rb")
238
+ end
239
+
240
+ it { expect(subject).to be false }
241
+ end
242
+ end
243
+
190
244
  describe '.order_option' do
191
245
  subject { described_class.order_option(cli_args) }
192
246
 
@@ -341,24 +395,13 @@ describe KnapsackPro::Adapters::RSpecAdapter do
341
395
  end
342
396
 
343
397
  context 'with no focus' do
344
- let(:logger) { instance_double(Logger) }
345
- let(:duration) { 65 }
346
- let(:global_time) { 'Global time execution for tests: 01m 05s' }
347
- let(:time_tracker) { instance_double(KnapsackPro::Formatters::TimeTracker) }
348
-
349
398
  it 'records time for current test path' do
350
399
  expect(config).to receive(:around).with(:each).and_yield(current_example)
351
- expect(config).to receive(:after).with(:suite).and_yield
352
- expect(::RSpec).to receive(:configure).twice.and_yield(config)
400
+ expect(config).to receive(:append_after).with(:suite)
401
+ expect(::RSpec).to receive(:configure).at_least(1).and_yield(config)
353
402
 
354
403
  expect(current_example).to receive(:run)
355
404
 
356
- expect(time_tracker).to receive(:batch_duration).and_return(duration)
357
- expect(KnapsackPro::Formatters::TimeTrackerFetcher).to receive(:call).and_return(time_tracker)
358
-
359
- expect(KnapsackPro).to receive(:logger).and_return(logger)
360
- expect(logger).to receive(:debug).with(global_time)
361
-
362
405
  subject.bind_time_tracker
363
406
  end
364
407
  end
@@ -378,16 +421,5 @@ describe KnapsackPro::Adapters::RSpecAdapter do
378
421
  subject.bind_save_report
379
422
  end
380
423
  end
381
-
382
- describe '#bind_before_queue_hook' do
383
- it do
384
- expect(config).to receive(:before).with(:suite).and_yield
385
- expect(::RSpec).to receive(:configure).and_yield(config)
386
-
387
- expect(KnapsackPro::Hooks::Queue).to receive(:call_before_queue)
388
-
389
- subject.bind_before_queue_hook
390
- end
391
- end
392
424
  end
393
425
  end
@@ -511,40 +511,6 @@ describe KnapsackPro::Config::Env do
511
511
  end
512
512
  end
513
513
 
514
- describe '.modify_default_rspec_formatters' do
515
- subject { described_class.modify_default_rspec_formatters }
516
-
517
- context 'when ENV exists' do
518
- let(:modify_default_rspec_formatters) { 'false' }
519
- before { stub_const("ENV", { 'KNAPSACK_PRO_MODIFY_DEFAULT_RSPEC_FORMATTERS' => modify_default_rspec_formatters }) }
520
- it { should eq modify_default_rspec_formatters }
521
- end
522
-
523
- context "when ENV doesn't exist" do
524
- it { should be true }
525
- end
526
- end
527
-
528
- describe '.modify_default_rspec_formatters?' do
529
- subject { described_class.modify_default_rspec_formatters? }
530
-
531
- before do
532
- expect(described_class).to receive(:modify_default_rspec_formatters).and_return(modify_default_rspec_formatters)
533
- end
534
-
535
- context 'when enabled' do
536
- let(:modify_default_rspec_formatters) { true }
537
-
538
- it { should be true }
539
- end
540
-
541
- context 'when disabled' do
542
- let(:modify_default_rspec_formatters) { false }
543
-
544
- it { should be false }
545
- end
546
- end
547
-
548
514
  describe '.branch_encrypted' do
549
515
  subject { described_class.branch_encrypted }
550
516
 
@@ -975,7 +941,7 @@ describe KnapsackPro::Config::Env do
975
941
  end
976
942
 
977
943
  context "when ENV doesn't exist" do
978
- it { should eql ::Logger::DEBUG }
944
+ it { should eql ::Logger::INFO }
979
945
  end
980
946
  end
981
947
 
@@ -0,0 +1,30 @@
1
+ require(KnapsackPro.root + '/lib/knapsack_pro/formatters/time_tracker')
2
+
3
+ describe KnapsackPro::Formatters::TimeTrackerFetcher do
4
+ describe '.unexecuted_test_files' do
5
+ subject { described_class.unexecuted_test_files(scheduled_paths) }
6
+
7
+ context 'when the time tracker formatter not found' do
8
+ let(:scheduled_paths) { ['a_spec.rb'] }
9
+
10
+ it do
11
+ expect(subject).to eq []
12
+ end
13
+ end
14
+
15
+ context 'when the time tracker formatter is found' do
16
+ let(:time_tracker) { instance_double(KnapsackPro::Formatters::TimeTracker) }
17
+ let(:scheduled_paths) { ['a_spec.rb', 'b_spec.rb'] }
18
+ let(:unexecuted_test_files) { double(:unexecuted_test_files) }
19
+
20
+ before do
21
+ expect(described_class).to receive(:call).and_return(time_tracker)
22
+ expect(time_tracker).to receive(:unexecuted_test_files).with(scheduled_paths).and_return(unexecuted_test_files)
23
+ end
24
+
25
+ it do
26
+ expect(subject).to eq unexecuted_test_files
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,6 +4,7 @@
4
4
  require 'rspec/core'
5
5
  require 'knapsack_pro'
6
6
  require 'stringio'
7
+ require 'tempfile'
7
8
  require_relative '../../../lib/knapsack_pro/formatters/time_tracker'
8
9
 
9
10
  class TestTimeTracker
@@ -327,24 +328,6 @@ class TestTimeTracker
327
328
  end
328
329
  end
329
330
 
330
- def test_batch_duration
331
- KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
332
- false
333
- end
334
-
335
- spec = <<~SPEC
336
- describe "KnapsackPro::Formatters::TimeTracker" do
337
- it do
338
- expect(1).to eq 1
339
- end
340
- end
341
- SPEC
342
-
343
- run_specs(spec) do |_, _, time_tracker|
344
- raise unless time_tracker.batch_duration > 0.0
345
- end
346
- end
347
-
348
331
  def test_unexecuted_test_files
349
332
  KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
350
333
  false
@@ -372,14 +355,6 @@ class TestTimeTracker
372
355
  KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
373
356
  false
374
357
  end
375
- KnapsackPro::Formatters::TimeTracker.class_eval do
376
- alias_method :original_stop, :stop
377
-
378
- # In Regular Mode, #subset is called before #stop.
379
- # This test makes #stop a noop to simulate that behavior.
380
- define_method(:stop) do |_|
381
- end
382
- end
383
358
 
384
359
  spec = <<~SPEC
385
360
  describe "KnapsackPro::Formatters::TimeTracker" do
@@ -401,23 +376,20 @@ class TestTimeTracker
401
376
  raise unless files[0]["time_execution"] > 0.10
402
377
  raise unless files[0]["time_execution"] < 0.15
403
378
  end
404
-
405
- ensure
406
- KnapsackPro::Formatters::TimeTracker.class_eval do
407
- undef :stop
408
- alias_method :stop, :original_stop
409
- end
410
379
  end
411
380
 
412
381
  private
413
382
 
414
383
  def run_specs(specs)
415
- paths = Array(specs).map.with_index do |spec, i|
416
- path = "spec/knapsack_pro/formatters/#{i}_#{SecureRandom.uuid}_spec.rb"
417
- File.open(path, 'w') { |file| file.write(spec) }
418
- path
384
+ files = Array(specs).map.with_index do |spec, i|
385
+ file = Tempfile.new(["tmp_time_tracker_#{i}", "_spec.rb"], "./spec/knapsack_pro/formatters/")
386
+ file.write(spec)
387
+ file.rewind
388
+ file
419
389
  end
420
390
 
391
+ paths = files.map(&:path).map { _1.sub("./", "") }
392
+
421
393
  options = ::RSpec::Core::ConfigurationOptions.new([
422
394
  "--format", KnapsackPro::Formatters::TimeTracker.to_s,
423
395
  *paths,
@@ -436,7 +408,6 @@ class TestTimeTracker
436
408
  yield(paths, times, time_tracker)
437
409
 
438
410
  ensure
439
- paths.each { |path| File.delete(path) }
440
411
  # Need to reset because RSpec keeps reusing the same instance.
441
412
  time_tracker.instance_variable_set(:@queue, {}) if time_tracker
442
413
  time_tracker.instance_variable_set(:@started, time_tracker.send(:now)) if time_tracker
@@ -93,8 +93,8 @@ describe KnapsackPro::Hooks::Queue do
93
93
  let(:subset_queue_id) { double }
94
94
 
95
95
  before do
96
- expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
97
- expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).twice.and_return(subset_queue_id)
96
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).at_least(:once).and_return(queue_id)
97
+ expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).at_least(:once).and_return(subset_queue_id)
98
98
 
99
99
  $expected_called_blocks = []
100
100
 
@@ -8,7 +8,7 @@ describe KnapsackPro::Presenter do
8
8
  expect(KnapsackPro).to receive(:tracker).and_return(tracker)
9
9
  end
10
10
 
11
- it { should eql "Global time execution for tests: 01h 02m 03s" }
11
+ it { should eql "Global test execution duration: 01h 02m 03s" }
12
12
  end
13
13
 
14
14
  describe '.pretty_seconds' do
@@ -0,0 +1,248 @@
1
+ require(KnapsackPro.root + '/lib/knapsack_pro/formatters/time_tracker')
2
+ require(KnapsackPro.root + '/lib/knapsack_pro/extensions/rspec_extension')
3
+
4
+ describe KnapsackPro::Pure::Queue::RSpecPure do
5
+ let(:rspec_pure) { described_class.new }
6
+
7
+ describe '#add_knapsack_pro_formatters_to' do
8
+ subject { rspec_pure.add_knapsack_pro_formatters_to(spec_opts) }
9
+
10
+ context 'when no spec_opts' do
11
+ let(:spec_opts) { nil }
12
+
13
+ it 'returns no spec_opts' do
14
+ expect(subject).to be nil
15
+ end
16
+ end
17
+
18
+ context 'when spec_opts have Knapsack Pro formatters' do
19
+ let(:spec_opts) { '--color --format d --format KnapsackPro::Formatters::TimeTracker' }
20
+
21
+ it 'returns spec_opts' do
22
+ expect(subject).to eq spec_opts
23
+ end
24
+ end
25
+
26
+ context 'when spec_opts have no Knapsack Pro formatters' do
27
+ let(:spec_opts) { '--color --format d' }
28
+
29
+ it 'returns spec_opts with added Knapsack Pro formatters' do
30
+ expect(subject).to eq '--color --format d --format KnapsackPro::Formatters::TimeTracker'
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#error_exit_code' do
36
+ subject { rspec_pure.error_exit_code(rspec_error_exit_code) }
37
+
38
+ context 'when RSpec has no defined error exit code' do
39
+ let(:rspec_error_exit_code) { nil }
40
+
41
+ it 'returns 1 as the default exit code' do
42
+ expect(subject).to eq 1
43
+ end
44
+ end
45
+
46
+ context 'when RSpec has a defined error exit code' do
47
+ let(:rspec_error_exit_code) { 2 }
48
+
49
+ it 'returns the custom exit code' do
50
+ expect(subject).to eq rspec_error_exit_code
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#args_with_seed_option_added_when_viable' do
56
+ let(:order_option) { KnapsackPro::Adapters::RSpecAdapter.order_option(args) }
57
+
58
+ subject { rspec_pure.args_with_seed_option_added_when_viable(order_option, seed, args) }
59
+
60
+ context 'when the order option is not random' do
61
+ let(:args) { ['--order', 'defined'] }
62
+ let(:seed) { KnapsackPro::Extensions::RSpecExtension::Seed.new(value: nil, used?: false) }
63
+
64
+ it 'does not add the seed option to args' do
65
+ expect(subject).to eq ['--order', 'defined']
66
+ end
67
+ end
68
+
69
+ ['random', 'rand'].each do |random_option_value|
70
+ context "when the order option is `#{random_option_value}`" do
71
+ let(:args) { ['--order', random_option_value] }
72
+
73
+ context 'when the seed is not used' do
74
+ let(:seed) { KnapsackPro::Extensions::RSpecExtension::Seed.new(value: '123', used?: false) }
75
+
76
+ it 'does not add the seed option to args' do
77
+ expect(subject).to eq ['--order', random_option_value]
78
+ end
79
+ end
80
+
81
+ context 'when the seed is used' do
82
+ let(:seed) { KnapsackPro::Extensions::RSpecExtension::Seed.new(value: '123', used?: true) }
83
+
84
+ it 'adds the seed option to args' do
85
+ expect(subject).to eq ['--order', random_option_value, '--seed', '123']
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ context 'when the order option is `rand:123`' do
92
+ let(:args) { ['--order', 'rand:123'] }
93
+ let(:seed) { KnapsackPro::Extensions::RSpecExtension::Seed.new(value: '123', used?: true) }
94
+
95
+ it 'does not add the seed option to args' do
96
+ expect(subject).to eq ['--order', 'rand:123']
97
+ end
98
+ end
99
+
100
+ context 'when the order option is not set in args AND seed is used' do
101
+ let(:args) { ['--format', 'documentation'] }
102
+ let(:seed) { KnapsackPro::Extensions::RSpecExtension::Seed.new(value: '123', used?: true) }
103
+
104
+ it 'adds the seed option to args' do
105
+ expect(subject).to eq ['--format', 'documentation', '--seed', '123']
106
+ end
107
+ end
108
+
109
+ context 'when the order option is not set in args AND seed is not used' do
110
+ let(:args) { ['--format', 'documentation'] }
111
+ let(:seed) { KnapsackPro::Extensions::RSpecExtension::Seed.new(value: '123', used?: false) }
112
+
113
+ it 'does not add the seed option to args' do
114
+ expect(subject).to eq ['--format', 'documentation']
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#prepare_cli_args' do
120
+ subject { rspec_pure.prepare_cli_args(args, has_format_option, has_require_rails_helper_option, rails_helper_exists, test_dir) }
121
+
122
+ context 'when no args' do
123
+ let(:args) { nil }
124
+ let(:has_format_option) { false }
125
+ let(:has_require_rails_helper_option) { false }
126
+ let(:test_dir) { 'spec' }
127
+
128
+ context 'when rails_helper does not exist' do
129
+ let(:rails_helper_exists) { false }
130
+
131
+ it 'adds the default progress formatter, the default path and the time tracker formatter, does not add require rails_helper' do
132
+ expect(subject).to eq [
133
+ '--format', 'progress',
134
+ '--default-path', 'spec',
135
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
136
+ ]
137
+ end
138
+ end
139
+
140
+ context 'when rails_helper exists' do
141
+ let(:rails_helper_exists) { true }
142
+
143
+ it 'adds the default progress formatter, require rails_helper, the default path and the time tracker formatter' do
144
+ expect(subject).to eq [
145
+ '--format', 'progress',
146
+ '--require', 'rails_helper',
147
+ '--default-path', 'spec',
148
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
149
+ ]
150
+ end
151
+ end
152
+ end
153
+
154
+ context 'when args are present and a custom test directory is set' do
155
+ let(:args) { '--color --profile --require rails_helper' }
156
+ let(:has_format_option) { false }
157
+ let(:has_require_rails_helper_option) { true }
158
+ let(:rails_helper_exists) { true }
159
+ let(:test_dir) { 'custom_spec_dir' }
160
+
161
+ it do
162
+ expect(subject).to eq [
163
+ '--color',
164
+ '--profile',
165
+ '--require', 'rails_helper',
166
+ '--format', 'progress',
167
+ '--default-path', 'custom_spec_dir',
168
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
169
+ ]
170
+ end
171
+ end
172
+
173
+ context 'when args are present and has format option' do
174
+ let(:args) { '--color --profile --format d --require rails_helper' }
175
+ let(:has_format_option) { true }
176
+ let(:has_require_rails_helper_option) { true }
177
+ let(:rails_helper_exists) { true }
178
+ let(:test_dir) { 'spec' }
179
+
180
+ it 'uses the format option from args instead of the default formatter' do
181
+ expect(subject).to eq [
182
+ '--color',
183
+ '--profile',
184
+ '--format', 'd',
185
+ '--require', 'rails_helper',
186
+ '--default-path', 'spec',
187
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
188
+ ]
189
+ end
190
+ end
191
+ end
192
+
193
+ describe '#rspec_command' do
194
+ let(:args) { ['--format', 'documentation'] }
195
+ let(:test_file_paths) { ['a_spec.rb', 'b_spec.rb'] }
196
+
197
+ subject { rspec_pure.rspec_command(args, test_file_paths, scope) }
198
+
199
+ context 'when there are no test file paths' do
200
+ let(:scope) { :queue_finished }
201
+ let(:test_file_paths) { [] }
202
+
203
+ it 'returns no messages' do
204
+ expect(subject).to eq []
205
+ end
206
+ end
207
+
208
+ context 'when a subset of queue (a batch of tests fetched from the Queue API)' do
209
+ let(:scope) { :batch_finished }
210
+
211
+ it 'returns messages with the RSpec command' do
212
+ expect(subject).to eq([
213
+ 'To retry the last batch of tests fetched from the Queue API, please run the following command on your machine:',
214
+ 'bundle exec rspec --format documentation "a_spec.rb" "b_spec.rb"',
215
+ ])
216
+ end
217
+ end
218
+
219
+ context 'when all tests fetched from the Queue API' do
220
+ let(:scope) { :queue_finished }
221
+
222
+ it 'returns messages with the RSpec command' do
223
+ expect(subject).to eq([
224
+ 'To retry all the tests assigned to this CI node, please run the following command on your machine:',
225
+ 'bundle exec rspec --format documentation "a_spec.rb" "b_spec.rb"',
226
+ ])
227
+ end
228
+ end
229
+
230
+ describe '#exit_summary' do
231
+ subject { rspec_pure.exit_summary(unexecuted_test_files) }
232
+
233
+ context 'when there are no unexecuted test files' do
234
+ let(:unexecuted_test_files) { [] }
235
+
236
+ it { expect(subject).to be_nil }
237
+ end
238
+
239
+ context 'when there are unexecuted test files' do
240
+ let(:unexecuted_test_files) { ['b_spec.rb', 'c_spec.rb'] }
241
+
242
+ it 'returns a warning message' do
243
+ expect(subject).to eq 'Unexecuted tests on this CI node (including pending tests): b_spec.rb c_spec.rb'
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end