tryouts 3.6.1 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d17810b847cd0aa319faef9d52e3297f8ab4388ce650caf1db8bdb36904d75e3
4
- data.tar.gz: c6eefacdbdae1d7274d783364f640879417c994adf68fe26de639e111614977a
3
+ metadata.gz: 7178f4f14ad2015fb3e5a795bbdd7813b4a184b56413535d7ddfff569badca9d
4
+ data.tar.gz: ff451b947073ebfbaece457e3b94cb090410ff86aa8ca09e8fdc8c998e04118c
5
5
  SHA512:
6
- metadata.gz: 3de8c49bb538a704bbd9209116b8fabc20b6af5ad3f74a44c5cff764657c4f33ebb6d5f0be80d3dfcbe19458c671a4184f45123f118dd75a960f27d0a4570a55
7
- data.tar.gz: 164d339b908ea278c7901ff9ba096bf5df407cd2c66610bb02e7f190da67cc76c620f8c1043694a040c0d1f78765854e5f13006f7da4feb164354f5048ca7de7
6
+ metadata.gz: d15d3afd82d4cef85ffe9eb481b5bfd68971c2cbc4247f8f6b46fbf53e7292ae6d22d396b1b2070481f0034c12079f8183ff66903a05f6a36dc754a7b33aef55
7
+ data.tar.gz: 936ecb57906f16befe499de544032e9f1cd25ed50f757652556f357ac80b6ff7d14dbb3787c8ff2eb2d93460f3c59a224eecbc2b491a936038394013976a3b42
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Ruby tests that read like documentation.**
4
4
 
5
- A modern test framework for Ruby that uses comments to define expectations. Tryouts are meant to double as documentation, so the Ruby code should be plain and reminiscent of real code.
5
+ A modern Ruby testing framework that uses simple comments to define what should happen. With Tryouts, your tests double as documentation, allowing you to write straightforward Ruby code that feels as natural as everyday coding.
6
6
 
7
7
  > [!NOTE]
8
8
  > **Agent-Optimized Output**: Tryouts includes specialized output modes for LLM consumption with `--agent` flag, providing structured, token-efficient test results that are 60-80% smaller than traditional output while preserving debugging context.
data/exe/try CHANGED
@@ -48,6 +48,9 @@ begin
48
48
  # Add original command to options for agent formatter
49
49
  options[:original_command] = original_command
50
50
 
51
+ # Track whether user explicitly provided paths
52
+ explicit_paths_given = !files.empty?
53
+
51
54
  # Expand files if directories are given, preserving line specs
52
55
  expanded_files = []
53
56
  files.each do |file_or_dir|
@@ -65,6 +68,12 @@ begin
65
68
  end
66
69
  files = expanded_files
67
70
 
71
+ # If user provided explicit paths but nothing matched, exit with error
72
+ if explicit_paths_given && files.empty?
73
+ warn 'Error: No test files found matching the given paths'
74
+ exit 1
75
+ end
76
+
68
77
  # Default file discovery if no files specified
69
78
  if files.empty?
