cuprum-cli 0.1.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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +34 -0
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/LICENSE +21 -0
  5. data/README.md +163 -0
  6. data/lib/cuprum/cli/argument.rb +172 -0
  7. data/lib/cuprum/cli/arguments/class_methods.rb +283 -0
  8. data/lib/cuprum/cli/arguments.rb +16 -0
  9. data/lib/cuprum/cli/coercion.rb +131 -0
  10. data/lib/cuprum/cli/command.rb +102 -0
  11. data/lib/cuprum/cli/commands/ci/report.rb +121 -0
  12. data/lib/cuprum/cli/commands/ci/rspec_command.rb +108 -0
  13. data/lib/cuprum/cli/commands/ci/rspec_each_command.rb +185 -0
  14. data/lib/cuprum/cli/commands/ci.rb +12 -0
  15. data/lib/cuprum/cli/commands/echo_command.rb +76 -0
  16. data/lib/cuprum/cli/commands/file/generate_file.rb +141 -0
  17. data/lib/cuprum/cli/commands/file/new_command.rb +86 -0
  18. data/lib/cuprum/cli/commands/file/render_erb.rb +88 -0
  19. data/lib/cuprum/cli/commands/file/resolve_template.rb +136 -0
  20. data/lib/cuprum/cli/commands/file/templates/rspec.rb.erb +14 -0
  21. data/lib/cuprum/cli/commands/file/templates/ruby.rb.erb +29 -0
  22. data/lib/cuprum/cli/commands/file/templates.rb +71 -0
  23. data/lib/cuprum/cli/commands/file.rb +14 -0
  24. data/lib/cuprum/cli/commands.rb +12 -0
  25. data/lib/cuprum/cli/dependencies/file_system/mock.rb +297 -0
  26. data/lib/cuprum/cli/dependencies/file_system.rb +247 -0
  27. data/lib/cuprum/cli/dependencies/standard_io/helpers.rb +138 -0
  28. data/lib/cuprum/cli/dependencies/standard_io/mock.rb +85 -0
  29. data/lib/cuprum/cli/dependencies/standard_io.rb +110 -0
  30. data/lib/cuprum/cli/dependencies/system_command/mock.rb +57 -0
  31. data/lib/cuprum/cli/dependencies/system_command.rb +147 -0
  32. data/lib/cuprum/cli/dependencies.rb +25 -0
  33. data/lib/cuprum/cli/errors/files/file_not_writeable.rb +42 -0
  34. data/lib/cuprum/cli/errors/files/missing_parameter.rb +71 -0
  35. data/lib/cuprum/cli/errors/files/missing_template.rb +36 -0
  36. data/lib/cuprum/cli/errors/files/template_error.rb +37 -0
  37. data/lib/cuprum/cli/errors/files/template_not_resolved.rb +54 -0
  38. data/lib/cuprum/cli/errors/files.rb +19 -0
  39. data/lib/cuprum/cli/errors/system_command_failure.rb +44 -0
  40. data/lib/cuprum/cli/errors.rb +11 -0
  41. data/lib/cuprum/cli/integrations/thor/arguments_parser.rb +99 -0
  42. data/lib/cuprum/cli/integrations/thor/registry.rb +42 -0
  43. data/lib/cuprum/cli/integrations/thor/task.rb +211 -0
  44. data/lib/cuprum/cli/integrations/thor.rb +14 -0
  45. data/lib/cuprum/cli/integrations.rb +8 -0
  46. data/lib/cuprum/cli/metadata.rb +215 -0
  47. data/lib/cuprum/cli/option.rb +165 -0
  48. data/lib/cuprum/cli/options/class_methods.rb +232 -0
  49. data/lib/cuprum/cli/options/quiet.rb +32 -0
  50. data/lib/cuprum/cli/options/verbose.rb +32 -0
  51. data/lib/cuprum/cli/options.rb +18 -0
  52. data/lib/cuprum/cli/registry.rb +141 -0
  53. data/lib/cuprum/cli/rspec/deferred/arguments_examples.rb +203 -0
  54. data/lib/cuprum/cli/rspec/deferred/ci/report_examples.rb +450 -0
  55. data/lib/cuprum/cli/rspec/deferred/ci.rb +8 -0
  56. data/lib/cuprum/cli/rspec/deferred/dependencies/file_system_examples.rb +1469 -0
  57. data/lib/cuprum/cli/rspec/deferred/dependencies.rb +8 -0
  58. data/lib/cuprum/cli/rspec/deferred/metadata_examples.rb +856 -0
  59. data/lib/cuprum/cli/rspec/deferred/options_examples.rb +234 -0
  60. data/lib/cuprum/cli/rspec/deferred/registry_examples.rb +451 -0
  61. data/lib/cuprum/cli/rspec/deferred.rb +8 -0
  62. data/lib/cuprum/cli/rspec.rb +8 -0
  63. data/lib/cuprum/cli/version.rb +59 -0
  64. data/lib/cuprum/cli.rb +47 -0
  65. metadata +173 -0
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/sleeping_king_studios/deferred/provider'
4
+
5
+ require 'cuprum/cli/rspec/deferred'
6
+
7
+ module Cuprum::Cli::RSpec::Deferred
8
+ # Deferred examples for testing command arguments.
9
+ module ArgumentsExamples
10
+ include RSpec::SleepingKingStudios::Deferred::Provider
11
+
12
+ deferred_examples 'should define argument' \
13
+ do |index, argument_name, **argument_options|
14
+ describe "should define argument #{argument_name.inspect}" do
15
+ expect_method =
16
+ argument_options
17
+ .fetch(:define_method, argument_options[:type] != :boolean)
18
+ expect_predicate =
19
+ argument_options
20
+ .fetch(:define_predicate, argument_options[:type] == :boolean)
21
+
22
+ let(:configured_default) do
23
+ value = argument_options[:default]
24
+
25
+ value.is_a?(Proc) ? instance_exec(&value) : value
26
+ end
27
+ let(:configured_description) do
28
+ value = argument_options[:description]
29
+
30
+ value.is_a?(Proc) ? instance_exec(&value) : value
31
+ end
32
+ let(:configured_parameter_name) do
33
+ value = argument_options[:parameter_name]
34
+
35
+ value.is_a?(Proc) ? instance_exec(&value) : value
36
+ end
37
+ let(:configured_required) do
38
+ value = argument_options[:required] ? true : false
39
+
40
+ value.is_a?(Proc) ? instance_exec(&value) : value
41
+ end
42
+ let(:configured_type) do
43
+ value = argument_options.fetch(:type, :string)
44
+
45
+ value.is_a?(Proc) ? instance_exec(&value) : value
46
+ end
47
+ let(:configured_variadic) do
48
+ value = argument_options.fetch(:variadic, false)
49
+
50
+ value.is_a?(Proc) ? instance_exec(&value) : value
51
+ end
52
+ let(:configured_arguments) do
53
+ value = argument_options.fetch(:arguments) do
54
+ defined?(arguments) ? arguments : {}
55
+ end
56
+
57
+ value.is_a?(Proc) ? instance_exec(&value) : value
58
+ end
59
+ let(:defined_argument) { described_class.arguments[index] }
60
+
61
+ define_method :set_argument do |argument, value|
62
+ arguments = subject.instance_variable_get(:@arguments)
63
+
64
+ arguments[argument] = value
65
+ end
66
+
67
+ it { expect(described_class.arguments.size).to be >= 1 + index }
68
+
69
+ describe '#:argument_name' do
70
+ if expect_method
71
+ let(:reader_name) { argument_name }
72
+
73
+ it { expect(subject).to respond_to(reader_name).with(0).arguments }
74
+
75
+ context 'when the argument is not initialized' do
76
+ before(:example) do
77
+ set_argument(argument_name, configured_default)
78
+ end
79
+
80
+ it 'should return the default value' do
81
+ expect(subject.public_send(reader_name))
82
+ .to be == configured_default
83
+ end
84
+ end
85
+
86
+ context 'when the argument is set' do
87
+ let(:value) { 'argument value' }
88
+
89
+ before(:example) do
90
+ set_argument(argument_name, value)
91
+ end
92
+
93
+ it { expect(subject.public_send(reader_name)).to be == value }
94
+ end
95
+ else
96
+ it { expect(subject).not_to respond_to(argument_name) }
97
+ end
98
+ end
99
+
100
+ describe '#:argument_name?' do
101
+ if expect_predicate
102
+ let(:predicate_name) { "#{argument_name}?" }
103
+
104
+ it 'should define the predicate' do
105
+ expect(subject).to respond_to(predicate_name).with(0).arguments
106
+ end
107
+
108
+ context 'when the argument is not initialized' do
109
+ let(:expected) do
110
+ next false if configured_default.nil?
111
+ next false if configured_default == false
112
+ next true unless configured_default.respond_to?(:empty?)
113
+
114
+ !configured_default.empty?
115
+ end
116
+
117
+ before(:example) do
118
+ set_argument(argument_name, configured_default)
119
+ end
120
+
121
+ it 'should return the default value' do
122
+ expect(subject.public_send(predicate_name)).to be == expected
123
+ end
124
+ end
125
+
126
+ context 'when the argument is set to false' do
127
+ before(:example) do
128
+ set_argument(argument_name, false)
129
+ end
130
+
131
+ it { expect(subject.public_send(predicate_name)).to be false }
132
+ end
133
+
134
+ context 'when the argument is set to true' do
135
+ before(:example) do
136
+ set_argument(argument_name, true)
137
+ end
138
+
139
+ it { expect(subject.public_send(predicate_name)).to be true }
140
+ end
141
+
142
+ if argument_options[:type] != :boolean
143
+ context 'when the argument is set to an Object' do
144
+ before(:example) do
145
+ set_argument(argument_name, Object.new.freeze)
146
+ end
147
+
148
+ it { expect(subject.public_send(predicate_name)).to be true }
149
+ end
150
+
151
+ context 'when the argument is set to an empty value' do
152
+ before(:example) do
153
+ set_argument(argument_name, '')
154
+ end
155
+
156
+ it { expect(subject.public_send(predicate_name)).to be false }
157
+ end
158
+
159
+ context 'when the argument is set to a non-empty value' do
160
+ before(:example) do
161
+ set_argument(argument_name, 'value')
162
+ end
163
+
164
+ it { expect(subject.public_send(predicate_name)).to be true }
165
+ end
166
+ end
167
+ else
168
+ it { expect(subject).not_to respond_to(:"#{argument_name}?") }
169
+ end
170
+ end
171
+
172
+ describe '#default' do
173
+ it { expect(defined_argument.default).to be == configured_default }
174
+ end
175
+
176
+ describe '#description' do
177
+ it 'should return the option description' do
178
+ expect(defined_argument.description).to be == configured_description
179
+ end
180
+ end
181
+
182
+ describe '#parameter_name' do
183
+ it 'should return the option parameter name' do
184
+ expect(defined_argument.parameter_name)
185
+ .to be == configured_parameter_name
186
+ end
187
+ end
188
+
189
+ describe '#required?' do
190
+ it { expect(defined_argument.required?).to be configured_required }
191
+ end
192
+
193
+ describe '#type' do
194
+ it { expect(defined_argument.type).to be configured_type }
195
+ end
196
+
197
+ describe '#variadic?' do
198
+ it { expect(defined_argument.variadic?).to be configured_variadic }
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,450 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/sleeping_king_studios/deferred/provider'
4
+
5
+ require 'cuprum/cli/rspec/deferred/ci'
6
+
7
+ module Cuprum::Cli::RSpec::Deferred::Ci
8
+ # Deferred examples for testing CI reports.
9
+ module ReportExamples
10
+ include RSpec::SleepingKingStudios::Deferred::Provider
11
+
12
+ deferred_examples 'should define report subclasses' do
13
+ describe '.define' do
14
+ let(:properties) { super().merge(custom_property: 'custom value') }
15
+ let(:symbols) { %i[custom_property] }
16
+ let(:block) do
17
+ lambda do
18
+ private def item_name = 'trial'
19
+ end
20
+ end
21
+ let(:subclass) { described_class.define(*symbols, &block) }
22
+ let(:expected_members) do
23
+ described_class.members.concat(symbols)
24
+ end
25
+
26
+ it 'should define the class method' do
27
+ expect(described_class)
28
+ .to respond_to(:define)
29
+ .with_unlimited_arguments
30
+ .and_a_block
31
+ end
32
+
33
+ it { expect(subclass).to be_a(Class).and be < Data }
34
+
35
+ it { expect(subclass.members).to be == expected_members }
36
+
37
+ describe 'with a report subclass' do
38
+ let(:described_class) { super().define(*symbols, &block) }
39
+ let(:empty_properties) do
40
+ {
41
+ custom_property: nil,
42
+ duration: 0,
43
+ total_count: 0
44
+ }
45
+ end
46
+ let(:other_properties) do
47
+ {
48
+ custom_property: 'Other Value',
49
+ duration: 5.0,
50
+ error_count: 5,
51
+ failure_count: 15,
52
+ label: 'Other Report',
53
+ pending_count: 25,
54
+ success_count: 35,
55
+ total_count: 75
56
+ }
57
+ end
58
+
59
+ include_deferred 'should implement the CI report interface',
60
+ item_name: 'trials'
61
+ end
62
+ end
63
+ end
64
+
65
+ deferred_examples 'should implement the CI report interface' \
66
+ do |item_name: 'item'|
67
+ describe '#duration' do
68
+ include_examples 'should define reader',
69
+ :duration,
70
+ -> { properties[:duration] }
71
+ end
72
+
73
+ describe '#error_count' do
74
+ include_examples 'should define reader', :error_count, 0
75
+
76
+ context 'when initialized with error_count: value' do
77
+ let(:properties) { super().merge(error_count: 10) }
78
+
79
+ it { expect(subject.error_count).to be == properties[:error_count] }
80
+ end
81
+ end
82
+
83
+ describe '#errored?' do
84
+ include_examples 'should define predicate', :errored?, false
85
+
86
+ context 'when initialized with error_count: value' do
87
+ let(:properties) { super().merge(error_count: 10) }
88
+
89
+ it { expect(subject.errored?).to be true }
90
+ end
91
+ end
92
+
93
+ describe '#failure?' do
94
+ include_examples 'should define predicate', :failure?, false
95
+
96
+ context 'when initialized with failure_count: value' do
97
+ let(:properties) { super().merge(failure_count: 20) }
98
+
99
+ it { expect(subject.failure?).to be true }
100
+ end
101
+ end
102
+
103
+ describe '#failure_count' do
104
+ include_examples 'should define reader', :failure_count, 0
105
+
106
+ context 'when initialized with failure_count: value' do
107
+ let(:properties) { super().merge(failure_count: 20) }
108
+
109
+ it 'should return the failure count' do
110
+ expect(subject.failure_count).to be == properties[:failure_count]
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '#label' do
116
+ include_examples 'should define reader', :label, nil
117
+
118
+ context 'when initialized with label: value' do
119
+ let(:properties) { super().merge(label: 'Custom Integration') }
120
+
121
+ it { expect(subject.label).to be == properties[:label] }
122
+ end
123
+ end
124
+
125
+ describe '#merge' do
126
+ it 'should define the method' do
127
+ expect(subject)
128
+ .to respond_to(:merge)
129
+ .with(1).argument
130
+ .and_keywords(:with_label)
131
+ end
132
+
133
+ describe 'with nil' do
134
+ let(:error_message) do
135
+ message = tools.assertions.error_message_for(
136
+ 'instance_of',
137
+ as: 'report',
138
+ expected: described_class
139
+ )
140
+
141
+ /#{message}/
142
+ end
143
+
144
+ it 'should raise an exception' do
145
+ expect { subject.merge(nil) }
146
+ .to raise_error ArgumentError, error_message
147
+ end
148
+ end
149
+
150
+ describe 'with an Object' do
151
+ let(:error_message) do
152
+ message = tools.assertions.error_message_for(
153
+ 'instance_of',
154
+ as: 'report',
155
+ expected: described_class
156
+ )
157
+
158
+ /#{message}/
159
+ end
160
+
161
+ it 'should raise an exception' do
162
+ expect { subject.merge(Object.new.freeze) }
163
+ .to raise_error ArgumentError, error_message
164
+ end
165
+ end
166
+
167
+ describe 'with an empty report' do
168
+ let(:empty_properties) do
169
+ next super() if defined?(super())
170
+
171
+ {
172
+ duration: 0,
173
+ total_count: 0
174
+ }
175
+ end
176
+ let(:other_report) do
177
+ described_class.new(**empty_properties)
178
+ end
179
+ let(:merged) { subject.merge(other_report) }
180
+ let(:expected) do
181
+ {
182
+ duration: subject.duration,
183
+ error_count: subject.error_count,
184
+ failure_count: subject.failure_count,
185
+ label: subject.label,
186
+ pending_count: subject.pending_count,
187
+ success_count: subject.success_count,
188
+ total_count: subject.total_count
189
+ }
190
+ end
191
+
192
+ it { expect(merged).to be_a described_class }
193
+
194
+ it { expect(merged).to have_attributes(**expected) }
195
+
196
+ describe 'with label: value' do
197
+ let(:with_label) { 'Merged Report' }
198
+ let(:merged) { subject.merge(other_report, with_label:) }
199
+
200
+ it { expect(merged.label).to be == with_label }
201
+ end
202
+
203
+ context 'when initialized with label: value' do
204
+ let(:properties) { super().merge(label: 'Custom Integration') }
205
+
206
+ it { expect(merged.label).to be == subject.label }
207
+
208
+ describe 'with label: value' do
209
+ let(:with_label) { 'Merged Report' }
210
+ let(:merged) { subject.merge(other_report, with_label:) }
211
+
212
+ it { expect(merged.label).to be == with_label }
213
+ end
214
+ end
215
+
216
+ context 'when initialized with multiple counts' do
217
+ let(:properties) do
218
+ super().merge(
219
+ error_count: 10,
220
+ failure_count: 20,
221
+ pending_count: 30
222
+ )
223
+ end
224
+
225
+ it { expect(merged).to have_attributes(**expected) }
226
+ end
227
+ end
228
+
229
+ describe 'with a non-empty report' do
230
+ let(:other_properties) do
231
+ next super() if defined?(super())
232
+
233
+ {
234
+ duration: 5.0,
235
+ error_count: 5,
236
+ failure_count: 15,
237
+ label: 'Other Report',
238
+ pending_count: 25,
239
+ success_count: 35,
240
+ total_count: 75
241
+ }
242
+ end
243
+ let(:other_report) do
244
+ described_class.new(**other_properties)
245
+ end
246
+ let(:merged) { subject.merge(other_report) }
247
+ let(:expected) do
248
+ {
249
+ duration: subject.duration + other_report.duration,
250
+ error_count: subject.error_count + other_report.error_count,
251
+ failure_count: subject.failure_count + other_report.failure_count,
252
+ label: other_report.label,
253
+ pending_count: subject.pending_count + other_report.pending_count,
254
+ success_count: subject.success_count + other_report.success_count,
255
+ total_count: subject.total_count + other_report.total_count
256
+ }
257
+ end
258
+
259
+ it { expect(merged).to be_a described_class }
260
+
261
+ it { expect(merged).to have_attributes(**expected) }
262
+
263
+ describe 'with label: value' do
264
+ let(:with_label) { 'Merged Report' }
265
+ let(:merged) { subject.merge(other_report, with_label:) }
266
+
267
+ it { expect(merged.label).to be == with_label }
268
+ end
269
+
270
+ context 'when initialized with label: value' do
271
+ let(:properties) { super().merge(label: 'Custom Integration') }
272
+ let(:expected_label) { "#{subject.label} + #{other_report.label}" }
273
+
274
+ it { expect(merged.label).to be == expected_label }
275
+
276
+ describe 'with label: value' do
277
+ let(:with_label) { 'Merged Report' }
278
+ let(:merged) { subject.merge(other_report, with_label:) }
279
+
280
+ it { expect(merged.label).to be == with_label }
281
+ end
282
+ end
283
+
284
+ context 'when initialized with multiple counts' do
285
+ let(:properties) do
286
+ super().merge(
287
+ error_count: 10,
288
+ failure_count: 20,
289
+ pending_count: 30
290
+ )
291
+ end
292
+
293
+ it { expect(merged).to have_attributes(**expected) }
294
+ end
295
+ end
296
+ end
297
+
298
+ describe '#pending?' do
299
+ include_examples 'should define predicate', :pending?, false
300
+
301
+ context 'when initialized with pending_count: value' do
302
+ let(:properties) { super().merge(pending_count: 30) }
303
+
304
+ it { expect(subject.pending?).to be true }
305
+ end
306
+ end
307
+
308
+ describe '#pending_count' do
309
+ include_examples 'should define reader', :pending_count, 0
310
+
311
+ context 'when initialized with pending_count: value' do
312
+ let(:properties) { super().merge(pending_count: 30) }
313
+
314
+ it 'should reutrn the pending count' do
315
+ expect(subject.pending_count).to be == properties[:pending_count]
316
+ end
317
+ end
318
+ end
319
+
320
+ describe '#success?' do
321
+ include_examples 'should define predicate', :success?, true
322
+
323
+ context 'when initialized with error_count: value' do
324
+ let(:properties) { super().merge(error_count: 10) }
325
+
326
+ it { expect(subject.success?).to be false }
327
+ end
328
+
329
+ context 'when initialized with failure_count: value' do
330
+ let(:properties) { super().merge(failure_count: 20) }
331
+
332
+ it { expect(subject.success?).to be false }
333
+ end
334
+
335
+ context 'when initialized with pending_count: value' do
336
+ let(:properties) { super().merge(pending_count: 30) }
337
+
338
+ it { expect(subject.success?).to be true }
339
+ end
340
+ end
341
+
342
+ describe '#success_count' do
343
+ include_examples 'should define reader',
344
+ :success_count,
345
+ -> { properties[:total_count] }
346
+
347
+ context 'when initialized with failure_count: value' do
348
+ let(:properties) { super().merge(failure_count: 20) }
349
+ let(:expected) do
350
+ properties[:total_count] - properties[:failure_count]
351
+ end
352
+
353
+ it { expect(subject.success_count).to be == expected }
354
+ end
355
+
356
+ context 'when initialized with pending_count: value' do
357
+ let(:properties) { super().merge(pending_count: 20) }
358
+ let(:expected) do
359
+ properties[:total_count] - properties[:pending_count]
360
+ end
361
+
362
+ it { expect(subject.success_count).to be == expected }
363
+ end
364
+
365
+ context 'when initialized with multiple counts' do
366
+ let(:properties) do
367
+ super().merge(failure_count: 10, pending_count: 20)
368
+ end
369
+ let(:expected) do
370
+ properties[:total_count] - (
371
+ properties[:pending_count] + properties[:failure_count]
372
+ )
373
+ end
374
+
375
+ it { expect(subject.success_count).to be == expected }
376
+ end
377
+
378
+ context 'when initialized with success_count: value' do
379
+ let(:properties) { super().merge(success_count: 25) }
380
+
381
+ it 'should return the success count' do
382
+ expect(subject.success_count).to be == properties[:success_count]
383
+ end
384
+
385
+ context 'when initialized with multiple counts' do
386
+ let(:properties) do
387
+ super().merge(failure_count: 10, pending_count: 20)
388
+ end
389
+
390
+ it 'should return the success count' do
391
+ expect(subject.success_count).to be == properties[:success_count]
392
+ end
393
+ end
394
+ end
395
+ end
396
+
397
+ describe '#summary' do
398
+ let(:item_label) { tools.str.pluralize(item_name) }
399
+ let(:expected) do
400
+ "#{properties[:total_count]} #{item_label}, " \
401
+ "#{properties.fetch(:failure_count, 0)} failures"
402
+ end
403
+
404
+ it { expect(subject).to respond_to(:summary).with(0).arguments }
405
+
406
+ it { expect(subject.summary).to be == expected }
407
+
408
+ context 'when initialized with error_count: value' do
409
+ let(:properties) { super().merge(error_count: 10) }
410
+ let(:expected) { "#{super()}, #{properties[:error_count]} errors" }
411
+
412
+ it { expect(subject.summary).to be == expected }
413
+ end
414
+
415
+ context 'when initialized with failure_count: value' do
416
+ let(:properties) { super().merge(failure_count: 20) }
417
+
418
+ it { expect(subject.summary).to be == expected }
419
+ end
420
+
421
+ context 'when initialized with pending_count: value' do
422
+ let(:properties) { super().merge(pending_count: 30) }
423
+ let(:expected) do
424
+ "#{super()}, #{properties[:pending_count]} pending"
425
+ end
426
+
427
+ it { expect(subject.summary).to be == expected }
428
+ end
429
+
430
+ context 'when initialized with multiple counts' do
431
+ let(:properties) do
432
+ super().merge(error_count: 10, failure_count: 20, pending_count: 30)
433
+ end
434
+ let(:expected) do
435
+ "#{super()}, #{properties[:pending_count]} pending, " \
436
+ "#{properties[:error_count]} errors"
437
+ end
438
+
439
+ it { expect(subject.summary).to be == expected }
440
+ end
441
+ end
442
+
443
+ describe '#total_count' do
444
+ include_examples 'should define reader',
445
+ :total_count,
446
+ -> { properties[:total_count] }
447
+ end
448
+ end
449
+ end
450
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/cli/rspec/deferred'
4
+
5
+ module Cuprum::Cli::RSpec::Deferred
6
+ # Namespace for deferred examples used to test CI command functionality.
7
+ module Ci; end
8
+ end