super_diff 0.4.2 → 0.5.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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -8
  3. data/lib/super_diff.rb +20 -11
  4. data/lib/super_diff/active_record.rb +20 -24
  5. data/lib/super_diff/active_record/diff_formatters/active_record_relation.rb +3 -3
  6. data/lib/super_diff/active_record/differs/active_record_relation.rb +3 -5
  7. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_model.rb +32 -22
  8. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_relation.rb +17 -7
  9. data/lib/super_diff/active_record/operation_tree_builders.rb +14 -0
  10. data/lib/super_diff/active_record/{operational_sequencers → operation_tree_builders}/active_record_model.rb +2 -2
  11. data/lib/super_diff/active_record/{operational_sequencers → operation_tree_builders}/active_record_relation.rb +4 -4
  12. data/lib/super_diff/active_record/{operation_sequences.rb → operation_trees.rb} +2 -2
  13. data/lib/super_diff/active_record/{operation_sequences → operation_trees}/active_record_relation.rb +2 -2
  14. data/lib/super_diff/active_support.rb +16 -19
  15. data/lib/super_diff/active_support/diff_formatters/hash_with_indifferent_access.rb +3 -3
  16. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +3 -5
  17. data/lib/super_diff/active_support/object_inspection/inspectors/hash_with_indifferent_access.rb +17 -7
  18. data/lib/super_diff/active_support/operation_tree_builders.rb +10 -0
  19. data/lib/super_diff/active_support/{operational_sequencers → operation_tree_builders}/hash_with_indifferent_access.rb +2 -2
  20. data/lib/super_diff/active_support/{operation_sequences.rb → operation_trees.rb} +2 -2
  21. data/lib/super_diff/active_support/{operation_sequences → operation_trees}/hash_with_indifferent_access.rb +2 -2
  22. data/lib/super_diff/configuration.rb +60 -0
  23. data/lib/super_diff/diff_formatters.rb +3 -3
  24. data/lib/super_diff/diff_formatters/array.rb +3 -3
  25. data/lib/super_diff/diff_formatters/base.rb +3 -2
  26. data/lib/super_diff/diff_formatters/collection.rb +2 -2
  27. data/lib/super_diff/diff_formatters/custom_object.rb +3 -3
  28. data/lib/super_diff/diff_formatters/default_object.rb +6 -8
  29. data/lib/super_diff/diff_formatters/defaults.rb +10 -0
  30. data/lib/super_diff/diff_formatters/hash.rb +3 -3
  31. data/lib/super_diff/diff_formatters/main.rb +41 -0
  32. data/lib/super_diff/diff_formatters/multiline_string.rb +3 -3
  33. data/lib/super_diff/differs.rb +4 -11
  34. data/lib/super_diff/differs/array.rb +2 -11
  35. data/lib/super_diff/differs/base.rb +20 -3
  36. data/lib/super_diff/differs/custom_object.rb +2 -11
  37. data/lib/super_diff/differs/default_object.rb +2 -8
  38. data/lib/super_diff/differs/defaults.rb +12 -0
  39. data/lib/super_diff/differs/hash.rb +2 -11
  40. data/lib/super_diff/differs/main.rb +48 -0
  41. data/lib/super_diff/differs/multiline_string.rb +2 -14
  42. data/lib/super_diff/differs/time_like.rb +15 -0
  43. data/lib/super_diff/equality_matchers.rb +3 -9
  44. data/lib/super_diff/equality_matchers/array.rb +1 -7
  45. data/lib/super_diff/equality_matchers/base.rb +1 -1
  46. data/lib/super_diff/equality_matchers/default.rb +1 -7
  47. data/lib/super_diff/equality_matchers/defaults.rb +12 -0
  48. data/lib/super_diff/equality_matchers/hash.rb +1 -7
  49. data/lib/super_diff/equality_matchers/main.rb +21 -0
  50. data/lib/super_diff/equality_matchers/multiline_string.rb +1 -7
  51. data/lib/super_diff/errors.rb +16 -0
  52. data/lib/super_diff/errors/no_diff_formatter_available_error.rb +21 -0
  53. data/lib/super_diff/errors/no_differ_available_error.rb +24 -0
  54. data/lib/super_diff/errors/no_operational_sequencer_available_error.rb +22 -0
  55. data/lib/super_diff/implementation_checks.rb +19 -0
  56. data/lib/super_diff/object_inspection.rb +1 -10
  57. data/lib/super_diff/object_inspection/inspection_tree.rb +6 -2
  58. data/lib/super_diff/object_inspection/inspectors.rb +5 -1
  59. data/lib/super_diff/object_inspection/inspectors/array.rb +20 -10
  60. data/lib/super_diff/object_inspection/inspectors/base.rb +36 -0
  61. data/lib/super_diff/object_inspection/inspectors/custom_object.rb +24 -14
  62. data/lib/super_diff/object_inspection/inspectors/default_object.rb +44 -30
  63. data/lib/super_diff/object_inspection/inspectors/defaults.rb +15 -0
  64. data/lib/super_diff/object_inspection/inspectors/hash.rb +20 -10
  65. data/lib/super_diff/object_inspection/inspectors/main.rb +35 -0
  66. data/lib/super_diff/object_inspection/inspectors/primitive.rb +20 -5
  67. data/lib/super_diff/object_inspection/inspectors/string.rb +15 -5
  68. data/lib/super_diff/object_inspection/inspectors/time_like.rb +23 -0
  69. data/lib/super_diff/object_inspection/nodes/inspection.rb +9 -2
  70. data/lib/super_diff/operation_tree_builders.rb +18 -0
  71. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/array.rb +38 -59
  72. data/lib/super_diff/operation_tree_builders/base.rb +98 -0
  73. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/custom_object.rb +3 -3
  74. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/default_object.rb +8 -3
  75. data/lib/super_diff/operation_tree_builders/defaults.rb +5 -0
  76. data/lib/super_diff/operation_tree_builders/hash.rb +226 -0
  77. data/lib/super_diff/operation_tree_builders/main.rb +42 -0
  78. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/multiline_string.rb +3 -3
  79. data/lib/super_diff/operation_tree_builders/time_like.rb +34 -0
  80. data/lib/super_diff/operation_trees.rb +13 -0
  81. data/lib/super_diff/{operation_sequences → operation_trees}/array.rb +5 -1
  82. data/lib/super_diff/{operation_sequences → operation_trees}/base.rb +7 -1
  83. data/lib/super_diff/{operation_sequences → operation_trees}/custom_object.rb +5 -1
  84. data/lib/super_diff/{operation_sequences → operation_trees}/default_object.rb +10 -8
  85. data/lib/super_diff/operation_trees/defaults.rb +5 -0
  86. data/lib/super_diff/{operation_sequences → operation_trees}/hash.rb +5 -1
  87. data/lib/super_diff/operation_trees/main.rb +35 -0
  88. data/lib/super_diff/operation_trees/multiline_string.rb +18 -0
  89. data/lib/super_diff/operations/unary_operation.rb +3 -0
  90. data/lib/super_diff/rspec.rb +45 -13
  91. data/lib/super_diff/rspec/augmented_matcher.rb +1 -1
  92. data/lib/super_diff/rspec/differ.rb +2 -17
  93. data/lib/super_diff/rspec/differs/collection_containing_exactly.rb +2 -7
  94. data/lib/super_diff/rspec/differs/collection_including.rb +2 -7
  95. data/lib/super_diff/rspec/differs/hash_including.rb +2 -7
  96. data/lib/super_diff/rspec/differs/object_having_attributes.rb +2 -7
  97. data/lib/super_diff/rspec/matcher_text_builders/match.rb +1 -1
  98. data/lib/super_diff/rspec/matcher_text_builders/respond_to.rb +1 -1
  99. data/lib/super_diff/rspec/matcher_text_template.rb +1 -1
  100. data/lib/super_diff/rspec/object_inspection.rb +0 -1
  101. data/lib/super_diff/rspec/object_inspection/inspectors.rb +16 -0
  102. data/lib/super_diff/rspec/object_inspection/inspectors/collection_containing_exactly.rb +17 -8
  103. data/lib/super_diff/rspec/object_inspection/inspectors/collection_including.rb +15 -9
  104. data/lib/super_diff/rspec/object_inspection/inspectors/hash_including.rb +20 -10
  105. data/lib/super_diff/rspec/object_inspection/inspectors/instance_of.rb +23 -0
  106. data/lib/super_diff/rspec/object_inspection/inspectors/kind_of.rb +23 -0
  107. data/lib/super_diff/rspec/object_inspection/inspectors/object_having_attributes.rb +20 -11
  108. data/lib/super_diff/rspec/object_inspection/inspectors/primitive.rb +13 -0
  109. data/lib/super_diff/rspec/object_inspection/inspectors/value_within.rb +29 -0
  110. data/lib/super_diff/rspec/operation_tree_builders.rb +22 -0
  111. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/collection_containing_exactly.rb +5 -5
  112. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/collection_including.rb +2 -2
  113. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/hash_including.rb +3 -11
  114. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/object_having_attributes.rb +4 -8
  115. data/lib/super_diff/version.rb +1 -1
  116. data/spec/examples.txt +397 -393
  117. data/spec/integration/rspec/have_attributes_matcher_spec.rb +354 -227
  118. data/spec/integration/rspec/include_matcher_spec.rb +2 -2
  119. data/spec/integration/rspec/unhandled_errors_spec.rb +68 -12
  120. data/spec/support/command_runner.rb +3 -0
  121. data/spec/support/integration/helpers.rb +12 -96
  122. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +14 -29
  123. data/spec/support/integration/test_programs/base.rb +120 -0
  124. data/spec/support/integration/test_programs/plain.rb +13 -0
  125. data/spec/support/integration/test_programs/rspec_active_record.rb +17 -0
  126. data/spec/support/integration/test_programs/rspec_rails.rb +17 -0
  127. data/spec/support/models/active_record/person.rb +4 -11
  128. data/spec/support/models/active_record/shipping_address.rb +10 -14
  129. data/spec/support/object_id.rb +6 -5
  130. data/spec/tmp/integration_spec.rb +15 -0
  131. data/spec/unit/{equality_matcher_spec.rb → equality_matchers/main_spec.rb} +157 -1
  132. data/spec/unit/object_inspection_spec.rb +77 -1
  133. data/super_diff.gemspec +0 -1
  134. metadata +72 -64
  135. data/lib/super_diff/active_record/object_inspection/map_extension.rb +0 -18
  136. data/lib/super_diff/active_record/operational_sequencers.rb +0 -14
  137. data/lib/super_diff/active_support/object_inspection/map_extension.rb +0 -15
  138. data/lib/super_diff/active_support/operational_sequencers.rb +0 -10
  139. data/lib/super_diff/diff_formatter.rb +0 -32
  140. data/lib/super_diff/differ.rb +0 -51
  141. data/lib/super_diff/differs/time.rb +0 -24
  142. data/lib/super_diff/equality_matcher.rb +0 -32
  143. data/lib/super_diff/no_differ_available_error.rb +0 -22
  144. data/lib/super_diff/no_operational_sequencer_available_error.rb +0 -20
  145. data/lib/super_diff/object_inspection/inspector.rb +0 -27
  146. data/lib/super_diff/object_inspection/inspectors/time.rb +0 -13
  147. data/lib/super_diff/object_inspection/map.rb +0 -30
  148. data/lib/super_diff/operation_sequences.rb +0 -9
  149. data/lib/super_diff/operational_sequencer.rb +0 -48
  150. data/lib/super_diff/operational_sequencers.rb +0 -17
  151. data/lib/super_diff/operational_sequencers/base.rb +0 -89
  152. data/lib/super_diff/operational_sequencers/hash.rb +0 -85
  153. data/lib/super_diff/operational_sequencers/time_like.rb +0 -30
  154. data/lib/super_diff/rspec/configuration.rb +0 -31
  155. data/lib/super_diff/rspec/object_inspection/map_extension.rb +0 -23
  156. data/lib/super_diff/rspec/operational_sequencers.rb +0 -22
