Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import maps: use wpt_internal for parsing unit tests
https://chromium-review.googlesource.com/c/chromium/src/+/3816001/ removed the test coverage in wpt/external for parsing import maps. Although we plan to eventually convert those tests into resolution tests, it's still nice to have unit test-like coverage for our import map parser, so this CL copies over the data files in their current form and creates a small harness for directly testing them. Change-Id: I40837cb336e721e6e52c5f959a46c9220e225edf Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3815111 Commit-Queue: Domenic Denicola <domenic@chromium.org> Reviewed-by: Hiroshige Hayashizaki <hiroshige@chromium.org> Cr-Commit-Position: refs/heads/main@{#1032873}
- Loading branch information
Showing
13 changed files
with
942 additions
and
0 deletions.
There are no files selected for viewing
15 changes: 15 additions & 0 deletions
15
third_party/blink/web_tests/wpt_internal/import-maps/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Import maps internal tests | ||
|
||
These tests are essentially unit tests of the import map parser. The only | ||
observable effect of an import map is how it impacts module resolution, which is | ||
tested in `external/wpt`. But it's nice to have these sorts of parsing unit | ||
tests too. | ||
|
||
## Format | ||
|
||
The format is similar to the resolution tests format, which is described in | ||
`external/wpt/import-maps/README.md`. The only differences are that for a given | ||
test object: | ||
|
||
* Instead of `expectedResults`, we have `expectedParsedImportMap`. | ||
* `baseURL` is not applicable and cannot appear. |
111 changes: 111 additions & 0 deletions
111
third_party/blink/web_tests/wpt_internal/import-maps/parsing.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
|
||
<meta name="variant" content="?parsing-addresses-absolute.json"> | ||
<meta name="variant" content="?parsing-addresses-invalid.json"> | ||
<meta name="variant" content="?parsing-addresses.json"> | ||
<meta name="variant" content="?parsing-invalid-json.json"> | ||
<meta name="variant" content="?parsing-schema-normalization.json"> | ||
<meta name="variant" content="?parsing-schema-scope.json"> | ||
<meta name="variant" content="?parsing-schema-specifier-map.json"> | ||
<meta name="variant" content="?parsing-schema-toplevel.json"> | ||
<meta name="variant" content="?parsing-scope-keys.json"> | ||
<meta name="variant" content="?parsing-specifier-keys.json"> | ||
<meta name="variant" content="?parsing-trailing-slashes.json"> | ||
|
||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
|
||
<script> | ||
|
||
const filename = location.search.substring(1); | ||
promise_test(async () => { | ||
const res = await fetch('resources/' + filename); | ||
const json = await res.json(); | ||
const tests = await jsonToTests(json); | ||
|
||
for (const test of tests) { | ||
promise_test(async t => { | ||
const testHTML = ` | ||
<!DOCTYPE html> | ||
<base href="${test.importMapBaseURL}"> | ||
<script type="importmap"> | ||
${JSON.stringify(test.importMap)} | ||
</scri` + `pt> | ||
<script> | ||
parent.postMessage(internals.getParsedImportMap(document), '*'); | ||
</scri` + `pt> | ||
`; | ||
|
||
const iframe = document.createElement('iframe'); | ||
if (new URL(test.importMapBaseURL).protocol === 'data:') { | ||
iframe.src = 'data:text/html;base64,' + btoa(testHTML); | ||
} else { | ||
iframe.src = '/common/blank.html'; | ||
iframe.onload = () => { | ||
iframe.contentDocument.write(testHTML); | ||
iframe.contentDocument.close(); | ||
}; | ||
} | ||
document.body.append(iframe); | ||
|
||
let parsedImportMap = JSON.parse(await new Promise(resolve => { | ||
window.onmessage = t.step_func(e => { | ||
assert_equals(e.source, iframe.contentWindow); | ||
resolve(e.data); | ||
}); | ||
})); | ||
|
||
// internals.getParsedImportMap() returns an empty object instead of null for parse failures. | ||
// Translate it so the test comparison works as expected. | ||
if (Object.keys(parsedImportMap).length === 0) { | ||
parsedImportMap = null; | ||
} | ||
|
||
assert_equals( | ||
stringifyImportMap(parsedImportMap), | ||
stringifyImportMap(test.expectedParsedImportMap) | ||
); | ||
}, test.name); | ||
} | ||
}, 'Data fetching and setup'); | ||
|
||
function jsonToTests(json, inheritedProps = {}, name = '') { | ||
const baseProps = { | ||
importMap: orFallback(json, inheritedProps, 'importMap'), | ||
importMapBaseURL: orFallback(json, inheritedProps, 'importMapBaseURL'), | ||
expectedParsedImportMap: orFallback(json, inheritedProps, 'expectedParsedImportMap') | ||
}; | ||
|
||
if (json.tests) { | ||
// Parent node | ||
return Object.entries(json.tests).flatMap(([subName, subJSON]) => { | ||
const fullName = [name, json.name, subName].filter(Boolean).join(': '); | ||
return jsonToTests(subJSON, baseProps, fullName); | ||
}); | ||
} else { | ||
// Leaf (test) node | ||
return [{ name, ...baseProps }]; | ||
} | ||
} | ||
|
||
function orFallback(obj1, obj2, property) { | ||
return obj1.hasOwnProperty(property) ? obj1[property] : obj2[property]; | ||
} | ||
|
||
// Sort keys and then stringify for comparison. | ||
function stringifyImportMap(importMap) { | ||
function getKeys(m) { | ||
if (typeof m !== 'object') | ||
return []; | ||
|
||
let keys = []; | ||
for (const key in m) { | ||
keys.push(key); | ||
keys = keys.concat(getKeys(m[key])); | ||
} | ||
return keys; | ||
} | ||
return JSON.stringify(importMap, getKeys(importMap).sort()); | ||
} | ||
</script> |
65 changes: 65 additions & 0 deletions
65
..._party/blink/web_tests/wpt_internal/import-maps/resources/parsing-addresses-absolute.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
{ | ||
"name": "Absolute URL addresses", | ||
"tests": { | ||
"should only accept absolute URL addresses with fetch schemes": { | ||
"importMap": { | ||
"imports": { | ||
"about": "about:good", | ||
"blob": "blob:good", | ||
"data": "data:good", | ||
"file": "file:///good", | ||
"filesystem": "filesystem:http://example.com/good/", | ||
"http": "http://good/", | ||
"https": "https://good/", | ||
"ftp": "ftp://good/", | ||
"import": "import:bad", | ||
"mailto": "mailto:bad", | ||
"javascript": "javascript:bad", | ||
"wss": "wss:bad" | ||
} | ||
}, | ||
"importMapBaseURL": "https://base.example/path1/path2/path3", | ||
"expectedParsedImportMap": { | ||
"imports": { | ||
"about": "about:good", | ||
"blob": "blob:good", | ||
"data": "data:good", | ||
"file": "file:///good", | ||
"filesystem": "filesystem:http://example.com/good/", | ||
"http": "http://good/", | ||
"https": "https://good/", | ||
"ftp": "ftp://good/", | ||
"import": "import:bad", | ||
"javascript": "javascript:bad", | ||
"mailto": "mailto:bad", | ||
"wss": "wss://bad/" | ||
}, | ||
"scopes": {} | ||
} | ||
}, | ||
"should parse absolute URLs, ignoring unparseable ones": { | ||
"importMap": { | ||
"imports": { | ||
"unparseable2": "https://example.com:demo", | ||
"unparseable3": "http://[www.example.com]/", | ||
"invalidButParseable1": "https:example.org", | ||
"invalidButParseable2": "https://///example.com///", | ||
"prettyNormal": "https://example.net", | ||
"percentDecoding": "https://ex%41mple.com/" | ||
} | ||
}, | ||
"importMapBaseURL": "https://base.example/path1/path2/path3", | ||
"expectedParsedImportMap": { | ||
"imports": { | ||
"unparseable2": null, | ||
"unparseable3": null, | ||
"invalidButParseable1": "https://example.org/", | ||
"invalidButParseable2": "https://example.com///", | ||
"prettyNormal": "https://example.net/", | ||
"percentDecoding": "https://example.com/" | ||
}, | ||
"scopes": {} | ||
} | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...d_party/blink/web_tests/wpt_internal/import-maps/resources/parsing-addresses-invalid.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "Other invalid addresses", | ||
"tests": { | ||
"should ignore unprefixed strings that are not absolute URLs": { | ||
"importMap": { | ||
"imports": { | ||
"foo1": "bar", | ||
"foo2": "\\bar", | ||
"foo3": "~bar", | ||
"foo4": "#bar", | ||
"foo5": "?bar" | ||
} | ||
}, | ||
"importMapBaseURL": "https://base.example/path1/path2/path3", | ||
"expectedParsedImportMap": { | ||
"imports": { | ||
"foo1": null, | ||
"foo2": null, | ||
"foo3": null, | ||
"foo4": null, | ||
"foo5": null | ||
}, | ||
"scopes": {} | ||
} | ||
} | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
third_party/blink/web_tests/wpt_internal/import-maps/resources/parsing-addresses.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
{ | ||
"name": "Relative URL-like addresses", | ||
"tests": { | ||
"should accept strings prefixed with ./, ../, or /": { | ||
"importMap": { | ||
"imports": { | ||
"dotSlash": "./foo", | ||
"dotDotSlash": "../foo", | ||
"slash": "/foo" | ||
} | ||
}, | ||
"importMapBaseURL": "https://base.example/path1/path2/path3", | ||
"expectedParsedImportMap": { | ||
"imports": { | ||
"dotSlash": "https://base.example/path1/path2/foo", | ||
"dotDotSlash": "https://base.example/path1/foo", | ||
"slash": "https://base.example/foo" | ||
}, | ||
"scopes": {} | ||
} | ||
}, | ||
"should not accept strings prefixed with ./, ../, or / for data: base URLs": { | ||
"importMap": { | ||
"imports": { | ||
"dotSlash": "./foo", | ||
"dotDotSlash": "../foo", | ||
"slash": "/foo" | ||
} | ||
}, | ||
"importMapBaseURL": "data:text/html,test", | ||
"expectedParsedImportMap": { | ||
"imports": { | ||
"dotSlash": null, | ||
"dotDotSlash": null, | ||
"slash": null | ||
}, | ||
"scopes": {} | ||
} | ||
}, | ||
"should accept the literal strings ./, ../, or / with no suffix": { | ||
"importMap": { | ||
"imports": { | ||
"dotSlash": "./", | ||
"dotDotSlash": "../", | ||
"slash": "/" | ||
} | ||
}, | ||
"importMapBaseURL": "https://base.example/path1/path2/path3", | ||
"expectedParsedImportMap": { | ||
"imports": { | ||
"dotSlash": "https://base.example/path1/path2/", | ||
"dotDotSlash": "https://base.example/path1/", | ||
"slash": "https://base.example/" | ||
}, | ||
"scopes": {} | ||
} | ||
}, | ||
"should ignore percent-encoded variants of ./, ../, or /": { | ||
"importMap": { | ||
"imports": { | ||
"dotSlash1": "%2E/", | ||
"dotDotSlash1": "%2E%2E/", | ||
"dotSlash2": ".%2F", | ||
"dotDotSlash2": "..%2F", | ||
"slash2": "%2F", | ||
"dotSlash3": "%2E%2F", | ||
"dotDotSlash3": "%2E%2E%2F" | ||
} | ||
}, | ||
"importMapBaseURL": "https://base.example/path1/path2/path3", | ||
"expectedParsedImportMap": { | ||
"imports": { | ||
"dotSlash1": null, | ||
"dotDotSlash1": null, | ||
"dotSlash2": null, | ||
"dotDotSlash2": null, | ||
"slash2": null, | ||
"dotSlash3": null, | ||
"dotDotSlash3": null | ||
}, | ||
"scopes": {} | ||
} | ||
} | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
third_party/blink/web_tests/wpt_internal/import-maps/resources/parsing-invalid-json.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "Invalid JSON", | ||
"importMapBaseURL": "https://base.example/", | ||
"importMap": "{imports: {}}", | ||
"expectedParsedImportMap": null | ||
} |
31 changes: 31 additions & 0 deletions
31
...arty/blink/web_tests/wpt_internal/import-maps/resources/parsing-schema-normalization.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "Normalization", | ||
"importMapBaseURL": "https://base.example/", | ||
"tests": { | ||
"should normalize empty import maps to have imports and scopes keys": { | ||
"importMap": {}, | ||
"expectedParsedImportMap": { | ||
"imports": {}, | ||
"scopes": {} | ||
} | ||
}, | ||
"should normalize an import map without imports to have imports": { | ||
"importMap": { | ||
"scopes": {} | ||
}, | ||
"expectedParsedImportMap": { | ||
"imports": {}, | ||
"scopes": {} | ||
} | ||
}, | ||
"should normalize an import map without scopes to have scopes": { | ||
"importMap": { | ||
"imports": {} | ||
}, | ||
"expectedParsedImportMap": { | ||
"imports": {}, | ||
"scopes": {} | ||
} | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
third_party/blink/web_tests/wpt_internal/import-maps/resources/parsing-schema-scope.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
{ | ||
"name": "Mismatching scopes schema", | ||
"importMapBaseURL": "https://base.example/", | ||
"tests": { | ||
"should throw if a scope's value is not an object": { | ||
"expectedParsedImportMap": null, | ||
"tests": { | ||
"null": { | ||
"importMap": { | ||
"scopes": { | ||
"https://example.com/": null | ||
} | ||
} | ||
}, | ||
"boolean": { | ||
"importMap": { | ||
"scopes": { | ||
"https://example.com/": true | ||
} | ||
} | ||
}, | ||
"number": { | ||
"importMap": { | ||
"scopes": { | ||
"https://example.com/": 1 | ||
} | ||
} | ||
}, | ||
"string": { | ||
"importMap": { | ||
"scopes": { | ||
"https://example.com/": "foo" | ||
} | ||
} | ||
}, | ||
"array": { | ||
"importMap": { | ||
"scopes": { | ||
"https://example.com/": [] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.