Module: Insta::Minitest::Assertions

Defined in:
lib/insta/minitest/assertions.rb,
sig/insta/minitest/assertions.rbs

Instance Method Summary collapse

Instance Method Details

#_insta_snapshot_fileSnapshotFile

: () -> SnapshotFile

Returns:



123
124
125
126
127
128
129
# File 'lib/insta/minitest/assertions.rb', line 123

def _insta_snapshot_file
  @_insta_snapshot_file ||= SnapshotFile.new(
    Insta.configuration.snapshot_path,
    self.class.name || "Anonymous",
    name || "unknown"
  )
end

#assert_inline_snapshot(actual, expected = nil, serializer: nil, redact: nil) ⇒ Object

: ( | untyped, | ?String?, | ?serializer: Symbol?, | ?redact: Hash[String, untyped]? | ) -> void

Parameters:

  • actual (Object)
  • expected (Object) (defaults to: nil)
  • serializer: (Object) (defaults to: nil)
  • redact: (Object) (defaults to: nil)

Returns:

  • (Object)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/insta/minitest/assertions.rb', line 79

def assert_inline_snapshot(actual, expected = nil, serializer: nil, redact: nil)
  serializer_name = serializer || Insta.configuration.default_serializer
  actual = Redaction::Applicator.apply(actual, redact) if redact
  serialized = Serializers.serialize(serializer_name, actual)
  content = SnapshotContent.normalize(serialized)

  location = caller_locations(1, 1)&.first
  return flunk("Could not determine caller location") unless location

  file = location.path
  line = location.lineno

  return flunk("Could not determine source file") unless file

  if expected.nil?
    if Insta.configuration.new_snapshot == :review
      Inline::PendingStore.add(file: file, line: line, content: content, old_content: "", type: :insert)

      if ENV["INSTA_FORCE_PASS"]
        pass
      else
        flunk "New inline snapshot pending review at #{file}:#{line}\nRun `bundle exec insta review` to accept."
      end
    else
      Inline::PendingRegistry.add(file: file, line: line, content: content, type: :insert)
      pass
    end

    return
  end

  expected_normalized = SnapshotContent.normalize(expected.to_s)

  if content == expected_normalized
    pass
    return
  end

  handle_inline_mismatch(file, line, content, expected_normalized)
end

#assert_snapshot(actual, name: nil, serializer: nil, redact: nil, input: nil, description: nil, info: nil, options: nil) ⇒ Object

: ( | untyped, | ?name: String?, | ?serializer: Symbol?, | ?redact: Hash[String, untyped]?, | ?input: String?, | ?description: String?, | ?info: Hash[String, untyped]?, | ?options: Hash[Symbol, untyped]? | ) -> void

Parameters:

  • actual (Object)
  • name: (Object) (defaults to: nil)
  • serializer: (Object) (defaults to: nil)
  • redact: (Object) (defaults to: nil)
  • input: (Object) (defaults to: nil)
  • description: (Object) (defaults to: nil)
  • info: (Object) (defaults to: nil)
  • options: (Object) (defaults to: nil)

Returns:

  • (Object)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/insta/minitest/assertions.rb', line 17

def assert_snapshot(actual, name: nil, serializer: nil, redact: nil, input: nil, description: nil, info: nil, options: nil)
  expression = actual.class.name
  serializer_name = serializer || Insta.configuration.default_serializer
  actual = Redaction::Applicator.apply(actual, redact) if redact
  serialized = Serializers.serialize(serializer_name, actual)
  content = SnapshotContent.normalize(serialized)

  test_class = self.class.name || "Anonymous"
  test_method = self.name || "unknown"

  path = if name
           snapshot_file = SnapshotFile.new(
             Insta.configuration.snapshot_path,
             test_class,
             test_method
           )
           snapshot_file.named_path(name)
         else
           snapshot_file = _insta_snapshot_file
           snapshot_file.path_for(options || {})
         end

   = (
    test_class,
    test_method,
    expression: expression,
    input: input,
    description: description,
    info: info,
    options: options
  )

  existing = snapshot_file.read(path)

  unless existing
    handle_missing_snapshot(snapshot_file, path, content, )
    return
  end

  if existing.expression && existing.expression != expression
    caller_line = find_test_caller
    handle_type_mismatch(snapshot_file, path, content, , existing, expression, caller_line)
    return
  end

  expected = SnapshotContent.normalize(existing.content)

  if content == expected
    pass
    return
  end

  caller_line = find_test_caller
  handle_snapshot_mismatch(snapshot_file, path, content, , expected, test_class, test_method, caller_line)
end

#build_metadata(test_class, test_method, expression: nil, input: nil, description: nil, info: nil, options: nil) ⇒ Object

: (String, String, ?expression: String?, ?input: String?, ?description: String?, | ?info: Hash[String, untyped]?, ?options: Hash[Symbol, untyped]?) -> Snapshot::snapshot_metadata

Parameters:

  • test_class (Object)
  • test_method (Object)
  • expression: (Object) (defaults to: nil)
  • input: (Object) (defaults to: nil)
  • description: (Object) (defaults to: nil)
  • info: (Object) (defaults to: nil)
  • options: (Object) (defaults to: nil)

