-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reference implementation: migrate to JSON-based tests
In order to share common structure with Web Platform Tests, this PR migrates hard-coded Jest tests into JSON test metadata (__tests__/json/*.json, which are shared with https://github.com/web-platform-tests/wpt/tree/master/import-maps/common/resources) and test runners (__tests__/helpers/, which are Jest-specific). In the future we will likely use a script to download the json/ directory and not check it in to this repository, in order to maintain a single source of truth in the web platform tests repository.
- Loading branch information
1 parent
71c80b5
commit 6cb173d
Showing
28 changed files
with
1,486 additions
and
1,095 deletions.
There are no files selected for viewing
129 changes: 129 additions & 0 deletions
129
reference-implementation/__tests__/helpers/common-test-helper.js
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,129 @@ | ||
'use strict'; | ||
const assert = require('assert'); | ||
const { URL } = require('url'); | ||
const { parseFromString } = require('../../lib/parser.js'); | ||
const { resolve } = require('../../lib/resolver.js'); | ||
|
||
function assertNoExtraProperties(object, expectedProperties, description) { | ||
for (const actualProperty in object) { | ||
assert( | ||
expectedProperties.indexOf(actualProperty) !== -1, | ||
description + ': unexpected property ' + actualProperty | ||
); | ||
} | ||
} | ||
|
||
function assertOwnProperty(j, name) { | ||
assert(name in j); | ||
} | ||
|
||
// Parsed import maps in the reference implementation uses `URL`s instead of | ||
// strings as the values of specifier maps, while | ||
// expected import maps (taken from JSONs) uses strings. | ||
// This function converts `m` (expected import maps or its part) | ||
// into URL-based, for comparison. | ||
function replaceStringWithURL(m) { | ||
if (typeof m === 'string') { | ||
return new URL(m); | ||
} | ||
if (m === null || typeof m !== 'object') { | ||
return m; | ||
} | ||
|
||
const result = {}; | ||
for (const key in m) { | ||
result[key] = replaceStringWithURL(m[key]); | ||
} | ||
return result; | ||
} | ||
|
||
function runTests(j) { | ||
const { tests } = j; | ||
delete j.tests; | ||
|
||
if ('importMap' in j) { | ||
assertOwnProperty(j, 'importMap'); | ||
assertOwnProperty(j, 'importMapBaseURL'); | ||
try { | ||
j.parsedImportMap = parseFromString( | ||
JSON.stringify(j.importMap), | ||
new URL(j.importMapBaseURL) | ||
); | ||
} catch (e) { | ||
j.parsedImportMap = e; | ||
} | ||
delete j.importMap; | ||
delete j.importMapBaseURL; | ||
} | ||
|
||
assertNoExtraProperties( | ||
j, | ||
[ | ||
'expectedResults', 'expectedParsedImportMap', | ||
'baseURL', 'name', 'parsedImportMap', | ||
'importMap', 'importMapBaseURL', | ||
'link', 'details' | ||
], | ||
j.name | ||
); | ||
|
||
if (tests) { | ||
// Nested node. | ||
for (const testName in tests) { | ||
let fullTestName = testName; | ||
if (j.name) { | ||
fullTestName = j.name + ': ' + testName; | ||
} | ||
tests[testName].name = fullTestName; | ||
const k = Object.assign(Object.assign({}, j), tests[testName]); | ||
runTests(k); | ||
} | ||
} else { | ||
// Leaf node. | ||
for (const key of ['parsedImportMap', 'name']) { | ||
assertOwnProperty(j, key, j.name); | ||
} | ||
assert( | ||
'expectedResults' in j || | ||
'expectedParsedImportMap' in j, | ||
'expectedResults or expectedParsedImportMap should exist' | ||
); | ||
|
||
// Resolution tests. | ||
if ('expectedResults' in j) { | ||
it(j.name, () => { | ||
assertOwnProperty(j, 'baseURL'); | ||
describe( | ||
'Import map registration should be successful for resolution tests', | ||
() => { | ||
expect(j.parsedImportMap).not.toBeInstanceOf(Error); | ||
} | ||
); | ||
|
||
for (const specifier in j.expectedResults) { | ||
const expected = j.expectedResults[specifier]; | ||
if (expected === null) { | ||
expect(() => resolve(specifier, j.parsedImportMap, new URL(j.baseURL))).toThrow(TypeError); | ||
} else { | ||
// Should be resolved to `expected`. | ||
expect(resolve(specifier, j.parsedImportMap, new URL(j.baseURL))).toMatchURL(expected); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
// Parsing tests. | ||
if ('expectedParsedImportMap' in j) { | ||
it(j.name, () => { | ||
if (j.expectedParsedImportMap === null) { | ||
expect(j.parsedImportMap).toBeInstanceOf(TypeError); | ||
} else { | ||
expect(j.parsedImportMap) | ||
.toEqual(replaceStringWithURL(j.expectedParsedImportMap)); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
|
||
exports.runTests = runTests; |
This file was deleted.
Oops, something went wrong.
17 changes: 17 additions & 0 deletions
17
reference-implementation/__tests__/json/data-base-url.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,17 @@ | ||
{ | ||
"importMap": { | ||
"imports": { | ||
"foo/": "data:text/javascript,foo/" | ||
} | ||
}, | ||
"importMapBaseURL": "https://example.com/app/index.html", | ||
"baseURL": "https://example.com/js/app.mjs", | ||
"name": "data: base URL (?)", | ||
"tests": { | ||
"should favor the most-specific key": { | ||
"expectedResults": { | ||
"foo/bar": null | ||
} | ||
} | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
reference-implementation/__tests__/json/empty-import-map.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,56 @@ | ||
{ | ||
"importMap": {}, | ||
"importMapBaseURL": "https://example.com/app/index.html", | ||
"baseURL": "https://example.com/js/app.mjs", | ||
"tests": { | ||
"valid relative specifiers": { | ||
"expectedResults": { | ||
"./foo": "https://example.com/js/foo", | ||
"./foo/bar": "https://example.com/js/foo/bar", | ||
"./foo/../bar": "https://example.com/js/bar", | ||
"./foo/../../bar": "https://example.com/bar", | ||
"../foo": "https://example.com/foo", | ||
"../foo/bar": "https://example.com/foo/bar", | ||
"../../../foo/bar": "https://example.com/foo/bar", | ||
"/foo": "https://example.com/foo", | ||
"/foo/bar": "https://example.com/foo/bar", | ||
"/../../foo/bar": "https://example.com/foo/bar", | ||
"/../foo/../bar": "https://example.com/bar" | ||
} | ||
}, | ||
"fetch scheme absolute URLs": { | ||
"expectedResults": { | ||
"about:fetch-scheme": "about:fetch-scheme", | ||
"https://fetch-scheme.net": "https://fetch-scheme.net/", | ||
"https:fetch-scheme.org": "https://fetch-scheme.org/", | ||
"https://fetch%2Dscheme.com/": "https://fetch-scheme.com/", | ||
"https://///fetch-scheme.com///": "https://fetch-scheme.com///" | ||
} | ||
}, | ||
"non-fetch scheme absolute URLs": { | ||
"expectedResults": { | ||
"mailto:non-fetch-scheme": "mailto:non-fetch-scheme", | ||
"import:non-fetch-scheme": "import:non-fetch-scheme", | ||
"javascript:non-fetch-scheme": "javascript:non-fetch-scheme", | ||
"wss:non-fetch-scheme": "wss://non-fetch-scheme/" | ||
} | ||
}, | ||
"valid relative URLs that are invalid as specifiers should fail": { | ||
"expectedResults": { | ||
"invalid-specifier": null, | ||
"\\invalid-specifier": null, | ||
":invalid-specifier": null, | ||
"@invalid-specifier": null, | ||
"%2E/invalid-specifier": null, | ||
"%2E%2E/invalid-specifier": null, | ||
".%2Finvalid-specifier": null | ||
} | ||
}, | ||
"invalid absolute URLs should fail": { | ||
"expectedResults": { | ||
"https://invalid-url.com:demo": null, | ||
"http://[invalid-url.com]/": null | ||
} | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
reference-implementation/__tests__/json/overlapping-entries.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,25 @@ | ||
{ | ||
"importMapBaseURL": "https://example.com/app/index.html", | ||
"baseURL": "https://example.com/js/app.mjs", | ||
"name": "should favor the most-specific key", | ||
"tests": { | ||
"Overlapping entries with trailing slashes": { | ||
"importMap": { | ||
"imports": { | ||
"a": "/1", | ||
"a/": "/2/", | ||
"a/b": "/3", | ||
"a/b/": "/4/" | ||
} | ||
}, | ||
"expectedResults": { | ||
"a": "https://example.com/1", | ||
"a/": "https://example.com/2/", | ||
"a/x": "https://example.com/2/x", | ||
"a/b": "https://example.com/3", | ||
"a/b/": "https://example.com/4/", | ||
"a/b/c": "https://example.com/4/c" | ||
} | ||
} | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
reference-implementation/__tests__/json/packages-via-trailing-slashes.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,43 @@ | ||
{ | ||
"importMap": { | ||
"imports": { | ||
"moment": "/node_modules/moment/src/moment.js", | ||
"moment/": "/node_modules/moment/src/", | ||
"lodash-dot": "./node_modules/lodash-es/lodash.js", | ||
"lodash-dot/": "./node_modules/lodash-es/", | ||
"lodash-dotdot": "../node_modules/lodash-es/lodash.js", | ||
"lodash-dotdot/": "../node_modules/lodash-es/" | ||
} | ||
}, | ||
"importMapBaseURL": "https://example.com/app/index.html", | ||
"baseURL": "https://example.com/js/app.mjs", | ||
"name": "Package-like scenarios", | ||
"link": "https://github.com/WICG/import-maps#packages-via-trailing-slashes", | ||
"tests": { | ||
"package main modules": { | ||
"expectedResults": { | ||
"moment": "https://example.com/node_modules/moment/src/moment.js", | ||
"lodash-dot": "https://example.com/app/node_modules/lodash-es/lodash.js", | ||
"lodash-dotdot": "https://example.com/node_modules/lodash-es/lodash.js" | ||
} | ||
}, | ||
"package submodules": { | ||
"expectedResults": { | ||
"moment/foo": "https://example.com/node_modules/moment/src/foo", | ||
"lodash-dot/foo": "https://example.com/app/node_modules/lodash-es/foo", | ||
"lodash-dotdot/foo": "https://example.com/node_modules/lodash-es/foo" | ||
} | ||
}, | ||
"package names that end in a slash should just pass through": { | ||
"expectedResults": { | ||
"moment/": "https://example.com/node_modules/moment/src/" | ||
} | ||
}, | ||
"package modules that are not declared should fail": { | ||
"expectedResults": { | ||
"underscore/": null, | ||
"underscore/foo": null | ||
} | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
reference-implementation/__tests__/json/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,63 @@ | ||
{ | ||
"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": { | ||
"invalidButParseable1": "https://example.org/", | ||
"invalidButParseable2": "https://example.com///", | ||
"prettyNormal": "https://example.net/", | ||
"percentDecoding": "https://example.com/" | ||
}, | ||
"scopes": {} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.