70
79
  raw_files = Dir.glob(
@@ -412,10 +412,10 @@ class Tryouts
412
412
  output << summary
413
413
  output << ""
414
414
 
415
- # Show files with issues only
415
+ # Show files with issues only (unless suppressed)
416
416
  files_with_issues = @collected_files.select { |f| f[:failures].any? || f[:errors].any? }
417
417
 
418
- if files_with_issues.any?
418
+ if files_with_issues.any? && !@options[:agent_no_failures]
419
419
  files_with_issues.each do |file_data|
420
420
  break unless @budget.has_budget?
421
421
 
@@ -652,6 +652,18 @@ class Tryouts
652
652
  end
653
653
  end
654
654
 
655
+ # Add framework tips if requested
656
+ if @options[:agent_tips]
657
+ context_lines << ""
658
+ context_lines << render_framework_tips
659
+ end
660
+
661
+ # Add re-run command if requested and there are failures
662
+ if @options[:agent_command] && has_failures?
663
+ context_lines << ""
664
+ context_lines << render_rerun_command
665
+ end
666
+
655
667
  context_lines.join("\n")
656
668
  end
657
669
 
@@ -749,6 +761,38 @@ class Tryouts
749
761
  # Return empty hash on any error (timeout, permission, etc.)
750
762
  {}
751
763
  end
764
+
765
+ # Render framework tips and reminders for LLM context
766
+ def render_framework_tips
767
+ tips = []
768
+ tips << "Framework Tips:"
769
+ tips << " • Instance variables (@var) persist across testcases; local variables do not"
770
+ tips << " • Each testcase can have multiple expectations (multiple #=> lines)"
771
+ tips << " • Exception testing: Use #=!> to signal expected exception; 'error' variable becomes available"
772
+ tips << " • In exception tests, #=~> automatically refers to error.message for pattern matching"
773
+ tips.join("\n")
774
+ end
775
+
776
+ # Render copy-paste command for re-running failures with verbose-fails-stack
777
+ def render_rerun_command
778
+ files_with_issues = @collected_files.select { |f| f[:failures].any? || f[:errors].any? }
779
+ return "" if files_with_issues.empty?
780
+
781
+ cmd = []
782
+ cmd << "Re-run Command (verbose-fails-stack):"
783
+
784
+ # Build command parts
785
+ base_cmd = @options[:original_command]&.first || "try"
786
+ file_paths = files_with_issues.map { |f| f[:path] }.join(" ")
787
+
788
+ cmd << " #{base_cmd} -vfs #{file_paths}"
789
+ cmd.join("\n")
790
+ end
791
+
792
+ # Check if there are any failures or errors
793
+ def has_failures?
794
+ @collected_files.any? { |f| f[:failures].any? || f[:errors].any? }
795
+ end
752
796
  end
753
797
  end
754
798
  end
@@ -156,10 +156,10 @@ class Tryouts
156
156
 
157
157
  # Show failure details for failed tests
158
158
  if result_packet.failed? || result_packet.error?
159
- show_failure_details(test_case, result_packet.actual_results, result_packet.expected_results)
159
+ show_failure_details(test_case, result_packet.actual_results, result_packet.expected_results, result_packet.result_value)
160
160
  # Show exception details for passed exception expectations
161
161
  elsif result_packet.passed? && has_exception_expectations?(test_case)
162
- show_exception_details(test_case, result_packet.actual_results, result_packet.expected_results)
162
+ show_exception_details(test_case, result_packet.actual_results, result_packet.expected_results, result_packet.result_value)
163
163
  end
164
164
  end
165
165
 
@@ -273,7 +273,7 @@ class Tryouts
273
273
  test_case.expectations.any? { |exp| exp.type == :exception }
274
274
  end
275
275
 
276
- def show_exception_details(test_case, actual_results, expected_results = [])
276
+ def show_exception_details(test_case, actual_results, expected_results = [], exception_object = nil)
277
277
  return if actual_results.empty?
278
278
 
279
279
  puts indent_text('Exception Details:', 2)
@@ -288,6 +288,19 @@ class Tryouts
288
288
  puts indent_text("Result: #{Console.color(:green, expected.inspect)}", 3) if expected
289
289
  end
290
290
  end
291
+
292
+ # Show backtrace when --stack flag is used
293
+ if @show_stack_traces && exception_object.is_a?(Exception) && exception_object.backtrace
294
+ puts
295
+ puts indent_text('Backtrace:', 2)
296
+ Console.pretty_backtrace(exception_object.backtrace, limit: 15).each do |line|
297
+ puts indent_text(Console.color(:dim, line), 3)
298
+ end
299
+ if exception_object.backtrace.length > 15
300
+ puts indent_text(Console.color(:dim, "... (#{exception_object.backtrace.length - 15} more lines)"), 3)
301
+ end
302
+ end
303
+
291
304
  puts
292
305
  end
293
306
 
@@ -309,7 +322,7 @@ class Tryouts
309
322
  puts
310
323
  end
311
324
 
312
- def show_failure_details(test_case, actual_results, expected_results = [])
325
+ def show_failure_details(test_case, actual_results, expected_results = [], exception_object = nil)
313
326
  return if actual_results.empty?
314
327
 
315
328
  actual_results.each_with_index do |actual, idx|
@@ -325,8 +338,19 @@ class Tryouts
325
338
  puts indent_text("Expected: #{Console.color(:green, expected_line.content)}", 2)
326
339
  puts indent_text("Actual: #{Console.color(:red, actual.inspect)}", 2)
327
340
  else
328
- # For error cases (empty expected_results), just show the error
329
- puts indent_text("Error: #{Console.color(:red, actual.inspect)}", 2)
341
+ # For error cases (empty expected_results), show formatted error with stack trace
342
+ if actual.is_a?(String) && actual.include?("\n")
343
+ # Multi-line error (with stack trace) - format properly
344
+ lines = actual.split("\n")
345
+ puts indent_text("Error: #{Console.color(:red, lines.first)}", 2)
346
+ # Show remaining lines (stack trace) with proper indentation
347
+ lines[1..].each do |line|
348
+ puts indent_text(" #{Console.color(:red, line)}", 2)
349
+ end
350
+ else
351
+ # Single-line error
352
+ puts indent_text("Error: #{Console.color(:red, actual.inspect)}", 2)
353
+ end
330
354
  end
331
355
 
332
356
  # Show difference if both are strings
@@ -336,6 +360,18 @@ class Tryouts
336
360
 
337
361
  puts
338
362
  end
363
+
364
+ # Show backtrace for exception expectation failures when --stack flag is used
365
+ if @show_stack_traces && exception_object.is_a?(Exception) && exception_object.backtrace
366
+ puts indent_text('Backtrace:', 2)
367
+ Console.pretty_backtrace(exception_object.backtrace, limit: 15).each do |line|
368
+ puts indent_text(Console.color(:dim, line), 3)
369
+ end
370
+ if exception_object.backtrace.length > 15
371
+ puts indent_text(Console.color(:dim, "... (#{exception_object.backtrace.length - 15} more lines)"), 3)
372
+ end
373
+ puts
374
+ end
339
375
  end
340
376
 
341
377
  def show_string_diff(expected, actual)
@@ -384,9 +420,10 @@ class Tryouts
384
420
  # No output in fails mode
385
421
  end
386
422
 
387
- # Suppress file result summaries in fails-only mode
423
+ # Show file result summaries in fails-only mode (matching compact behavior)
388
424
  def file_result(_file_path, total_tests:, failed_count:, error_count:, elapsed_time: nil)
389
- # No output in fails mode - let the batch_summary handle failures
425
+ # Always show summary - this matches compact formatter behavior
426
+ super
390
427
  end
391
428
 
392
429
  def live_status_capabilities
@@ -24,6 +24,9 @@ class Tryouts
24
24
  --agent-focus first-failure # Show first failure per file
25
25
  --agent-focus critical # Show errors/exceptions only
26
26
  --agent-limit 1000 # Limit output to 1000 tokens
27
+ --agent-tips # Include framework tips for LLMs
28
+ --agent-command # Include copy-paste re-run command
29
+ --agent-no-failures # Suppress failure details (summary only)
27
30
 
28
31
  File Naming & Organization:
29
32
  Files must end with '_try.rb' or '.try.rb' (e.g., auth_service_try.rb, user_model.try.rb)
@@ -142,6 +145,18 @@ class Tryouts
142
145
  options[:agent] = true
143
146
  options[:agent_focus] = focus.to_sym
144
147
  end
148
+ opts.on('--agent-tips', 'Include tryouts framework tips and reminders in agent output') do
149
+ options[:agent] = true
150
+ options[:agent_tips] = true
151
+ end
152
+ opts.on('--agent-command', 'Include copy-paste command for re-running failures with -vfs') do
153
+ options[:agent] = true
154
+ options[:agent_command] = true
155
+ end
156
+ opts.on('--agent-no-failures', 'Suppress detailed failure list (show summary/command only)') do
157
+ options[:agent] = true
158
+ options[:agent_no_failures] = true
159
+ end
145
160
 
146
161
  opts.separator "\nParser Options:"
147
162
  opts.on('--enhanced-parser', 'Use enhanced parser with inhouse comment extraction (default)') { options[:parser] = :enhanced }
@@ -44,20 +44,37 @@ class Tryouts
44
44
  end
45
45
 
46
46
  def evaluate_exception_condition(caught_error)
47
- @context.define_singleton_method(:error) { caught_error }
47
+ # Note: error variable is already available in context (set in evaluate_expectations)
48
48
 
49
49
  expectation_result = ExpectationResult.from_result(caught_error)
50
- expected_value = eval_expectation_content(@expectation.content, expectation_result)
50
+ expected_value = eval_expectation_content(@expectation.content, expectation_result)
51
51
 
52
- build_result(
53
- passed: !!expected_value,
54
- actual: caught_error.message,
55
- expected: expected_value,
56
- )
52
+ # Support two syntaxes:
53
+ # 1. Class constant: #=!> StandardError (checks exception class)
54
+ # 2. Boolean expression: #=!> error.message == "test" (checks truthy value)
55
+ if expected_value.is_a?(Class)
56
+ # Class-based exception checking (new behavior)
57
+ # Check if caught exception is instance of expected class (or subclass)
58
+ exception_matches = caught_error.is_a?(expected_value)
59
+
60
+ build_result(
61
+ passed: exception_matches,
62
+ actual: caught_error.class.name,
63
+ expected: expected_value.name,
64
+ )
65
+ else
66
+ # Boolean/truthy expression checking (legacy behavior)
67
+ # This supports expressions like: error.message == "test"
68
+ build_result(
69
+ passed: !!expected_value,
70
+ actual: caught_error.message,
71
+ expected: expected_value,
72
+ )
73
+ end
57
74
  rescue StandardError => ex
58
75
  build_result(
59
76
  passed: false,
60
- actual: caught_error.message,
77
+ actual: caught_error.class.name,
61
78
  expected: "EXPECTED: #{ex.message}",
62
79
  error: ex,
63
80
  )
@@ -42,9 +42,8 @@ class Tryouts
42
42
 
43
43
  # Auto-detect exceptions and use message for regex matching
44
44
  # This allows #=~> /pattern/ to work naturally with exception messages
45
+ # Note: error variable is already available in context (set in evaluate_expectations)
45
46
  string_result = if actual_result.is_a?(Exception)
46
- # Make error available in context for manual access if needed
47
- @context.define_singleton_method(:error) { actual_result }
48
47
  actual_result.message # Match against error message
49
48
  else
50
49
  actual_result.to_s # Normal case: convert to string
@@ -19,13 +19,10 @@ class Tryouts
19
19
  end
20
20
 
21
21
  def process
22
- testrun = create_parser(@file, @options).parse
23
-
24
- # Apply line spec filtering before reporting test counts
25
- if @options[:line_spec]
26
- testrun = filter_testrun_by_line_spec(testrun)
27
- end
22
+ testrun = create_parser(@file, @options).parse
28
23
 
24
+ # Report total test count (before filtering for display)
25
+ # Line spec filtering affects output only, not execution
29
26
  @global_tally[:aggregator].increment_total_files
30
27
  @output_manager.file_parsed(@file, testrun.total_tests)
31
28
  @output_manager.parser_warnings(@file, warnings: testrun.warnings)
@@ -45,34 +42,6 @@ class Tryouts
45
42
 
46
43
  private
47
44
 
48
- def filter_testrun_by_line_spec(testrun)
49
- require_relative 'cli/line_spec_parser'
50
-
51
- line_spec = @options[:line_spec]
52
-
53
- # Filter test cases to only those that match the line spec
54
- filtered_cases = testrun.test_cases.select do |test_case|
55
- Tryouts::CLI::LineSpecParser.matches?(test_case, line_spec)
56
- end
57
-
58
- # Check if any tests matched the line specification
59
- if filtered_cases.empty?
60
- @output_manager.file_failure(@file, "No test cases found matching line specification: #{line_spec}")
61
- return testrun # Return original testrun to avoid breaking the pipeline
62
- end
63
-
64
- # Create a new testrun with filtered cases
65
- # We need to preserve the setup and teardown but only include matching tests
66
- testrun.class.new(
67
- setup: testrun.setup,
68
- test_cases: filtered_cases,
69
- teardown: testrun.teardown,
70
- source_file: testrun.source_file,
71
- metadata: testrun.metadata,
72
- warnings: testrun.warnings
73
- )
74
- end
75
-
76
45
  def create_parser(file, options)
77
46
  parser_type = options[:parser] || :enhanced # enhanced parser is now the default
78
47
 
@@ -37,6 +37,7 @@ class Tryouts
37
37
  @start_time = nil
38
38
  @test_case_count = 0
39
39
  @setup_failed = false
40
+ @line_spec = options[:line_spec] # For output filtering only
40
41
 
41
42
  # Setup container for fresh context mode - preserves @instance_variables from setup
42
43
  @setup_container = nil
@@ -101,16 +102,26 @@ class Tryouts
101
102
  break
102
103
  end
103
104
 
104
- @output_manager&.test_start(test_case, idx, @test_case_count)
105
+ # Apply line_spec filter for output notifications (test_start/test_end)
106
+ # but still execute ALL tests regardless of filter
107
+ if should_display_test_result?(test_case)
108
+ @output_manager&.test_start(test_case, idx, @test_case_count)
109
+ end
110
+
105
111
  result = execute_single_test(test_case, before_test_hook, &) # runs the test code
106
- @output_manager&.test_end(test_case, idx, @test_case_count)
112
+
113
+ if should_display_test_result?(test_case)
114
+ @output_manager&.test_end(test_case, idx, @test_case_count)
115
+ end
107
116
 
108
117
  # Update circuit breaker state based on result
109
118
  update_circuit_breaker(result)
110
119
 
111
120
  result
112
121
  rescue StandardError => ex
113
- @output_manager&.test_end(test_case, idx, @test_case_count)
122
+ if should_display_test_result?(test_case)
123
+ @output_manager&.test_end(test_case, idx, @test_case_count)
124
+ end
114
125
  # Create error result packet to maintain consistent data flow
115
126
  error_result = build_error_result(test_case, ex)
116
127
  process_test_result(error_result)
@@ -333,6 +344,12 @@ class Tryouts
333
344
  def evaluate_expectations(test_case, actual_result, context, execution_time_ns = nil, stdout_content = nil, stderr_content = nil, caught_exception = nil)
334
345
  return { passed: true, actual_results: [], expected_results: [] } if test_case.expectations.empty?
335
346
 
347
+ # Make error variable available to ALL expectations in exception test cases
348
+ # This allows #=/=> error.message.nil?, #=~> /pattern/ (auto-targets error.message), etc.
349
+ if caught_exception
350
+ context.define_singleton_method(:error) { caught_exception }
351
+ end
352
+
336
353
  evaluation_results = test_case.expectations.map do |expectation|
337
354
  evaluator = ExpectationEvaluators::Registry.evaluator_for(expectation, test_case, context)
338
355
 
@@ -398,11 +415,14 @@ class Tryouts
398
415
  @failed_count += 1
399
416
  end
400
417
 
401
- show_test_result(result)
418
+ # Apply line_spec filter for output only - test was still executed
419
+ if should_display_test_result?(result.test_case)
420
+ show_test_result(result)
402
421
 
403
- # Show captured output if any exists
404
- if result.has_output?
405
- @output_manager&.test_output(result.test_case, result.captured_output, result)
422
+ # Show captured output if any exists
423
+ if result.has_output?
424
+ @output_manager&.test_output(result.test_case, result.captured_output, result)
425
+ end
406
426
  end
407
427
  end
408
428
 
@@ -442,6 +462,17 @@ class Tryouts
442
462
 
443
463
  # For catastrophic errors, still raise to stop execution
444
464
  raise "Global setup failed (#{ex.class}): #{ex.message}"
465
+ rescue SystemExit, SignalException => ex
466
+ # Handle process control exceptions (exit, abort, signals) gracefully
467
+ @setup_failed = true
468
+ if @global_tally && @global_tally[:aggregator]
469
+ @global_tally[:aggregator].add_infrastructure_failure(
470
+ :setup, @testrun.source_file, "Setup terminated by #{ex.class}: #{ex.message}", ex
471
+ )
472
+ end
473
+
474
+ Tryouts.debug "Setup received #{ex.class}: #{ex.message}"
475
+ @output_manager&.error("Setup terminated by #{ex.class}: #{ex.message}")
445
476
  end
446
477
 
447
478
  # Setup execution for fresh context mode - creates @setup_container with @instance_variables
@@ -483,6 +514,17 @@ class Tryouts
483
514
 
484
515
  # For catastrophic errors, still raise to stop execution
485
516
  raise "Fresh context setup failed (#{ex.class}): #{ex.message}"
517
+ rescue SystemExit, SignalException => ex
518
+ # Handle process control exceptions (exit, abort, signals) gracefully
519
+ @setup_failed = true
520
+ if @global_tally && @global_tally[:aggregator]
521
+ @global_tally[:aggregator].add_infrastructure_failure(
522
+ :setup, @testrun.source_file, "Setup terminated by #{ex.class}: #{ex.message}", ex
523
+ )
524
+ end
525
+
526
+ Tryouts.debug "Setup received #{ex.class}: #{ex.message}"
527
+ @output_manager&.error("Setup terminated by #{ex.class}: #{ex.message}")
486
528
  end
487
529
 
488
530
  # Global teardown execution
@@ -521,6 +563,17 @@ class Tryouts
521
563
  else
522
564
  @output_manager&.error('Continuing despite teardown failure')
523
565
  end
566
+ rescue SystemExit, SignalException => ex
567
+ # Handle process control exceptions (exit, abort, signals) gracefully
568
+ if @global_tally && @global_tally[:aggregator]
569
+ @global_tally[:aggregator].add_infrastructure_failure(
570
+ :teardown, @testrun.source_file, "Teardown terminated by #{ex.class}: #{ex.message}", ex
571
+ )
572
+ end
573
+
574
+ Tryouts.debug "Teardown received #{ex.class}: #{ex.message}"
575
+ @output_manager&.error("Teardown terminated by #{ex.class}: #{ex.message}")
576
+ @output_manager&.error('Continuing despite teardown termination')
524
577
  end
525
578
 
526
579
  # Result finalization and summary display
@@ -550,6 +603,15 @@ class Tryouts
550
603
  test_case.expectations.any? { |exp| exp.result_type? || exp.regex_match? }
551
604
  end
552
605
 
606
+ # Check if test result should be displayed based on line_spec filter
607
+ # All tests are EXECUTED regardless of line_spec, but only matching tests are DISPLAYED
608
+ def should_display_test_result?(test_case)
609
+ return true unless @line_spec
610
+
611
+ require_relative 'cli/line_spec_parser'
612
+ Tryouts::CLI::LineSpecParser.matches?(test_case, @line_spec)
613
+ end
614
+
553
615
  def capture_output
554
616
  old_stdout = $stdout
555
617
  old_stderr = $stderr
@@ -34,6 +34,7 @@ class Tryouts
34
34
  shared_context: @options[:shared_context],
35
35
  verbose: @options[:verbose],
36
36
  fails_only: @options[:fails_only],
37
+ line_spec: @options[:line_spec], # Pass line_spec for output filtering
37
38
  output_manager: @output_manager,
38
39
  global_tally: @global_tally,
39
40
  )