Returns:

  • (Object)


147
148
149
150
151
152
153
154
155
156
157
# File 'lib/insta/minitest/assertions.rb', line 147

def (test_class, test_method, expression: nil, input: nil, description: nil, info: nil, options: nil)
   = { "source" => "#{test_class}##{test_method}" }

  ["expression"] = expression if expression
  ["input"] = input if input
  ["description"] = description if description
  ["options"] = options if options && !options.empty?
  ["info"] = info if info

  
end

#find_test_callerString

: () -> String

Returns:

  • (String)


132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/insta/minitest/assertions.rb', line 132

def find_test_caller
  locations = caller_locations
  return locations&.first.to_s unless locations

  test_location = locations.find { |location|
    path = location.path

    path && !path.include?("lib/insta") && path.match?(/_test\.rb\z/)
  }

  (test_location || locations.first).to_s
end

#handle_inline_mismatch(file, line, content, expected_normalized) ⇒ void

This method returns an undefined value.

: (String, Integer, String, String) -> void

Parameters:

  • (String)
  • (Integer)
  • (String)
  • (String)


215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/insta/minitest/assertions.rb', line 215

def handle_inline_mismatch(file, line, content, expected_normalized)
  mode = Insta.configuration.resolved_update_mode

  case mode
  when :force
    Inline::PendingRegistry.add(file: file, line: line, content: content, type: :replace)
    pass
  when :no
    flunk Diff.failure_message(
      expected_normalized,
      content,
      "inline snapshot at #{file}:#{line}",
      nil,
      "#{file}:#{line}"
    )
  else # :auto, :pending
    Inline::PendingStore.add(
      file: file,
      line: line,
      content: content,
      old_content: expected_normalized,
      type: :replace
    )

    if ENV["INSTA_FORCE_PASS"]
      pass
    else
      flunk Diff.failure_message(
        expected_normalized,
        content,
        "inline snapshot at #{file}:#{line}",
        nil,
        "#{file}:#{line}"
      )
    end
  end
end

#handle_missing_snapshot(snapshot_file, path, content, metadata) ⇒ void

This method returns an undefined value.

: (SnapshotFile, Pathname, String, Snapshot::snapshot_metadata) -> void

Parameters:

  • (SnapshotFile)
  • (Pathname)
  • (String)
  • (Snapshot::snapshot_metadata)


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/insta/minitest/assertions.rb', line 160

def handle_missing_snapshot(snapshot_file, path, content, )
  mode = Insta.configuration.resolved_update_mode

  if mode == :no
    flunk "Snapshot file does not exist: #{path}\nRun with INSTA_UPDATE=force to create it."
    return
  end

  if Insta.configuration.new_snapshot == :review
    pending_path = snapshot_file.pending_path(path)
    snapshot_file.write(pending_path, content, )
    PendingLocations.add(pending_path.to_s, find_test_caller)

    if ENV["INSTA_FORCE_PASS"]
      pass
    else
      flunk "New snapshot pending review: #{path}\nRun `bundle exec insta review` to accept."
    end

    return
  end

  snapshot_file.write(path, content, )

  pass
end

#handle_snapshot_mismatch(snapshot_file, path, content, metadata, expected, test_class, test_method, caller_line) ⇒ void

This method returns an undefined value.

: (SnapshotFile, Pathname, String, Snapshot::snapshot_metadata, String, String, String, String) -> void

Parameters:

  • (SnapshotFile)
  • (Pathname)
  • (String)
  • (Snapshot::snapshot_metadata)
  • (String)
  • (String)
  • (String)
  • (String)


202
203
204
205
206
207
208
209
210
211
212
# File 'lib/insta/minitest/assertions.rb', line 202

def handle_snapshot_mismatch(snapshot_file, path, content, , expected, test_class, test_method, caller_line)
  result = SnapshotMismatchHandler.handle(snapshot_file, path, content, , expected, caller_line: caller_line)

  case result
  when :updated, :force_passed
    pass
  else
    label = "#{test_class}##{test_method}"
    flunk SnapshotMismatchHandler.failure_message(expected, content, label, path, caller_line: caller_line)
  end
end

#handle_type_mismatch(snapshot_file, path, content, metadata, existing, expression, caller_line) ⇒ void

This method returns an undefined value.

: (SnapshotFile, Pathname, String, Snapshot::snapshot_metadata, Snapshot, String?, String) -> void

Parameters:

  • (SnapshotFile)
  • (Pathname)
  • (String)
  • (Snapshot::snapshot_metadata)
  • (Snapshot)
  • (String, nil)
  • (String)


188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/insta/minitest/assertions.rb', line 188

def handle_type_mismatch(snapshot_file, path, content, , existing, expression, caller_line)
  expected = SnapshotContent.normalize(existing.content)
  result = SnapshotMismatchHandler.handle(snapshot_file, path, content, , expected, caller_line: caller_line)

  case result
  when :updated, :force_passed
    pass
  else
    flunk "Snapshot type mismatch: snapshot was #{existing.expression} but got #{expression}\n" \
          "Run `bundle exec insta review` or delete the snapshot file and re-run the test to update it."
  end
end