Skip to content

Commit 0c13060

Browse files
authored
More improvements to match output (#2195)
Particularly focussing on multiline outputs
1 parent c6072b4 commit 0c13060

File tree

5 files changed

+91
-21
lines changed

5 files changed

+91
-21
lines changed

R/expect-match.R

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,29 +117,73 @@ expect_match_ <- function(
117117
return(pass(act$val))
118118
}
119119

120-
text <- encodeString(act$val)
121120
if (length(act$val) == 1) {
122-
values <- paste0(title, ': "', text, '"')
123121
which <- ""
124122
} else {
125-
bullet <- ifelse(
126-
condition,
127-
cli::col_green(cli::symbol$tick),
128-
cli::col_red(cli::symbol$cross)
129-
)
130-
values <- paste0(title, ":\n", paste0(bullet, " ", text, collapse = "\n"))
131123
which <- if (all) "Every element of " else "Some element of "
132124
}
133125
match <- if (negate) "matches" else "does not match"
134126

135127
msg <- sprintf(
136-
"%s%s %s %s %s.\n%s",
128+
"%s%s %s %s %s.\n%s:\n%s",
137129
which,
138130
act$lab,
139131
match,
140132
if (fixed) "string" else "regexp",
141133
encodeString(regexp, quote = '"'),
142-
values
134+
title,
135+
paste0(show_text(act$val, condition), collapse = "\n")
143136
)
144137
return(fail(msg, info = info, trace_env = trace_env))
145138
}
139+
140+
141+
# Adapted from print.ellmer_prompt
142+
show_text <- function(
143+
x,
144+
condition,
145+
...,
146+
max_items = 20,
147+
max_lines = max_items * 25
148+
) {
149+
n <- length(x)
150+
n_extra <- length(x) - max_items
151+
if (n_extra > 0) {
152+
x <- x[seq_len(max_items)]
153+
condition <- condition[seq_len(max_items)]
154+
}
155+
156+
if (length(x) == 0) {
157+
return(character())
158+
}
159+
160+
bar <- if (cli::is_utf8_output()) "\u2502" else "|"
161+
162+
id <- ifelse(
163+
condition,
164+
cli::col_green(cli::symbol$tick),
165+
cli::col_red(cli::symbol$cross)
166+
)
167+
168+
indent <- paste0(id, " ", bar, " ")
169+
exdent <- paste0(" ", cli::col_grey(bar), " ")
170+
171+
x[is.na(x)] <- cli::col_red("<NA>")
172+
x <- paste0(indent, x)
173+
x <- gsub("\n", paste0("\n", exdent), x)
174+
175+
lines <- strsplit(x, "\n")
176+
ids <- rep(seq_along(x), length(lines))
177+
lines <- unlist(lines)
178+
179+
if (length(lines) > max_lines) {
180+
lines <- lines[seq_len(max_lines)]
181+
lines <- c(lines, paste0(exdent, "..."))
182+
n_extra <- n - ids[max_lines - 1]
183+
}
184+
185+
if (n_extra > 0) {
186+
lines <- c(lines, paste0("... and ", n_extra, " more.\n"))
187+
}
188+
lines
189+
}

tests/testthat/_snaps/expect-match.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,39 @@
55
---
66

77
`one` does not match regexp "asdf".
8-
Text: "bcde"
8+
Text:
9+
✖ │ bcde
910

1011
---
1112

1213
Every element of `many` does not match regexp "a".
1314
Text:
14-
✔ a
15-
✔ a
16-
✖ b
15+
a
16+
a
17+
b
1718

1819
---
1920

2021
Some element of `many` does not match regexp "c".
2122
Text:
22-
✖ a
23-
✖ a
24-
✖ b
23+
✖ │ a
24+
✖ │ a
25+
✖ │ b
26+
27+
---
28+
29+
Every element of `paragraph` does not match regexp "paragraph".
30+
Text:
31+
✔ │ This is a multiline
32+
│ paragraph.
33+
✖ │ Second element.
34+
35+
---
36+
37+
Every element of `na` does not match regexp "NA".
38+
Text:
39+
✔ │ NA
40+
✖ │ <NA>
2541

2642
# expect_match validates its inputs
2743

@@ -82,10 +98,12 @@
8298
# expect_no_match works
8399

84100
`x` matches string "e*".
85-
Text: "te*st"
101+
Text:
102+
x | te*st
86103

87104
---
88105

89106
`x` matches regexp "TEST".
90-
Text: "test"
107+
Text:
108+
x | test
91109

tests/testthat/_snaps/expect-output.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# expect = string checks for match
22

33
`g()` does not match regexp "x".
4-
Output: "!"
4+
Output:
5+
x | !
56

67
---
78

tests/testthat/_snaps/expect-self-test.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# expect_failure() can optionally match message
22

33
Failure message does not match regexp "banana".
4-
Text: "apple"
4+
Text:
5+
x | apple
56

67
# errors in expect_success bubble up
78

tests/testthat/test-expect-match.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ test_that("generates useful failure messages", {
1010
many <- c("a", "a", "b")
1111
expect_snapshot_failure(expect_match(many, "a"))
1212
expect_snapshot_failure(expect_match(many, "c", all = FALSE))
13+
14+
paragraph <- c("This is a multiline\nparagraph.", "Second element.")
15+
expect_snapshot_failure(expect_match(paragraph, "paragraph"))
16+
17+
na <- c("NA", NA)
18+
expect_snapshot_failure(expect_match(na, "NA"))
1319
})
1420

1521
test_that("expect_match validates its inputs", {

0 commit comments

Comments
 (0)