@@ -1,5 +1,5 @@
1
1
  # lib/tryouts/version.rb
2
2
 
3
3
  class Tryouts
4
- VERSION = '3.6.1'
4
+ VERSION = '3.7.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tryouts
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.1
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -9,6 +9,26 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: concurrent-ruby
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '2'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.0'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '2'
12
32
  - !ruby/object:Gem::Dependency
13
33
  name: irb
14
34
  requirement: !ruby/object:Gem::Requirement
@@ -38,33 +58,33 @@ dependencies:
38
58
  - !ruby/object:Gem::Version
39
59
  version: '1.0'
40
60
  - !ruby/object:Gem::Dependency
41
- name: concurrent-ruby
61
+ name: minitest
42
62
  requirement: !ruby/object:Gem::Requirement
43
63
  requirements:
44
64
  - - "~>"
45
65
  - !ruby/object:Gem::Version
46
- version: '1.0'
66
+ version: '5.0'
47
67
  type: :runtime
48
68
  prerelease: false
49
69
  version_requirements: !ruby/object:Gem::Requirement
50
70
  requirements:
51
71
  - - "~>"
52
72
  - !ruby/object:Gem::Version
53
- version: '1.0'
73
+ version: '5.0'
54
74
  - !ruby/object:Gem::Dependency