@@ -214,9 +214,9 @@ RSpec.describe "Integration with RSpec's #include matcher", type: :integration d
214
214
  alpha_line %|- city: "Hill Valley",|
215
215
  beta_line %|+ city: "Burbank",|
216
216
  # FIXME
217
- # plain_line %| zip: "90210",|
218
- plain_line %| zip: "90210"|
217
+ # alpha_line %|- state: "CA",|
219
218
  alpha_line %|- state: "CA"|
219
+ plain_line %| zip: "90210"|
220
220
  plain_line %| }|
221
221
  },
222
222
  )
@@ -15,7 +15,7 @@ RSpec.describe "Integration with RSpec and unhandled errors", type: :integration
15
15
 
16
16
  expected_output = build_expected_output(
17
17
  color_enabled: color_enabled,
18
- snippet: %|raise "Some kind of error or whatever\\n\\nThis is another line"|,
18
+ snippet: snippet,
19
19
  newline_before_expectation: true,
20
20
  indentation: 5,
21
21
  expectation: proc {
@@ -25,7 +25,7 @@ RSpec.describe "Integration with RSpec and unhandled errors", type: :integration
25
25
  newline
26
26
  plain_line "This is another line"
27
27
  end
28
- }
28
+ },
29
29
  )
30
30
 
