diff --git a/cli/tools/coverage/mod.rs b/cli/tools/coverage/mod.rs index ff843e602304dd..bc8ae47c6b1e94 100644 --- a/cli/tools/coverage/mod.rs +++ b/cli/tools/coverage/mod.rs @@ -712,11 +712,18 @@ fn filter_coverages( .ok() .map(|url| in_npm_pkg_checker.in_npm_package(&url)) .unwrap_or(false); + if is_internal { + return false; + } - let is_included = include.iter().any(|p| p.is_match(&e.url)); - let is_excluded = exclude.iter().any(|p| p.is_match(&e.url)); - - (include.is_empty() || is_included) && !is_excluded && !is_internal + // Script URLs are percent-encoded, so a file whose path holds a space + // or a non-ASCII character appears in the URL as escapes. A pattern + // matches when it matches either the URL or its decoded form. + let decoded_url = + percent_encoding::percent_decode_str(&e.url).decode_utf8_lossy(); + let matches = |p: &Regex| p.is_match(&e.url) || p.is_match(&decoded_url); + (include.is_empty() || include.iter().any(matches)) + && !exclude.iter().any(matches) }) .collect::>() } diff --git a/tests/specs/coverage/filter_non_ascii_path/__test__.jsonc b/tests/specs/coverage/filter_non_ascii_path/__test__.jsonc new file mode 100644 index 00000000000000..c8cf6f0c479d7a --- /dev/null +++ b/tests/specs/coverage/filter_non_ascii_path/__test__.jsonc @@ -0,0 +1,27 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "test --coverage=cov test.ts", + "output": "[WILDCARD]1 passed[WILDCARD]" + }, + { + // This step and the next spell the directory as the file system + // does. The last two steps spell it with the escapes its URL uses. + "args": ["coverage", "cov", "--include=wt 🦆"], + "output": "included.out" + }, + { + "args": ["coverage", "cov", "--exclude=wt 🦆"], + "output": "excluded.out" + }, + { + "args": ["coverage", "cov", "--include=wt%20%F0%9F%A6%86"], + "output": "included.out" + }, + { + "args": ["coverage", "cov", "--exclude=wt%20%F0%9F%A6%86"], + "output": "excluded.out" + } + ] +} diff --git a/tests/specs/coverage/filter_non_ascii_path/excluded.out b/tests/specs/coverage/filter_non_ascii_path/excluded.out new file mode 100644 index 00000000000000..44b34457133b11 --- /dev/null +++ b/tests/specs/coverage/filter_non_ascii_path/excluded.out @@ -0,0 +1,4 @@ +| File [WILDLINE] +| ----[WILDLINE] +| plain.ts [WILDLINE] +| All files [WILDLINE] diff --git a/tests/specs/coverage/filter_non_ascii_path/included.out b/tests/specs/coverage/filter_non_ascii_path/included.out new file mode 100644 index 00000000000000..8a91b070c5fb96 --- /dev/null +++ b/tests/specs/coverage/filter_non_ascii_path/included.out @@ -0,0 +1,4 @@ +| File [WILDLINE] +| ----[WILDLINE] +| duck.ts [WILDLINE] +| All files [WILDLINE] diff --git a/tests/specs/coverage/filter_non_ascii_path/plain/plain.ts b/tests/specs/coverage/filter_non_ascii_path/plain/plain.ts new file mode 100644 index 00000000000000..8d17f048bd2b4f --- /dev/null +++ b/tests/specs/coverage/filter_non_ascii_path/plain/plain.ts @@ -0,0 +1,3 @@ +export function f(): number { + return 1; +} diff --git a/tests/specs/coverage/filter_non_ascii_path/test.ts b/tests/specs/coverage/filter_non_ascii_path/test.ts new file mode 100644 index 00000000000000..5f3d0008c57aec --- /dev/null +++ b/tests/specs/coverage/filter_non_ascii_path/test.ts @@ -0,0 +1,7 @@ +import { f as g } from "./plain/plain.ts"; +import { f } from "./wt 🦆/duck.ts"; + +Deno.test("test", () => { + f(); + g(); +}); diff --git "a/tests/specs/coverage/filter_non_ascii_path/wt \360\237\246\206/duck.ts" "b/tests/specs/coverage/filter_non_ascii_path/wt \360\237\246\206/duck.ts" new file mode 100644 index 00000000000000..8d17f048bd2b4f --- /dev/null +++ "b/tests/specs/coverage/filter_non_ascii_path/wt \360\237\246\206/duck.ts" @@ -0,0 +1,3 @@ +export function f(): number { + return 1; +}