55
- name: minitest
75
+ name: pastel
56
76
  requirement: !ruby/object:Gem::Requirement
57
77
  requirements:
58
78
  - - "~>"
59
79
  - !ruby/object:Gem::Version
60
- version: '5.0'
80
+ version: '0.8'
61
81
  type: :runtime
62
82
  prerelease: false
63
83
  version_requirements: !ruby/object:Gem::Requirement
64
84
  requirements:
65
85
  - - "~>"
66
86
  - !ruby/object:Gem::Version
67
- version: '5.0'
87
+ version: '0.8'
68
88
  - !ruby/object:Gem::Dependency
69
89
  name: rspec
70
90
  requirement: !ruby/object:Gem::Requirement
@@ -85,20 +105,6 @@ dependencies:
85
105
  - - "<"
86
106
  - !ruby/object:Gem::Version
87
107
  version: '5.0'
88
- - !ruby/object:Gem::Dependency
89
- name: pastel
90
- requirement: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - "~>"
93
- - !ruby/object:Gem::Version
94
- version: '0.8'
95
- type: :runtime
96
- prerelease: false
97
- version_requirements: !ruby/object:Gem::Requirement
98
- requirements:
99
- - - "~>"
100
- - !ruby/object:Gem::Version
101
- version: '0.8'
102
108
  - !ruby/object:Gem::Dependency
103
109
  name: tty-cursor
104
110
  requirement: !ruby/object:Gem::Requirement