31
31
  expect(program).
@@ -48,7 +48,7 @@ RSpec.describe "Integration with RSpec and unhandled errors", type: :integration
48
48
 
49
49
  expected_output = build_expected_output(
50
50
  color_enabled: color_enabled,
51
- snippet: %|raise "Some kind of error or whatever"|,
51
+ snippet: snippet,
52
52
  newline_before_expectation: true,
53
53
  indentation: 5,
54
54
  expectation: proc {
@@ -56,7 +56,7 @@ RSpec.describe "Integration with RSpec and unhandled errors", type: :integration
56
56
  indent by: 2 do
57
57
  red_line "Some kind of error or whatever"
58
58
  end
59
- }
59
+ },
60
60
  )
61
61
 
62
62
  expect(program).
@@ -67,23 +67,79 @@ RSpec.describe "Integration with RSpec and unhandled errors", type: :integration
67
67
  end
68
68
  end
69
69
 
70
- context "when multiple exception occur" do
71
- it "highlights the first line in red, and then leaves the rest of the message alone" do
70
+ context "when multiple exceptions occur" do
71
+ it "displays all exceptions, and for each exception, highlights the first line in red and leaves the rest of the message alone" do
72
72
  as_both_colored_and_uncolored do |color_enabled|
73
- program = <<~PROGRAM.strip
74
- #{set_up_with("super_diff/rspec", color_enabled: color_enabled)}
73
+ snippet = <<~TEST.strip
74
+ raise "Some kind of error or whatever\\n\\nThis is another line"
75
+ TEST
76
+ code = <<~CODE
75
77
  RSpec.describe "test" do
