Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion demo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@
expect("\"Hello, ---world\"").to match("Hello, world")
end

it "strings with newlines" do
output = "\"l appears 1 times\"\n\"o appears 2 times\"\n\"o appears 2 times\"\n\"p appears 1 times\""
expect(output).to match("\"l appears 1 times\"\n\"o appears 2 times\"\n\"e appears 1 times\"\n\"p appears 1 times\"")
end

# Change Matchers
it "change" do
x = 5
Expand Down Expand Up @@ -396,7 +401,7 @@ def initialize
"Truthiness Matchers" => ["be_truthy", "be_falsey / be_falsy", "be_nil"],
"Predicate Matchers" => ["be_empty", "have_key"],
"Collection Matchers" => ["include", "include with multiple items", "include with hash", "start_with", "end_with", "match (regex)", "match (regex) with custom message", "contain_exactly", "match_array", "all"],
"String Matchers" => ["match with string", "unescaping quotes in actual"],
"String Matchers" => ["match with string", "unescaping quotes in actual", "strings with newlines"],
"Change Matchers" => ["change", "change by", "change by_at_least", "change by_at_most"],
"Output Matchers" => ["output to stdout", "output to stderr"],
"Exception Matchers" => ["raise_error", "raise_error with message", "raise_error when none raised", "unexpected exception (outside expect block)"],
Expand Down
10 changes: 9 additions & 1 deletion lib/rspec/enriched_json/expectation_helper_wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,15 @@ def truncate_string(str)

def unescape_string_double_quotes(str)
if str.start_with?('"') && str.end_with?('"')
return str.undump
begin
# Only undump if it's a valid dumped string
# Check if the string is properly escaped by attempting undump
str.undump
rescue RuntimeError => e
# If undump fails, just return the original string
# This handles cases where the string has quotes but isn't a valid dump format
str
Comment on lines +92 to +95
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a safety measure or do we know of an exact case where this would happen?

If an exact case is known, it should be added to the specs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think undump fails anytime that undumping would result in an invalid string

For example:

"\"Hello, World\"".undump => "Hello, World"
"\"Hello, \"World\"".undump => Exception

end
else
str
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/enriched_json/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module RSpec
module EnrichedJson
VERSION = "0.6.1"
VERSION = "0.6.2"
end
end
27 changes: 27 additions & 0 deletions spec/edge_cases_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,31 @@ def to_s
expect(e.details[:expected]["to_s"]).to eq("age")
end
end

context "handling strings with newlines" do
it "handles strings with embedded newlines and quotes" do
# This was causing "invalid dumped string" errors before the fix
output = "\"l appears 1 times\"\n\"o appears 2 times\"\n\"o appears 2 times\"\n\"p appears 1 times\""
expected = "\"l appears 1 times\"\n\"o appears 2 times\"\n\"e appears 1 times\"\n\"p appears 1 times\""

expect(output).to eq(expected)
rescue RSpec::EnrichedJson::EnrichedExpectationNotMetError => e
# Verify the strings are properly serialized without undump errors
expect(e.details[:actual]).to be_a(String)
expect(e.details[:expected]).to be_a(String)

# The actual should contain the newlines (actual newlines, not escaped)
expect(e.details[:actual]).to include("\n")
expect(e.details[:actual]).to include("l appears 1 times")
expect(e.details[:actual]).to include("o appears 2 times")

# The expected should also be properly serialized
expect(e.details[:expected]).to include("\n")
expect(e.details[:expected]).to include("e appears 1 times")

# Should not have serialization errors
expect(e.details[:actual]).not_to be_a(Hash)
expect(e.details[:actual]).not_to include("serialization_error")
end
end
end