76
78
  after(:each) do
77
- raise "Some kind of after error or whatever\\n\\nThis is another line"
79
+ #{snippet}
78
80
  end
81
+
79
82
  it "passes" do
80
- raise "Some kind of error or whatever\\n\\nThis is another line"
83
+ #{snippet}
84
+ end
85
+ end
86
+ CODE
87
+
88
+ program = make_plain_test_program(
89
+ code,
90
+ color_enabled: color_enabled,
91
+ preserve_as_whole_file: true,
92
+ )
93
+
94
+ expected_output1 = colored(color_enabled: color_enabled) do
95
+ indent by: 5 do
96
+ line do
97
+ plain "1.1) "
98
+ bold "Failure/Error: "
99
+ plain snippet
100
+ end
101
+
102
+ newline
103
+
104
+ indent by: 5 do
105
+ red_line "RuntimeError:"
106
+ indent by: 2 do
107
+ red_line "Some kind of error or whatever"
108
+ newline
109
+ line "This is another line"
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ expected_output2 = colored(color_enabled: color_enabled) do
116
+ indent by: 5 do
117
+ line do
118
+ plain "1.2) "
119
+ bold "Failure/Error: "
120
+ plain snippet
121
+ end
122
+
123
+ newline
124
+
125
+ indent by: 5 do
126
+ red_line "RuntimeError:"
127
+ indent by: 2 do
128
+ red_line "Some kind of error or whatever"
129
+ newline
130
+ line "This is another line"
131
+ end
81
132
  end
82
133
  end
83
- PROGRAM
134
+ end
135
+
136
+ expect(program).
137
+ to produce_output_when_run(expected_output1).
138
+ in_color(color_enabled)
84
139
 
85
140
  expect(program).
86
- to produce_output_when_run('Some kind of after error or whatever')
141
+ to produce_output_when_run(expected_output2).
142
+ in_color(color_enabled)
87
143
  end
88
144
  end
89
145
  end
@@ -120,6 +120,9 @@ Output:
120
120
  @env = extract_env_from(@options)
121
121
 
122
122
  @process = ChildProcess.build(*command)
123
+ # @env.each do |key, value|
124
+ # @process.environment[key] = value
125
+ # end
123
126
  @process.io.stdout = @process.io.stderr = @writer
124
127
 
125
128
  @wrapper = -> (block) { block.call }
@@ -8,104 +8,24 @@ module SuperDiff
8
8
  end
9
9
  end
10
10
 
11
- def make_plain_test_program(test, color_enabled:)
12
- <<~PROGRAM
13
- #{set_up_with("super_diff/rspec", color_enabled: color_enabled)}
14
- #{describe_block_including(test)}
15
- PROGRAM
11
+ def make_plain_test_program(
12
+ test,
13
+ color_enabled:,
14
+ preserve_as_whole_file: false
15
+ )
16
+ TestPrograms::Plain.new(
17
+ test,
18
+ color_enabled: color_enabled,
19
+ preserve_as_whole_file: preserve_as_whole_file,
20
+ )
16
21
  end
17
22
 
18
23
  def make_rspec_active_record_program(test, color_enabled:)
19
- <<~PROGRAM
20
- #{
21
- set_up_active_record_around do
22
- set_up_with(
23
- "super_diff/rspec", "super_diff/active_record",
24
- color_enabled: color_enabled
25
- )
26
- end
27
- }
28
- #{describe_block_including(test)}
29
- PROGRAM
24
+ TestPrograms::RspecActiveRecord.new(test, color_enabled: color_enabled)
30
25
  end
31
26
 
32
27
  def make_rspec_rails_test_program(test, color_enabled:)
33
- <<~PROGRAM
34
- #{
35
- set_up_active_record_around do
36
- set_up_with("super_diff/rspec-rails", color_enabled: color_enabled)
37
- end
38
- }
39
- #{describe_block_including(test)}
40
- PROGRAM
41
- end
42
-
43
- def set_up_active_record_around(&block)
44
- <<~PROGRAM
45
- require "active_record"
46
-
47
- ActiveRecord::Base.establish_connection(
48
- adapter: "sqlite3",
49
- database: ":memory:"
50
- )
51
-
52
- RSpec.configuration do |config|
53
- config.before do
54
- SuperDiff::Test::Models::ActiveRecord::Person.delete_all
55
- SuperDiff::Test::Models::ActiveRecord::ShippingAddress.delete_all
56
- end
57
- end
58
-
59
- #{block.call}
60
-
61
- Dir.glob(SUPPORT_DIR.join("models/active_record/*.rb")).each do |path|
62
- require path
63
- end
64
- PROGRAM
65
- end
66
-
67
- def set_up_with(*libraries, color_enabled:)
68
- <<~SETUP
69
- PROJECT_DIRECTORY = Pathname.new("#{PROJECT_DIRECTORY}")
70
- SUPPORT_DIR = PROJECT_DIRECTORY.join("spec/support")
71
- INSIDE_INTEGRATION_TEST = true
72
-
73
- $LOAD_PATH.unshift(PROJECT_DIRECTORY.join("lib"))
74
- #\$LOAD_PATH.unshift(PROJECT_DIRECTORY)
75
-
76
- begin
77
- require "pry-byebug"
78
- rescue LoadError
79
- require "pry-nav"
80
- end
81
-
82
- module SuperDiff
83
- module IntegrationTests; end
84
- end
85
-
86
- RSpec.configure do |config|
87
- config.color_mode = :#{color_enabled ? "on" : "off"}
88
- config.include SuperDiff::IntegrationTests
89
- end
90
-
91
- #{libraries.map { |library| %( require "#{library}") }.join("\n")}
92
-
93
- Dir.glob(SUPPORT_DIR.join("{models,matchers}/*.rb")).each do |path|
94
- require path
95
- end
96
-
97
- require SUPPORT_DIR.join("integration/matchers")
98
- SETUP
99
- end
100
-
101
- def describe_block_including(test)
102
- <<~PROGRAM
103
- RSpec.describe "test" do
104
- it "passes" do
105
- #{reindent(test, level: 2)}
106
- end
107
- end
108
- PROGRAM
28
+ TestPrograms::RspecRails.new(test, color_enabled: color_enabled)
109
29
  end
110
30
 
111
31
  def build_expected_output(
@@ -179,9 +99,5 @@ module SuperDiff
179
99
  def colored(color_enabled: true, &block)
180
100
  SuperDiff::Helpers.style(color_enabled: color_enabled, &block).to_s.chomp
181
101
  end
182
-
183
- def reindent(code, level: 0)
184
- code.strip.split("\n").map { |line| (" " * level) + line }.join("\n")
185
- end
186
102
  end
187
103
  end
@@ -5,11 +5,8 @@ module SuperDiff
5
5
  end
6
6
 
7
7
  class ProduceOutputWhenRunMatcher
8
- PROJECT_DIRECTORY = Pathname.new("../../../../../").expand_path(__FILE__)
9
- TEMP_DIRECTORY = PROJECT_DIRECTORY.join("tmp")
10
-
11
8
  def initialize(expected_output)
12
- @expected_output = expected_output.to_s.strip
9
+ @expected_output = expected_output.to_s
13
10
  @output_processor = nil
14
11
  @expect_output_to_contain_color = nil
15
12
  end
@@ -25,9 +22,7 @@ module SuperDiff
25
22
  end
26
23
 
27
24
  def matches?(program)
28
- @program = program.strip
29
-
30
- TEMP_DIRECTORY.mkpath
25
+ @program = program
31
26
 
32
27
  output_matches? && presence_of_color_matches?
33
28
  end
@@ -48,13 +43,17 @@ module SuperDiff
48
43
  "Actual output:\n\n" +
49
44
  CommandRunner::OutputHelpers.bookended(actual_output)
50
45
 
51
- ::RSpec::Matchers::ExpectedsForMultipleDiffs.
52
- from(expected_output).
53
- message_with_diff(
54
- message,
55
- ::RSpec::Expectations.differ,
56
- actual_output,
57
- )
46
+ if ["1", "true"].include?(ENV["SHOW_DIFF"])
47
+ ::RSpec::Matchers::ExpectedsForMultipleDiffs.
48
+ from(expected_output).
49
+ message_with_diff(
50
+ message,
51
+ ::RSpec::Expectations.differ,
52
+ actual_output,
53
+ )
54
+ else
55
+ message
56
+ end
58
57
  end
59
58
  end
60
59
 
@@ -77,7 +76,7 @@ module SuperDiff
77
76
 
78
77
  def actual_output
79
78
  @_actual_output ||= begin
80
- output = run_command.output.strip
79
+ output = program.run.output.strip
81
80
 
82
81
  if output_processor
83
82
  output.gsub!(output_processor[0], output_processor[1])
@@ -87,20 +86,6 @@ module SuperDiff
87
86
  end
88
87
  end
89
88
 
90
- def run_command
91
- CommandRunner.run(
92
- "rspec --options /tmp/dummy-rspec-config",
93
- tempfile.to_s,
94
- env: { "DISABLE_PRY" => "true" },
95
- )
96
- end
97
-
98
- def tempfile
99
- @_tempfile =
100
- TEMP_DIRECTORY.join("integration_spec.rb").
101
- tap { |tempfile| tempfile.write(program) }
102
- end
103
-
104
89
  def presence_of_color_matches?
105
90
  @expect_output_to_contain_color.nil? ||
106
91
  output_has_color? == expect_output_to_contain_color?
@@ -0,0 +1,120 @@
1
+ module SuperDiff
2
+ module IntegrationTests
3
+ module TestPrograms
4
+ class Base
5
+ extend AttrExtras.mixin
6
+
7
+ PROJECT_DIRECTORY = Pathname.new("../../../..").expand_path(__dir__)
8
+ TEMP_DIRECTORY = PROJECT_DIRECTORY.join("tmp")
9
+
10
+ attr_private :code, :color_enabled, :preserve_as_whole_file
11
+
12
+ def initialize(code, color_enabled:, preserve_as_whole_file: false)
13
+ @code = code.strip
14
+ @color_enabled = color_enabled
15
+ @preserve_as_whole_file = preserve_as_whole_file
16
+ end
17
+
18
+ def run
19
+ result_of_command
20
+ end
21
+
22
+ protected
23
+
24
+ def test_plan_prelude
25
+ ""
26
+ end
27
+
28
+ def test_plan_command
29
+ raise NotImplementedError
30
+ end
31
+
32
+ private
33
+
34
+ attr_query :color_enabled?
35
+ attr_query :preserve_as_whole_file?
36
+
37
+ def result_of_command
38
+ @_result_of_command ||=
39
+ if zeus_running?
40
+ Bundler.with_unbundled_env { CommandRunner.run(*command) }
41
+ else
42
+ CommandRunner.run(*command)
43
+ end
44
+ end
45
+
46
+ def command
47
+ if ENV["RAILS_ENV"]
48
+ raise "RAILS_ENV is being set somehow?!"
49
+ end
50
+
51
+ if zeus_running?
52
+ ["zeus", test_plan_command, color_option, tempfile.to_s]
53
+ else
54
+ [
55
+ "rspec",
56
+ "--options",
57
+ "/tmp/dummy-rspec-config",
58
+ tempfile.to_s,
59
+ ]
60
+ end
61
+ end
62
+
63
+ def zeus_running?
64
+ PROJECT_DIRECTORY.join(".zeus.sock").exist?
65
+ end
66
+
67
+ def color_option
68
+ color_enabled ? "--color" : "--no-color"
69
+ end
70
+
71
+ def tempfile
72
+ @_tempfile ||= begin
73
+ TEMP_DIRECTORY.mkpath
74
+ TEMP_DIRECTORY.join("integration_spec.rb").tap do |file|
75
+ file.write(program)
76
+ end
77
+ end
78
+ end
79
+
80
+ def program
81
+ if zeus_running?
82
+ minimal_program
83
+ else
84
+ <<~PROGRAM
85
+ require "#{PROJECT_DIRECTORY.join("support/test_plan.rb")}"
86
+
87
+ test_plan = TestPlan.new(
88
+ using_outside_of_zeus: true,
89
+ color_enabled: #{color_enabled?}
90
+ )
91
+ test_plan.boot
92
+ #{test_plan_prelude}
93
+ test_plan.#{test_plan_command}
94
+
95
+ #{minimal_program}
96
+ PROGRAM
97
+ end
98
+ end
99
+
100
+ def minimal_program
101
+ if preserve_as_whole_file?
102
+ code
103
+ else
104
+ <<~PROGRAM
105
+ RSpec.describe "test" do
106
+ it "passes" do
107
+ #{reindent(code, level: 2)}
108
+ end
109
+ end
110
+ PROGRAM
111
+ end
112
+ end
113
+
114
+ def reindent(code, level: 0)
115
+ code.strip.split("\n").map { |line| (" " * level) + line }.join("\n")
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end