From eb7bfd835862148f7c4757db776e53971611011e Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 17:04:02 -0700 Subject: [PATCH 001/243] Consolidate test generation --- build.js | 336 ++++++++++++++----------------------------------------- 1 file changed, 86 insertions(+), 250 deletions(-) diff --git a/build.js b/build.js index a63441c42..2eadeaf86 100644 --- a/build.js +++ b/build.js @@ -158,69 +158,27 @@ function cssPropertyToIDLAttribute(property, lowercaseFirst) { return output; } -function buildCSSTests(propertyNames, method, basename) { - const lines = []; - - for (const name of propertyNames) { - const ident = `css.properties.${name}`; - const customExpr = getCustomTestCSS(name); - - if (customExpr) { - if (method === 'custom' || method === 'all') { - lines.push(`bcd.addTest("${ident}", "${customExpr}", 'CSS');`); - } - } else { - if (method === 'CSSStyleDeclaration' || method === 'all') { - const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); - lines.push(`bcd.addTest("${ident}", ${JSON.stringify( - {property: attrName, scope: 'document.body.style'} - )}, 'CSS');`); - } - if (method === 'CSS.supports' || method === 'all') { - lines.push(`bcd.addTest("${ident}", ${JSON.stringify( - {property: name, scope: 'CSS.supports'} - )}, 'CSS');`); - } - } - } - - lines.push( - method === 'all' ? - 'bcd.run("CSS", bcd.finishIndividual);' : - 'bcd.run("CSS");' - ); - - const pathname = path.join('css', 'properties', basename); - const filename = path.join(generatedDir, pathname); - writeTestFile(filename, lines); - return pathname; -} - function buildCSS(bcd, webref) { const propertySet = new Set; collectCSSPropertiesFromBCD(bcd, propertySet); collectCSSPropertiesFromReffy(webref, propertySet); - const propertyNames = Array.from(propertySet); - propertyNames.sort(); - - const mainTests = [ - ['http', buildCSSTests(propertyNames, - 'CSSStyleDeclaration', 'in-style.html')], - ['http', buildCSSTests(propertyNames, - 'CSS.supports', 'dot-supports.html')], - ['http', buildCSSTests(propertyNames, - 'custom', 'custom-support-test.html')] - ]; + const tests = []; - const individualItems = []; + for (const name of Array.from(propertySet).sort()) { + const ident = `css.properties.${name}`; + const customExpr = getCustomTestCSS(name); - for (const property of propertyNames) { - buildCSSTests([property], 'all', `${property}/index.html`); - individualItems.push(`css.properties.${property}`); + if (customExpr) { + tests.push(ident, customExpr, "CSS", []); + } else { + const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); + tests.push(ident, {property: attrName, scope: 'document.body.style'}, "CSS", []); + tests.push(ident, {property: name, scope: 'CSS.supports'}, "CSS", []); + } } - return [mainTests, individualItems]; + return tests; } /* istanbul ignore next */ @@ -336,6 +294,80 @@ function getExposureSet(node) { } function buildIDLTests(ast) { + +} + +function allowDuplicates(dfn, member) { + switch (dfn.name) { + // TODO: sort this out spec-side + case 'SVGAElement': + return member.name === 'href'; + // TODO: handle non-conflicting [Exposed] and drop this + case 'WebGLRenderingContext': + case 'WebGL2RenderingContext': + return member.name === 'canvas'; + } + return false; +} + +function validateIDL(ast) { + const ignoreRules = new Set([ + 'constructor-member', + 'dict-arg-default', + 'replace-void', + 'require-exposed' + ]); + + const validations = WebIDL2.validate(ast); + + // Monkey-patching support for https://github.com/w3c/webidl2.js/issues/484 + for (const dfn of ast) { + if (!dfn.members || dfn.members.length == 0) { + continue; + } + const names = new Set(); + for (const member of dfn.members) { + if (!member.name) { + continue; + } + if (member.type === 'operation') { + // Overloading across partials/mixins are checked in mergeMembers. + continue; + } + if (allowDuplicates(dfn, member)) { + continue; + } + if (!names.has(member.name)) { + names.add(member.name); + } else { + validations.push({ + ruleName: 'no-duplicate-member', + // eslint-disable-next-line max-len + message: `Validation error: Duplicate member ${member.name} in ${dfn.type} ${dfn.name}` + }); + } + } + } + + const validationErrors = []; + for (const {ruleName, message} of validations) { + if (ignoreRules.has(ruleName)) { + continue; + } + validationErrors.push(`${message} [${ruleName}]`); + } + + if (validationErrors.length) { + throw new Error(`Validation errors:\n\n${validationErrors.join('\n')}`); + } + + return true; +} + +function buildIDL(_, webref) { + const ast = flattenIDL(webref.idl, collectExtraIDL()); + validateIDL(ast); + const tests = []; const interfaces = ast.filter((dfn) => @@ -493,202 +525,6 @@ function buildIDLTests(ast) { return tests; } -function allowDuplicates(dfn, member) { - switch (dfn.name) { - // TODO: sort this out spec-side - case 'SVGAElement': - return member.name === 'href'; - // TODO: handle non-conflicting [Exposed] and drop this - case 'WebGLRenderingContext': - case 'WebGL2RenderingContext': - return member.name === 'canvas'; - } - return false; -} - -function validateIDL(ast) { - const ignoreRules = new Set([ - 'constructor-member', - 'dict-arg-default', - 'replace-void', - 'require-exposed' - ]); - - const validations = WebIDL2.validate(ast); - - // Monkey-patching support for https://github.com/w3c/webidl2.js/issues/484 - for (const dfn of ast) { - if (!dfn.members || dfn.members.length == 0) { - continue; - } - const names = new Set(); - for (const member of dfn.members) { - if (!member.name) { - continue; - } - if (member.type === 'operation') { - // Overloading across partials/mixins are checked in mergeMembers. - continue; - } - if (allowDuplicates(dfn, member)) { - continue; - } - if (!names.has(member.name)) { - names.add(member.name); - } else { - validations.push({ - ruleName: 'no-duplicate-member', - // eslint-disable-next-line max-len - message: `Validation error: Duplicate member ${member.name} in ${dfn.type} ${dfn.name}` - }); - } - } - } - - const validationErrors = []; - for (const {ruleName, message} of validations) { - if (ignoreRules.has(ruleName)) { - continue; - } - validationErrors.push(`${message} [${ruleName}]`); - } - - if (validationErrors.length) { - throw new Error(`Validation errors:\n\n${validationErrors.join('\n')}`); - } - - return true; -} - -function buildIDLWindow(tests) { - const lines = []; - - for (const [name, expr, exposureSet, memberTests] of tests) { - if (!exposureSet.has('Window')) { - continue; - } - lines.push( - `bcd.addTest('api.${name}', ${JSON.stringify(expr)}, 'Window');` - ); - - for (const [memberName, memberExpr] of memberTests) { - lines.push( - // eslint-disable-next-line max-len - `bcd.addTest('api.${name}.${memberName}', ${JSON.stringify(memberExpr)}, 'Window');` - ); - } - } - - lines.push('bcd.run("Window");'); - const pathname = path.join('api', 'interfaces.html'); - const filename = path.join(generatedDir, pathname); - writeTestFile(filename, lines); - return [['http', pathname], ['https', pathname]]; -} - -function buildIDLWorker(tests) { - const lines = []; - - for (const [name, expr, exposureSet, memberTests] of tests) { - if (!(exposureSet.has('Worker') || exposureSet.has('DedicatedWorker'))) { - continue; - } - lines.push( - `bcd.addTest('api.${name}', ${JSON.stringify(expr)}, 'Worker');` - ); - - for (const [memberName, memberExpr] of memberTests) { - lines.push( - // eslint-disable-next-line max-len - `bcd.addTest('api.${name}.${memberName}', ${JSON.stringify(memberExpr)}, 'Worker');` - ); - } - } - - lines.push('bcd.run("Worker");'); - const pathname = path.join('api', 'workerinterfaces.html'); - const filename = path.join(generatedDir, pathname); - writeTestFile(filename, lines); - return [['http', pathname], ['https', pathname]]; -} - -function buildIDLServiceWorker(tests) { - const lines = []; - - for (const [name, expr, exposureSet, memberTests] of tests) { - if (!exposureSet.has('ServiceWorker')) { - continue; - } - lines.push( - `bcd.addTest('api.${name}', ${JSON.stringify(expr)}, 'ServiceWorker');` - ); - - for (const [memberName, memberExpr] of memberTests) { - lines.push( - // eslint-disable-next-line max-len - `bcd.addTest('api.${name}.${memberName}', ${JSON.stringify(memberExpr)}, 'ServiceWorker');` - ); - } - } - - lines.push('bcd.run("ServiceWorker");'); - const pathname = path.join('api', 'serviceworkerinterfaces.html'); - const filename = path.join(generatedDir, pathname); - writeTestFile(filename, lines); - return [['https', pathname]]; -} - -function buildIDLIndividual(tests) { - const handledIfaces = []; - - for (const [name, expr, exposureSet, memberTests] of tests) { - handledIfaces.push(`api.${name}`); - const lines = []; - - const scope = exposureSet.has('Window') ? 'Window' : - (exposureSet.has('Worker') || exposureSet.has('DedicatedWorker')) ? - 'Worker' : exposureSet.has('ServiceWorker') ? 'ServiceWorker' : null; - - lines.push( - `bcd.addTest('api.${name}', ${JSON.stringify(expr)}, '${scope}');` - ); - - for (const [memberName, memberExpr] of memberTests) { - handledIfaces.push(`api.${name}.${memberName}`); - // eslint-disable-next-line max-len - const test = `bcd.addTest('api.${name}.${memberName}', ${JSON.stringify(memberExpr)}, '${scope}');`; - lines.push(test); - - const pathname = path.join('api', `${name}/${memberName}/index.html`); - const filename = path.join(generatedDir, pathname); - writeTestFile(filename, [ - test, `bcd.run("${scope}", bcd.finishIndividual);` - ]); - } - - lines.push(`bcd.run("${scope}", bcd.finishIndividual);`); - const pathname = path.join('api', `${name}/index.html`); - const filename = path.join(generatedDir, pathname); - writeTestFile(filename, lines); - } - - return handledIfaces; -} - -function buildIDL(_, webref) { - const ast = flattenIDL(webref.idl, collectExtraIDL()); - validateIDL(ast); - const tests = buildIDLTests(ast); - let testpaths = []; - for (const buildFunc of [ - buildIDLWindow, buildIDLWorker, buildIDLServiceWorker - ]) { - testpaths = testpaths.concat(buildFunc(tests)); - } - const handledIfaces = buildIDLIndividual(tests); - return [testpaths, handledIfaces]; -} - async function writeManifest(manifest) { manifest.items.sort((a, b) => { return a.pathname.localeCompare(b.pathname) || From 32323e2129fb7d32f538ec58beb2ad6f5b40a847 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 17:06:22 -0700 Subject: [PATCH 002/243] Swap bcd/webref arguments --- build.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.js b/build.js index 2eadeaf86..2c1e1cf55 100644 --- a/build.js +++ b/build.js @@ -158,7 +158,7 @@ function cssPropertyToIDLAttribute(property, lowercaseFirst) { return output; } -function buildCSS(bcd, webref) { +function buildCSS(webref, bcd) { const propertySet = new Set; collectCSSPropertiesFromBCD(bcd, propertySet); collectCSSPropertiesFromReffy(webref, propertySet); @@ -364,7 +364,7 @@ function validateIDL(ast) { return true; } -function buildIDL(_, webref) { +function buildIDL(webref) { const ast = flattenIDL(webref.idl, collectExtraIDL()); validateIDL(ast); @@ -570,7 +570,7 @@ function copyResources() { }); } -async function build(bcd, webref) { +async function build(webref, bcd) { const manifest = { items: [], individualItems: {} @@ -578,7 +578,7 @@ async function build(bcd, webref) { loadCustomTests(); for (const buildFunc of [buildCSS, buildIDL]) { - const [items, individualItems] = buildFunc(bcd, webref); + const [items, individualItems] = buildFunc(webref, bcd); for (let [protocol, pathname] of items) { if (!pathname.startsWith('/')) { pathname = `/${pathname}`; @@ -599,7 +599,7 @@ async function build(bcd, webref) { if (require.main === module) { const bcd = require('mdn-browser-compat-data'); const webref = require('./webref'); - build(bcd, webref).catch((reason) => { + build(webref, bcd).catch((reason) => { console.error(reason); process.exit(1); }); From 985e5163fc21948934ee88e796fb63a6ff0c06d0 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 17:10:51 -0700 Subject: [PATCH 003/243] Remove loadCustomTests() --- build.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/build.js b/build.js index 2c1e1cf55..e6cb03a05 100644 --- a/build.js +++ b/build.js @@ -18,16 +18,12 @@ const fs = require('fs-extra'); const path = require('path'); const WebIDL2 = require('webidl2'); +const customTests = require('./custom-tests.json'); + const generatedDir = path.join(__dirname, 'generated'); const copyright = ['']; -// Custom tests are defined in custom-tests.json -let customTests = { - 'api': {}, - 'css': {} -}; - function writeText(filename, content) { if (Array.isArray(content)) { content = content.join('\n'); @@ -60,10 +56,6 @@ function writeTestFile(filename, lines) { writeText(filename, content); } -function loadCustomTests(newTests) { - customTests = newTests ? newTests : require('./custom-tests.json'); -} - function getCustomTestAPI(name, member) { let test = false; @@ -576,7 +568,6 @@ async function build(webref, bcd) { individualItems: {} }; - loadCustomTests(); for (const buildFunc of [buildCSS, buildIDL]) { const [items, individualItems] = buildFunc(webref, bcd); for (let [protocol, pathname] of items) { From c038806cde8ac3d35dacb97c026a3d6f71f577e3 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 17:11:12 -0700 Subject: [PATCH 004/243] Remove unused function --- build.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.js b/build.js index e6cb03a05..f0d9c16e1 100644 --- a/build.js +++ b/build.js @@ -285,10 +285,6 @@ function getExposureSet(node) { return globals; } -function buildIDLTests(ast) { - -} - function allowDuplicates(dfn, member) { switch (dfn.name) { // TODO: sort this out spec-side From 3e59f03a6a31c4d75490de9d755291b5fe760c50 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 17:11:27 -0700 Subject: [PATCH 005/243] Move interface member loading to flattenMembers() --- build.js | 107 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/build.js b/build.js index f0d9c16e1..13cd6f814 100644 --- a/build.js +++ b/build.js @@ -256,6 +256,60 @@ function flattenIDL(specIDLs, collectExtraIDL) { return ast; } +function flattenMembers(iface) { + const members = iface.members.filter((member) => member.name); + for (const member of iface.members.filter((member) => !member.name)) { + switch (member.type) { + case 'constructor': + members.push({name: iface.name, type: 'constructor'}); + break; + case 'iterable': + members.push( + {name: 'entries', type: 'operation'}, + {name: 'keys', type: 'operation'}, + {name: 'values', type: 'operation'}, + {name: 'forEach', type: 'operation'}, + {name: '@@iterator', type: 'symbol'} + ); + break; + case 'maplike': + members.push( + {name: 'size', type: 'operation'}, + {name: 'entries', type: 'operation'}, + {name: 'keys', type: 'operation'}, + {name: 'values', type: 'operation'}, + {name: 'get', type: 'operation'}, + {name: 'has', type: 'operation'}, + {name: 'clear', type: 'operation'}, + {name: 'delete', type: 'operation'}, + {name: 'set', type: 'operation'}, + {name: 'forEach', type: 'operation'} + ); + break; + case 'setlike': + members.push( + {name: 'size', type: 'operation'}, + {name: 'entries', type: 'operation'}, + {name: 'values', type: 'operation'}, + {name: 'keys', type: 'operation'}, + {name: 'has', type: 'operation'}, + {name: 'add', type: 'operation'}, + {name: 'delete', type: 'operation'}, + {name: 'clear', type: 'operation'} + ); + break; + case 'operation': + // We don't care about setter/getter functions + break; + } + } + if (getExtAttr(iface, 'Constructor')) { + members.push({name: iface.name, type: 'constructor'}); + } + + return members.sort((a, b) => a.name.localeCompare(b.name)); +} + function getExtAttr(node, name) { return node.extAttrs && node.extAttrs.find((i) => i.name === name); } @@ -376,60 +430,9 @@ function buildIDL(webref) { const exposureSet = getExposureSet(iface); const isGlobal = !!getExtAttr(iface, 'Global'); const customIfaceTest = getCustomTestAPI(iface.name); + const members = flattenMembers(iface); const memberTests = []; - // members - const members = iface.members.filter((member) => member.name); - for (const member of iface.members.filter((member) => !member.name)) { - switch (member.type) { - case 'constructor': - members.push({name: iface.name, type: 'constructor'}); - break; - case 'iterable': - members.push( - {name: 'entries', type: 'operation'}, - {name: 'keys', type: 'operation'}, - {name: 'values', type: 'operation'}, - {name: 'forEach', type: 'operation'}, - {name: '@@iterator', type: 'symbol'} - ); - break; - case 'maplike': - members.push( - {name: 'size', type: 'operation'}, - {name: 'entries', type: 'operation'}, - {name: 'keys', type: 'operation'}, - {name: 'values', type: 'operation'}, - {name: 'get', type: 'operation'}, - {name: 'has', type: 'operation'}, - {name: 'clear', type: 'operation'}, - {name: 'delete', type: 'operation'}, - {name: 'set', type: 'operation'}, - {name: 'forEach', type: 'operation'} - ); - break; - case 'setlike': - members.push( - {name: 'size', type: 'operation'}, - {name: 'entries', type: 'operation'}, - {name: 'values', type: 'operation'}, - {name: 'keys', type: 'operation'}, - {name: 'has', type: 'operation'}, - {name: 'add', type: 'operation'}, - {name: 'delete', type: 'operation'}, - {name: 'clear', type: 'operation'} - ); - break; - case 'operation': - // We don't care about setter/getter functions - break; - } - } - if (getExtAttr(iface, 'Constructor')) { - members.push({name: iface.name, type: 'constructor'}); - } - members.sort((a, b) => a.name.localeCompare(b.name)); - // Avoid generating duplicate tests for operations. const handledMemberNames = new Set(); From 2c0f8e73fd2e7511e85991b73c26afaf0d41d587 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 17:50:11 -0700 Subject: [PATCH 006/243] Move all imports to top --- build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.js b/build.js index 13cd6f814..9dd6af6f7 100644 --- a/build.js +++ b/build.js @@ -17,8 +17,10 @@ const fs = require('fs-extra'); const path = require('path'); const WebIDL2 = require('webidl2'); +const bcd = require('mdn-browser-compat-data'); const customTests = require('./custom-tests.json'); +const webref = require('./webref'); const generatedDir = path.join(__dirname, 'generated'); @@ -587,8 +589,6 @@ async function build(webref, bcd) { /* istanbul ignore if */ if (require.main === module) { - const bcd = require('mdn-browser-compat-data'); - const webref = require('./webref'); build(webref, bcd).catch((reason) => { console.error(reason); process.exit(1); From 9a54b73de2f8586d7b30ce6d9ca3f6e9a8a4a86b Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 17:55:56 -0700 Subject: [PATCH 007/243] Rewrite manifest to be a list of all tests --- build.js | 64 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/build.js b/build.js index 9dd6af6f7..0a8ebf5c7 100644 --- a/build.js +++ b/build.js @@ -157,19 +157,17 @@ function buildCSS(webref, bcd) { collectCSSPropertiesFromBCD(bcd, propertySet); collectCSSPropertiesFromReffy(webref, propertySet); - const tests = []; + const tests = {}; for (const name of Array.from(propertySet).sort()) { - const ident = `css.properties.${name}`; - const customExpr = getCustomTestCSS(name); - - if (customExpr) { - tests.push(ident, customExpr, "CSS", []); - } else { - const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); - tests.push(ident, {property: attrName, scope: 'document.body.style'}, "CSS", []); - tests.push(ident, {property: name, scope: 'CSS.supports'}, "CSS", []); - } + const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); + tests[`css.properties.${name}`] = { + "test": getCustomTestCSS(name) || [ + {property: attrName, scope: 'document.body.style'}, + {property: name, scope: 'CSS.supports'} + ], + "scope": "CSS" + }; } return tests; @@ -412,7 +410,7 @@ function buildIDL(webref) { const ast = flattenIDL(webref.idl, collectExtraIDL()); validateIDL(ast); - const tests = []; + const tests = {}; const interfaces = ast.filter((dfn) => dfn.type === 'interface' || @@ -432,6 +430,12 @@ function buildIDL(webref) { const exposureSet = getExposureSet(iface); const isGlobal = !!getExtAttr(iface, 'Global'); const customIfaceTest = getCustomTestAPI(iface.name); + + tests[`api.${iface.name}`] = { + "test": customIfaceTest || {property: iface.name, scope: 'self'}, + "scope": Array.from(exposureSet) + }; + const members = flattenMembers(iface); const memberTests = []; @@ -503,26 +507,18 @@ function buildIDL(webref) { } } - memberTests.push([`${member.name}`, expr]); + tests[`api.${iface.name}.${member.name}`] = { + "test": expr, + "scope": Array.from(exposureSet) + }; handledMemberNames.add(member.name); } - - tests.push([ - iface.name, - customIfaceTest || {property: iface.name, scope: 'self'}, - exposureSet, - memberTests - ]); } return tests; } async function writeManifest(manifest) { - manifest.items.sort((a, b) => { - return a.pathname.localeCompare(b.pathname) || - a.protocol.localeCompare(b.protocol); - }); writeText('MANIFEST.json', JSON.stringify(manifest, null, ' ')); } @@ -565,12 +561,21 @@ function copyResources() { async function build(webref, bcd) { const manifest = { - items: [], - individualItems: {} + tests: {}, + endpoints: { + main: {}, + individual: {} + } }; - for (const buildFunc of [buildCSS, buildIDL]) { - const [items, individualItems] = buildFunc(webref, bcd); + for (const buildFunc of [buildIDL, buildCSS]) { + const tests = buildFunc(webref, bcd); + manifest.tests = Object.assign(manifest.tests, tests); + for (const [test] in Object.entries(tests)) { + console.log(test); + } + + continue; // XXX convert code below for (let [protocol, pathname] of items) { if (!pathname.startsWith('/')) { pathname = `/${pathname}`; @@ -583,6 +588,7 @@ async function build(webref, bcd) { } } } + await writeManifest(manifest); copyResources(); } @@ -604,7 +610,7 @@ if (require.main === module) { cssPropertyToIDLAttribute, flattenIDL, getExposureSet, - buildIDLTests, + buildIDL, validateIDL }; } From 0e69a78974d0803cb2d55ef384352d4591e7f10e Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 18:38:24 -0700 Subject: [PATCH 008/243] Add "combinator" to tests --- build.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build.js b/build.js index 0a8ebf5c7..6d4ab149c 100644 --- a/build.js +++ b/build.js @@ -166,6 +166,7 @@ function buildCSS(webref, bcd) { {property: attrName, scope: 'document.body.style'}, {property: name, scope: 'CSS.supports'} ], + "combinator": "or", "scope": "CSS" }; } @@ -433,6 +434,7 @@ function buildIDL(webref) { tests[`api.${iface.name}`] = { "test": customIfaceTest || {property: iface.name, scope: 'self'}, + "combinator": "and", "scope": Array.from(exposureSet) }; @@ -509,6 +511,7 @@ function buildIDL(webref) { tests[`api.${iface.name}.${member.name}`] = { "test": expr, + "combinator": "and", "scope": Array.from(exposureSet) }; handledMemberNames.add(member.name); @@ -571,8 +574,8 @@ async function build(webref, bcd) { for (const buildFunc of [buildIDL, buildCSS]) { const tests = buildFunc(webref, bcd); manifest.tests = Object.assign(manifest.tests, tests); - for (const [test] in Object.entries(tests)) { - console.log(test); + for (const [ident, test] of Object.entries(tests)) { + console.log(ident, test); } continue; // XXX convert code below From ad38d4f84bbe183b60675fccfd1baef0e42cf50b Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 18:59:57 -0700 Subject: [PATCH 009/243] Hook up test endpoints --- build.js | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/build.js b/build.js index 6d4ab149c..67b8fcb59 100644 --- a/build.js +++ b/build.js @@ -575,19 +575,38 @@ async function build(webref, bcd) { const tests = buildFunc(webref, bcd); manifest.tests = Object.assign(manifest.tests, tests); for (const [ident, test] of Object.entries(tests)) { - console.log(ident, test); - } + const scopes = Array.isArray(test.scope) ? test.scope : [test.scope]; + for (const scope of scopes) { + let endpoint = ''; + switch (scope) { + case 'Window': + endpoint = '/api/interfaces'; + break; + case 'Worker': + endpoint = '/api/workerinterfaces'; + break; + case 'ServiceWorker': + endpoint = '/api/serviceworkerinterfaces'; + break; + case 'CSS': + endpoint = '/css/properties'; + break; + } - continue; // XXX convert code below - for (let [protocol, pathname] of items) { - if (!pathname.startsWith('/')) { - pathname = `/${pathname}`; + if (!(endpoint in manifest.endpoints.main)) { + manifest.endpoints.main[endpoint] = []; + } + manifest.endpoints.main[endpoint].push(ident); } - manifest.items.push({pathname, protocol}); - } - if (individualItems) { - for (const item of individualItems) { - manifest.individualItems[item] = item.replace(/\./g, '/'); + + let url = ''; + for (const part of ident.split('.')) { + url += '/' + part; + + if (!(url in manifest.endpoints.individual)) { + manifest.endpoints.individual[url] = []; + } + manifest.endpoints.individual[url].push(ident); } } } From f30041df5f9d2b2f7f968172420b1975df76933c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 19:05:51 -0700 Subject: [PATCH 010/243] Cleanup code --- build.js | 45 +++++++++------------------------------------ 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/build.js b/build.js index 67b8fcb59..6524beb2d 100644 --- a/build.js +++ b/build.js @@ -24,8 +24,6 @@ const webref = require('./webref'); const generatedDir = path.join(__dirname, 'generated'); -const copyright = ['']; - function writeText(filename, content) { if (Array.isArray(content)) { content = content.join('\n'); @@ -35,29 +33,6 @@ function writeText(filename, content) { fs.writeFileSync(filename, content, 'utf8'); } -function writeTestFile(filename, lines) { - const content = [ - '', - '', - '', - ...copyright, - '', - '', - '', - '', - '', - '', - '

Running tests...

', - '', - '', - '' - ]; - - writeText(filename, content); -} - function getCustomTestAPI(name, member) { let test = false; @@ -162,12 +137,12 @@ function buildCSS(webref, bcd) { for (const name of Array.from(propertySet).sort()) { const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); tests[`css.properties.${name}`] = { - "test": getCustomTestCSS(name) || [ + 'test': getCustomTestCSS(name) || [ {property: attrName, scope: 'document.body.style'}, {property: name, scope: 'CSS.supports'} ], - "combinator": "or", - "scope": "CSS" + 'combinator': 'or', + 'scope': 'CSS' }; } @@ -433,13 +408,12 @@ function buildIDL(webref) { const customIfaceTest = getCustomTestAPI(iface.name); tests[`api.${iface.name}`] = { - "test": customIfaceTest || {property: iface.name, scope: 'self'}, - "combinator": "and", - "scope": Array.from(exposureSet) + 'test': customIfaceTest || {property: iface.name, scope: 'self'}, + 'combinator': 'and', + 'scope': Array.from(exposureSet) }; const members = flattenMembers(iface); - const memberTests = []; // Avoid generating duplicate tests for operations. const handledMemberNames = new Set(); @@ -510,9 +484,9 @@ function buildIDL(webref) { } tests[`api.${iface.name}.${member.name}`] = { - "test": expr, - "combinator": "and", - "scope": Array.from(exposureSet) + 'test': expr, + 'combinator': 'and', + 'scope': Array.from(exposureSet) }; handledMemberNames.add(member.name); } @@ -624,7 +598,6 @@ if (require.main === module) { } else { module.exports = { writeText, - loadCustomTests, getCustomTestAPI, getCustomTestCSS, collectCSSPropertiesFromBCD, From 6397cbae28cb148d6e758a93edbde72affbe51ff Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 19:23:06 -0700 Subject: [PATCH 011/243] Update ESLint's max-len rule to ignore strings and string-like objects --- .eslintrc.json | 11 ++++++++++- build.js | 5 ----- test/selenium/selenium.js | 1 - test/unit/build.js | 13 ------------- test/unit/github.js | 2 -- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index b28e78223..e05271cd1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -8,7 +8,16 @@ "rules": { "comma-dangle": ["error", "never"], "require-jsdoc": "off", - "no-unused-vars": ["error", {"varsIgnorePattern": "^_$"}] + "no-unused-vars": ["error", {"varsIgnorePattern": "^_$"}], + "max-len": ["error", { + "code": 80, + "tabWidth": 2, + "ignoreStrings": true, + "ignoreTemplateLiterals": true, + "ignoreRegExpLiterals": true, + "ignoreUrls": true, + "ignorePattern": "goog.(module|require)" + }] }, "env": { "es6": true, diff --git a/build.js b/build.js index 6524beb2d..b7f3c097f 100644 --- a/build.js +++ b/build.js @@ -165,7 +165,6 @@ function mergeMembers(target, source) { } for (const {type, name} of source.members) { if (type === 'operation' && targetOperations.has(name)) { - // eslint-disable-next-line max-len throw new Error(`Operation overloading across partials/mixins for ${target.name}.${name}`); } } @@ -192,7 +191,6 @@ function flattenIDL(specIDLs, collectExtraIDL) { it.type === dfn.type && it.name === dfn.name); if (!target) { - // eslint-disable-next-line max-len throw new Error(`Original definition not found for partial ${dfn.type} ${dfn.name}`); } @@ -209,14 +207,12 @@ function flattenIDL(specIDLs, collectExtraIDL) { it.type === 'interface mixin' && it.name === dfn.includes); if (!mixin) { - // eslint-disable-next-line max-len throw new Error(`Interface mixin ${dfn.includes} not found for target ${dfn.target}`); } const target = ast.find((it) => !it.partial && it.type === 'interface' && it.name === dfn.target); if (!target) { - // eslint-disable-next-line max-len throw new Error(`Target ${dfn.target} not found for interface mixin ${dfn.includes}`); } @@ -360,7 +356,6 @@ function validateIDL(ast) { } else { validations.push({ ruleName: 'no-duplicate-member', - // eslint-disable-next-line max-len message: `Validation error: Duplicate member ${member.name} in ${dfn.type} ${dfn.name}` }); } diff --git a/test/selenium/selenium.js b/test/selenium/selenium.js index dbac186d7..df8346f53 100644 --- a/test/selenium/selenium.js +++ b/test/selenium/selenium.js @@ -61,7 +61,6 @@ const seleniumUrl = secrets.selenium.url && secrets.selenium.url .replace('$ACCESSKEY$', secrets.selenium.accesskey); if (!seleniumUrl) { - // eslint-disable-next-line max-len console.error('A Selenium remote WebDriver URL is not defined in secrets.json. Please define your Selenium remote.'); process.exit(1); } diff --git a/test/unit/build.js b/test/unit/build.js index 84b8aef41..9c7f5fa3e 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -423,7 +423,6 @@ describe('build', () => { expect(() => { flattenIDL(specIDLs, historicalIDL); - // eslint-disable-next-line max-len }).to.throw('Target DummyError not found for interface mixin DummyErrorHelper'); }); @@ -437,7 +436,6 @@ describe('build', () => { expect(() => { flattenIDL(specIDLs, historicalIDL); - // eslint-disable-next-line max-len }).to.throw('Interface mixin DummyErrorHelper not found for target DummyError'); }); @@ -455,7 +453,6 @@ describe('build', () => { }; expect(() => { flattenIDL(specIDLs, historicalIDL); - // eslint-disable-next-line max-len }).to.throw('Operation overloading across partials/mixins for CSS.supports'); }); @@ -591,21 +588,16 @@ describe('build', () => { loadCustomTests({ 'api': { 'ANGLE_instanced_arrays': { - // eslint-disable-next-line max-len '__base': 'var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');', '__test': 'return !!instance;', - // eslint-disable-next-line max-len 'drawArraysInstancedANGLE': 'return instance && \'drawArraysInstancedANGLE\' in instance;' } }, 'css': {} }); assert.deepEqual(buildIDLTests(ast), [ - // eslint-disable-next-line max-len ['ANGLE_instanced_arrays', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', new Set(['Window']), [ - // eslint-disable-next-line max-len ['drawArraysInstancedANGLE', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawArraysInstancedANGLE\' in instance;})()'], - // eslint-disable-next-line max-len ['drawElementsInstancedANGLE', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()'] ] ]]); @@ -1189,13 +1181,11 @@ describe('build', () => { 'css': {} }); assert.deepEqual(buildIDLTests(ast), [ - // eslint-disable-next-line max-len [ 'CSS', '(function() {var css = CSS;return !!css;})()', new Set(['Window']), [ - // eslint-disable-next-line max-len ['paintWorklet', '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()'] ] ] @@ -1245,11 +1235,8 @@ describe('build', () => { 'css': {} }); assert.deepEqual(buildIDLTests(ast), [ - // eslint-disable-next-line max-len ['ElementRegistrationOptions', '(function() {var ers = ElementRegistrationOptions;return !!ers;})()', new Set(['Window']), [ - // eslint-disable-next-line max-len ['extends', '(function() {var ers = ElementRegistrationOptions;return ers && \'extends\' in ers;})()'], - // eslint-disable-next-line max-len ['prototype', '(function() {var ers = ElementRegistrationOptions;return ers && \'prototype\' in ers;})()'] ] ]]); diff --git a/test/unit/github.js b/test/unit/github.js index 830b8a241..da9ed8731 100644 --- a/test/unit/github.js +++ b/test/unit/github.js @@ -23,7 +23,6 @@ const appversion = require('../../package.json').version; const REPORT = { results: {}, - // eslint-disable-next-line max-len userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15' }; @@ -57,7 +56,6 @@ describe('GitHub export', () => { mock.git.expects('createRef').once().withArgs({ owner: 'foolip', - // eslint-disable-next-line max-len ref: `refs/heads/collector/${appversion}-safari-12.0-mac-os-10.14-afd516a15d`, repo: 'mdn-bcd-results', sha: '753c6ed8e991e9729353a63d650ff0f5bd902b69' From b7c525f36957460f4c80bf49be862d309dae489f Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 19:55:31 -0700 Subject: [PATCH 012/243] Remove unreachable code --- build.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.js b/build.js index b7f3c097f..115c8c37b 100644 --- a/build.js +++ b/build.js @@ -53,10 +53,6 @@ function getCustomTestAPI(name, member) { false; } } - } else { - if (name in customTests.api && member in customTests.api[name]) { - test = customTests.api[name][member]; - } } if (test) { From 1c4b31c161487f68b8260fa8c92e9386d7689485 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 19:56:00 -0700 Subject: [PATCH 013/243] Separate buildIDL and buildIDLTests --- build.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/build.js b/build.js index 115c8c37b..5da38ae1f 100644 --- a/build.js +++ b/build.js @@ -373,10 +373,7 @@ function validateIDL(ast) { return true; } -function buildIDL(webref) { - const ast = flattenIDL(webref.idl, collectExtraIDL()); - validateIDL(ast); - +function buildIDLTests(ast) { const tests = {}; const interfaces = ast.filter((dfn) => @@ -486,6 +483,12 @@ function buildIDL(webref) { return tests; } +function buildIDL(webref) { + const ast = flattenIDL(webref.idl, collectExtraIDL()); + validateIDL(ast); + return buildIDLTests(ast); +} + async function writeManifest(manifest) { writeText('MANIFEST.json', JSON.stringify(manifest, null, ' ')); } @@ -596,7 +599,7 @@ if (require.main === module) { cssPropertyToIDLAttribute, flattenIDL, getExposureSet, - buildIDL, + buildIDLTests, validateIDL }; } From f96bf896373c0951a54ae74640fea019b2d46c20 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 19:56:27 -0700 Subject: [PATCH 014/243] Update tests for build.js --- test/unit/build.js | 1117 ++++++++++++++++++++------------------------ 1 file changed, 515 insertions(+), 602 deletions(-) diff --git a/test/unit/build.js b/test/unit/build.js index 9c7f5fa3e..fdf25a5a7 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -22,13 +22,12 @@ const assert = chai.assert; const expect = chai.expect; const WebIDL2 = require('webidl2'); +const proxyquire = require('proxyquire'); + const fs = require('fs'); const { writeText, - loadCustomTests, - getCustomTestAPI, - getCustomTestCSS, collectCSSPropertiesFromBCD, collectCSSPropertiesFromReffy, cssPropertyToIDLAttribute, @@ -36,7 +35,9 @@ const { getExposureSet, buildIDLTests, validateIDL -} = require('../../build'); +} = proxyquire('../../build', { + './custom-tests.json': {'api': {}, 'css': {}} +}); describe('build', () => { describe('writeText', () => { @@ -59,8 +60,8 @@ describe('build', () => { describe('getCustomTestAPI', () => { describe('no custom tests', () => { - beforeEach(() => { - loadCustomTests({api: {}, css: {}}); + const {getCustomTestAPI} = proxyquire('../../build', { + './custom-tests.json': {api: {}, css: {}} }); it('interface', () => { @@ -73,16 +74,15 @@ describe('build', () => { }); describe('custom test for interface only', () => { - beforeEach(() => { - loadCustomTests({ + const {getCustomTestAPI} = proxyquire('../../build', { + './custom-tests.json': { api: { 'foo': { '__base': 'var a = 1;', '__test': 'return a;' } - }, - css: {} - }); + } + } }); it('interface', () => { @@ -101,15 +101,14 @@ describe('build', () => { }); describe('custom test for interface only, no base', () => { - beforeEach(() => { - loadCustomTests({ + const {getCustomTestAPI} = proxyquire('../../build', { + './custom-tests.json': { api: { 'foo': { '__test': 'return 1;' } - }, - css: {} - }); + } + } }); it('interface', () => { @@ -122,16 +121,15 @@ describe('build', () => { }); describe('custom test for member only', () => { - beforeEach(() => { - loadCustomTests({ + const {getCustomTestAPI} = proxyquire('../../build', { + './custom-tests.json': { api: { 'foo': { '__base': 'var a = 1;', 'bar': 'return a + 1;' } - }, - css: {} - }); + } + } }); it('interface', () => { @@ -150,15 +148,14 @@ describe('build', () => { }); describe('custom test for member only, no __base', () => { - beforeEach(() => { - loadCustomTests({ + const {getCustomTestAPI} = proxyquire('../../build', { + './custom-tests.json': { api: { 'foo': { 'bar': 'return 1 + 1;' } - }, - css: {} - }); + } + } }); it('interface', () => { @@ -174,17 +171,16 @@ describe('build', () => { }); describe('custom test for interface and member', () => { - beforeEach(() => { - loadCustomTests({ + const {getCustomTestAPI} = proxyquire('../../build', { + './custom-tests.json': { api: { 'foo': { '__base': 'var a = 1;', '__test': 'return a;', 'bar': 'return a + 1;' } - }, - css: {} - }); + } + } }); it('interface', () => { @@ -205,16 +201,20 @@ describe('build', () => { describe('getCustomTestCSS', () => { it('no custom tests', () => { - loadCustomTests({api: {}, css: {}}); + const {getCustomTestCSS} = proxyquire('../../build', { + './custom-tests.json': {api: {}, css: {}} + }); + assert.equal(getCustomTestCSS('foo'), false); }); it('custom test for property', () => { - loadCustomTests({ - api: {}, - css: { - properties: { - foo: 'return 1;' + const {getCustomTestCSS} = proxyquire('../../build', { + './custom-tests.json': { + css: { + properties: { + foo: 'return 1;' + } } } }); @@ -512,14 +512,21 @@ describe('build', () => { describe('buildIDLTests', () => { it('interface with attribute', () => { const ast = WebIDL2.parse(`interface Attr { attribute any name; };`); - assert.deepEqual(buildIDLTests(ast), [ - ['Attr', {property: 'Attr', scope: 'self'}, new Set(['Window']), [ - ['name', [ + assert.deepEqual(buildIDLTests(ast), { + 'api.Attr': { + 'test': {property: 'Attr', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.Attr.name': { + 'test': [ {property: 'Attr', scope: 'self'}, {property: 'name', scope: 'Attr.prototype'} - ]] - ] - ]]); + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('interface with method', () => { @@ -527,14 +534,21 @@ describe('build', () => { `interface Node { boolean contains(Node? other); };`); - assert.deepEqual(buildIDLTests(ast), [ - ['Node', {property: 'Node', scope: 'self'}, new Set(['Window']), [ - ['contains', [ + assert.deepEqual(buildIDLTests(ast), { + 'api.Node': { + 'test': {property: 'Node', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.Node.contains': { + 'test': [ {property: 'Node', scope: 'self'}, {property: 'contains', scope: 'Node.prototype'} - ]] - ] - ]]); + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('interface with static method', () => { @@ -542,15 +556,22 @@ describe('build', () => { `interface MediaSource { static boolean isTypeSupported(DOMString type); };`); - assert.deepEqual(buildIDLTests(ast), [ - ['MediaSource', {property: 'MediaSource', scope: 'self'}, - new Set(['Window']), [ - ['isTypeSupported', [ - {property: 'MediaSource', scope: 'self'}, - {property: 'isTypeSupported', scope: 'MediaSource'} - ]] - ] - ]]); + + assert.deepEqual(buildIDLTests(ast), { + 'api.MediaSource': { + 'test': {property: 'MediaSource', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.MediaSource.isTypeSupported': { + 'test': [ + {property: 'MediaSource', scope: 'self'}, + {property: 'isTypeSupported', scope: 'MediaSource'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('interface with const', () => { @@ -558,14 +579,22 @@ describe('build', () => { `interface Window { const boolean isWindow = true; };`); - assert.deepEqual(buildIDLTests(ast), [ - ['Window', {property: 'Window', scope: 'self'}, new Set(['Window']), [ - ['isWindow', [ + + assert.deepEqual(buildIDLTests(ast), { + 'api.Window': { + 'test': {property: 'Window', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.Window.isWindow': { + 'test': [ {property: 'Window', scope: 'self'}, {property: 'isWindow', scope: 'Window'} - ]] - ] - ]]); + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('interface with custom test', () => { @@ -585,27 +614,40 @@ describe('build', () => { GLsizei primcoun ); };`); - loadCustomTests({ - 'api': { - 'ANGLE_instanced_arrays': { - '__base': 'var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');', - '__test': 'return !!instance;', - 'drawArraysInstancedANGLE': 'return instance && \'drawArraysInstancedANGLE\' in instance;' + const {buildIDLTests} = proxyquire('../../build', { + './custom-tests.json': { + 'api': { + 'ANGLE_instanced_arrays': { + '__base': 'var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');', + '__test': 'return !!instance;', + 'drawArraysInstancedANGLE': 'return true && instance && \'drawArraysInstancedANGLE\' in instance;' + } } + } + }); + + assert.deepEqual(buildIDLTests(ast), { + 'api.ANGLE_instanced_arrays': { + 'test': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', + 'combinator': 'and', + 'scope': ['Window'] }, - 'css': {} + 'api.ANGLE_instanced_arrays.drawArraysInstancedANGLE': { + 'test': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return true && instance && \'drawArraysInstancedANGLE\' in instance;})()', + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.ANGLE_instanced_arrays.drawElementsInstancedANGLE': { + 'test': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()', + 'combinator': 'and', + 'scope': ['Window'] + } }); - assert.deepEqual(buildIDLTests(ast), [ - ['ANGLE_instanced_arrays', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', new Set(['Window']), [ - ['drawArraysInstancedANGLE', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawArraysInstancedANGLE\' in instance;})()'], - ['drawElementsInstancedANGLE', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()'] - ] - ]]); }); it('interface with legacy namespace', () => { const ast = WebIDL2.parse(`[LegacyNamespace] interface Legacy {};`); - assert.deepEqual(buildIDLTests(ast), []); + assert.deepEqual(buildIDLTests(ast), {}); }); it('global interface', () => { @@ -614,454 +656,291 @@ describe('build', () => { attribute boolean isLoaded; const boolean active = true; };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'WindowOrWorkerGlobalScope', - { - 'property': 'WindowOrWorkerGlobalScope', - 'scope': 'self' - }, - new Set(['Window']), - [ - [ - 'active', - { - 'property': 'active', - 'scope': 'self' - } - ], - [ - 'isLoaded', - { - 'property': 'isLoaded', - 'scope': 'self' - } - ] - ] - ] - ]); + + assert.deepEqual(buildIDLTests(ast), { + 'api.WindowOrWorkerGlobalScope': { + 'test': {property: 'WindowOrWorkerGlobalScope', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.WindowOrWorkerGlobalScope.active': { + 'test': {property: 'active', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.WindowOrWorkerGlobalScope.isLoaded': { + 'test': {property: 'isLoaded', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('interface with constructor operation', () => { const ast = WebIDL2.parse(`interface Number { constructor(optional any value); };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'Number', - { - 'property': 'Number', - 'scope': 'self' - }, - new Set(['Window']), - [ - [ - 'Number', - [ - { - 'property': 'Number', - 'scope': 'self' - }, - { - 'property': 'constructor', - 'scope': 'Number' - } - ] - ] - ] - ] - ]); + + assert.deepEqual(buildIDLTests(ast), { + 'api.Number': { + 'test': {property: 'Number', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.Number.Number': { + 'test': [ + {property: 'Number', scope: 'self'}, + {property: 'constructor', scope: 'Number'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('interface with constructor in ExtAttr', () => { const ast = WebIDL2.parse(`[Constructor(optional any value)] interface Number {};`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'Number', - { - 'property': 'Number', - 'scope': 'self' - }, - new Set(['Window']), - [ - [ - 'Number', - [ - { - 'property': 'Number', - 'scope': 'self' - }, - { - 'property': 'constructor', - 'scope': 'Number' - } - ] - ] - ] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.Number': { + 'test': {property: 'Number', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.Number.Number': { + 'test': [ + {property: 'Number', scope: 'self'}, + {property: 'constructor', scope: 'Number'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('iterable interface', () => { const ast = WebIDL2.parse(`interface DoubleList { iterable; };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'DoubleList', - { - 'property': 'DoubleList', - 'scope': 'self' - }, - new Set(['Window']), - [ - [ - '@@iterator', - [ - { - 'property': 'DoubleList', - 'scope': 'self' - }, - { - 'property': 'Symbol', - 'scope': 'self' - }, - { - 'property': 'iterator', - 'scope': 'Symbol' - }, - { - 'property': 'Symbol.iterator', - 'scope': 'DoubleList.prototype' - } - ] - ], - [ - 'entries', - [ - { - 'property': 'DoubleList', - 'scope': 'self' - }, - { - 'property': 'entries', - 'scope': 'DoubleList.prototype' - } - ] - ], - [ - 'forEach', - [ - { - 'property': 'DoubleList', - 'scope': 'self' - }, - { - 'property': 'forEach', - 'scope': 'DoubleList.prototype' - } - ] - ], - [ - 'keys', - [ - { - 'property': 'DoubleList', - 'scope': 'self' - }, - { - 'property': 'keys', - 'scope': 'DoubleList.prototype' - } - ] - ], - [ - 'values', - [ - { - 'property': 'DoubleList', - 'scope': 'self' - }, - { - 'property': 'values', - 'scope': 'DoubleList.prototype' - } - ] - ] - ] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.DoubleList': { + 'test': {property: 'DoubleList', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleList.@@iterator': { + 'test': [ + {'property': 'DoubleList', 'scope': 'self'}, + {'property': 'Symbol', 'scope': 'self'}, + {'property': 'iterator', 'scope': 'Symbol'}, + {'property': 'Symbol.iterator', 'scope': 'DoubleList.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleList.entries': { + 'test': [ + {'property': 'DoubleList', 'scope': 'self'}, + {'property': 'entries', 'scope': 'DoubleList.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleList.forEach': { + 'test': [ + {'property': 'DoubleList', 'scope': 'self'}, + {'property': 'forEach', 'scope': 'DoubleList.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleList.keys': { + 'test': [ + {'property': 'DoubleList', 'scope': 'self'}, + {'property': 'keys', 'scope': 'DoubleList.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleList.values': { + 'test': [ + {'property': 'DoubleList', 'scope': 'self'}, + {'property': 'values', 'scope': 'DoubleList.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('maplike interface', () => { const ast = WebIDL2.parse(`interface DoubleMap { maplike; };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'DoubleMap', - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - new Set(['Window']), - [ - [ - 'clear', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'clear', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'delete', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'delete', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'entries', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'entries', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'forEach', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'forEach', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'get', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'get', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'has', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'has', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'keys', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'keys', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'set', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'set', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'size', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'size', - 'scope': 'DoubleMap.prototype' - } - ] - ], - [ - 'values', - [ - { - 'property': 'DoubleMap', - 'scope': 'self' - }, - { - 'property': 'values', - 'scope': 'DoubleMap.prototype' - } - ] - ] - ] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.DoubleMap': { + 'test': {property: 'DoubleMap', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.clear': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'clear', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.delete': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'delete', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.entries': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'entries', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.forEach': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'forEach', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.get': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'get', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.has': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'has', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.keys': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'keys', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.set': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'set', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.size': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'size', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleMap.values': { + 'test': [ + {'property': 'DoubleMap', 'scope': 'self'}, + {'property': 'values', 'scope': 'DoubleMap.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('setlike interface', () => { const ast = WebIDL2.parse(`interface DoubleSet { setlike; };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'DoubleSet', - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - new Set(['Window']), - [ - [ - 'add', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'add', - 'scope': 'DoubleSet.prototype' - } - ] - ], - [ - 'clear', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'clear', - 'scope': 'DoubleSet.prototype' - } - ] - ], - [ - 'delete', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'delete', - 'scope': 'DoubleSet.prototype' - } - ] - ], - [ - 'entries', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'entries', - 'scope': 'DoubleSet.prototype' - } - ] - ], - [ - 'has', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'has', - 'scope': 'DoubleSet.prototype' - } - ] - ], - [ - 'keys', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'keys', - 'scope': 'DoubleSet.prototype' - } - ] - ], - [ - 'size', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'size', - 'scope': 'DoubleSet.prototype' - } - ] - ], - [ - 'values', - [ - { - 'property': 'DoubleSet', - 'scope': 'self' - }, - { - 'property': 'values', - 'scope': 'DoubleSet.prototype' - } - ] - ] - ] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.DoubleSet': { + 'test': {property: 'DoubleSet', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.add': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'add', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.clear': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'clear', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.delete': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'delete', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.entries': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'entries', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.has': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'has', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.keys': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'keys', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.size': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'size', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.DoubleSet.values': { + 'test': [ + {'property': 'DoubleSet', 'scope': 'self'}, + {'property': 'values', 'scope': 'DoubleSet.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('interface with getter/setter', () => { @@ -1069,17 +948,13 @@ describe('build', () => { getter GetMe (unsigned long index); setter void (GetMe data, optional unsigned long index); };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'GetMe', - { - 'property': 'GetMe', - 'scope': 'self' - }, - new Set(['Window']), - [] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.GetMe': { + 'test': {property: 'GetMe', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('varied scopes', () => { @@ -1089,27 +964,28 @@ describe('build', () => { [Exposed=(Window,Worker)] interface MessageChannel {}; namespace CSS {}; `); - assert.deepEqual(buildIDLTests(ast), [ - ['CSS', {property: 'CSS', scope: 'self'}, new Set(['Window']), []], - [ - 'MessageChannel', - {property: 'MessageChannel', scope: 'self'}, - new Set(['Window', 'Worker']), - [] - ], - [ - 'Worker', - {property: 'Worker', scope: 'self'}, - new Set(['Window']), - [] - ], - [ - 'WorkerSync', - {property: 'WorkerSync', scope: 'self'}, - new Set(['Worker']), - [] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.CSS': { + 'test': {property: 'CSS', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.MessageChannel': { + 'test': {property: 'MessageChannel', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window', 'Worker'] + }, + 'api.Worker': { + 'test': {property: 'Worker', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.WorkerSync': { + 'test': {property: 'WorkerSync', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Worker'] + } + }); }); it('operator variations', () => { @@ -1120,19 +996,21 @@ describe('build', () => { void disconnect (AudioNode destinationNode); }; `); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'AudioNode', - {property: 'AudioNode', scope: 'self'}, - new Set(['Window']), - [ - ['disconnect', [ - {property: 'AudioNode', scope: 'self'}, - {property: 'disconnect', scope: 'AudioNode.prototype'} - ]] - ] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.AudioNode': { + 'test': {property: 'AudioNode', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.AudioNode.disconnect': { + 'test': [ + {property: 'AudioNode', scope: 'self'}, + {property: 'disconnect', scope: 'AudioNode.prototype'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('namespace with attribute', () => { @@ -1140,14 +1018,21 @@ describe('build', () => { `namespace CSS { readonly attribute any paintWorklet; };`); - assert.deepEqual(buildIDLTests(ast), [ - ['CSS', {property: 'CSS', scope: 'self'}, new Set(['Window']), [ - ['paintWorklet', [ + assert.deepEqual(buildIDLTests(ast), { + 'api.CSS': { + 'test': {property: 'CSS', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.CSS.paintWorklet': { + 'test': [ {property: 'CSS', scope: 'self'}, {property: 'paintWorklet', scope: 'CSS'} - ]] - ] - ]]); + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('namespace with method', () => { @@ -1155,14 +1040,21 @@ describe('build', () => { `namespace CSS { boolean supports(CSSOMString property, CSSOMString value); };`); - assert.deepEqual(buildIDLTests(ast), [ - ['CSS', {property: 'CSS', scope: 'self'}, new Set(['Window']), [ - ['supports', [ + assert.deepEqual(buildIDLTests(ast), { + 'api.CSS': { + 'test': {property: 'CSS', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.CSS.supports': { + 'test': [ {property: 'CSS', scope: 'self'}, {property: 'supports', scope: 'CSS'} - ]] - ] - ]]); + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('namespace with custom test', () => { @@ -1170,26 +1062,31 @@ describe('build', () => { `namespace CSS { readonly attribute any paintWorklet; };`); - loadCustomTests({ - 'api': { - 'CSS': { - '__base': 'var css = CSS;', - '__test': 'return !!css;', - 'paintWorklet': 'return css && \'paintWorklet\' in css;' + + const {buildIDLTests} = proxyquire('../../build', { + './custom-tests.json': { + 'api': { + 'CSS': { + '__base': 'var css = CSS;', + '__test': 'return !!css;', + 'paintWorklet': 'return css && \'paintWorklet\' in css;' + } } + } + }); + + assert.deepEqual(buildIDLTests(ast), { + 'api.CSS': { + 'test': '(function() {var css = CSS;return !!css;})()', + 'combinator': 'and', + 'scope': ['Window'] }, - 'css': {} + 'api.CSS.paintWorklet': { + 'test': '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()', + 'combinator': 'and', + 'scope': ['Window'] + } }); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'CSS', - '(function() {var css = CSS;return !!css;})()', - new Set(['Window']), - [ - ['paintWorklet', '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()'] - ] - ] - ]); }); it('dictionary', () => { @@ -1198,23 +1095,29 @@ describe('build', () => { object? prototype = null; DOMString? extends = null; };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'ElementRegistrationOptions', - {property: 'ElementRegistrationOptions', scope: 'self'}, - new Set(['Window']), - [ - ['extends', [ - {property: 'ElementRegistrationOptions', scope: 'self'}, - {property: 'extends', scope: 'ElementRegistrationOptions'} - ]], - ['prototype', [ - {property: 'ElementRegistrationOptions', scope: 'self'}, - {property: 'prototype', scope: 'ElementRegistrationOptions'} - ]] - ] - ] - ]); + assert.deepEqual(buildIDLTests(ast), { + 'api.ElementRegistrationOptions': { + 'test': {property: 'ElementRegistrationOptions', scope: 'self'}, + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.ElementRegistrationOptions.extends': { + 'test': [ + {property: 'ElementRegistrationOptions', scope: 'self'}, + {property: 'extends', scope: 'ElementRegistrationOptions'} + ], + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.ElementRegistrationOptions.prototype': { + 'test': [ + {property: 'ElementRegistrationOptions', scope: 'self'}, + {property: 'prototype', scope: 'ElementRegistrationOptions'} + ], + 'combinator': 'and', + 'scope': ['Window'] + } + }); }); it('dictionary with custom test', () => { @@ -1223,23 +1126,33 @@ describe('build', () => { object? prototype = null; DOMString? extends = null; };`); - loadCustomTests({ - 'api': { - 'ElementRegistrationOptions': { - '__base': 'var ers = ElementRegistrationOptions;', - '__test': 'return !!ers;', - 'extends': 'return ers && \'extends\' in ers;', - 'prototype': 'return ers && \'prototype\' in ers;' + const {buildIDLTests} = proxyquire('../../build', { + './custom-tests.json': { + 'api': { + 'ElementRegistrationOptions': { + '__base': 'var instance = ElementRegistrationOptions;' + } } + } + }); + + assert.deepEqual(buildIDLTests(ast), { + 'api.ElementRegistrationOptions': { + 'test': '(function() {var instance = ElementRegistrationOptions;return !!instance;})()', + 'combinator': 'and', + 'scope': ['Window'] }, - 'css': {} + 'api.ElementRegistrationOptions.extends': { + 'test': '(function() {var instance = ElementRegistrationOptions;return instance && \'extends\' in instance;})()', + 'combinator': 'and', + 'scope': ['Window'] + }, + 'api.ElementRegistrationOptions.prototype': { + 'test': '(function() {var instance = ElementRegistrationOptions;return instance && \'prototype\' in instance;})()', + 'combinator': 'and', + 'scope': ['Window'] + } }); - assert.deepEqual(buildIDLTests(ast), [ - ['ElementRegistrationOptions', '(function() {var ers = ElementRegistrationOptions;return !!ers;})()', new Set(['Window']), [ - ['extends', '(function() {var ers = ElementRegistrationOptions;return ers && \'extends\' in ers;})()'], - ['prototype', '(function() {var ers = ElementRegistrationOptions;return ers && \'prototype\' in ers;})()'] - ] - ]]); }); }); From fc24e8289876846c85746ac889a2387572ffb6c0 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:17:56 -0700 Subject: [PATCH 015/243] Rename writeText to writeFile and make async --- build.js | 10 +++++----- test/unit/build.js | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build.js b/build.js index 5da38ae1f..c4be03c1e 100644 --- a/build.js +++ b/build.js @@ -24,13 +24,13 @@ const webref = require('./webref'); const generatedDir = path.join(__dirname, 'generated'); -function writeText(filename, content) { +async function writeFile(filename, content) { if (Array.isArray(content)) { content = content.join('\n'); } content = content.trimEnd() + '\n'; - fs.ensureDirSync(path.dirname(filename)); - fs.writeFileSync(filename, content, 'utf8'); + await fs.ensureDir(path.dirname(filename)); + await fs.writeFile(filename, content, 'utf8'); } function getCustomTestAPI(name, member) { @@ -490,7 +490,7 @@ function buildIDL(webref) { } async function writeManifest(manifest) { - writeText('MANIFEST.json', JSON.stringify(manifest, null, ' ')); + await writeFile('MANIFEST.json', JSON.stringify(manifest, null, ' ')); } function copyResources() { @@ -591,7 +591,7 @@ if (require.main === module) { }); } else { module.exports = { - writeText, + writeFile, getCustomTestAPI, getCustomTestCSS, collectCSSPropertiesFromBCD, diff --git a/test/unit/build.js b/test/unit/build.js index fdf25a5a7..959ad12c8 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -27,10 +27,10 @@ const proxyquire = require('proxyquire'); const fs = require('fs'); const { - writeText, collectCSSPropertiesFromBCD, collectCSSPropertiesFromReffy, cssPropertyToIDLAttribute, + writeFile, flattenIDL, getExposureSet, buildIDLTests, @@ -40,16 +40,16 @@ const { }); describe('build', () => { - describe('writeText', () => { + describe('writeFile', () => { const filepath = '.testtmp'; - it('simple supported', () => { - writeText(filepath, 'foo\nbar'); + it('simple supported', async () => { + await writeFile(filepath, 'foo\nbar'); assert.fileContent(filepath, 'foo\nbar\n'); }); - it('array', () => { - writeText(filepath, ['foo', 'bar', 'baz']); + it('array', async () => { + await writeFile(filepath, ['foo', 'bar', 'baz']); assert.fileContent(filepath, 'foo\nbar\nbaz\n'); }); From 448bc9c7e952a7e1954adee2c16fa41b51a2f2f2 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:19:51 -0700 Subject: [PATCH 016/243] Reorder functions --- build.js | 163 +++++++++++++++++++++++---------------------- test/unit/build.js | 9 +-- 2 files changed, 87 insertions(+), 85 deletions(-) diff --git a/build.js b/build.js index c4be03c1e..6b03d871a 100644 --- a/build.js +++ b/build.js @@ -68,83 +68,6 @@ function getCustomTestCSS(name) { `(function() {${customTests.css.properties[name]}})()`; } -function collectCSSPropertiesFromBCD(bcd, propertySet) { - for (const [prop, data] of Object.entries(bcd.css.properties)) { - propertySet.add(prop); - if (!data.__compat) { - // TODO: this misses stuff like css.properties['row-gap'].flex_content - continue; - } - const support = data.__compat.support; - if (!support) { - continue; - } - // eslint-disable-next-line no-inner-declarations - function process(statement) { - if (Array.isArray(statement)) { - statement.forEach(process); - return; - } - if (statement.alternative_name) { - propertySet.add(statement.alternative_name); - } - } - for (const statement of Object.values(support)) { - process(statement); - } - } -} - -function collectCSSPropertiesFromReffy(webref, propertySet) { - for (const data of Object.values(webref.css)) { - for (const prop of Object.keys(data.properties)) { - propertySet.add(prop); - } - } -} - -// https://drafts.csswg.org/cssom/#css-property-to-idl-attribute -function cssPropertyToIDLAttribute(property, lowercaseFirst) { - let output = ''; - let uppercaseNext = false; - if (lowercaseFirst) { - property = property.substr(1); - } - for (const c of property) { - if (c === '-') { - uppercaseNext = true; - } else if (uppercaseNext) { - uppercaseNext = false; - output += c.toUpperCase(); - } else { - output += c; - } - } - return output; -} - -function buildCSS(webref, bcd) { - const propertySet = new Set; - collectCSSPropertiesFromBCD(bcd, propertySet); - collectCSSPropertiesFromReffy(webref, propertySet); - - const tests = {}; - - for (const name of Array.from(propertySet).sort()) { - const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); - tests[`css.properties.${name}`] = { - 'test': getCustomTestCSS(name) || [ - {property: attrName, scope: 'document.body.style'}, - {property: name, scope: 'CSS.supports'} - ], - 'combinator': 'or', - 'scope': 'CSS' - }; - } - - return tests; -} - /* istanbul ignore next */ function collectExtraIDL() { const idl = fs.readFileSync('./non-standard.idl', 'utf8'); @@ -489,6 +412,83 @@ function buildIDL(webref) { return buildIDLTests(ast); } +function collectCSSPropertiesFromBCD(bcd, propertySet) { + for (const [prop, data] of Object.entries(bcd.css.properties)) { + propertySet.add(prop); + if (!data.__compat) { + // TODO: this misses stuff like css.properties['row-gap'].flex_content + continue; + } + const support = data.__compat.support; + if (!support) { + continue; + } + // eslint-disable-next-line no-inner-declarations + function process(statement) { + if (Array.isArray(statement)) { + statement.forEach(process); + return; + } + if (statement.alternative_name) { + propertySet.add(statement.alternative_name); + } + } + for (const statement of Object.values(support)) { + process(statement); + } + } +} + +function collectCSSPropertiesFromReffy(webref, propertySet) { + for (const data of Object.values(webref.css)) { + for (const prop of Object.keys(data.properties)) { + propertySet.add(prop); + } + } +} + +// https://drafts.csswg.org/cssom/#css-property-to-idl-attribute +function cssPropertyToIDLAttribute(property, lowercaseFirst) { + let output = ''; + let uppercaseNext = false; + if (lowercaseFirst) { + property = property.substr(1); + } + for (const c of property) { + if (c === '-') { + uppercaseNext = true; + } else if (uppercaseNext) { + uppercaseNext = false; + output += c.toUpperCase(); + } else { + output += c; + } + } + return output; +} + +function buildCSS(webref, bcd) { + const propertySet = new Set; + collectCSSPropertiesFromBCD(bcd, propertySet); + collectCSSPropertiesFromReffy(webref, propertySet); + + const tests = {}; + + for (const name of Array.from(propertySet).sort()) { + const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); + tests[`css.properties.${name}`] = { + 'test': getCustomTestCSS(name) || [ + {property: attrName, scope: 'document.body.style'}, + {property: name, scope: 'CSS.supports'} + ], + 'combinator': 'or', + 'scope': 'CSS' + }; + } + + return tests; +} + async function writeManifest(manifest) { await writeFile('MANIFEST.json', JSON.stringify(manifest, null, ' ')); } @@ -594,12 +594,13 @@ if (require.main === module) { writeFile, getCustomTestAPI, getCustomTestCSS, - collectCSSPropertiesFromBCD, - collectCSSPropertiesFromReffy, - cssPropertyToIDLAttribute, flattenIDL, getExposureSet, buildIDLTests, - validateIDL + validateIDL, + collectCSSPropertiesFromBCD, + collectCSSPropertiesFromReffy, + cssPropertyToIDLAttribute, + buildCSS }; } diff --git a/test/unit/build.js b/test/unit/build.js index 959ad12c8..9246bf6a5 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -27,14 +27,15 @@ const proxyquire = require('proxyquire'); const fs = require('fs'); const { - collectCSSPropertiesFromBCD, - collectCSSPropertiesFromReffy, - cssPropertyToIDLAttribute, writeFile, flattenIDL, getExposureSet, + validateIDL, buildIDLTests, - validateIDL + collectCSSPropertiesFromBCD, + collectCSSPropertiesFromReffy, + cssPropertyToIDLAttribute, + buildCSS } = proxyquire('../../build', { './custom-tests.json': {'api': {}, 'css': {}} }); From 5fef9750470cdef2eebe39ef702221ffa0997376 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:40:00 -0700 Subject: [PATCH 017/243] Overhaul tests.js to accommodate to new database format --- app.js | 6 +++--- tests.js | 53 +++++++++++++++++++++++------------------------------ 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/app.js b/app.js index dcc900dee..7523d0b79 100644 --- a/app.js +++ b/app.js @@ -73,8 +73,8 @@ app.use(express.static('generated')); app.get('/api/tests', (req, res) => { const {after, limit} = req.query; - const list = tests.list(after, limit ? +limit : 0); - const individualList = tests.listIndividual(after, limit ? +limit : 0); + const list = tests.listEndpoints(); + const individualList = tests.listIndividual(); res.json([list, individualList]); }); @@ -96,7 +96,7 @@ app.post('/api/results', (req, res) => { // Include next test in response as a convenience. try { - const next = tests.list(forURL, 1)[0]; + const next = tests.next(forURL); if (next) { response.next = next; } diff --git a/tests.js b/tests.js index dab0cdcde..ccd032355 100644 --- a/tests.js +++ b/tests.js @@ -16,45 +16,38 @@ class Tests { constructor(options) { - this.items = options.manifest.items - .filter((item) => !options.httpOnly || item.protocol === 'http'); - this.individualItems = options.manifest.individualItems; + this.tests = options.manifest.tests; + this.endpoints = options.manifest.endpoints.main; + this.individualEndpoints = options.manifest.endpoints.individual; this.host = options.host; } - list(after, limit) { - let begin; let end; - if (after) { - const afterURL = new URL(after); - const afterIndex = this.items.findIndex((item) => { - const itemURL = new URL(`${item.protocol}://${this.host}${item.pathname}`); - return itemURL.pathname === afterURL.pathname && - itemURL.protocol === afterURL.protocol; - }); - - if (afterIndex === -1) { - throw new Error(`${after} not found in test manifest`); - } - - begin = afterIndex + 1; - if (limit) { - end = afterIndex + 1 + limit; - } + next(after) { + const afterURL = new URL(after); + if (afterURL.protocol === 'http') { + return `https://${this.host}${afterURL.pathname}`; } else { - begin = 0; - if (limit) { - end = limit; - } + const endpoints = Object.keys(this.endpoints); + const endpoint = endpoints[endpoints.findIndex((item) => { + return item === afterURL.pathname; + })]; + + return `http://${this.host}${endpoint}`; } + } - return this.items.slice(begin, end).map((item) => { - return `${item.protocol}://${this.host}${item.pathname}`; - }); + getTests(endpoint) { + return this.endpoints[endpoint] || this.individualEndpoints[endpoint]; + } + + listEndpoints() { + return Object.keys(this.endpoints); } listIndividual() { - return Object.entries(this.individualItems) - .sort((a, b) => (a[0].localeCompare(b[0]))); + return Object.keys(this.individualEndpoints).map((item) => { + return [item.substr(1).replace(/\//g, '.'), item]; + }); } } From d86e950535bd8a4fa0c41962fe154d36994235f1 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:50:48 -0700 Subject: [PATCH 018/243] Make sure an endpoint is selected when building --- build.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build.js b/build.js index 6b03d871a..c7d6d3290 100644 --- a/build.js +++ b/build.js @@ -561,10 +561,12 @@ async function build(webref, bcd) { break; } - if (!(endpoint in manifest.endpoints.main)) { - manifest.endpoints.main[endpoint] = []; + if (endpoint) { + if (!(endpoint in manifest.endpoints.main)) { + manifest.endpoints.main[endpoint] = []; + } + manifest.endpoints.main[endpoint].push(ident); } - manifest.endpoints.main[endpoint].push(ident); } let url = ''; From 591339bde482cd955e7bf42b2c5c3e27593cb144 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:51:03 -0700 Subject: [PATCH 019/243] Prevent duplicate tests in endpoints --- build.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.js b/build.js index c7d6d3290..aefdb5835 100644 --- a/build.js +++ b/build.js @@ -565,7 +565,9 @@ async function build(webref, bcd) { if (!(endpoint in manifest.endpoints.main)) { manifest.endpoints.main[endpoint] = []; } - manifest.endpoints.main[endpoint].push(ident); + if (!(ident in manifest.endpoints.main[endpoint])) { + manifest.endpoints.main[endpoint].push(ident); + } } } @@ -576,7 +578,9 @@ async function build(webref, bcd) { if (!(url in manifest.endpoints.individual)) { manifest.endpoints.individual[url] = []; } - manifest.endpoints.individual[url].push(ident); + if (!(ident in manifest.endpoints.individual[url])) { + manifest.endpoints.individual[url].push(ident); + } } } } From f68dd8be97b34c1ff72d82439084ec7054cb7812 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:51:38 -0700 Subject: [PATCH 020/243] Add DedicatedWorker scope for endpoints --- build.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build.js b/build.js index aefdb5835..61331b45d 100644 --- a/build.js +++ b/build.js @@ -551,6 +551,7 @@ async function build(webref, bcd) { endpoint = '/api/interfaces'; break; case 'Worker': + case 'DedicatedWorker': endpoint = '/api/workerinterfaces'; break; case 'ServiceWorker': From 682b3fbfa68b20bfe2d191e82609b1ae7997038a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:53:17 -0700 Subject: [PATCH 021/243] Generate URLs from endpoints --- app.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app.js b/app.js index 7523d0b79..d47602201 100644 --- a/app.js +++ b/app.js @@ -138,6 +138,20 @@ app.post('/api/results/export/github', (req, res) => { .catch(/* istanbul ignore next */ (err) => catchError(err, res)); }); +for (const endpoint of tests.listEndpoints()) { + app.get(endpoint, (req, res) => { + // XXX Build tests + res.status(201).json(tests.getTests(endpoint)); + }); +} + +for (const [_, endpoint] of tests.listIndividual()) { + app.get(endpoint, (req, res) => { + // XXX Build tests + res.status(201).json(tests.getTests(endpoint)); + }); +} + /* istanbul ignore if */ if (require.main === module) { // Start the server From 010ddcd201982b302fb4ea887f4d89f083cf4ea0 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 20:53:31 -0700 Subject: [PATCH 022/243] Connect getTests to obtain actual tests --- tests.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests.js b/tests.js index ccd032355..75478ee74 100644 --- a/tests.js +++ b/tests.js @@ -37,7 +37,14 @@ class Tests { } getTests(endpoint) { - return this.endpoints[endpoint] || this.individualEndpoints[endpoint]; + const idents = this.endpoints[endpoint] || this.individualEndpoints[endpoint]; + const tests = {}; + + for (const ident of idents) { + tests[ident] = this.tests[ident]; + } + + return tests; } listEndpoints() { From 56e431305d9d82f0208c66e4f59ded07782a1b93 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 21:48:26 -0700 Subject: [PATCH 023/243] Rename finishIndividual to finishAndDisplay --- static/resources/harness.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index 84c8083c6..264e49098 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -422,7 +422,7 @@ }; } - function finishIndividual(results) { + function finishAndDisplay(results) { var response = ''; for (var i=0; i Date: Thu, 3 Sep 2020 21:54:08 -0700 Subject: [PATCH 024/243] Generate test pages --- app.js | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index d47602201..caaebbfe4 100644 --- a/app.js +++ b/app.js @@ -64,6 +64,45 @@ function catchError(err, res) { res.status(500).end(); } +function generateTestPage(tests, individual) { + const lines = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '

Running tests...

', + '', '', ''); + + return lines.join("\n"); +}; + const app = express(); app.use(cookieParser()); app.use(cookieSession); @@ -140,15 +179,13 @@ app.post('/api/results/export/github', (req, res) => { for (const endpoint of tests.listEndpoints()) { app.get(endpoint, (req, res) => { - // XXX Build tests - res.status(201).json(tests.getTests(endpoint)); + res.send(generateTestPage(tests.getTests(endpoint))); }); } for (const [_, endpoint] of tests.listIndividual()) { app.get(endpoint, (req, res) => { - // XXX Build tests - res.status(201).json(tests.getTests(endpoint)); + res.send(generateTestPage(tests.getTests(endpoint, true))) }); } From 5113b8329205b23348f40dfe5ffac0764d218d56 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:10:56 -0700 Subject: [PATCH 025/243] Add support for scope --- app.js | 21 +++++++++++++-------- build.js | 10 +++++++--- tests.js | 8 +++++++- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/app.js b/app.js index caaebbfe4..e7a545ff1 100644 --- a/app.js +++ b/app.js @@ -64,7 +64,10 @@ function catchError(err, res) { res.status(500).end(); } -function generateTestPage(tests, individual) { +function generateTestPage(endpoint) { + const theseTests = tests.getTests(endpoint); + const testScope = tests.getScope(endpoint); + const lines = [ '', '', @@ -86,16 +89,18 @@ function generateTestPage(tests, individual) { '', '', ''); @@ -179,13 +184,13 @@ app.post('/api/results/export/github', (req, res) => { for (const endpoint of tests.listEndpoints()) { app.get(endpoint, (req, res) => { - res.send(generateTestPage(tests.getTests(endpoint))); + res.send(generateTestPage(endpoint)); }); } for (const [_, endpoint] of tests.listIndividual()) { app.get(endpoint, (req, res) => { - res.send(generateTestPage(tests.getTests(endpoint, true))) + res.send(generateTestPage(endpoint)); }); } diff --git a/build.js b/build.js index 61331b45d..a1954769c 100644 --- a/build.js +++ b/build.js @@ -564,10 +564,14 @@ async function build(webref, bcd) { if (endpoint) { if (!(endpoint in manifest.endpoints.main)) { - manifest.endpoints.main[endpoint] = []; + manifest.endpoints.main[endpoint] = { + scope: scope, + httpsOnly: scope === 'ServiceWorker', + entries: [] + }; } - if (!(ident in manifest.endpoints.main[endpoint])) { - manifest.endpoints.main[endpoint].push(ident); + if (!(ident in manifest.endpoints.main[endpoint].entries)) { + manifest.endpoints.main[endpoint].entries.push(ident); } } } diff --git a/tests.js b/tests.js index 75478ee74..8b0dccf7e 100644 --- a/tests.js +++ b/tests.js @@ -37,7 +37,8 @@ class Tests { } getTests(endpoint) { - const idents = this.endpoints[endpoint] || this.individualEndpoints[endpoint]; + const idents = this.endpoints[endpoint].entries + || this.individualEndpoints[endpoint]; const tests = {}; for (const ident of idents) { @@ -47,6 +48,11 @@ class Tests { return tests; } + getScope(endpoint) { + const e = this.endpoints[endpoint]; + return e ? e.scope : ""; + } + listEndpoints() { return Object.keys(this.endpoints); } From c7c175923d03940a1dc739bdec141b75f36cd9ff Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:11:12 -0700 Subject: [PATCH 026/243] Add support for HTTPS-only tests (like service workers) --- tests.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests.js b/tests.js index 8b0dccf7e..669ad3643 100644 --- a/tests.js +++ b/tests.js @@ -20,19 +20,33 @@ class Tests { this.endpoints = options.manifest.endpoints.main; this.individualEndpoints = options.manifest.endpoints.individual; this.host = options.host; + this.httpOnly = options.httpOnly; } next(after) { const afterURL = new URL(after); - if (afterURL.protocol === 'http') { + if (!this.httpOnly && afterURL.protocol === 'http:') { return `https://${this.host}${afterURL.pathname}`; } else { - const endpoints = Object.keys(this.endpoints); - const endpoint = endpoints[endpoints.findIndex((item) => { + const endpoints = this.listEndpoints(); + const index = endpoints.findIndex((item) => { return item === afterURL.pathname; - })]; + }) + 1; - return `http://${this.host}${endpoint}`; + if (index >= endpoints.length) { + return null; + } + + if (this.endpoints[endpoints[index]].httpsOnly) { + if (this.httpOnly) { + // Skip this endpoint and go to the next + return next(endpoints[index]); + } else { + return `https://${this.host}${endpoints[index]}`; + } + } + + return `http://${this.host}${endpoints[index]}`; } } From 05afad5854a515515fafa7711698b43410c67de1 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:18:35 -0700 Subject: [PATCH 027/243] Ignore major categories when generating individual test endpoints --- build.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.js b/build.js index a1954769c..04c12e0cb 100644 --- a/build.js +++ b/build.js @@ -580,6 +580,11 @@ async function build(webref, bcd) { for (const part of ident.split('.')) { url += '/' + part; + if (['/api', '/css', '/css/properties'].includes(url)) { + // Ignore things tested in main endpoints + continue; + } + if (!(url in manifest.endpoints.individual)) { manifest.endpoints.individual[url] = []; } From 15f1f1e031bc64fb4f14b3d833fa6ba11a6414fa Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:18:57 -0700 Subject: [PATCH 028/243] Fix scope generation for CSS --- build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.js b/build.js index 04c12e0cb..facf0dbb2 100644 --- a/build.js +++ b/build.js @@ -482,7 +482,7 @@ function buildCSS(webref, bcd) { {property: name, scope: 'CSS.supports'} ], 'combinator': 'or', - 'scope': 'CSS' + 'scope': ['CSS'] }; } From 0904f888cd6c99b54e2693aeccee5821592c76be Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:22:21 -0700 Subject: [PATCH 029/243] Fix individual tests --- app.js | 16 +++++++++++----- tests.js | 5 +++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app.js b/app.js index e7a545ff1..6480a5d37 100644 --- a/app.js +++ b/app.js @@ -66,7 +66,8 @@ function catchError(err, res) { function generateTestPage(endpoint) { const theseTests = tests.getTests(endpoint); - const testScope = tests.getScope(endpoint); + let testScope = tests.getScope(endpoint); + let individual = false; const lines = [ '', @@ -91,16 +92,21 @@ function generateTestPage(endpoint) { for (const [ident, test] of Object.entries(theseTests)) { for (const scope of test.scope) { - if (testScope && scope == testScope) { + if (!testScope) { + // Set scope to the first found scope if it's an individual test + testScope = scope; + individual = true; + } + if (scope == testScope) { lines.push(`bcd.addTest("${ident}", ${JSON.stringify(test.test)}, "${scope}");`); } } } - if (testScope) { - lines.push(`bcd.run('${testScope}');`); + if (individual) { + lines.push(`bcd.run('${testScope}', bcd.finishAndDisplay);`); } else { - lines.push(`bcd.run('', bcd.finishAndDisplay);`); + lines.push(`bcd.run('${testScope}');`); } lines.push('', '', ''); diff --git a/tests.js b/tests.js index 669ad3643..f8ef97e20 100644 --- a/tests.js +++ b/tests.js @@ -51,8 +51,9 @@ class Tests { } getTests(endpoint) { - const idents = this.endpoints[endpoint].entries - || this.individualEndpoints[endpoint]; + const idents = this.endpoints[endpoint] ? + this.endpoints[endpoint].entries : + this.individualEndpoints[endpoint]; const tests = {}; for (const ident of idents) { From 1534048cb7bd5bd92dc0462bc1468961060a235c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:23:40 -0700 Subject: [PATCH 030/243] Fix ESLint issues --- app.js | 7 +++---- test/unit/build.js | 2 +- tests.js | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app.js b/app.js index 6480a5d37..ecd93a82e 100644 --- a/app.js +++ b/app.js @@ -87,7 +87,7 @@ function generateTestPage(endpoint) { '', '', '

Running tests...

', - '', '', ''); - return lines.join("\n"); -}; + return lines.join('\n'); +} const app = express(); app.use(cookieParser()); @@ -122,7 +122,6 @@ app.use(express.static('static')); app.use(express.static('generated')); app.get('/api/tests', (req, res) => { - const {after, limit} = req.query; const list = tests.listEndpoints(); const individualList = tests.listIndividual(); res.json([list, individualList]); diff --git a/test/unit/build.js b/test/unit/build.js index 9246bf6a5..2d6fb3eb2 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -626,7 +626,7 @@ describe('build', () => { } } }); - + assert.deepEqual(buildIDLTests(ast), { 'api.ANGLE_instanced_arrays': { 'test': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', diff --git a/tests.js b/tests.js index f8ef97e20..af5fc148a 100644 --- a/tests.js +++ b/tests.js @@ -40,7 +40,7 @@ class Tests { if (this.endpoints[endpoints[index]].httpsOnly) { if (this.httpOnly) { // Skip this endpoint and go to the next - return next(endpoints[index]); + return this.next(endpoints[index]); } else { return `https://${this.host}${endpoints[index]}`; } @@ -51,7 +51,7 @@ class Tests { } getTests(endpoint) { - const idents = this.endpoints[endpoint] ? + const idents = this.endpoints[endpoint] ? this.endpoints[endpoint].entries : this.individualEndpoints[endpoint]; const tests = {}; @@ -65,7 +65,7 @@ class Tests { getScope(endpoint) { const e = this.endpoints[endpoint]; - return e ? e.scope : ""; + return e ? e.scope : ''; } listEndpoints() { From 107ee663eef1615e90ca1a0ce292be3e9bf04f30 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:30:04 -0700 Subject: [PATCH 031/243] Account for name change of Reffy-Reports to Webref --- build.js | 6 +++--- test/unit/build.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.js b/build.js index facf0dbb2..102a0483d 100644 --- a/build.js +++ b/build.js @@ -439,7 +439,7 @@ function collectCSSPropertiesFromBCD(bcd, propertySet) { } } -function collectCSSPropertiesFromReffy(webref, propertySet) { +function collectCSSPropertiesFromWebref(webref, propertySet) { for (const data of Object.values(webref.css)) { for (const prop of Object.keys(data.properties)) { propertySet.add(prop); @@ -470,7 +470,7 @@ function cssPropertyToIDLAttribute(property, lowercaseFirst) { function buildCSS(webref, bcd) { const propertySet = new Set; collectCSSPropertiesFromBCD(bcd, propertySet); - collectCSSPropertiesFromReffy(webref, propertySet); + collectCSSPropertiesFromWebref(webref, propertySet); const tests = {}; @@ -615,7 +615,7 @@ if (require.main === module) { buildIDLTests, validateIDL, collectCSSPropertiesFromBCD, - collectCSSPropertiesFromReffy, + collectCSSPropertiesFromWebref, cssPropertyToIDLAttribute, buildCSS }; diff --git a/test/unit/build.js b/test/unit/build.js index 2d6fb3eb2..721af33cc 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -33,7 +33,7 @@ const { validateIDL, buildIDLTests, collectCSSPropertiesFromBCD, - collectCSSPropertiesFromReffy, + collectCSSPropertiesFromWebref, cssPropertyToIDLAttribute, buildCSS } = proxyquire('../../build', { @@ -323,7 +323,7 @@ describe('build', () => { }); }); - it('collectCSSPropertiesFromReffy', () => { + it('collectCSSPropertiesFromWebref', () => { const webref = { css: { 'css-fonts': { @@ -340,7 +340,7 @@ describe('build', () => { } }; const propertySet = new Set(); - collectCSSPropertiesFromReffy(webref, propertySet); + collectCSSPropertiesFromWebref(webref, propertySet); const properties = Array.from(propertySet); assert.deepEqual(properties, ['font-family', 'font-weight', 'grid']); }); From 80a78ad3a53ff9bd3d0d13445b6848d365bcf29d Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:30:12 -0700 Subject: [PATCH 032/243] Add test for buildCSS --- test/unit/build.js | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/unit/build.js b/test/unit/build.js index 721af33cc..c0a9d5f6b 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -1224,4 +1224,69 @@ describe('build', () => { }).to.throw(); }); }); + + it('buildCSS', () => { + const bcd = { + css: { + properties: { + appearance: { + __compat: { + support: {} + } + } + } + } + }; + + const webref = { + css: { + 'css-fonts': { + properties: { + 'font-family': {}, + 'font-weight': {} + } + }, + 'css-grid': { + properties: { + 'grid': {} + } + } + } + }; + + assert.deepEqual(buildCSS(webref, bcd), { + 'css.properties.appearance': { + 'test': [ + {property: 'appearance', scope: 'document.body.style'}, + {property: 'appearance', scope: 'CSS.supports'} + ], + 'combinator': 'or', + 'scope': ['CSS'] + }, + 'css.properties.font-family': { + 'test': [ + {property: 'fontFamily', scope: 'document.body.style'}, + {property: 'font-family', scope: 'CSS.supports'} + ], + 'combinator': 'or', + 'scope': ['CSS'] + }, + 'css.properties.font-weight': { + 'test': [ + {property: 'fontWeight', scope: 'document.body.style'}, + {property: 'font-weight', scope: 'CSS.supports'} + ], + 'combinator': 'or', + 'scope': ['CSS'] + }, + 'css.properties.grid': { + 'test': [ + {property: 'grid', scope: 'document.body.style'}, + {property: 'grid', scope: 'CSS.supports'} + ], + 'combinator': 'or', + 'scope': ['CSS'] + } + }); + }); }); From a89826be5a6d102664e25a646b05d780f19d0788 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:37:41 -0700 Subject: [PATCH 033/243] Fix tests + ESLint issues --- test/app/results.js | 8 ++-- test/app/tests.js | 8 ++-- test/unit/tests.js | 107 ++++++++++++++++++++++---------------------- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/test/app/results.js b/test/app/results.js index 6a39cb371..9909e19f1 100644 --- a/test/app/results.js +++ b/test/app/results.js @@ -19,7 +19,7 @@ const chai = require('chai'); const chaiHttp = require('chai-http'); const manifest = require('../../MANIFEST.json'); -const manifestItems = manifest.items.filter((item) => item.protocol === 'http'); +const manifestItems = Object.entries(manifest.endpoints.main); chai.use(chaiHttp); const agent = chai.request.agent(app); @@ -45,8 +45,8 @@ describe('/api/results', () => { assert.deepEqual(res.body, {}); }); - const testURL = `http://localhost:8080${manifestItems[0].pathname}`; - const testURL2 = `https://host.test${manifestItems[1].pathname}`; + const testURL = `http://localhost:8080${manifestItems[0][0]}`; + const testURL2 = `https://host.test${manifestItems[1][0]}`; it('submit valid results', async () => { const res = await agent.post('/api/results') @@ -54,7 +54,7 @@ describe('/api/results', () => { .send({x: 1}); assert.equal(res.status, 201); assert.deepEqual(res.body, { - 'next': `http://localhost:8080${manifestItems[1].pathname}` + 'next': `http://localhost:8080${manifestItems[1][0]}` }); }); diff --git a/test/app/tests.js b/test/app/tests.js index a6724460a..e914db1d0 100644 --- a/test/app/tests.js +++ b/test/app/tests.js @@ -23,11 +23,13 @@ const agent = chai.request.agent(app); const assert = chai.assert; describe('/api/tests', () => { - it('list one test', async () => { - const res = await agent.get('/api/tests?limit=1'); + it('list tests', async () => { + const res = await agent.get('/api/tests'); assert.equal(res.status, 200); assert.isArray(res.body); - assert.equal(res.body[0].length, 1); + assert.isArray(res.body[0]); + assert.isArray(res.body[1]); + assert.equal(res.body.length, 2); }); }); diff --git a/test/unit/tests.js b/test/unit/tests.js index c37cb2e86..9b03be404 100644 --- a/test/unit/tests.js +++ b/test/unit/tests.js @@ -18,19 +18,39 @@ const assert = require('assert'); const Tests = require('../../tests'); const MANIFEST = { - items: [{ - pathname: '/a/test.html', - protocol: 'http' - }, { - pathname: '/b/test.html', - protocol: 'http' - }, { - pathname: '/b/test.html', - protocol: 'https' - }, { - pathname: '/c/test.html', - protocol: 'https' - }] + tests: { + 'api.AbortController': true, + 'api.AbortController.controller': false, + 'api.FooBar': null + }, + endpoints: { + main: { + '/api/interfaces': { + scope: 'Window', + httpsOnly: false, + entries: [ + 'api.AbortController', + 'api.AbortController.controller' + ] + }, + '/api/serviceworkerinterfaces': { + scope: 'ServiceWorker', + httpsOnly: true, + entries: [ + 'api.AbortController' + ] + } + }, + individual: { + '/api/AbortController': [ + 'api.AbortController', + 'api.AbortController.controller' + ], + '/api/AbortController/controller': [ + 'api.AbortController.controller' + ] + } + } }; describe('Tests', () => { @@ -39,54 +59,33 @@ describe('Tests', () => { host: 'host.test' }); - it('list all tests', () => { - assert.deepEqual(tests.list(), [ - 'http://host.test/a/test.html', - 'http://host.test/b/test.html', - 'https://host.test/b/test.html', - 'https://host.test/c/test.html' - ]); - }); - - it('list first test', () => { - assert.deepEqual(tests.list(undefined, 1), [ - 'http://host.test/a/test.html' - ]); + it('getTests', () => { + assert.deepEqual(tests.getTests('/api/interfaces'), { + 'api.AbortController': true, + 'api.AbortController.controller': false + }); + assert.deepEqual(tests.getTests('/api/serviceworkerinterfaces'), { + 'api.AbortController': true + }); }); - it('list middle two tests', () => { - assert.deepEqual(tests.list('http://host.test/a/test.html', 2), [ - 'http://host.test/b/test.html', - 'https://host.test/b/test.html' - ]); + it('getScope', () => { + assert.equal(tests.getScope('/api/interfaces'), 'Window'); + assert.equal(tests.getScope('/api/serviceworkerinterfaces'), 'ServiceWorker'); + assert.equal(tests.getScope('/api/dummy'), ''); }); - it('list last two tests', () => { - assert.deepEqual(tests.list('http://host.test/b/test.html'), [ - 'https://host.test/b/test.html', - 'https://host.test/c/test.html' + it('listEndpoints', () => { + assert.deepEqual(tests.listEndpoints(), [ + '/api/interfaces', + '/api/serviceworkerinterfaces' ]); }); - it('list after last test', () => { - assert.deepEqual(tests.list('https://host.test/c/test.html'), []); - }); - - it('list after non-existent test', () => { - assert.throws(() => { - tests.list('https://host.test/not/a/test.html'); - }, Error); - }); - - it('list HTTP-only tests', () => { - const httpTests = new Tests({ - manifest: MANIFEST, - host: 'host.test', - httpOnly: true - }); - assert.deepEqual(httpTests.list(), [ - 'http://host.test/a/test.html', - 'http://host.test/b/test.html' + it('listIndividual', () => { + assert.deepEqual(tests.listIndividual(), [ + ['api.AbortController', '/api/AbortController'], + ['api.AbortController.controller', '/api/AbortController/controller'] ]); }); }); From f2170fe596dcff1deee8b57f2ef4ab3b6b8ab86a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:57:12 -0700 Subject: [PATCH 034/243] Move test code compilation to server-side --- static/resources/harness.js | 55 ++++++++++++++++++++++--------------- tests.js | 24 +++++++++++++++- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index 264e49098..d75ff4d6b 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -67,27 +67,8 @@ pending.push({name: name, code: code, scope: scope, info: info}); } - // Each test is mapped to an object like this: - // { - // "name": "api.Attr.localName", - // "result": true, - // "prefix": "", - // "info": { - // "code": "'localName' in Attr.prototype", - // "scope": "Window" - // } - // } - // - // If the test doesn't return true or false, or if it throws, `result` will - // be null and a `message` property is set to an explanation. - function test(data) { - var result = {name: data.name, info: {}}; - var category = data.name.split('.')[0]; - - var prefixesToTest = ['']; - if (category in prefixes) { - prefixesToTest = prefixes[category]; - } + function testWithPrefix(data) { + // XXX Kept for reference for prefixes, not actively used try { var parentPrefix = ''; @@ -217,12 +198,42 @@ result.result = null; result.message = 'threw ' + stringify(err); } + } + + // Each test is mapped to an object like this: + // { + // "name": "api.Attr.localName", + // "result": true, + // "prefix": "", + // "info": { + // "code": "'localName' in Attr.prototype", + // "scope": "Window" + // } + // } + // + // If the test doesn't return true or false, or if it throws, `result` will + // be null and a `message` property is set to an explanation. + function test(data) { + var result = {name: data.name, info: {}}; + var category = data.name.split('.')[0]; + + var prefixesToTest = ['']; + if (category in prefixes) { + prefixesToTest = prefixes[category]; + } + + try { + result.result = eval(data.code); + } catch (err) { + result.result = null; + result.message = 'threw ' + stringify(err); + } if (data.info !== undefined) { result.info = Object.assign({}, result.info, data.info); } - result.info.code = compiledCode.join(' && '); + result.info.code = data.code; result.info.scope = data.scope; return result; diff --git a/tests.js b/tests.js index af5fc148a..13f7ade25 100644 --- a/tests.js +++ b/tests.js @@ -50,6 +50,26 @@ class Tests { } } + compileTest(test) { + let compiledCode = []; + + for (const subtest of test.test) { + if (typeof(subtest) === 'string') { + compiledCode.push(subtest); + } else if (subtest.property == 'constructor') { + compiledCode.push('new '+subtest.scope+'()'); + } else if (subtest.scope === 'CSS.supports') { + compiledCode.push(`CSS.supports("${subtest.property}", "inherit");`); + } else if (stringStartsWith(subtest.property, 'Symbol.')) { + compiledCode.push(`${subtest.property} in ${subtest.scope}`); + } else { + compiledCode.push(`"${subtest.property}" in ${subtest.scope}`); + } + } + + return compiledCode.join(test.comparator == "and" ? " && " : " || "); + } + getTests(endpoint) { const idents = this.endpoints[endpoint] ? this.endpoints[endpoint].entries : @@ -57,7 +77,9 @@ class Tests { const tests = {}; for (const ident of idents) { - tests[ident] = this.tests[ident]; + let test = this.tests[ident]; + test.test = compileTest(test); + tests[ident] = test; } return tests; From 22f1639fec4cae069d3d012402ccde3cb8549478 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 22:57:33 -0700 Subject: [PATCH 035/243] Fix typo --- tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.js b/tests.js index 13f7ade25..22ac721e5 100644 --- a/tests.js +++ b/tests.js @@ -78,7 +78,7 @@ class Tests { for (const ident of idents) { let test = this.tests[ident]; - test.test = compileTest(test); + test.test = this.compileTest(test); tests[ident] = test; } From 524d57b1315c64e46b9c49dd9a3b90a09d574dec Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:00:50 -0700 Subject: [PATCH 036/243] Restore old test() function for historical purposes (remove later) --- static/resources/harness.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index d75ff4d6b..1765b0520 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -67,8 +67,19 @@ pending.push({name: name, code: code, scope: scope, info: info}); } + // eslint-disable-next-line no-unused-vars function testWithPrefix(data) { - // XXX Kept for reference for prefixes, not actively used + // XXX Not actively used; kept for historical purposes. Code compilation + // has been moved to the server-side, aside from prefixes. Once prefixes + // are implemented, remove this code + + var result = {name: data.name, info: {}}; + var category = data.name.split('.')[0]; + + var prefixesToTest = ['']; + if (category in prefixes) { + prefixesToTest = prefixes[category]; + } try { var parentPrefix = ''; @@ -198,6 +209,15 @@ result.result = null; result.message = 'threw ' + stringify(err); } + + if (data.info !== undefined) { + result.info = Object.assign({}, result.info, data.info); + } + + result.info.code = compiledCode.join(' && '); + result.info.scope = data.scope; + + return result; } // Each test is mapped to an object like this: From 00ee03e332ee07c022e41d9eedce8faff9d058dd Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:00:55 -0700 Subject: [PATCH 037/243] Remove unused code --- static/resources/harness.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index 1765b0520..e2b7ed18b 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -235,12 +235,6 @@ // be null and a `message` property is set to an explanation. function test(data) { var result = {name: data.name, info: {}}; - var category = data.name.split('.')[0]; - - var prefixesToTest = ['']; - if (category in prefixes) { - prefixesToTest = prefixes[category]; - } try { result.result = eval(data.code); From 1e832496eed60249a29e8af3bb0f14845c834850 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:01:13 -0700 Subject: [PATCH 038/243] Don't use unneeded polyfill --- tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.js b/tests.js index 22ac721e5..f2ed6383a 100644 --- a/tests.js +++ b/tests.js @@ -60,7 +60,7 @@ class Tests { compiledCode.push('new '+subtest.scope+'()'); } else if (subtest.scope === 'CSS.supports') { compiledCode.push(`CSS.supports("${subtest.property}", "inherit");`); - } else if (stringStartsWith(subtest.property, 'Symbol.')) { + } else if (subtest.property.startsWith('Symbol.')) { compiledCode.push(`${subtest.property} in ${subtest.scope}`); } else { compiledCode.push(`"${subtest.property}" in ${subtest.scope}`); From 45b9b64359b45c5ff460130113fee868991b2f1b Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:01:21 -0700 Subject: [PATCH 039/243] Fix ESLint issues --- tests.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests.js b/tests.js index f2ed6383a..0f740cfe5 100644 --- a/tests.js +++ b/tests.js @@ -51,7 +51,7 @@ class Tests { } compileTest(test) { - let compiledCode = []; + const compiledCode = []; for (const subtest of test.test) { if (typeof(subtest) === 'string') { @@ -67,7 +67,7 @@ class Tests { } } - return compiledCode.join(test.comparator == "and" ? " && " : " || "); + return compiledCode.join(test.comparator == 'and' ? ' && ' : ' || '); } getTests(endpoint) { @@ -77,7 +77,7 @@ class Tests { const tests = {}; for (const ident of idents) { - let test = this.tests[ident]; + const test = this.tests[ident]; test.test = this.compileTest(test); tests[ident] = test; } From 0a1cfc2a8cf77ba14439766ca74225f95b6001ab Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:09:08 -0700 Subject: [PATCH 040/243] Fix test iteration --- tests.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests.js b/tests.js index 0f740cfe5..bbd16e48e 100644 --- a/tests.js +++ b/tests.js @@ -52,8 +52,9 @@ class Tests { compileTest(test) { const compiledCode = []; + const subtests = Array.isArray(test.test) ? test.test : [test.test]; - for (const subtest of test.test) { + for (const subtest of subtests) { if (typeof(subtest) === 'string') { compiledCode.push(subtest); } else if (subtest.property == 'constructor') { @@ -67,7 +68,7 @@ class Tests { } } - return compiledCode.join(test.comparator == 'and' ? ' && ' : ' || '); + return compiledCode.join(test.combinator == 'and' ? ' && ' : ' || '); } getTests(endpoint) { From 7638c2c996b2286d926ef9bbcf74c866fb8aa600 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:09:24 -0700 Subject: [PATCH 041/243] Re-add constructor testing --- static/resources/harness.js | 43 ++++++++++++++++++++++++++++++++++++- tests.js | 2 +- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index e2b7ed18b..ec48b888d 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -67,6 +67,37 @@ pending.push({name: name, code: code, scope: scope, info: info}); } + function testConstructor(iface) { + var result = {}; + + try { + eval('new '+iface+'()'); + result.result = true; + } catch (err) { + if ( + stringIncludes(err.message, 'Illegal constructor') || + stringIncludes(err.message, 'Function expected') + ) { + result.result = false; + } else if ( + stringIncludes(err.message, 'Not enough arguments') || + stringIncludes(err.message, 'argument required') || + stringIncludes(err.message, 'arguments required') || + stringIncludes(err.message, 'Argument not optional') + ) { + // If it failed to construct and it's not illegal or just needs + // more arguments, the constructor's good + result.result = true; + } else { + result.result = null; + } + + result.message = 'threw ' + stringify(err); + } + + return result; + } + // eslint-disable-next-line no-unused-vars function testWithPrefix(data) { // XXX Not actively used; kept for historical purposes. Code compilation @@ -237,7 +268,15 @@ var result = {name: data.name, info: {}}; try { - result.result = eval(data.code); + var value = eval(data.code); + if (typeof value === 'object' && 'result' in value) { + result.result = value.result; + if (value.message) { + result.message = value.message; + } + } else { + result.result = value; + } } catch (err) { result.result = null; result.message = 'threw ' + stringify(err); @@ -453,6 +492,7 @@ var result = results[i]; response += result.name + ': ' + result.result; if (result.prefix) response += ' (' + result.prefix + ' prefix)'; + if (result.message) response += ' (' + result.message + ')'; response += '\n' + result.info.code + ';\n\n'; } updateStatus(response.replace(/\n/g, '
')); @@ -515,6 +555,7 @@ global.stringify = stringify; global.bcd = { + testConstructor: testConstructor, addTest: addTest, test: test, run: run, diff --git a/tests.js b/tests.js index bbd16e48e..d623c57ed 100644 --- a/tests.js +++ b/tests.js @@ -58,7 +58,7 @@ class Tests { if (typeof(subtest) === 'string') { compiledCode.push(subtest); } else if (subtest.property == 'constructor') { - compiledCode.push('new '+subtest.scope+'()'); + compiledCode.push(`bcd.testConstructor('${subtest.scope}')`); } else if (subtest.scope === 'CSS.supports') { compiledCode.push(`CSS.supports("${subtest.property}", "inherit");`); } else if (subtest.property.startsWith('Symbol.')) { From e28822c334dfc80f8a131a42d940f0852ccf964c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:16:57 -0700 Subject: [PATCH 042/243] Restore old code bits --- static/resources/harness.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index ec48b888d..c6eba4e44 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -269,13 +269,16 @@ try { var value = eval(data.code); - if (typeof value === 'object' && 'result' in value) { + if (value && typeof value === 'object' && 'result' in value) { result.result = value.result; if (value.message) { result.message = value.message; } - } else { + } else if (typeof value === 'boolean') { result.result = value; + } else { + result.result = null; + result.message = 'returned ' + stringify(value); } } catch (err) { result.result = null; From 9e4995438899690362de040efaf67b8c5ad85481 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:17:14 -0700 Subject: [PATCH 043/243] Fix tests --- static/test/test.js | 16 ++++------- test/unit/tests.js | 70 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/static/test/test.js b/static/test/test.js index f94e98471..d33face5a 100644 --- a/static/test/test.js +++ b/static/test/test.js @@ -38,8 +38,7 @@ describe('harness.js', function() { assert.deepStrictEqual(results, [{ name: 'name', result: true, - info: {code: 'true', scope: 'test'}, - prefix: '' + info: {code: 'true', scope: 'test'} }]); done(); }); @@ -60,12 +59,12 @@ describe('harness.js', function() { it('return null', function(done) { bcd.addTest('name', 'null', 'test'); bcd.run('Window', function(results) { + console.log(results); assert.deepStrictEqual(results, [{ name: 'name', result: null, message: 'returned null', - info: {code: 'null', scope: 'test'}, - prefix: '' + info: {code: 'null', scope: 'test'} }]); done(); }); @@ -81,8 +80,7 @@ describe('harness.js', function() { name: 'name', result: null, message: 'returned Symbol(bar)', - info: {code: 'Symbol(\'bar\')', scope: 'test'}, - prefix: '' + info: {code: 'Symbol(\'bar\')', scope: 'test'} }]); done(); }); @@ -95,8 +93,7 @@ describe('harness.js', function() { name: 'name', result: null, message: 'returned undefined', - info: {code: 'undefined', scope: 'test'}, - prefix: '' + info: {code: 'undefined', scope: 'test'} }]); done(); }); @@ -133,8 +130,7 @@ describe('harness.js', function() { assert.deepEqual(results, [{ name: 'first', result: true, - info: {code: 'true', scope: 'test', a: 1}, - prefix: '' + info: {code: 'true', scope: 'test', a: 1} }, { name: 'second', result: false, diff --git a/test/unit/tests.js b/test/unit/tests.js index 9b03be404..1c36e5065 100644 --- a/test/unit/tests.js +++ b/test/unit/tests.js @@ -19,8 +19,34 @@ const Tests = require('../../tests'); const MANIFEST = { tests: { - 'api.AbortController': true, - 'api.AbortController.controller': false, + 'api.AbortController': { + "test": { + "property": "AbortController", + "scope": "self" + }, + "combinator": "and", + "scope": [ + "Window", + "Worker" + ] + }, + 'api.AbortController.signal': { + "test": [ + { + "property": "AbortController", + "scope": "self" + }, + { + "property": "signal", + "scope": "AbortController" + } + ], + "combinator": "and", + "scope": [ + "Window", + "Worker" + ] + }, 'api.FooBar': null }, endpoints: { @@ -30,24 +56,29 @@ const MANIFEST = { httpsOnly: false, entries: [ 'api.AbortController', - 'api.AbortController.controller' + 'api.AbortController.signal' ] }, - '/api/serviceworkerinterfaces': { - scope: 'ServiceWorker', + '/api/workerinterfaces': { + scope: 'Worker', httpsOnly: true, entries: [ 'api.AbortController' ] + }, + '/api/serviceworkerinterfaces': { + scope: 'ServiceWorker', + httpsOnly: true, + entries: [] } }, individual: { '/api/AbortController': [ 'api.AbortController', - 'api.AbortController.controller' + 'api.AbortController.signal' ], - '/api/AbortController/controller': [ - 'api.AbortController.controller' + '/api/AbortController/signal': [ + 'api.AbortController.signal' ] } } @@ -61,11 +92,23 @@ describe('Tests', () => { it('getTests', () => { assert.deepEqual(tests.getTests('/api/interfaces'), { - 'api.AbortController': true, - 'api.AbortController.controller': false + 'api.AbortController': { + "test": '"AbortController" in self', + "combinator": "and", + "scope": ["Window", "Worker"] + }, + 'api.AbortController.signal': { + "test": '"AbortController" in self && "signal" in AbortController', + "combinator": "and", + "scope": ["Window", "Worker"] + } }); - assert.deepEqual(tests.getTests('/api/serviceworkerinterfaces'), { - 'api.AbortController': true + assert.deepEqual(tests.getTests('/api/workerinterfaces'), { + 'api.AbortController': { + "test": '"AbortController" in self', + "combinator": "and", + "scope": ["Window", "Worker"] + } }); }); @@ -78,6 +121,7 @@ describe('Tests', () => { it('listEndpoints', () => { assert.deepEqual(tests.listEndpoints(), [ '/api/interfaces', + '/api/workerinterfaces', '/api/serviceworkerinterfaces' ]); }); @@ -85,7 +129,7 @@ describe('Tests', () => { it('listIndividual', () => { assert.deepEqual(tests.listIndividual(), [ ['api.AbortController', '/api/AbortController'], - ['api.AbortController.controller', '/api/AbortController/controller'] + ['api.AbortController.signal', '/api/AbortController/signal'] ]); }); }); From 9e2e2098a19a8d5e0315b639c3cbaf110170f49e Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:17:41 -0700 Subject: [PATCH 044/243] Fix ESLint issues --- static/test/test.js | 1 - test/unit/tests.js | 50 ++++++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/static/test/test.js b/static/test/test.js index d33face5a..545ae719f 100644 --- a/static/test/test.js +++ b/static/test/test.js @@ -59,7 +59,6 @@ describe('harness.js', function() { it('return null', function(done) { bcd.addTest('name', 'null', 'test'); bcd.run('Window', function(results) { - console.log(results); assert.deepStrictEqual(results, [{ name: 'name', result: null, diff --git a/test/unit/tests.js b/test/unit/tests.js index 1c36e5065..ee51f4981 100644 --- a/test/unit/tests.js +++ b/test/unit/tests.js @@ -20,31 +20,31 @@ const Tests = require('../../tests'); const MANIFEST = { tests: { 'api.AbortController': { - "test": { - "property": "AbortController", - "scope": "self" + 'test': { + 'property': 'AbortController', + 'scope': 'self' }, - "combinator": "and", - "scope": [ - "Window", - "Worker" + 'combinator': 'and', + 'scope': [ + 'Window', + 'Worker' ] }, 'api.AbortController.signal': { - "test": [ + 'test': [ { - "property": "AbortController", - "scope": "self" + 'property': 'AbortController', + 'scope': 'self' }, { - "property": "signal", - "scope": "AbortController" + 'property': 'signal', + 'scope': 'AbortController' } ], - "combinator": "and", - "scope": [ - "Window", - "Worker" + 'combinator': 'and', + 'scope': [ + 'Window', + 'Worker' ] }, 'api.FooBar': null @@ -93,21 +93,21 @@ describe('Tests', () => { it('getTests', () => { assert.deepEqual(tests.getTests('/api/interfaces'), { 'api.AbortController': { - "test": '"AbortController" in self', - "combinator": "and", - "scope": ["Window", "Worker"] + 'test': '"AbortController" in self', + 'combinator': 'and', + 'scope': ['Window', 'Worker'] }, 'api.AbortController.signal': { - "test": '"AbortController" in self && "signal" in AbortController', - "combinator": "and", - "scope": ["Window", "Worker"] + 'test': '"AbortController" in self && "signal" in AbortController', + 'combinator': 'and', + 'scope': ['Window', 'Worker'] } }); assert.deepEqual(tests.getTests('/api/workerinterfaces'), { 'api.AbortController': { - "test": '"AbortController" in self', - "combinator": "and", - "scope": ["Window", "Worker"] + 'test': '"AbortController" in self', + 'combinator': 'and', + 'scope': ['Window', 'Worker'] } }); }); From 19914dd9a1e216d4e36c6f359e0f38ec6377c01f Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:18:40 -0700 Subject: [PATCH 045/243] Bump to version 0.1.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9b1fc3ce..7f801e6f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mdn-bcd-collector", - "version": "0.0.6", + "version": "0.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a425367ac..2b3049b41 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mdn-bcd-collector", "description": "Data collection service for mdn/browser-compat-data", - "version": "0.0.6", + "version": "0.1.0", "private": true, "license": "Apache-2.0", "repository": { From 8ea1526d3bec6b663102b6b50a66afd584bc8a9a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:28:29 -0700 Subject: [PATCH 046/243] Move test code compilation into build script --- app.js | 2 +- build.js | 41 ++++++++++++++++++++++++++++++++--------- tests.js | 25 +------------------------ 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/app.js b/app.js index ecd93a82e..5c922501f 100644 --- a/app.js +++ b/app.js @@ -98,7 +98,7 @@ function generateTestPage(endpoint) { individual = true; } if (scope == testScope) { - lines.push(`bcd.addTest("${ident}", ${JSON.stringify(test.test)}, "${scope}");`); + lines.push(`bcd.addTest("${ident}", ${JSON.stringify(test.code)}, "${scope}");`); } } } diff --git a/build.js b/build.js index 102a0483d..5abe8e947 100644 --- a/build.js +++ b/build.js @@ -68,6 +68,29 @@ function getCustomTestCSS(name) { `(function() {${customTests.css.properties[name]}})()`; } +function compileTest(test) { + const newTest = test; + const compiledCode = []; + const subtests = Array.isArray(test.code) ? test.code : [test.code]; + + for (const subtest of subtests) { + if (typeof(subtest) === 'string') { + compiledCode.push(subtest); + } else if (subtest.property == 'constructor') { + compiledCode.push(`bcd.testConstructor('${subtest.scope}')`); + } else if (subtest.scope === 'CSS.supports') { + compiledCode.push(`CSS.supports("${subtest.property}", "inherit");`); + } else if (subtest.property.startsWith('Symbol.')) { + compiledCode.push(`${subtest.property} in ${subtest.scope}`); + } else { + compiledCode.push(`"${subtest.property}" in ${subtest.scope}`); + } + } + + newTest.code = compiledCode.join(test.combinator == 'and' ? ' && ' : ' || '); + return newTest; +} + /* istanbul ignore next */ function collectExtraIDL() { const idl = fs.readFileSync('./non-standard.idl', 'utf8'); @@ -318,11 +341,11 @@ function buildIDLTests(ast) { const isGlobal = !!getExtAttr(iface, 'Global'); const customIfaceTest = getCustomTestAPI(iface.name); - tests[`api.${iface.name}`] = { - 'test': customIfaceTest || {property: iface.name, scope: 'self'}, + tests[`api.${iface.name}`] = compileTest({ + 'code': customIfaceTest || {property: iface.name, scope: 'self'}, 'combinator': 'and', 'scope': Array.from(exposureSet) - }; + }); const members = flattenMembers(iface); @@ -394,11 +417,11 @@ function buildIDLTests(ast) { } } - tests[`api.${iface.name}.${member.name}`] = { - 'test': expr, + tests[`api.${iface.name}.${member.name}`] = compileTest({ + 'code': expr, 'combinator': 'and', 'scope': Array.from(exposureSet) - }; + }); handledMemberNames.add(member.name); } } @@ -476,14 +499,14 @@ function buildCSS(webref, bcd) { for (const name of Array.from(propertySet).sort()) { const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); - tests[`css.properties.${name}`] = { - 'test': getCustomTestCSS(name) || [ + tests[`css.properties.${name}`] = compileTest({ + 'code': getCustomTestCSS(name) || [ {property: attrName, scope: 'document.body.style'}, {property: name, scope: 'CSS.supports'} ], 'combinator': 'or', 'scope': ['CSS'] - }; + }); } return tests; diff --git a/tests.js b/tests.js index d623c57ed..af5fc148a 100644 --- a/tests.js +++ b/tests.js @@ -50,27 +50,6 @@ class Tests { } } - compileTest(test) { - const compiledCode = []; - const subtests = Array.isArray(test.test) ? test.test : [test.test]; - - for (const subtest of subtests) { - if (typeof(subtest) === 'string') { - compiledCode.push(subtest); - } else if (subtest.property == 'constructor') { - compiledCode.push(`bcd.testConstructor('${subtest.scope}')`); - } else if (subtest.scope === 'CSS.supports') { - compiledCode.push(`CSS.supports("${subtest.property}", "inherit");`); - } else if (subtest.property.startsWith('Symbol.')) { - compiledCode.push(`${subtest.property} in ${subtest.scope}`); - } else { - compiledCode.push(`"${subtest.property}" in ${subtest.scope}`); - } - } - - return compiledCode.join(test.combinator == 'and' ? ' && ' : ' || '); - } - getTests(endpoint) { const idents = this.endpoints[endpoint] ? this.endpoints[endpoint].entries : @@ -78,9 +57,7 @@ class Tests { const tests = {}; for (const ident of idents) { - const test = this.tests[ident]; - test.test = this.compileTest(test); - tests[ident] = test; + tests[ident] = this.tests[ident]; } return tests; From 20cbcd6bf222c6778050cbfa03ccd1e2ef8d99fa Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:35:37 -0700 Subject: [PATCH 047/243] Add additional constructor error message catch --- static/resources/harness.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index c6eba4e44..6c679e766 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -83,7 +83,8 @@ stringIncludes(err.message, 'Not enough arguments') || stringIncludes(err.message, 'argument required') || stringIncludes(err.message, 'arguments required') || - stringIncludes(err.message, 'Argument not optional') + stringIncludes(err.message, 'Argument not optional') || + stringIncludes(err.message, 'Arguments can\'t be empty') ) { // If it failed to construct and it's not illegal or just needs // more arguments, the constructor's good From 093ea28414400dbf4b6e4d25a0cdee8cc742577b Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:40:42 -0700 Subject: [PATCH 048/243] Fix HTTPS skipping --- tests.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests.js b/tests.js index af5fc148a..3866eefa4 100644 --- a/tests.js +++ b/tests.js @@ -38,11 +38,12 @@ class Tests { } if (this.endpoints[endpoints[index]].httpsOnly) { + const newUrl = `https://${this.host}${endpoints[index]}`; if (this.httpOnly) { // Skip this endpoint and go to the next - return this.next(endpoints[index]); + return this.next(newUrl); } else { - return `https://${this.host}${endpoints[index]}`; + return newUrl; } } From 6b47a5e8bd680620162280287512f8254dd11b9a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:41:07 -0700 Subject: [PATCH 049/243] Change /api/ to /backend/ for all backend --- app.js | 8 ++++---- static/index.html | 2 +- static/resources/harness.js | 2 +- static/results/index.html | 4 ++-- test/app/results.js | 22 +++++++++++----------- test/app/tests.js | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/app.js b/app.js index 5c922501f..e2ba791b9 100644 --- a/app.js +++ b/app.js @@ -121,13 +121,13 @@ app.use(express.json({limit: '32mb'})); app.use(express.static('static')); app.use(express.static('generated')); -app.get('/api/tests', (req, res) => { +app.get('/backend/tests', (req, res) => { const list = tests.listEndpoints(); const individualList = tests.listIndividual(); res.json([list, individualList]); }); -app.post('/api/results', (req, res) => { +app.post('/backend/results', (req, res) => { if (!req.is('json')) { res.status(400).end(); return; @@ -163,7 +163,7 @@ app.post('/api/results', (req, res) => { .catch(/* istanbul ignore next */ (err) => catchError(err, res)); }); -app.get('/api/results', (req, res) => { +app.get('/backend/results', (req, res) => { storage.getAll(req.sessionID) .then((results) => { res.status(200).json(results); @@ -172,7 +172,7 @@ app.get('/api/results', (req, res) => { }); /* istanbul ignore next: we don't want to create lots of dummy PRs */ -app.post('/api/results/export/github', (req, res) => { +app.post('/backend/results/export/github', (req, res) => { storage.getAll(req.sessionID) .then(async (results) => { const userAgent = req.get('User-Agent'); diff --git a/static/index.html b/static/index.html index 748bb6a23..5301e15af 100644 --- a/static/index.html +++ b/static/index.html @@ -24,7 +24,7 @@ var button = document.getElementById('start'); var dropdown = document.getElementById('tests'); var client = new XMLHttpRequest(); - client.open('GET', '/api/tests', true); + client.open('GET', '/backend/tests', true); client.send(); client.onreadystatechange = function() { if (client.readyState == 4) { diff --git a/static/resources/harness.js b/static/resources/harness.js index 6c679e766..bf7ad5693 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -477,7 +477,7 @@ function report(results) { var body = JSON.stringify(results); var client = new XMLHttpRequest(); - client.open('POST', '/api/results?for='+encodeURIComponent(location.href)); + client.open('POST', '/backend/results?for='+encodeURIComponent(location.href)); client.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); client.send(body); client.onreadystatechange = function() { diff --git a/static/results/index.html b/static/results/index.html index a82bc8019..6f7f00583 100644 --- a/static/results/index.html +++ b/static/results/index.html @@ -16,7 +16,7 @@ Loading page...
Back to start page @@ -27,7 +27,7 @@ var status = document.getElementById('status'); var link = document.getElementById('link'); var client = new XMLHttpRequest(); - client.open('POST', '/api/results/export/github', true); + client.open('POST', '/backend/results/export/github', true); client.send(); status.textContent = 'Exporting...'; client.onreadystatechange = function() { diff --git a/test/app/results.js b/test/app/results.js index 9909e19f1..c352084c6 100644 --- a/test/app/results.js +++ b/test/app/results.js @@ -25,22 +25,22 @@ chai.use(chaiHttp); const agent = chai.request.agent(app); const assert = chai.assert; -describe('/api/results', () => { +describe('/backend/results', () => { it('missing `Content-Type` header', async () => { - const res = await agent.post('/api/results') + const res = await agent.post('/backend/results') .set('Content-Type', 'text/plain') .send('string'); assert.equal(res.status, 400); }); it('missing `for` param', async () => { - const res = await agent.post('/api/results') + const res = await agent.post('/backend/results') .send({}); assert.equal(res.status, 400); }); it('list results before', async () => { - const res = await agent.get('/api/results'); + const res = await agent.get('/backend/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, {}); }); @@ -49,7 +49,7 @@ describe('/api/results', () => { const testURL2 = `https://host.test${manifestItems[1][0]}`; it('submit valid results', async () => { - const res = await agent.post('/api/results') + const res = await agent.post('/backend/results') .query({for: testURL}) .send({x: 1}); assert.equal(res.status, 201); @@ -59,7 +59,7 @@ describe('/api/results', () => { }); it('list results after valid', async () => { - const res = await agent.get('/api/results'); + const res = await agent.get('/backend/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { '__version': version, @@ -68,14 +68,14 @@ describe('/api/results', () => { }); it('submit duplicate results', async () => { - const res = await agent.post('/api/results') + const res = await agent.post('/backend/results') .query({for: testURL}) .send({x: 2}); assert.equal(res.status, 201); }); it('list results after duplicate', async () => { - const res = await agent.get('/api/results'); + const res = await agent.get('/backend/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { '__version': version, @@ -84,7 +84,7 @@ describe('/api/results', () => { }); it('submit results for new/last manifest', async () => { - const res = await agent.post('/api/results') + const res = await agent.post('/backend/results') .query({for: testURL2}) .send({y: 3}); assert.equal(res.status, 201); @@ -92,7 +92,7 @@ describe('/api/results', () => { }); it('list results after new/last manifest', async () => { - const res = await agent.get('/api/results'); + const res = await agent.get('/backend/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { '__version': version, @@ -102,7 +102,7 @@ describe('/api/results', () => { }); it('submit invalid results', async () => { - const res = await agent.post('/api/results') + const res = await agent.post('/backend/results') .query({for: testURL}) .send('my bad results'); assert.equal(res.status, 400); diff --git a/test/app/tests.js b/test/app/tests.js index e914db1d0..5334f34bd 100644 --- a/test/app/tests.js +++ b/test/app/tests.js @@ -22,9 +22,9 @@ chai.use(chaiHttp); const agent = chai.request.agent(app); const assert = chai.assert; -describe('/api/tests', () => { +describe('/backend/tests', () => { it('list tests', async () => { - const res = await agent.get('/api/tests'); + const res = await agent.get('/backend/tests'); assert.equal(res.status, 200); assert.isArray(res.body); assert.isArray(res.body[0]); From 3c6097b1cc2888542e8c96e0168d4857d7a51b6a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 3 Sep 2020 23:42:03 -0700 Subject: [PATCH 050/243] Fix ESLint issues --- static/resources/harness.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index bf7ad5693..978739d2b 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -83,7 +83,7 @@ stringIncludes(err.message, 'Not enough arguments') || stringIncludes(err.message, 'argument required') || stringIncludes(err.message, 'arguments required') || - stringIncludes(err.message, 'Argument not optional') || + stringIncludes(err.message, 'Argument not optional') || stringIncludes(err.message, 'Arguments can\'t be empty') ) { // If it failed to construct and it's not illegal or just needs @@ -477,7 +477,9 @@ function report(results) { var body = JSON.stringify(results); var client = new XMLHttpRequest(); - client.open('POST', '/backend/results?for='+encodeURIComponent(location.href)); + client.open( + 'POST', '/backend/results?for='+encodeURIComponent(location.href) + ); client.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); client.send(body); client.onreadystatechange = function() { From 2e581e5b948e5488ad21dc422b308ff911252eef Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 00:00:26 -0700 Subject: [PATCH 051/243] Fix tests to accommodate for build-time compilation of code --- build.js | 4 +- test/app/results.js | 2 +- test/unit/build.js | 250 ++++++++++++-------------------------------- test/unit/tests.js | 22 +--- 4 files changed, 75 insertions(+), 203 deletions(-) diff --git a/build.js b/build.js index 5abe8e947..d2ea92322 100644 --- a/build.js +++ b/build.js @@ -77,9 +77,9 @@ function compileTest(test) { if (typeof(subtest) === 'string') { compiledCode.push(subtest); } else if (subtest.property == 'constructor') { - compiledCode.push(`bcd.testConstructor('${subtest.scope}')`); + compiledCode.push(`bcd.testConstructor("${subtest.scope}")`); } else if (subtest.scope === 'CSS.supports') { - compiledCode.push(`CSS.supports("${subtest.property}", "inherit");`); + compiledCode.push(`CSS.supports("${subtest.property}", "inherit")`); } else if (subtest.property.startsWith('Symbol.')) { compiledCode.push(`${subtest.property} in ${subtest.scope}`); } else { diff --git a/test/app/results.js b/test/app/results.js index c352084c6..3da882711 100644 --- a/test/app/results.js +++ b/test/app/results.js @@ -46,7 +46,7 @@ describe('/backend/results', () => { }); const testURL = `http://localhost:8080${manifestItems[0][0]}`; - const testURL2 = `https://host.test${manifestItems[1][0]}`; + const testURL2 = `https://host.test${manifestItems[manifestItems.length - 1][0]}`; it('submit valid results', async () => { const res = await agent.post('/backend/results') diff --git a/test/unit/build.js b/test/unit/build.js index c0a9d5f6b..fa0854c61 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -515,15 +515,12 @@ describe('build', () => { const ast = WebIDL2.parse(`interface Attr { attribute any name; };`); assert.deepEqual(buildIDLTests(ast), { 'api.Attr': { - 'test': {property: 'Attr', scope: 'self'}, + 'code': '"Attr" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.Attr.name': { - 'test': [ - {property: 'Attr', scope: 'self'}, - {property: 'name', scope: 'Attr.prototype'} - ], + 'code': '"Attr" in self && "name" in Attr.prototype', 'combinator': 'and', 'scope': ['Window'] } @@ -537,15 +534,12 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.Node': { - 'test': {property: 'Node', scope: 'self'}, + 'code': '"Node" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.Node.contains': { - 'test': [ - {property: 'Node', scope: 'self'}, - {property: 'contains', scope: 'Node.prototype'} - ], + 'code': '"Node" in self && "contains" in Node.prototype', 'combinator': 'and', 'scope': ['Window'] } @@ -560,15 +554,12 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.MediaSource': { - 'test': {property: 'MediaSource', scope: 'self'}, + 'code': '"MediaSource" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.MediaSource.isTypeSupported': { - 'test': [ - {property: 'MediaSource', scope: 'self'}, - {property: 'isTypeSupported', scope: 'MediaSource'} - ], + 'code': '"MediaSource" in self && "isTypeSupported" in MediaSource', 'combinator': 'and', 'scope': ['Window'] } @@ -583,15 +574,12 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Window': { - 'test': {property: 'Window', scope: 'self'}, + 'code': '"Window" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.Window.isWindow': { - 'test': [ - {property: 'Window', scope: 'self'}, - {property: 'isWindow', scope: 'Window'} - ], + 'code': '"Window" in self && "isWindow" in Window', 'combinator': 'and', 'scope': ['Window'] } @@ -629,17 +617,17 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.ANGLE_instanced_arrays': { - 'test': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', + 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', 'combinator': 'and', 'scope': ['Window'] }, 'api.ANGLE_instanced_arrays.drawArraysInstancedANGLE': { - 'test': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return true && instance && \'drawArraysInstancedANGLE\' in instance;})()', + 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return true && instance && \'drawArraysInstancedANGLE\' in instance;})()', 'combinator': 'and', 'scope': ['Window'] }, 'api.ANGLE_instanced_arrays.drawElementsInstancedANGLE': { - 'test': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()', + 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()', 'combinator': 'and', 'scope': ['Window'] } @@ -660,17 +648,17 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.WindowOrWorkerGlobalScope': { - 'test': {property: 'WindowOrWorkerGlobalScope', scope: 'self'}, + 'code': '"WindowOrWorkerGlobalScope" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.WindowOrWorkerGlobalScope.active': { - 'test': {property: 'active', scope: 'self'}, + 'code': '"active" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.WindowOrWorkerGlobalScope.isLoaded': { - 'test': {property: 'isLoaded', scope: 'self'}, + 'code': '"isLoaded" in self', 'combinator': 'and', 'scope': ['Window'] } @@ -684,15 +672,12 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Number': { - 'test': {property: 'Number', scope: 'self'}, + 'code': '"Number" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.Number.Number': { - 'test': [ - {property: 'Number', scope: 'self'}, - {property: 'constructor', scope: 'Number'} - ], + 'code': '"Number" in self && bcd.testConstructor("Number")', 'combinator': 'and', 'scope': ['Window'] } @@ -704,15 +689,12 @@ describe('build', () => { interface Number {};`); assert.deepEqual(buildIDLTests(ast), { 'api.Number': { - 'test': {property: 'Number', scope: 'self'}, + 'code': '"Number" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.Number.Number': { - 'test': [ - {property: 'Number', scope: 'self'}, - {property: 'constructor', scope: 'Number'} - ], + 'code': '"Number" in self && bcd.testConstructor("Number")', 'combinator': 'and', 'scope': ['Window'] } @@ -725,49 +707,32 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.DoubleList': { - 'test': {property: 'DoubleList', scope: 'self'}, + 'code': '"DoubleList" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.@@iterator': { - 'test': [ - {'property': 'DoubleList', 'scope': 'self'}, - {'property': 'Symbol', 'scope': 'self'}, - {'property': 'iterator', 'scope': 'Symbol'}, - {'property': 'Symbol.iterator', 'scope': 'DoubleList.prototype'} - ], + 'code': '"DoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in DoubleList.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.entries': { - 'test': [ - {'property': 'DoubleList', 'scope': 'self'}, - {'property': 'entries', 'scope': 'DoubleList.prototype'} - ], + 'code': '"DoubleList" in self && "entries" in DoubleList.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.forEach': { - 'test': [ - {'property': 'DoubleList', 'scope': 'self'}, - {'property': 'forEach', 'scope': 'DoubleList.prototype'} - ], + 'code': '"DoubleList" in self && "forEach" in DoubleList.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.keys': { - 'test': [ - {'property': 'DoubleList', 'scope': 'self'}, - {'property': 'keys', 'scope': 'DoubleList.prototype'} - ], + 'code': '"DoubleList" in self && "keys" in DoubleList.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.values': { - 'test': [ - {'property': 'DoubleList', 'scope': 'self'}, - {'property': 'values', 'scope': 'DoubleList.prototype'} - ], + 'code': '"DoubleList" in self && "values" in DoubleList.prototype', 'combinator': 'and', 'scope': ['Window'] } @@ -780,87 +745,57 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.DoubleMap': { - 'test': {property: 'DoubleMap', scope: 'self'}, + 'code': '"DoubleMap" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.clear': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'clear', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "clear" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.delete': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'delete', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "delete" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.entries': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'entries', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "entries" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.forEach': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'forEach', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "forEach" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.get': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'get', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "get" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.has': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'has', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "has" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.keys': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'keys', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "keys" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.set': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'set', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "set" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.size': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'size', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "size" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.values': { - 'test': [ - {'property': 'DoubleMap', 'scope': 'self'}, - {'property': 'values', 'scope': 'DoubleMap.prototype'} - ], + 'code': '"DoubleMap" in self && "values" in DoubleMap.prototype', 'combinator': 'and', 'scope': ['Window'] } @@ -873,71 +808,47 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.DoubleSet': { - 'test': {property: 'DoubleSet', scope: 'self'}, + 'code': '"DoubleSet" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.add': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'add', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "add" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.clear': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'clear', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "clear" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.delete': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'delete', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "delete" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.entries': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'entries', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "entries" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.has': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'has', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "has" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.keys': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'keys', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "keys" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.size': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'size', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "size" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.values': { - 'test': [ - {'property': 'DoubleSet', 'scope': 'self'}, - {'property': 'values', 'scope': 'DoubleSet.prototype'} - ], + 'code': '"DoubleSet" in self && "values" in DoubleSet.prototype', 'combinator': 'and', 'scope': ['Window'] } @@ -951,7 +862,7 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.GetMe': { - 'test': {property: 'GetMe', scope: 'self'}, + 'code': '"GetMe" in self', 'combinator': 'and', 'scope': ['Window'] } @@ -967,22 +878,22 @@ describe('build', () => { `); assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'test': {property: 'CSS', scope: 'self'}, + 'code': '"CSS" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.MessageChannel': { - 'test': {property: 'MessageChannel', scope: 'self'}, + 'code': '"MessageChannel" in self', 'combinator': 'and', 'scope': ['Window', 'Worker'] }, 'api.Worker': { - 'test': {property: 'Worker', scope: 'self'}, + 'code': '"Worker" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.WorkerSync': { - 'test': {property: 'WorkerSync', scope: 'self'}, + 'code': '"WorkerSync" in self', 'combinator': 'and', 'scope': ['Worker'] } @@ -999,15 +910,12 @@ describe('build', () => { `); assert.deepEqual(buildIDLTests(ast), { 'api.AudioNode': { - 'test': {property: 'AudioNode', scope: 'self'}, + 'code': '"AudioNode" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.AudioNode.disconnect': { - 'test': [ - {property: 'AudioNode', scope: 'self'}, - {property: 'disconnect', scope: 'AudioNode.prototype'} - ], + 'code': '"AudioNode" in self && "disconnect" in AudioNode.prototype', 'combinator': 'and', 'scope': ['Window'] } @@ -1021,15 +929,12 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'test': {property: 'CSS', scope: 'self'}, + 'code': '"CSS" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.CSS.paintWorklet': { - 'test': [ - {property: 'CSS', scope: 'self'}, - {property: 'paintWorklet', scope: 'CSS'} - ], + 'code': '"CSS" in self && "paintWorklet" in CSS', 'combinator': 'and', 'scope': ['Window'] } @@ -1043,15 +948,12 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'test': {property: 'CSS', scope: 'self'}, + 'code': '"CSS" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.CSS.supports': { - 'test': [ - {property: 'CSS', scope: 'self'}, - {property: 'supports', scope: 'CSS'} - ], + 'code': '"CSS" in self && "supports" in CSS', 'combinator': 'and', 'scope': ['Window'] } @@ -1078,12 +980,12 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'test': '(function() {var css = CSS;return !!css;})()', + 'code': '(function() {var css = CSS;return !!css;})()', 'combinator': 'and', 'scope': ['Window'] }, 'api.CSS.paintWorklet': { - 'test': '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()', + 'code': '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()', 'combinator': 'and', 'scope': ['Window'] } @@ -1098,23 +1000,17 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.ElementRegistrationOptions': { - 'test': {property: 'ElementRegistrationOptions', scope: 'self'}, + 'code': '"ElementRegistrationOptions" in self', 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.extends': { - 'test': [ - {property: 'ElementRegistrationOptions', scope: 'self'}, - {property: 'extends', scope: 'ElementRegistrationOptions'} - ], + 'code': '"ElementRegistrationOptions" in self && "extends" in ElementRegistrationOptions', 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.prototype': { - 'test': [ - {property: 'ElementRegistrationOptions', scope: 'self'}, - {property: 'prototype', scope: 'ElementRegistrationOptions'} - ], + 'code': '"ElementRegistrationOptions" in self && "prototype" in ElementRegistrationOptions', 'combinator': 'and', 'scope': ['Window'] } @@ -1139,17 +1035,17 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.ElementRegistrationOptions': { - 'test': '(function() {var instance = ElementRegistrationOptions;return !!instance;})()', + 'code': '(function() {var instance = ElementRegistrationOptions;return !!instance;})()', 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.extends': { - 'test': '(function() {var instance = ElementRegistrationOptions;return instance && \'extends\' in instance;})()', + 'code': '(function() {var instance = ElementRegistrationOptions;return instance && \'extends\' in instance;})()', 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.prototype': { - 'test': '(function() {var instance = ElementRegistrationOptions;return instance && \'prototype\' in instance;})()', + 'code': '(function() {var instance = ElementRegistrationOptions;return instance && \'prototype\' in instance;})()', 'combinator': 'and', 'scope': ['Window'] } @@ -1256,34 +1152,22 @@ describe('build', () => { assert.deepEqual(buildCSS(webref, bcd), { 'css.properties.appearance': { - 'test': [ - {property: 'appearance', scope: 'document.body.style'}, - {property: 'appearance', scope: 'CSS.supports'} - ], + 'code': '"appearance" in document.body.style || CSS.supports("appearance", "inherit")', 'combinator': 'or', 'scope': ['CSS'] }, 'css.properties.font-family': { - 'test': [ - {property: 'fontFamily', scope: 'document.body.style'}, - {property: 'font-family', scope: 'CSS.supports'} - ], + 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', 'combinator': 'or', 'scope': ['CSS'] }, 'css.properties.font-weight': { - 'test': [ - {property: 'fontWeight', scope: 'document.body.style'}, - {property: 'font-weight', scope: 'CSS.supports'} - ], + 'code': '"fontWeight" in document.body.style || CSS.supports("font-weight", "inherit")', 'combinator': 'or', 'scope': ['CSS'] }, 'css.properties.grid': { - 'test': [ - {property: 'grid', scope: 'document.body.style'}, - {property: 'grid', scope: 'CSS.supports'} - ], + 'code': '"grid" in document.body.style || CSS.supports("grid", "inherit")', 'combinator': 'or', 'scope': ['CSS'] } diff --git a/test/unit/tests.js b/test/unit/tests.js index ee51f4981..28e387ef0 100644 --- a/test/unit/tests.js +++ b/test/unit/tests.js @@ -20,10 +20,7 @@ const Tests = require('../../tests'); const MANIFEST = { tests: { 'api.AbortController': { - 'test': { - 'property': 'AbortController', - 'scope': 'self' - }, + 'code': '"AbortController" in self', 'combinator': 'and', 'scope': [ 'Window', @@ -31,16 +28,7 @@ const MANIFEST = { ] }, 'api.AbortController.signal': { - 'test': [ - { - 'property': 'AbortController', - 'scope': 'self' - }, - { - 'property': 'signal', - 'scope': 'AbortController' - } - ], + 'code': '"AbortController" in self && "signal" in AbortController', 'combinator': 'and', 'scope': [ 'Window', @@ -93,19 +81,19 @@ describe('Tests', () => { it('getTests', () => { assert.deepEqual(tests.getTests('/api/interfaces'), { 'api.AbortController': { - 'test': '"AbortController" in self', + 'code': '"AbortController" in self', 'combinator': 'and', 'scope': ['Window', 'Worker'] }, 'api.AbortController.signal': { - 'test': '"AbortController" in self && "signal" in AbortController', + 'code': '"AbortController" in self && "signal" in AbortController', 'combinator': 'and', 'scope': ['Window', 'Worker'] } }); assert.deepEqual(tests.getTests('/api/workerinterfaces'), { 'api.AbortController': { - 'test': '"AbortController" in self', + 'code': '"AbortController" in self', 'combinator': 'and', 'scope': ['Window', 'Worker'] } From 6ba9b0eff777d289a42247bc110bef5ebfedcf29 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 00:02:14 -0700 Subject: [PATCH 052/243] Don't include combinator in compiled tests --- build.js | 1 + test/unit/build.js | 67 ---------------------------------------------- test/unit/tests.js | 5 ---- 3 files changed, 1 insertion(+), 72 deletions(-) diff --git a/build.js b/build.js index d2ea92322..5e37b0d2c 100644 --- a/build.js +++ b/build.js @@ -88,6 +88,7 @@ function compileTest(test) { } newTest.code = compiledCode.join(test.combinator == 'and' ? ' && ' : ' || '); + delete newTest.combinator; return newTest; } diff --git a/test/unit/build.js b/test/unit/build.js index fa0854c61..9fced5ccd 100644 --- a/test/unit/build.js +++ b/test/unit/build.js @@ -516,12 +516,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Attr': { 'code': '"Attr" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.Attr.name': { 'code': '"Attr" in self && "name" in Attr.prototype', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -535,12 +533,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Node': { 'code': '"Node" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.Node.contains': { 'code': '"Node" in self && "contains" in Node.prototype', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -555,12 +551,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.MediaSource': { 'code': '"MediaSource" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.MediaSource.isTypeSupported': { 'code': '"MediaSource" in self && "isTypeSupported" in MediaSource', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -575,12 +569,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Window': { 'code': '"Window" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.Window.isWindow': { 'code': '"Window" in self && "isWindow" in Window', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -618,17 +610,14 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.ANGLE_instanced_arrays': { 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', - 'combinator': 'and', 'scope': ['Window'] }, 'api.ANGLE_instanced_arrays.drawArraysInstancedANGLE': { 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return true && instance && \'drawArraysInstancedANGLE\' in instance;})()', - 'combinator': 'and', 'scope': ['Window'] }, 'api.ANGLE_instanced_arrays.drawElementsInstancedANGLE': { 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -649,17 +638,14 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.WindowOrWorkerGlobalScope': { 'code': '"WindowOrWorkerGlobalScope" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.WindowOrWorkerGlobalScope.active': { 'code': '"active" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.WindowOrWorkerGlobalScope.isLoaded': { 'code': '"isLoaded" in self', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -673,12 +659,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Number': { 'code': '"Number" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.Number.Number': { 'code': '"Number" in self && bcd.testConstructor("Number")', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -690,12 +674,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Number': { 'code': '"Number" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.Number.Number': { 'code': '"Number" in self && bcd.testConstructor("Number")', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -708,32 +690,26 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.DoubleList': { 'code': '"DoubleList" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.@@iterator': { 'code': '"DoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in DoubleList.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.entries': { 'code': '"DoubleList" in self && "entries" in DoubleList.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.forEach': { 'code': '"DoubleList" in self && "forEach" in DoubleList.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.keys': { 'code': '"DoubleList" in self && "keys" in DoubleList.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleList.values': { 'code': '"DoubleList" in self && "values" in DoubleList.prototype', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -746,57 +722,46 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.DoubleMap': { 'code': '"DoubleMap" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.clear': { 'code': '"DoubleMap" in self && "clear" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.delete': { 'code': '"DoubleMap" in self && "delete" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.entries': { 'code': '"DoubleMap" in self && "entries" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.forEach': { 'code': '"DoubleMap" in self && "forEach" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.get': { 'code': '"DoubleMap" in self && "get" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.has': { 'code': '"DoubleMap" in self && "has" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.keys': { 'code': '"DoubleMap" in self && "keys" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.set': { 'code': '"DoubleMap" in self && "set" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.size': { 'code': '"DoubleMap" in self && "size" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleMap.values': { 'code': '"DoubleMap" in self && "values" in DoubleMap.prototype', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -809,47 +774,38 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.DoubleSet': { 'code': '"DoubleSet" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.add': { 'code': '"DoubleSet" in self && "add" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.clear': { 'code': '"DoubleSet" in self && "clear" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.delete': { 'code': '"DoubleSet" in self && "delete" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.entries': { 'code': '"DoubleSet" in self && "entries" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.has': { 'code': '"DoubleSet" in self && "has" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.keys': { 'code': '"DoubleSet" in self && "keys" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.size': { 'code': '"DoubleSet" in self && "size" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] }, 'api.DoubleSet.values': { 'code': '"DoubleSet" in self && "values" in DoubleSet.prototype', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -863,7 +819,6 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.GetMe': { 'code': '"GetMe" in self', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -879,22 +834,18 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { 'code': '"CSS" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.MessageChannel': { 'code': '"MessageChannel" in self', - 'combinator': 'and', 'scope': ['Window', 'Worker'] }, 'api.Worker': { 'code': '"Worker" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.WorkerSync': { 'code': '"WorkerSync" in self', - 'combinator': 'and', 'scope': ['Worker'] } }); @@ -911,12 +862,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.AudioNode': { 'code': '"AudioNode" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.AudioNode.disconnect': { 'code': '"AudioNode" in self && "disconnect" in AudioNode.prototype', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -930,12 +879,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { 'code': '"CSS" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.CSS.paintWorklet': { 'code': '"CSS" in self && "paintWorklet" in CSS', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -949,12 +896,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { 'code': '"CSS" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.CSS.supports': { 'code': '"CSS" in self && "supports" in CSS', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -981,12 +926,10 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { 'code': '(function() {var css = CSS;return !!css;})()', - 'combinator': 'and', 'scope': ['Window'] }, 'api.CSS.paintWorklet': { 'code': '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -1001,17 +944,14 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.ElementRegistrationOptions': { 'code': '"ElementRegistrationOptions" in self', - 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.extends': { 'code': '"ElementRegistrationOptions" in self && "extends" in ElementRegistrationOptions', - 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.prototype': { 'code': '"ElementRegistrationOptions" in self && "prototype" in ElementRegistrationOptions', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -1036,17 +976,14 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.ElementRegistrationOptions': { 'code': '(function() {var instance = ElementRegistrationOptions;return !!instance;})()', - 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.extends': { 'code': '(function() {var instance = ElementRegistrationOptions;return instance && \'extends\' in instance;})()', - 'combinator': 'and', 'scope': ['Window'] }, 'api.ElementRegistrationOptions.prototype': { 'code': '(function() {var instance = ElementRegistrationOptions;return instance && \'prototype\' in instance;})()', - 'combinator': 'and', 'scope': ['Window'] } }); @@ -1153,22 +1090,18 @@ describe('build', () => { assert.deepEqual(buildCSS(webref, bcd), { 'css.properties.appearance': { 'code': '"appearance" in document.body.style || CSS.supports("appearance", "inherit")', - 'combinator': 'or', 'scope': ['CSS'] }, 'css.properties.font-family': { 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', - 'combinator': 'or', 'scope': ['CSS'] }, 'css.properties.font-weight': { 'code': '"fontWeight" in document.body.style || CSS.supports("font-weight", "inherit")', - 'combinator': 'or', 'scope': ['CSS'] }, 'css.properties.grid': { 'code': '"grid" in document.body.style || CSS.supports("grid", "inherit")', - 'combinator': 'or', 'scope': ['CSS'] } }); diff --git a/test/unit/tests.js b/test/unit/tests.js index 28e387ef0..f987bc298 100644 --- a/test/unit/tests.js +++ b/test/unit/tests.js @@ -21,7 +21,6 @@ const MANIFEST = { tests: { 'api.AbortController': { 'code': '"AbortController" in self', - 'combinator': 'and', 'scope': [ 'Window', 'Worker' @@ -29,7 +28,6 @@ const MANIFEST = { }, 'api.AbortController.signal': { 'code': '"AbortController" in self && "signal" in AbortController', - 'combinator': 'and', 'scope': [ 'Window', 'Worker' @@ -82,19 +80,16 @@ describe('Tests', () => { assert.deepEqual(tests.getTests('/api/interfaces'), { 'api.AbortController': { 'code': '"AbortController" in self', - 'combinator': 'and', 'scope': ['Window', 'Worker'] }, 'api.AbortController.signal': { 'code': '"AbortController" in self && "signal" in AbortController', - 'combinator': 'and', 'scope': ['Window', 'Worker'] } }); assert.deepEqual(tests.getTests('/api/workerinterfaces'), { 'api.AbortController': { 'code': '"AbortController" in self', - 'combinator': 'and', 'scope': ['Window', 'Worker'] } }); From 6f2cde9267489ed0c313934323a1a7dba0cafef6 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 12:42:31 -0700 Subject: [PATCH 053/243] Remove Prettier --- .prettierrc | 5 ----- package-lock.json | 6 ------ package.json | 1 - 3 files changed, 12 deletions(-) delete mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 5cc08c868..000000000 --- a/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "arrowParens": "avoid", - "proseWrap": "always", - "printWidth": "80" -} diff --git a/package-lock.json b/package-lock.json index 7f801e6f8..8bc8d6557 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4008,12 +4008,6 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "prettier": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz", - "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==", - "dev": true - }, "prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", diff --git a/package.json b/package.json index 2b3049b41..857d47c0d 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "eslint-plugin-prettier": "^3.1.4", "mocha": "8.1.1", "nyc": "15.1.0", - "prettier": "^2.1.1", "proxyquire": "2.1.3", "puppeteer": "5.2.1", "selenium-webdriver": "^3.6.0", From 18eac00d6831e0a183e83fae96a9fd55f7e09f50 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 12:43:05 -0700 Subject: [PATCH 054/243] Revert "Change /api/ to /backend/ for all backend" This reverts commit 6b47a5e8bd680620162280287512f8254dd11b9a. --- app.js | 8 ++++---- static/index.html | 2 +- static/resources/harness.js | 4 +--- static/results/index.html | 4 ++-- test/app/results.js | 22 +++++++++++----------- test/app/tests.js | 4 ++-- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/app.js b/app.js index e2ba791b9..5c922501f 100644 --- a/app.js +++ b/app.js @@ -121,13 +121,13 @@ app.use(express.json({limit: '32mb'})); app.use(express.static('static')); app.use(express.static('generated')); -app.get('/backend/tests', (req, res) => { +app.get('/api/tests', (req, res) => { const list = tests.listEndpoints(); const individualList = tests.listIndividual(); res.json([list, individualList]); }); -app.post('/backend/results', (req, res) => { +app.post('/api/results', (req, res) => { if (!req.is('json')) { res.status(400).end(); return; @@ -163,7 +163,7 @@ app.post('/backend/results', (req, res) => { .catch(/* istanbul ignore next */ (err) => catchError(err, res)); }); -app.get('/backend/results', (req, res) => { +app.get('/api/results', (req, res) => { storage.getAll(req.sessionID) .then((results) => { res.status(200).json(results); @@ -172,7 +172,7 @@ app.get('/backend/results', (req, res) => { }); /* istanbul ignore next: we don't want to create lots of dummy PRs */ -app.post('/backend/results/export/github', (req, res) => { +app.post('/api/results/export/github', (req, res) => { storage.getAll(req.sessionID) .then(async (results) => { const userAgent = req.get('User-Agent'); diff --git a/static/index.html b/static/index.html index 5301e15af..748bb6a23 100644 --- a/static/index.html +++ b/static/index.html @@ -24,7 +24,7 @@ var button = document.getElementById('start'); var dropdown = document.getElementById('tests'); var client = new XMLHttpRequest(); - client.open('GET', '/backend/tests', true); + client.open('GET', '/api/tests', true); client.send(); client.onreadystatechange = function() { if (client.readyState == 4) { diff --git a/static/resources/harness.js b/static/resources/harness.js index 978739d2b..3a9e59769 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -477,9 +477,7 @@ function report(results) { var body = JSON.stringify(results); var client = new XMLHttpRequest(); - client.open( - 'POST', '/backend/results?for='+encodeURIComponent(location.href) - ); + client.open('POST', '/api/results?for='+encodeURIComponent(location.href)); client.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); client.send(body); client.onreadystatechange = function() { diff --git a/static/results/index.html b/static/results/index.html index 6f7f00583..a82bc8019 100644 --- a/static/results/index.html +++ b/static/results/index.html @@ -16,7 +16,7 @@ Loading page...
Back to start page @@ -27,7 +27,7 @@ var status = document.getElementById('status'); var link = document.getElementById('link'); var client = new XMLHttpRequest(); - client.open('POST', '/backend/results/export/github', true); + client.open('POST', '/api/results/export/github', true); client.send(); status.textContent = 'Exporting...'; client.onreadystatechange = function() { diff --git a/test/app/results.js b/test/app/results.js index 3da882711..56b3c8c47 100644 --- a/test/app/results.js +++ b/test/app/results.js @@ -25,22 +25,22 @@ chai.use(chaiHttp); const agent = chai.request.agent(app); const assert = chai.assert; -describe('/backend/results', () => { +describe('/api/results', () => { it('missing `Content-Type` header', async () => { - const res = await agent.post('/backend/results') + const res = await agent.post('/api/results') .set('Content-Type', 'text/plain') .send('string'); assert.equal(res.status, 400); }); it('missing `for` param', async () => { - const res = await agent.post('/backend/results') + const res = await agent.post('/api/results') .send({}); assert.equal(res.status, 400); }); it('list results before', async () => { - const res = await agent.get('/backend/results'); + const res = await agent.get('/api/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, {}); }); @@ -49,7 +49,7 @@ describe('/backend/results', () => { const testURL2 = `https://host.test${manifestItems[manifestItems.length - 1][0]}`; it('submit valid results', async () => { - const res = await agent.post('/backend/results') + const res = await agent.post('/api/results') .query({for: testURL}) .send({x: 1}); assert.equal(res.status, 201); @@ -59,7 +59,7 @@ describe('/backend/results', () => { }); it('list results after valid', async () => { - const res = await agent.get('/backend/results'); + const res = await agent.get('/api/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { '__version': version, @@ -68,14 +68,14 @@ describe('/backend/results', () => { }); it('submit duplicate results', async () => { - const res = await agent.post('/backend/results') + const res = await agent.post('/api/results') .query({for: testURL}) .send({x: 2}); assert.equal(res.status, 201); }); it('list results after duplicate', async () => { - const res = await agent.get('/backend/results'); + const res = await agent.get('/api/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { '__version': version, @@ -84,7 +84,7 @@ describe('/backend/results', () => { }); it('submit results for new/last manifest', async () => { - const res = await agent.post('/backend/results') + const res = await agent.post('/api/results') .query({for: testURL2}) .send({y: 3}); assert.equal(res.status, 201); @@ -92,7 +92,7 @@ describe('/backend/results', () => { }); it('list results after new/last manifest', async () => { - const res = await agent.get('/backend/results'); + const res = await agent.get('/api/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { '__version': version, @@ -102,7 +102,7 @@ describe('/backend/results', () => { }); it('submit invalid results', async () => { - const res = await agent.post('/backend/results') + const res = await agent.post('/api/results') .query({for: testURL}) .send('my bad results'); assert.equal(res.status, 400); diff --git a/test/app/tests.js b/test/app/tests.js index 5334f34bd..e914db1d0 100644 --- a/test/app/tests.js +++ b/test/app/tests.js @@ -22,9 +22,9 @@ chai.use(chaiHttp); const agent = chai.request.agent(app); const assert = chai.assert; -describe('/backend/tests', () => { +describe('/api/tests', () => { it('list tests', async () => { - const res = await agent.get('/backend/tests'); + const res = await agent.get('/api/tests'); assert.equal(res.status, 200); assert.isArray(res.body); assert.isArray(res.body[0]); From ce91c538c44cf285597d4a15f4841172c8b7696d Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 13:17:17 -0700 Subject: [PATCH 055/243] Place all tests under /tests/ --- build.js | 12 ++++++------ tests.js | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build.js b/build.js index 5e37b0d2c..f6b2151fa 100644 --- a/build.js +++ b/build.js @@ -572,17 +572,17 @@ async function build(webref, bcd) { let endpoint = ''; switch (scope) { case 'Window': - endpoint = '/api/interfaces'; + endpoint = '/tests/api/interfaces'; break; case 'Worker': case 'DedicatedWorker': - endpoint = '/api/workerinterfaces'; + endpoint = '/tests/api/workerinterfaces'; break; case 'ServiceWorker': - endpoint = '/api/serviceworkerinterfaces'; + endpoint = '/tests/api/serviceworkerinterfaces'; break; case 'CSS': - endpoint = '/css/properties'; + endpoint = '/tests/css/properties'; break; } @@ -600,11 +600,11 @@ async function build(webref, bcd) { } } - let url = ''; + let url = '/tests'; for (const part of ident.split('.')) { url += '/' + part; - if (['/api', '/css', '/css/properties'].includes(url)) { + if (['/tests/api', '/tests/css', '/tests/css/properties'].includes(url)) { // Ignore things tested in main endpoints continue; } diff --git a/tests.js b/tests.js index 3866eefa4..76ce54dce 100644 --- a/tests.js +++ b/tests.js @@ -74,9 +74,9 @@ class Tests { } listIndividual() { - return Object.keys(this.individualEndpoints).map((item) => { - return [item.substr(1).replace(/\//g, '.'), item]; - }); + return Object.keys(this.individualEndpoints).map((item) => ( + [item.substr(1).replace('tests/', '').replace(/\//g, '.'), item] + )); } } From 33d2b3fba789236a90b01bb13a83d94e3a095eb0 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 13:19:34 -0700 Subject: [PATCH 056/243] Move /test/ to /unittest/ --- build.js | 6 +++--- static/{test => unittest}/index.html | 0 static/{test => unittest}/test.js | 0 test/puppeteer/harness.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename static/{test => unittest}/index.html (100%) rename static/{test => unittest}/test.js (100%) diff --git a/build.js b/build.js index f6b2151fa..ceb0ffbaf 100644 --- a/build.js +++ b/build.js @@ -522,9 +522,9 @@ function copyResources() { ['json3/lib/json3.min.js', 'resources'], ['core-js-bundle/minified.js', 'resources', 'core.js'], ['core-js-bundle/minified.js.map', 'resources', 'core.js.map'], - ['chai/chai.js', 'test'], - ['mocha/mocha.css', 'test'], - ['mocha/mocha.js', 'test'] + ['chai/chai.js', 'unittest'], + ['mocha/mocha.css', 'unittest'], + ['mocha/mocha.js', 'unittest'] ]; for (const [srcInModules, destInGenerated, newFilename] of resources) { const src = require.resolve(srcInModules); diff --git a/static/test/index.html b/static/unittest/index.html similarity index 100% rename from static/test/index.html rename to static/unittest/index.html diff --git a/static/test/test.js b/static/unittest/test.js similarity index 100% rename from static/test/test.js rename to static/unittest/test.js diff --git a/test/puppeteer/harness.js b/test/puppeteer/harness.js index 25eaf2d92..c87c447b9 100644 --- a/test/puppeteer/harness.js +++ b/test/puppeteer/harness.js @@ -49,7 +49,7 @@ describe('/resources/harness.js', () => { }); page.on('error', reject); }); - await page.goto(`http://localhost:${port}/test/#reporter=json`); + await page.goto(`http://localhost:${port}/unittest/#reporter=json`); const report = await reportPromise; assert.equal(report.stats.failures, 0); }); From 435c73d3544d6776ba0812a9e16b7546375cd976 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:03:45 -0700 Subject: [PATCH 057/243] Move Selenium file to root --- package.json | 4 ++-- test/selenium/selenium.js => selenium.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename test/selenium/selenium.js => selenium.js (98%) diff --git a/package.json b/package.json index 857d47c0d..466d52db2 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,10 @@ "gcp-build": "npm run build", "deploy": "gcloud app deploy", "start": "node app.js", - "coverage": "NODE_ENV=test nyc mocha --recursive test --exclude test/puppeteer/* --exclude test/selenium/*", + "coverage": "NODE_ENV=test nyc mocha --recursive test --exclude test/puppeteer/*", "puppeteer": "NODE_ENV=test mocha test/puppeteer --timeout 30000 --slow 10000", "test": "npm run coverage && npm run puppeteer", - "selenium": "mocha test/selenium", + "selenium": "mocha selenium", "update-bcd": "node update-bcd.js" }, "dependencies": { diff --git a/test/selenium/selenium.js b/selenium.js similarity index 98% rename from test/selenium/selenium.js rename to selenium.js index df8346f53..dd707d7bd 100644 --- a/test/selenium/selenium.js +++ b/selenium.js @@ -50,7 +50,7 @@ if (process.env.BROWSER) { browsersToTest = {[process.env.BROWSER]: browsersToTest[process.env.BROWSER]}; } -const secrets = require('../../secrets.json'); +const secrets = require('./secrets.json'); const host = process.env.NODE_ENV === 'test' ? `http://localhost:8080` : From f2ea990061409874e8d4b07ffa34f52889939075 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:05:14 -0700 Subject: [PATCH 058/243] Make npm run test perform lint and unit tests --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 466d52db2..8d754ed70 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "start": "node app.js", "coverage": "NODE_ENV=test nyc mocha --recursive test --exclude test/puppeteer/*", "puppeteer": "NODE_ENV=test mocha test/puppeteer --timeout 30000 --slow 10000", - "test": "npm run coverage && npm run puppeteer", + "unittest": "npm run coverage && npm run puppeteer", + "test": "npm run lint && npm run unittest", "selenium": "mocha selenium", "update-bcd": "node update-bcd.js" }, From 8d71cc06244d9ba4e20c40d3dda5b646586a62a4 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:09:35 -0700 Subject: [PATCH 059/243] Finish moving /test/ to /unittest/ --- README.md | 2 +- package.json | 4 ++-- {test => unittest}/app/results.js | 0 {test => unittest}/app/tests.js | 0 {test => unittest}/integration/reffy-reports.js | 0 {test => unittest}/puppeteer/harness.js | 0 {test => unittest}/unit/build.js | 0 {test => unittest}/unit/github.js | 0 {test => unittest}/unit/storage.js | 0 {test => unittest}/unit/tests.js | 0 {test => unittest}/unit/update-bcd.js | 0 11 files changed, 3 insertions(+), 3 deletions(-) rename {test => unittest}/app/results.js (100%) rename {test => unittest}/app/tests.js (100%) rename {test => unittest}/integration/reffy-reports.js (100%) rename {test => unittest}/puppeteer/harness.js (100%) rename {test => unittest}/unit/build.js (100%) rename {test => unittest}/unit/github.js (100%) rename {test => unittest}/unit/storage.js (100%) rename {test => unittest}/unit/tests.js (100%) rename {test => unittest}/unit/update-bcd.js (100%) diff --git a/README.md b/README.md index b12a04a4b..bda0977e0 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,6 @@ You can also test just a single browser by defining the `BROWSER` environment va BROWSER=chrome npm run selenium -## Running the tests +## Running the unit tests and linter npm test diff --git a/package.json b/package.json index 8d754ed70..f61102e1f 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "gcp-build": "npm run build", "deploy": "gcloud app deploy", "start": "node app.js", - "coverage": "NODE_ENV=test nyc mocha --recursive test --exclude test/puppeteer/*", - "puppeteer": "NODE_ENV=test mocha test/puppeteer --timeout 30000 --slow 10000", + "coverage": "NODE_ENV=test nyc mocha --recursive unittest --exclude unittest/puppeteer/*", + "puppeteer": "NODE_ENV=test mocha unittest/puppeteer --timeout 30000 --slow 10000", "unittest": "npm run coverage && npm run puppeteer", "test": "npm run lint && npm run unittest", "selenium": "mocha selenium", diff --git a/test/app/results.js b/unittest/app/results.js similarity index 100% rename from test/app/results.js rename to unittest/app/results.js diff --git a/test/app/tests.js b/unittest/app/tests.js similarity index 100% rename from test/app/tests.js rename to unittest/app/tests.js diff --git a/test/integration/reffy-reports.js b/unittest/integration/reffy-reports.js similarity index 100% rename from test/integration/reffy-reports.js rename to unittest/integration/reffy-reports.js diff --git a/test/puppeteer/harness.js b/unittest/puppeteer/harness.js similarity index 100% rename from test/puppeteer/harness.js rename to unittest/puppeteer/harness.js diff --git a/test/unit/build.js b/unittest/unit/build.js similarity index 100% rename from test/unit/build.js rename to unittest/unit/build.js diff --git a/test/unit/github.js b/unittest/unit/github.js similarity index 100% rename from test/unit/github.js rename to unittest/unit/github.js diff --git a/test/unit/storage.js b/unittest/unit/storage.js similarity index 100% rename from test/unit/storage.js rename to unittest/unit/storage.js diff --git a/test/unit/tests.js b/unittest/unit/tests.js similarity index 100% rename from test/unit/tests.js rename to unittest/unit/tests.js diff --git a/test/unit/update-bcd.js b/unittest/unit/update-bcd.js similarity index 100% rename from test/unit/update-bcd.js rename to unittest/unit/update-bcd.js From f0dde30f7e4eda70e9094adcf3bc2005bbb695ff Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:12:30 -0700 Subject: [PATCH 060/243] Remove Prettier from ESLint --- .eslintrc.json | 1 - package-lock.json | 24 ------------------------ package.json | 1 - static/.eslintrc.json | 12 ++++++++++-- 4 files changed, 10 insertions(+), 28 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index e05271cd1..e47ec3714 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,5 @@ { "extends": ["eslint:recommended", "google"], - "plugins": ["prettier"], "parser": "babel-eslint", "parserOptions": { "ecmaVersion": 8 diff --git a/package-lock.json b/package-lock.json index 8bc8d6557..98f2e7015 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1917,15 +1917,6 @@ "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", "dev": true }, - "eslint-plugin-prettier": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", - "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, "eslint-scope": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", @@ -2125,12 +2116,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4008,15 +3993,6 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", diff --git a/package.json b/package.json index f61102e1f..aec9a25f8 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "compare-versions": "^3.6.0", "eslint": "7.8.0", "eslint-config-google": "0.14.0", - "eslint-plugin-prettier": "^3.1.4", "mocha": "8.1.1", "nyc": "15.1.0", "proxyquire": "2.1.3", diff --git a/static/.eslintrc.json b/static/.eslintrc.json index 6fa1c04e2..ba3dda857 100644 --- a/static/.eslintrc.json +++ b/static/.eslintrc.json @@ -1,6 +1,5 @@ { "extends": ["eslint:recommended", "google"], - "plugins": ["prettier"], "parserOptions": { "ecmaVersion": 3 }, @@ -9,7 +8,16 @@ "require-jsdoc": "off", "no-var": "off", "guard-for-in": "off", - "no-invalid-this": "off" + "no-invalid-this": "off", + "max-len": ["error", { + "code": 80, + "tabWidth": 2, + "ignoreStrings": true, + "ignoreTemplateLiterals": true, + "ignoreRegExpLiterals": true, + "ignoreUrls": true, + "ignorePattern": "goog.(module|require)" + }] }, "root": true } From 580a4eae749b36275223ac22b9323eb795a73a20 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:15:52 -0700 Subject: [PATCH 061/243] Don't include copyright in generated test files --- app.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app.js b/app.js index 5c922501f..2ea775c32 100644 --- a/app.js +++ b/app.js @@ -73,13 +73,6 @@ function generateTestPage(endpoint) { '', '', '', - '', '', '', '', From 1715f919557e1bded37f6f86b1157d59649c56a7 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:22:06 -0700 Subject: [PATCH 062/243] Add .nycrc --- .nycrc.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .nycrc.json diff --git a/.nycrc.json b/.nycrc.json new file mode 100644 index 000000000..3a4ab208e --- /dev/null +++ b/.nycrc.json @@ -0,0 +1,8 @@ +{ + "all": true, + "exclude": [ + "**/generated/**", + "**/static/**", + "**/unittest/**" + ] +} \ No newline at end of file From 048930a64ca96d378f59ee1fa238af528141bfdd Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:42:49 -0700 Subject: [PATCH 063/243] Include harness.js coverage in nyc reports --- .nycrc.json | 3 +- package-lock.json | 131 ++++++++++++++++++++++++++++++++++ package.json | 1 + unittest/puppeteer/harness.js | 12 +++- 4 files changed, 145 insertions(+), 2 deletions(-) diff --git a/.nycrc.json b/.nycrc.json index 3a4ab208e..35b4de0cf 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -3,6 +3,7 @@ "exclude": [ "**/generated/**", "**/static/**", - "**/unittest/**" + "**/unittest/**", + "**/json3.min.js" ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 98f2e7015..40648841f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1395,6 +1395,12 @@ } } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, "color": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", @@ -4167,6 +4173,125 @@ } } }, + "puppeteer-to-istanbul": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/puppeteer-to-istanbul/-/puppeteer-to-istanbul-1.4.0.tgz", + "integrity": "sha512-dzW8u/PMqMZppvoXCFod8IkCTI2JL0yP2YUBbaALnX+iJJ6gqjk77fIoK9MqnMqRZAcoa81GLFfZExakWg/Q4Q==", + "dev": true, + "requires": { + "clone": "^2.1.2", + "mkdirp": "^1.0.4", + "v8-to-istanbul": "^1.2.1", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", @@ -4968,6 +5093,12 @@ "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", "dev": true }, + "v8-to-istanbul": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-1.2.1.tgz", + "integrity": "sha512-NglPycIwSQeSJj7VJ6L8vTsPKC9MG5Lcx4n3SvYqNHzklbMI4dGcLJnkLPEPJ3uB8UyTdWviMhM0Ptq+xD5UFQ==", + "dev": true + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index aec9a25f8..01e309c58 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "nyc": "15.1.0", "proxyquire": "2.1.3", "puppeteer": "5.2.1", + "puppeteer-to-istanbul": "^1.4.0", "selenium-webdriver": "^3.6.0", "sinon": "9.0.3" } diff --git a/unittest/puppeteer/harness.js b/unittest/puppeteer/harness.js index c87c447b9..4a0716f5c 100644 --- a/unittest/puppeteer/harness.js +++ b/unittest/puppeteer/harness.js @@ -16,6 +16,7 @@ const assert = require('assert'); const puppeteer = require('puppeteer'); +const pti = require('puppeteer-to-istanbul'); const {app} = require('../../app'); @@ -41,6 +42,8 @@ describe('/resources/harness.js', () => { after(() => browser.close()); const page = await browser.newPage(); + if (product == 'chrome') await page.coverage.startJSCoverage(); + const reportPromise = new Promise((resolve, reject) => { page.on('console', (msg) => { if (msg.type() === consoleLogType[product]) { @@ -49,9 +52,16 @@ describe('/resources/harness.js', () => { }); page.on('error', reject); }); + await page.goto(`http://localhost:${port}/unittest/#reporter=json`); const report = await reportPromise; + + if (product == 'chrome') { + const jsCoverage = await page.coverage.stopJSCoverage(); + pti.write([...jsCoverage], { includeHostname: false, storagePath: './.nyc_output' }) + } + assert.equal(report.stats.failures, 0); - }); + }).slow(10000).timeout(30000); } }); From e5bd910e8c0c7ff2bb2a23f95f311b5c6a84947b Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:43:31 -0700 Subject: [PATCH 064/243] Merge npm run coverage && npm run puppeteer into npm run unittest --- .github/workflows/pull_request.yml | 3 +-- .github/workflows/push.yml | 3 +-- package.json | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 5ca268154..4b86b1026 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -12,7 +12,6 @@ jobs: - run: npm ci - run: npm run lint - run: npm run build - - run: npm run coverage - - run: npm run puppeteer + - run: npm run unittest env: FORCE_COLOR: 3 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6df1d3d18..7316fc89e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -15,8 +15,7 @@ jobs: - run: npm ci - run: npm run lint - run: npm run build - - run: npm run coverage - - run: npm run puppeteer + - run: npm run unittest deploy: name: Deploy needs: test diff --git a/package.json b/package.json index 01e309c58..df4949def 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,7 @@ "gcp-build": "npm run build", "deploy": "gcloud app deploy", "start": "node app.js", - "coverage": "NODE_ENV=test nyc mocha --recursive unittest --exclude unittest/puppeteer/*", - "puppeteer": "NODE_ENV=test mocha unittest/puppeteer --timeout 30000 --slow 10000", - "unittest": "npm run coverage && npm run puppeteer", + "unittest": "NODE_ENV=test nyc mocha --recursive unittest", "test": "npm run lint && npm run unittest", "selenium": "mocha selenium", "update-bcd": "node update-bcd.js" From 4ba1beb92dccc2e4a604ce4fc73e7ecb8ea8d673 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:45:52 -0700 Subject: [PATCH 065/243] Fix ESLint issues --- unittest/puppeteer/harness.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/puppeteer/harness.js b/unittest/puppeteer/harness.js index 4a0716f5c..24b7344a6 100644 --- a/unittest/puppeteer/harness.js +++ b/unittest/puppeteer/harness.js @@ -58,7 +58,7 @@ describe('/resources/harness.js', () => { if (product == 'chrome') { const jsCoverage = await page.coverage.stopJSCoverage(); - pti.write([...jsCoverage], { includeHostname: false, storagePath: './.nyc_output' }) + pti.write(jsCoverage, {includeHostname: false, storagePath: './.nyc_output'}); } assert.equal(report.stats.failures, 0); From 82a6d54f822ebbd1253709aaf69596a004592084 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:49:52 -0700 Subject: [PATCH 066/243] Move test page generation to Tests class --- app.js | 47 ++--------------------------------------------- tests.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/app.js b/app.js index 2ea775c32..af314ff5e 100644 --- a/app.js +++ b/app.js @@ -64,49 +64,6 @@ function catchError(err, res) { res.status(500).end(); } -function generateTestPage(endpoint) { - const theseTests = tests.getTests(endpoint); - let testScope = tests.getScope(endpoint); - let individual = false; - - const lines = [ - '', - '', - '', - '', - '', - '', - '', - '', - '', - '

Running tests...

', - '', '', ''); - - return lines.join('\n'); -} - const app = express(); app.use(cookieParser()); app.use(cookieSession); @@ -182,13 +139,13 @@ app.post('/api/results/export/github', (req, res) => { for (const endpoint of tests.listEndpoints()) { app.get(endpoint, (req, res) => { - res.send(generateTestPage(endpoint)); + res.send(tests.generateTestPage(endpoint)); }); } for (const [_, endpoint] of tests.listIndividual()) { app.get(endpoint, (req, res) => { - res.send(generateTestPage(endpoint)); + res.send(tests.generateTestPage(endpoint)); }); } diff --git a/tests.js b/tests.js index 76ce54dce..7cda67f37 100644 --- a/tests.js +++ b/tests.js @@ -69,6 +69,49 @@ class Tests { return e ? e.scope : ''; } + generateTestPage(endpoint) { + const theseTests = this.getTests(endpoint); + let testScope = this.getScope(endpoint); + let individual = false; + + const lines = [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '

Running tests...

', + '', '', ''); + + return lines.join('\n'); + } + listEndpoints() { return Object.keys(this.endpoints); } From f518398f37f81e6c7a16a73a9743673e17550978 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:56:26 -0700 Subject: [PATCH 067/243] Simplify endpoint generation --- app.js | 13 +++---------- tests.js | 29 ++++++++++++++++++----------- unittest/unit/tests.js | 39 ++++++++++++++++++++++++--------------- 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/app.js b/app.js index af314ff5e..f15100a3a 100644 --- a/app.js +++ b/app.js @@ -72,9 +72,7 @@ app.use(express.static('static')); app.use(express.static('generated')); app.get('/api/tests', (req, res) => { - const list = tests.listEndpoints(); - const individualList = tests.listIndividual(); - res.json([list, individualList]); + res.json([tests.listMainEndpoints(), tests.listIndividual()]); }); app.post('/api/results', (req, res) => { @@ -100,6 +98,7 @@ app.post('/api/results', (req, res) => { response.next = next; } } catch (err) { + /* istanbul ignore next */ logger.warn(`Results submitted for URL not in manifest: ${forURL}`); // note: indistinguishable from finishing last test to client } @@ -137,13 +136,7 @@ app.post('/api/results/export/github', (req, res) => { .catch(/* istanbul ignore next */ (err) => catchError(err, res)); }); -for (const endpoint of tests.listEndpoints()) { - app.get(endpoint, (req, res) => { - res.send(tests.generateTestPage(endpoint)); - }); -} - -for (const [_, endpoint] of tests.listIndividual()) { +for (const endpoint of tests.listAllEndpoints()) { app.get(endpoint, (req, res) => { res.send(tests.generateTestPage(endpoint)); }); diff --git a/tests.js b/tests.js index 7cda67f37..3616d49a1 100644 --- a/tests.js +++ b/tests.js @@ -23,12 +23,29 @@ class Tests { this.httpOnly = options.httpOnly; } + listMainEndpoints() { + return Object.keys(this.endpoints); + } + + listIndividual() { + return Object.keys(this.individualEndpoints).map((item) => ( + [item.substr(1).replace('tests/', '').replace(/\//g, '.'), item] + )); + } + + listAllEndpoints() { + return [ + ...this.listMainEndpoints(), + ...this.listIndividual().map((item) => (item[1])) + ]; + } + next(after) { const afterURL = new URL(after); if (!this.httpOnly && afterURL.protocol === 'http:') { return `https://${this.host}${afterURL.pathname}`; } else { - const endpoints = this.listEndpoints(); + const endpoints = this.listMainEndpoints(); const index = endpoints.findIndex((item) => { return item === afterURL.pathname; }) + 1; @@ -111,16 +128,6 @@ class Tests { return lines.join('\n'); } - - listEndpoints() { - return Object.keys(this.endpoints); - } - - listIndividual() { - return Object.keys(this.individualEndpoints).map((item) => ( - [item.substr(1).replace('tests/', '').replace(/\//g, '.'), item] - )); - } } module.exports = Tests; diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index f987bc298..d4dcd26c0 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -76,6 +76,30 @@ describe('Tests', () => { host: 'host.test' }); + it('listMainEndpoints', () => { + assert.deepEqual(tests.listMainEndpoints(), [ + '/api/interfaces', + '/api/workerinterfaces', + '/api/serviceworkerinterfaces' + ]); + }); + + it('listIndividual', () => { + assert.deepEqual(tests.listIndividual(), [ + ['api.AbortController', '/api/AbortController'], + ['api.AbortController.signal', '/api/AbortController/signal'] + ]); + }); + + it('listAllEndpoints', () => { + assert.deepEqual(tests.listAllEndpoints(), [ + '/api/interfaces', + '/api/workerinterfaces', + '/api/serviceworkerinterfaces', + '/api/AbortController', + '/api/AbortController/signal' + ]); + }); it('getTests', () => { assert.deepEqual(tests.getTests('/api/interfaces'), { 'api.AbortController': { @@ -100,19 +124,4 @@ describe('Tests', () => { assert.equal(tests.getScope('/api/serviceworkerinterfaces'), 'ServiceWorker'); assert.equal(tests.getScope('/api/dummy'), ''); }); - - it('listEndpoints', () => { - assert.deepEqual(tests.listEndpoints(), [ - '/api/interfaces', - '/api/workerinterfaces', - '/api/serviceworkerinterfaces' - ]); - }); - - it('listIndividual', () => { - assert.deepEqual(tests.listIndividual(), [ - ['api.AbortController', '/api/AbortController'], - ['api.AbortController.signal', '/api/AbortController/signal'] - ]); - }); }); From ae904dc8fe5d64cfd43a4d6f337bd97e90c517d6 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 14:59:47 -0700 Subject: [PATCH 068/243] Consolidate app.js tests --- unittest/app/{results.js => app.js} | 18 +++++++++++++++ unittest/app/tests.js | 36 ----------------------------- 2 files changed, 18 insertions(+), 36 deletions(-) rename unittest/app/{results.js => app.js} (87%) delete mode 100644 unittest/app/tests.js diff --git a/unittest/app/results.js b/unittest/app/app.js similarity index 87% rename from unittest/app/results.js rename to unittest/app/app.js index 56b3c8c47..e04bcee39 100644 --- a/unittest/app/results.js +++ b/unittest/app/app.js @@ -109,4 +109,22 @@ describe('/api/results', () => { }); }); +describe('/api/tests', () => { + it('list tests', async () => { + const res = await agent.get('/api/tests'); + assert.equal(res.status, 200); + assert.isArray(res.body); + assert.isArray(res.body[0]); + assert.isArray(res.body[1]); + assert.equal(res.body.length, 2); + }); +}); + +describe('/tests/', () => { + it('get first test', async () => { + const res = await agent.get(manifestItems[0][0]); + assert.equal(res.status, 200); + }); +}); + after(() => agent.close()); diff --git a/unittest/app/tests.js b/unittest/app/tests.js deleted file mode 100644 index e914db1d0..000000000 --- a/unittest/app/tests.js +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -const {app} = require('../../app'); -const chai = require('chai'); -const chaiHttp = require('chai-http'); - -chai.use(chaiHttp); -const agent = chai.request.agent(app); -const assert = chai.assert; - -describe('/api/tests', () => { - it('list tests', async () => { - const res = await agent.get('/api/tests'); - assert.equal(res.status, 200); - assert.isArray(res.body); - assert.isArray(res.body[0]); - assert.isArray(res.body[1]); - assert.equal(res.body.length, 2); - }); -}); - -after(() => agent.close()); From b2eabcfb2949f2c326b80bfc7020d38b063ba7ab Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 15:06:25 -0700 Subject: [PATCH 069/243] Account for reffy->webref rename in tests --- unittest/integration/{reffy-reports.js => webref.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename unittest/integration/{reffy-reports.js => webref.js} (100%) diff --git a/unittest/integration/reffy-reports.js b/unittest/integration/webref.js similarity index 100% rename from unittest/integration/reffy-reports.js rename to unittest/integration/webref.js From be1cf71cc83b8bacd44c208bc6eb727c2db402e5 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 15:25:47 -0700 Subject: [PATCH 070/243] Stringify dictionaries in writeFile() --- build.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.js b/build.js index ceb0ffbaf..0496f88e7 100644 --- a/build.js +++ b/build.js @@ -27,8 +27,11 @@ const generatedDir = path.join(__dirname, 'generated'); async function writeFile(filename, content) { if (Array.isArray(content)) { content = content.join('\n'); + } else if (typeof content === 'Object') { + content = JSON.stringify(content, null, ' '); } content = content.trimEnd() + '\n'; + await fs.ensureDir(path.dirname(filename)); await fs.writeFile(filename, content, 'utf8'); } From 56c83ef22a4967b4ea92804117ba251cae2efd42 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 15:26:00 -0700 Subject: [PATCH 071/243] Remove redundant writeManifest function --- build.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/build.js b/build.js index 0496f88e7..caabf2872 100644 --- a/build.js +++ b/build.js @@ -516,10 +516,6 @@ function buildCSS(webref, bcd) { return tests; } -async function writeManifest(manifest) { - await writeFile('MANIFEST.json', JSON.stringify(manifest, null, ' ')); -} - function copyResources() { const resources = [ ['json3/lib/json3.min.js', 'resources'], @@ -622,7 +618,7 @@ async function build(webref, bcd) { } } - await writeManifest(manifest); + await writeFile('MANIFEST.json', manifest); copyResources(); } From 2d11403b04e5e39337b9503cda645ec407aa2b31 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 15:53:01 -0700 Subject: [PATCH 072/243] Fix issues in writeFile --- build.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.js b/build.js index caabf2872..5ba5af02f 100644 --- a/build.js +++ b/build.js @@ -27,11 +27,11 @@ const generatedDir = path.join(__dirname, 'generated'); async function writeFile(filename, content) { if (Array.isArray(content)) { content = content.join('\n'); - } else if (typeof content === 'Object') { + } else if (typeof content === 'object') { content = JSON.stringify(content, null, ' '); } content = content.trimEnd() + '\n'; - + await fs.ensureDir(path.dirname(filename)); await fs.writeFile(filename, content, 'utf8'); } From 4cad78eb3455cbff202009c3769fd775cef1440a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 15:53:16 -0700 Subject: [PATCH 073/243] Make copyResources() asynchronous --- build.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build.js b/build.js index 5ba5af02f..1dd95f93e 100644 --- a/build.js +++ b/build.js @@ -516,7 +516,7 @@ function buildCSS(webref, bcd) { return tests; } -function copyResources() { +async function copyResources() { const resources = [ ['json3/lib/json3.min.js', 'resources'], ['core-js-bundle/minified.js', 'resources', 'core.js'], @@ -529,16 +529,16 @@ function copyResources() { const src = require.resolve(srcInModules); const destDir = path.join(generatedDir, destInGenerated); const dest = path.join(destDir, path.basename(src)); - fs.ensureDirSync(path.dirname(dest)); - fs.copyFileSync(src, dest); + await fs.ensureDir(path.dirname(dest)); + await fs.copyFile(src, dest); if (newFilename) { - fs.renameSync(dest, path.join(destDir, newFilename)); + await fs.rename(dest, path.join(destDir, newFilename)); } } // Fix source mapping in core-js const corejsPath = path.join(generatedDir, 'resources', 'core.js'); - fs.readFile(corejsPath, 'utf8', function(err, data) { + await fs.readFile(corejsPath, 'utf8', function(err, data) { if (err) { return console.log(err); } @@ -547,7 +547,7 @@ function copyResources() { 'sourceMappingURL=core.js.map' ); - fs.writeFile(corejsPath, result, 'utf8', function(err) { + fs.writeFileSync(corejsPath, result, 'utf8', function(err) { if (err) return console.log(err); }); }); @@ -619,7 +619,7 @@ async function build(webref, bcd) { } await writeFile('MANIFEST.json', manifest); - copyResources(); + await copyResources(); } /* istanbul ignore if */ From 990e66d7f691fc5f193a3e9ea9688d2d3703b04d Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 15:57:06 -0700 Subject: [PATCH 074/243] Add additional tests/coverage ignore statements --- app.js | 15 ++++++++------- build.js | 2 ++ logger.js | 1 + unittest/app/app.js | 18 ++++++++++++------ unittest/unit/build.js | 5 +++++ unittest/unit/tests.js | 1 + 6 files changed, 29 insertions(+), 13 deletions(-) diff --git a/app.js b/app.js index f15100a3a..b06d226ac 100644 --- a/app.js +++ b/app.js @@ -23,6 +23,13 @@ const logger = require('./logger'); const appversion = require('./package.json').version; const PORT = process.env.PORT || 8080; +const host = process.env.NODE_ENV === 'production' ? + 'mdn-bcd-collector.appspot.com' : + `localhost:${PORT}`; + +const secrets = process.env.NODE_ENV === 'test' ? + require('./secrets.sample.json') : + require('./secrets.json'); // TODO: none of this setup is pretty const {CloudStorage, MemoryStorage} = require('./storage'); @@ -30,10 +37,6 @@ const storage = process.env.NODE_ENV === 'production' ? new CloudStorage : new MemoryStorage; -const secrets = process.env.NODE_ENV === 'test' ? - require('./secrets.sample.json') : - require('./secrets.json'); - const github = require('./github')( secrets.github.token ? {auth: `token ${secrets.github.token}`} : @@ -43,9 +46,7 @@ const github = require('./github')( const Tests = require('./tests'); const tests = new Tests({ manifest: require('./MANIFEST.json'), - host: process.env.NODE_ENV === 'production' ? - 'mdn-bcd-collector.appspot.com' : - `localhost:${PORT}`, + host: host, httpOnly: process.env.NODE_ENV !== 'production' }); diff --git a/build.js b/build.js index 1dd95f93e..de863b81a 100644 --- a/build.js +++ b/build.js @@ -433,6 +433,7 @@ function buildIDLTests(ast) { return tests; } +/* istanbul ignore next */ function buildIDL(webref) { const ast = flattenIDL(webref.idl, collectExtraIDL()); validateIDL(ast); @@ -516,6 +517,7 @@ function buildCSS(webref, bcd) { return tests; } +/* istanbul ignore next */ async function copyResources() { const resources = [ ['json3/lib/json3.min.js', 'resources'], diff --git a/logger.js b/logger.js index 2a6d9c079..00b5ae813 100644 --- a/logger.js +++ b/logger.js @@ -18,6 +18,7 @@ const winston = require('winston'); const {LoggingWinston} = require('@google-cloud/logging-winston'); function getTransport() { + /* istanbul ignore if */ if (process.env.NODE_ENV === 'production' || process.env.GOOGLE_APPLICATION_CREDENTIALS) { return new LoggingWinston(); diff --git a/unittest/app/app.js b/unittest/app/app.js index e04bcee39..d80823c70 100644 --- a/unittest/app/app.js +++ b/unittest/app/app.js @@ -19,7 +19,8 @@ const chai = require('chai'); const chaiHttp = require('chai-http'); const manifest = require('../../MANIFEST.json'); -const manifestItems = Object.entries(manifest.endpoints.main); +const mainEndpoints = Object.entries(manifest.endpoints.main); +const individualEndpoints = Object.entries(manifest.endpoints.individual); chai.use(chaiHttp); const agent = chai.request.agent(app); @@ -45,8 +46,8 @@ describe('/api/results', () => { assert.deepEqual(res.body, {}); }); - const testURL = `http://localhost:8080${manifestItems[0][0]}`; - const testURL2 = `https://host.test${manifestItems[manifestItems.length - 1][0]}`; + const testURL = `http://localhost:8080${mainEndpoints[0][0]}`; + const testURL2 = `https://host.test${mainEndpoints[mainEndpoints.length - 1][0]}`; it('submit valid results', async () => { const res = await agent.post('/api/results') @@ -54,7 +55,7 @@ describe('/api/results', () => { .send({x: 1}); assert.equal(res.status, 201); assert.deepEqual(res.body, { - 'next': `http://localhost:8080${manifestItems[1][0]}` + 'next': `http://localhost:8080${mainEndpoints[1][0]}` }); }); @@ -121,8 +122,13 @@ describe('/api/tests', () => { }); describe('/tests/', () => { - it('get first test', async () => { - const res = await agent.get(manifestItems[0][0]); + it('get a main test', async () => { + const res = await agent.get(mainEndpoints[0][0]); + assert.equal(res.status, 200); + }); + + it('get an individual test', async () => { + const res = await agent.get(individualEndpoints[0][0]); assert.equal(res.status, 200); }); }); diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 9fced5ccd..20832385a 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -54,6 +54,11 @@ describe('build', () => { assert.fileContent(filepath, 'foo\nbar\nbaz\n'); }); + it('dictionary', async () => { + await writeFile(filepath, {'foo': ['bar', 'baz']}); + assert.fileContent(filepath, '{\n "foo": [\n "bar",\n "baz"\n ]\n}\n'); + }); + afterEach(() => { fs.unlinkSync(filepath); }); diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index d4dcd26c0..a6e6b1246 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -100,6 +100,7 @@ describe('Tests', () => { '/api/AbortController/signal' ]); }); + it('getTests', () => { assert.deepEqual(tests.getTests('/api/interfaces'), { 'api.AbortController': { From 415b9fc861837f3b0a7f2f80fd022fa42441eb1a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 17:40:33 -0700 Subject: [PATCH 075/243] Separate manifest building into separate function --- build.js | 102 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/build.js b/build.js index de863b81a..5461b7b0c 100644 --- a/build.js +++ b/build.js @@ -555,72 +555,76 @@ async function copyResources() { }); } -async function build(webref, bcd) { +function buildManifest(tests) { const manifest = { - tests: {}, + tests: tests, endpoints: { main: {}, individual: {} } }; - for (const buildFunc of [buildIDL, buildCSS]) { - const tests = buildFunc(webref, bcd); - manifest.tests = Object.assign(manifest.tests, tests); - for (const [ident, test] of Object.entries(tests)) { - const scopes = Array.isArray(test.scope) ? test.scope : [test.scope]; - for (const scope of scopes) { - let endpoint = ''; - switch (scope) { - case 'Window': - endpoint = '/tests/api/interfaces'; - break; - case 'Worker': - case 'DedicatedWorker': - endpoint = '/tests/api/workerinterfaces'; - break; - case 'ServiceWorker': - endpoint = '/tests/api/serviceworkerinterfaces'; - break; - case 'CSS': - endpoint = '/tests/css/properties'; - break; - } + for (const [ident, test] of Object.entries(manifest.tests)) { + const scopes = Array.isArray(test.scope) ? test.scope : [test.scope]; + for (const scope of scopes) { + let endpoint = ''; + switch (scope) { + case 'Window': + endpoint = '/tests/api/interfaces'; + break; + case 'Worker': + case 'DedicatedWorker': + endpoint = '/tests/api/workerinterfaces'; + break; + case 'ServiceWorker': + endpoint = '/tests/api/serviceworkerinterfaces'; + break; + case 'CSS': + endpoint = '/tests/css/properties'; + break; + } - if (endpoint) { - if (!(endpoint in manifest.endpoints.main)) { - manifest.endpoints.main[endpoint] = { - scope: scope, - httpsOnly: scope === 'ServiceWorker', - entries: [] - }; - } - if (!(ident in manifest.endpoints.main[endpoint].entries)) { - manifest.endpoints.main[endpoint].entries.push(ident); - } + if (endpoint) { + if (!(endpoint in manifest.endpoints.main)) { + manifest.endpoints.main[endpoint] = { + scope: scope, + httpsOnly: scope === 'ServiceWorker', + entries: [] + }; + } + if (!(ident in manifest.endpoints.main[endpoint].entries)) { + manifest.endpoints.main[endpoint].entries.push(ident); } } + } - let url = '/tests'; - for (const part of ident.split('.')) { - url += '/' + part; + let url = '/tests'; + for (const part of ident.split('.')) { + url += '/' + part; - if (['/tests/api', '/tests/css', '/tests/css/properties'].includes(url)) { - // Ignore things tested in main endpoints - continue; - } + if (['/tests/api', '/tests/css', '/tests/css/properties'].includes(url)) { + // Ignore things tested in main endpoints + continue; + } - if (!(url in manifest.endpoints.individual)) { - manifest.endpoints.individual[url] = []; - } - if (!(ident in manifest.endpoints.individual[url])) { - manifest.endpoints.individual[url].push(ident); - } + if (!(url in manifest.endpoints.individual)) { + manifest.endpoints.individual[url] = []; + } + if (!(ident in manifest.endpoints.individual[url])) { + manifest.endpoints.individual[url].push(ident); } } } - await writeFile('MANIFEST.json', manifest); + return manifest; +} + +async function build(webref, bcd) { + const IDLTests = buildIDL(webref); + const CSSTests = buildCSS(webref, bcd); + const tests = Object.assign(IDLTests, CSSTests); + + await writeFile('MANIFEST.json', buildManifest(tests)); await copyResources(); } From 594ad50bc4fece9dd618eb5a79c6b893ea21cc62 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 18:10:58 -0700 Subject: [PATCH 076/243] Add additional tests for build.js --- build.js | 8 +++-- unittest/unit/build.js | 82 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/build.js b/build.js index 5461b7b0c..6fc49d449 100644 --- a/build.js +++ b/build.js @@ -95,7 +95,6 @@ function compileTest(test) { return newTest; } -/* istanbul ignore next */ function collectExtraIDL() { const idl = fs.readFileSync('./non-standard.idl', 'utf8'); return WebIDL2.parse(idl); @@ -433,7 +432,6 @@ function buildIDLTests(ast) { return tests; } -/* istanbul ignore next */ function buildIDL(webref) { const ast = flattenIDL(webref.idl, collectExtraIDL()); validateIDL(ast); @@ -619,6 +617,7 @@ function buildManifest(tests) { return manifest; } +/* istanbul ignore next */ async function build(webref, bcd) { const IDLTests = buildIDL(webref); const CSSTests = buildCSS(webref, bcd); @@ -639,13 +638,16 @@ if (require.main === module) { writeFile, getCustomTestAPI, getCustomTestCSS, + collectExtraIDL, flattenIDL, getExposureSet, buildIDLTests, + buildIDL, validateIDL, collectCSSPropertiesFromBCD, collectCSSPropertiesFromWebref, cssPropertyToIDLAttribute, - buildCSS + buildCSS, + buildManifest }; } diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 20832385a..71ed6cd8e 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -30,12 +30,15 @@ const { writeFile, flattenIDL, getExposureSet, + collectExtraIDL, validateIDL, buildIDLTests, + buildIDL, collectCSSPropertiesFromBCD, collectCSSPropertiesFromWebref, cssPropertyToIDLAttribute, - buildCSS + buildCSS, + buildManifest } = proxyquire('../../build', { './custom-tests.json': {'api': {}, 'css': {}} }); @@ -356,6 +359,15 @@ describe('build', () => { 'webkitLineClamp'); }); + it('collectExtraIDL', () => { + assert.typeOf(collectExtraIDL(), 'array'); + }); + + it('buildIDL', () => { + const webref = require('../../webref'); + assert.typeOf(buildIDL(webref), 'object'); + }); + describe('flattenIDL', () => { const historicalIDL = WebIDL2.parse(`interface DOMError {};`); @@ -1111,4 +1123,72 @@ describe('build', () => { } }); }); + + it('buildManifest', () => { + const tests = { + 'api.Attr': { + 'code': '"Attr" in self', + 'scope': ['Window', 'Worker', 'ServiceWorker'] + }, + 'api.Attr.name': { + 'code': '"Attr" in self && "name" in Attr.prototype', + 'scope': ['Window', 'Worker'] + }, + 'css.properties.font-family': { + 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', + 'scope': ['CSS'] + } + }; + const expectedManifest = { + 'endpoints': { + 'individual': { + '/tests/api/Attr': ['api.Attr', 'api.Attr.name'], + '/tests/api/Attr/name': ['api.Attr.name'], + '/tests/css/properties/font-family': [ + 'css.properties.font-family' + ] + }, + 'main': { + '/tests/api/interfaces': { + 'entries': ['api.Attr', 'api.Attr.name'], + 'httpsOnly': false, + 'scope': 'Window' + }, + '/tests/api/serviceworkerinterfaces': { + 'entries': ['api.Attr'], + 'httpsOnly': true, + 'scope': 'ServiceWorker' + }, + '/tests/api/workerinterfaces': { + 'entries': ['api.Attr', 'api.Attr.name'], + 'httpsOnly': false, + 'scope': 'Worker' + }, + '/tests/css/properties': { + 'entries': ['css.properties.font-family'], + 'httpsOnly': false, + 'scope': 'CSS' + } + } + }, + 'tests': { + 'api.Attr': { + 'code': '"Attr" in self', + 'scope': ['Window', 'Worker', 'ServiceWorker'] + }, + 'api.Attr.name': { + 'code': '"Attr" in self && "name" in Attr.prototype', + 'scope': ['Window', 'Worker'] + }, + 'css.properties.font-family': { + 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', + 'scope': ['CSS'] + } + } + }; + + const manifest = buildManifest(tests); + + assert.deepEqual(manifest, expectedManifest); + }); }); From 27c99da43c36e537c143e729a9f6b613df22e8bc Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 18:40:56 -0700 Subject: [PATCH 077/243] Use filesystem mocking for writeFile tests --- package-lock.json | 6 ++++++ package.json | 1 + unittest/unit/build.js | 12 +++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40648841f..950f4a81d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3559,6 +3559,12 @@ } } }, + "mock-fs": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", + "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", + "dev": true + }, "module-not-found-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", diff --git a/package.json b/package.json index df4949def..ce008993f 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "eslint": "7.8.0", "eslint-config-google": "0.14.0", "mocha": "8.1.1", + "mock-fs": "^4.13.0", "nyc": "15.1.0", "proxyquire": "2.1.3", "puppeteer": "5.2.1", diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 71ed6cd8e..915917152 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -22,10 +22,9 @@ const assert = chai.assert; const expect = chai.expect; const WebIDL2 = require('webidl2'); +const mockFs = require('mock-fs'); const proxyquire = require('proxyquire'); -const fs = require('fs'); - const { writeFile, flattenIDL, @@ -47,6 +46,13 @@ describe('build', () => { describe('writeFile', () => { const filepath = '.testtmp'; + beforeEach(() => { + mockFs({ + '.testtmp': '', + './custom-tests.json': {'api': {}, 'css': {}} + }); + }); + it('simple supported', async () => { await writeFile(filepath, 'foo\nbar'); assert.fileContent(filepath, 'foo\nbar\n'); @@ -63,7 +69,7 @@ describe('build', () => { }); afterEach(() => { - fs.unlinkSync(filepath); + mockFs.restore(); }); }); From 214fc39136baea07941a6dd4ebe9db7379bef74f Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 18:56:05 -0700 Subject: [PATCH 078/243] Add disabled copyResources tests --- unittest/unit/build.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 915917152..6ce7548bc 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -1197,4 +1197,32 @@ describe('build', () => { assert.deepEqual(manifest, expectedManifest); }); + +// describe('copyResources', () => { +// // XXX Cannot test with mock; see: +// // https://github.com/tschaub/mock-fs/issues/142 +// +// beforeEach(() => { +// mockFs({ +// 'generated': {} +// }); +// }); +// +// it('main', async () => { +// await copyResources(); +// assert.notIsEmptyDirectory('generated'); +// }); +// +// it('core.js map rename', async () => { +// await copyResources(); +// assert.fileContentMatch( +// 'generated/resources/core.js', +// /sourceMappingURL=core\.js\.map/ +// ); +// }); +// +// afterEach(() => { +// mockFs.restore(); +// }); +// }); }); From b6d0fb91278cb719ddd4a3b8eb265bc52544e7c4 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:13:42 -0700 Subject: [PATCH 079/243] Add more test coverage --- build.js | 3 +- unittest/unit/build.js | 57 +++++++++++++++++--------- unittest/unit/tests.js | 93 ++++++++++++++++++++++++++++++++---------- webref.js | 1 + 4 files changed, 111 insertions(+), 43 deletions(-) diff --git a/build.js b/build.js index 6fc49d449..083cd6573 100644 --- a/build.js +++ b/build.js @@ -563,8 +563,7 @@ function buildManifest(tests) { }; for (const [ident, test] of Object.entries(manifest.tests)) { - const scopes = Array.isArray(test.scope) ? test.scope : [test.scope]; - for (const scope of scopes) { + for (const scope of test.scope) { let endpoint = ''; switch (scope) { case 'Window': diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 6ce7548bc..458320dcf 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -1143,17 +1143,32 @@ describe('build', () => { 'css.properties.font-family': { 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', 'scope': ['CSS'] + }, + 'javascript.builtins.array': { + 'code': '[1, 2, 3]', + 'scope': ['JavaScript'] } }; const expectedManifest = { - 'endpoints': { - 'individual': { - '/tests/api/Attr': ['api.Attr', 'api.Attr.name'], - '/tests/api/Attr/name': ['api.Attr.name'], - '/tests/css/properties/font-family': [ - 'css.properties.font-family' - ] + 'tests': { + 'api.Attr': { + 'code': '"Attr" in self', + 'scope': ['Window', 'Worker', 'ServiceWorker'] + }, + 'api.Attr.name': { + 'code': '"Attr" in self && "name" in Attr.prototype', + 'scope': ['Window', 'Worker'] }, + 'css.properties.font-family': { + 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', + 'scope': ['CSS'] + }, + 'javascript.builtins.array': { + 'code': '[1, 2, 3]', + 'scope': ['JavaScript'] + } + }, + 'endpoints': { 'main': { '/tests/api/interfaces': { 'entries': ['api.Attr', 'api.Attr.name'], @@ -1175,20 +1190,22 @@ describe('build', () => { 'httpsOnly': false, 'scope': 'CSS' } - } - }, - 'tests': { - 'api.Attr': { - 'code': '"Attr" in self', - 'scope': ['Window', 'Worker', 'ServiceWorker'] }, - 'api.Attr.name': { - 'code': '"Attr" in self && "name" in Attr.prototype', - 'scope': ['Window', 'Worker'] - }, - 'css.properties.font-family': { - 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', - 'scope': ['CSS'] + 'individual': { + '/tests/api/Attr': ['api.Attr', 'api.Attr.name'], + '/tests/api/Attr/name': ['api.Attr.name'], + '/tests/css/properties/font-family': [ + 'css.properties.font-family' + ], + '/tests/javascript': [ + 'javascript.builtins.array' + ], + '/tests/javascript/builtins': [ + 'javascript.builtins.array' + ], + '/tests/javascript/builtins/array': [ + 'javascript.builtins.array' + ] } } }; diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index a6e6b1246..8d027c416 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -37,7 +37,7 @@ const MANIFEST = { }, endpoints: { main: { - '/api/interfaces': { + '/tests/api/interfaces': { scope: 'Window', httpsOnly: false, entries: [ @@ -45,25 +45,30 @@ const MANIFEST = { 'api.AbortController.signal' ] }, - '/api/workerinterfaces': { + '/tests/api/workerinterfaces': { scope: 'Worker', - httpsOnly: true, + httpsOnly: false, entries: [ 'api.AbortController' ] }, - '/api/serviceworkerinterfaces': { + '/tests/api/serviceworkerinterfaces': { scope: 'ServiceWorker', httpsOnly: true, entries: [] + }, + '/tests/css/properties': { + scope: 'CSS', + httpsOnly: false, + entries: [] } }, individual: { - '/api/AbortController': [ + '/tests/api/AbortController': [ 'api.AbortController', 'api.AbortController.signal' ], - '/api/AbortController/signal': [ + '/tests/api/AbortController/signal': [ 'api.AbortController.signal' ] } @@ -76,33 +81,79 @@ describe('Tests', () => { host: 'host.test' }); + describe('next', () => { + it('normal', () => { + assert.equal( + tests.next('http://host.test/tests/api/interfaces'), + 'https://host.test/tests/api/interfaces' + ); + assert.equal( + tests.next('https://host.test/tests/api/interfaces'), + 'http://host.test/tests/api/workerinterfaces' + ); + assert.equal( + tests.next('https://host.test/tests/api/workerinterfaces'), + 'https://host.test/tests/api/serviceworkerinterfaces' + ); + + assert.equal( + tests.next('https://host.test/tests/css/properties'), + null + ); + }); + + it('HTTP only', () => { + const theseTests = new Tests({ + manifest: MANIFEST, + host: 'host.test', + httpOnly: true + }); + + assert.equal( + theseTests.next('http://host.test/tests/api/interfaces'), + 'http://host.test/tests/api/workerinterfaces' + ); + assert.equal( + theseTests.next('http://host.test/tests/api/workerinterfaces'), + 'http://host.test/tests/css/properties' + ); + + assert.equal( + theseTests.next('http://host.test/tests/css/properties'), + null + ); + }); + }); + it('listMainEndpoints', () => { assert.deepEqual(tests.listMainEndpoints(), [ - '/api/interfaces', - '/api/workerinterfaces', - '/api/serviceworkerinterfaces' + '/tests/api/interfaces', + '/tests/api/workerinterfaces', + '/tests/api/serviceworkerinterfaces', + '/tests/css/properties' ]); }); it('listIndividual', () => { assert.deepEqual(tests.listIndividual(), [ - ['api.AbortController', '/api/AbortController'], - ['api.AbortController.signal', '/api/AbortController/signal'] + ['api.AbortController', '/tests/api/AbortController'], + ['api.AbortController.signal', '/tests/api/AbortController/signal'] ]); }); it('listAllEndpoints', () => { assert.deepEqual(tests.listAllEndpoints(), [ - '/api/interfaces', - '/api/workerinterfaces', - '/api/serviceworkerinterfaces', - '/api/AbortController', - '/api/AbortController/signal' + '/tests/api/interfaces', + '/tests/api/workerinterfaces', + '/tests/api/serviceworkerinterfaces', + '/tests/css/properties', + '/tests/api/AbortController', + '/tests/api/AbortController/signal' ]); }); it('getTests', () => { - assert.deepEqual(tests.getTests('/api/interfaces'), { + assert.deepEqual(tests.getTests('/tests/api/interfaces'), { 'api.AbortController': { 'code': '"AbortController" in self', 'scope': ['Window', 'Worker'] @@ -112,7 +163,7 @@ describe('Tests', () => { 'scope': ['Window', 'Worker'] } }); - assert.deepEqual(tests.getTests('/api/workerinterfaces'), { + assert.deepEqual(tests.getTests('/tests/api/workerinterfaces'), { 'api.AbortController': { 'code': '"AbortController" in self', 'scope': ['Window', 'Worker'] @@ -121,8 +172,8 @@ describe('Tests', () => { }); it('getScope', () => { - assert.equal(tests.getScope('/api/interfaces'), 'Window'); - assert.equal(tests.getScope('/api/serviceworkerinterfaces'), 'ServiceWorker'); - assert.equal(tests.getScope('/api/dummy'), ''); + assert.equal(tests.getScope('/tests/api/interfaces'), 'Window'); + assert.equal(tests.getScope('/tests/api/serviceworkerinterfaces'), 'ServiceWorker'); + assert.equal(tests.getScope('/tests/api/dummy'), ''); }); }); diff --git a/webref.js b/webref.js index 2ade3b85d..e49c8fabf 100644 --- a/webref.js +++ b/webref.js @@ -29,6 +29,7 @@ function loadTextFiles(relativeDir, extension, parse) { files.sort(); const results = {}; for (const file of files) { + /* istanbul ignore next */ if (path.extname(file) !== extension) { continue; } From 0d7c996ff857d4ac2e7a0091dfcaf2072043da3a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:18:29 -0700 Subject: [PATCH 080/243] Add HTML-format coverage command --- package-lock.json | 422 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 + 2 files changed, 424 insertions(+) diff --git a/package-lock.json b/package-lock.json index 950f4a81d..8a9d1d131 100644 --- a/package-lock.json +++ b/package-lock.json @@ -792,6 +792,12 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@tokenizer/token": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", + "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==", + "dev": true + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -815,16 +821,34 @@ "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==", "dev": true }, + "@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==", + "dev": true + }, "@types/long": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, + "@types/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true + }, "@types/node": { "version": "13.13.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.14.tgz", "integrity": "sha512-Az3QsOt1U/K1pbCQ0TXGELTuTkPLOiFIQf3ILzbOyo0FqgV9SxRnxbxM5QlAveERZMHpZY+7u3Jz2tKyl+yg6g==" }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "dev": true + }, "@types/superagent": { "version": "3.8.7", "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-3.8.7.tgz", @@ -1236,6 +1260,17 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", @@ -1629,6 +1664,24 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -1782,6 +1835,23 @@ "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + } + } + }, "es-abstract": { "version": "1.17.6", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", @@ -2167,6 +2237,18 @@ "flat-cache": "^2.0.1" } }, + "file-type": { + "version": "14.7.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-14.7.1.tgz", + "integrity": "sha512-sXAMgFk67fQLcetXustxfKX+PZgHIUFn96Xld9uH8aXPdX3xOp0/jg9OdouVTvQrf7mrn+wAa4jN/y9fUOOiRA==", + "dev": true, + "requires": { + "readable-web-to-node-stream": "^2.0.0", + "strtok3": "^6.0.3", + "token-types": "^2.0.0", + "typedarray-to-buffer": "^3.1.5" + } + }, "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", @@ -2468,6 +2550,12 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, "get-stream": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", @@ -2653,6 +2741,12 @@ "mime": "^2.2.0" } }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2708,6 +2802,12 @@ "resolved": "https://registry.npmjs.org/hex2dec/-/hex2dec-1.1.2.tgz", "integrity": "sha512-Yu+q/XWr2fFQ11tHxPq4p4EiNkb2y+lAacJNhAdRXVfRIcDH6gi7htWFnnlIzvqHMHoWeIsfXlNAjZInpAOJDA==" }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -2868,6 +2968,12 @@ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, + "is-docker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2983,6 +3089,15 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3197,6 +3312,12 @@ "bignumber.js": "^9.0.0" } }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3282,6 +3403,12 @@ "safe-buffer": "^5.0.1" } }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -3306,6 +3433,12 @@ "immediate": "~3.0.5" } }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -3431,6 +3564,43 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "meow": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", + "integrity": "sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "^4.0.2", + "normalize-package-data": "^2.5.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" + }, + "dependencies": { + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -3464,6 +3634,12 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -3479,6 +3655,25 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "dependencies": { + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + } + } + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -3636,6 +3831,26 @@ "process-on-spawn": "^1.0.0" } }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3849,6 +4064,29 @@ "mimic-fn": "^2.1.0" } }, + "open": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/open/-/open-7.2.1.tgz", + "integrity": "sha512-xbYCJib4spUdmcs0g/2mK1nKo/jO2T7INClWd/beL7PFkXRWgr8B23ssDHX/USPn2M2IjDR5UdpYs6I67SnTSA==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "open-cli": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/open-cli/-/open-cli-6.0.1.tgz", + "integrity": "sha512-A5h8MF3GrT1efn9TiO9LPajDnLtuEiGQT5G8TxWObBlgt1cZJF1YbQo/kNtsD1bJb7HxnT6SaSjzeLq0Rfhygw==", + "dev": true, + "requires": { + "file-type": "^14.1.4", + "get-stdin": "^7.0.0", + "meow": "^6.1.0", + "open": "^7.0.3", + "temp-write": "^4.0.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -3938,6 +4176,18 @@ "callsites": "^3.0.0" } }, + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3978,6 +4228,12 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "peek-readable": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.0.tgz", + "integrity": "sha512-KGuODSTV6hcgdZvDrIDBUkN0utcAVj1LL7FfGbM0viKTtCHmtZcuEJ+lGqsp0fTFkGqesdtemV2yUSMeyy3ddA==", + "dev": true + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -4303,6 +4559,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -4328,6 +4590,45 @@ "unpipe": "1.0.0" } }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -4342,6 +4643,12 @@ "util-deprecate": "~1.0.1" } }, + "readable-web-to-node-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-2.0.0.tgz", + "integrity": "sha512-+oZJurc4hXpaaqsN68GoZGQAQIA3qr09Or4fqEsargABnbe5Aau8hFn6ISVleT3cpY/0n/8drn7huyyEvTbghA==", + "dev": true + }, "readdir-enhanced": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/readdir-enhanced/-/readdir-enhanced-1.5.2.tgz", @@ -4362,6 +4669,16 @@ "picomatch": "^2.0.7" } }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -4680,6 +4997,38 @@ } } }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4780,12 +5129,32 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strtok3": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.4.tgz", + "integrity": "sha512-rqWMKwsbN9APU47bQTMEYTPcwdpKDtmf1jVhHzNW2cL1WqAxaM9iBb9t5P2fj+RV2YsErUWgQzHD5JwV0uCTEQ==", + "dev": true, + "requires": { + "@tokenizer/token": "^0.1.1", + "@types/debug": "^4.1.5", + "peek-readable": "^3.1.0" + } + }, "stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", @@ -4897,6 +5266,33 @@ "uuid": "^7.0.0" } }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "temp-write": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-4.0.0.tgz", + "integrity": "sha512-HIeWmj77uOOHb0QX7siN3OtwV3CTntquin6TNVg6SHOqCP3hYKmox90eeFOGaY1MqJ9WYDDjkyZrW6qS5AWpbw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "is-stream": "^2.0.0", + "make-dir": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -4984,6 +5380,22 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "token-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-2.0.0.tgz", + "integrity": "sha512-WWvu8sGK8/ZmGusekZJJ5NM6rRVTTDO7/bahz4NGiSDb/XsmdYBn6a1N/bymUHuWYTWeuLUg98wUzvE4jPdCZw==", + "dev": true, + "requires": { + "@tokenizer/token": "^0.1.0", + "ieee754": "^1.1.13" + } + }, + "trim-newlines": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", + "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", + "dev": true + }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -5105,6 +5517,16 @@ "integrity": "sha512-NglPycIwSQeSJj7VJ6L8vTsPKC9MG5Lcx4n3SvYqNHzklbMI4dGcLJnkLPEPJ3uB8UyTdWviMhM0Ptq+xD5UFQ==", "dev": true }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index ce008993f..338e66572 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "deploy": "gcloud app deploy", "start": "node app.js", "unittest": "NODE_ENV=test nyc mocha --recursive unittest", + "coverage": "nyc report -r lcov && open-cli coverage/lcov-report/index.html", "test": "npm run lint && npm run unittest", "selenium": "mocha selenium", "update-bcd": "node update-bcd.js" @@ -54,6 +55,7 @@ "mocha": "8.1.1", "mock-fs": "^4.13.0", "nyc": "15.1.0", + "open-cli": "^6.0.1", "proxyquire": "2.1.3", "puppeteer": "5.2.1", "puppeteer-to-istanbul": "^1.4.0", From 6244aef6d419f66ff32ce2f6772e07e5338e7f2e Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:20:28 -0700 Subject: [PATCH 081/243] Fix ESLint issues --- unittest/unit/tests.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index 8d027c416..746a8a812 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -84,21 +84,21 @@ describe('Tests', () => { describe('next', () => { it('normal', () => { assert.equal( - tests.next('http://host.test/tests/api/interfaces'), - 'https://host.test/tests/api/interfaces' + tests.next('http://host.test/tests/api/interfaces'), + 'https://host.test/tests/api/interfaces' ); assert.equal( - tests.next('https://host.test/tests/api/interfaces'), - 'http://host.test/tests/api/workerinterfaces' + tests.next('https://host.test/tests/api/interfaces'), + 'http://host.test/tests/api/workerinterfaces' ); assert.equal( - tests.next('https://host.test/tests/api/workerinterfaces'), - 'https://host.test/tests/api/serviceworkerinterfaces' + tests.next('https://host.test/tests/api/workerinterfaces'), + 'https://host.test/tests/api/serviceworkerinterfaces' ); assert.equal( - tests.next('https://host.test/tests/css/properties'), - null + tests.next('https://host.test/tests/css/properties'), + null ); }); @@ -110,17 +110,17 @@ describe('Tests', () => { }); assert.equal( - theseTests.next('http://host.test/tests/api/interfaces'), - 'http://host.test/tests/api/workerinterfaces' + theseTests.next('http://host.test/tests/api/interfaces'), + 'http://host.test/tests/api/workerinterfaces' ); assert.equal( - theseTests.next('http://host.test/tests/api/workerinterfaces'), - 'http://host.test/tests/css/properties' + theseTests.next('http://host.test/tests/api/workerinterfaces'), + 'http://host.test/tests/css/properties' ); assert.equal( - theseTests.next('http://host.test/tests/css/properties'), - null + theseTests.next('http://host.test/tests/css/properties'), + null ); }); }); From 00da20b06cbd01dcde17dde117684be1aee920c7 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:21:16 -0700 Subject: [PATCH 082/243] Don't include HTML coverage reports in nyc --- .nycrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.nycrc.json b/.nycrc.json index 35b4de0cf..9f5a27a55 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -4,6 +4,7 @@ "**/generated/**", "**/static/**", "**/unittest/**", - "**/json3.min.js" + "**/json3.min.js", + "**/coverage/**" ] } \ No newline at end of file From 077dccc45d9679f6ddc6070418870f80a21980c8 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:21:42 -0700 Subject: [PATCH 083/243] Rename harness.js mocha tests --- unittest/puppeteer/harness.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest/puppeteer/harness.js b/unittest/puppeteer/harness.js index 24b7344a6..f549bc902 100644 --- a/unittest/puppeteer/harness.js +++ b/unittest/puppeteer/harness.js @@ -28,7 +28,7 @@ const consoleLogType = { firefox: 'verbose' }; -describe('/resources/harness.js', () => { +describe('harness.js', () => { const port = process.env.PORT || 8081; let server; before(() => { From daa6271d9225bce15cd7c14925ccc3c3914218c8 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:50:38 -0700 Subject: [PATCH 084/243] Extend coverage to all of static folder --- .nycrc.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.nycrc.json b/.nycrc.json index 9f5a27a55..66f767946 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -2,9 +2,8 @@ "all": true, "exclude": [ "**/generated/**", - "**/static/**", "**/unittest/**", - "**/json3.min.js", - "**/coverage/**" + "**/coverage/**", + "**/json3.min.js" ] } \ No newline at end of file From afe5f74f2e69fa2f27de6add6b8860d546dbbf49 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:54:58 -0700 Subject: [PATCH 085/243] Properly link static folder in test coverage reports --- unittest/puppeteer/harness.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/unittest/puppeteer/harness.js b/unittest/puppeteer/harness.js index f549bc902..0aa6d65a7 100644 --- a/unittest/puppeteer/harness.js +++ b/unittest/puppeteer/harness.js @@ -17,6 +17,8 @@ const assert = require('assert'); const puppeteer = require('puppeteer'); const pti = require('puppeteer-to-istanbul'); +const fs = require('fs'); +const path = require('path'); const {app} = require('../../app'); @@ -58,7 +60,28 @@ describe('harness.js', () => { if (product == 'chrome') { const jsCoverage = await page.coverage.stopJSCoverage(); - pti.write(jsCoverage, {includeHostname: false, storagePath: './.nyc_output'}); + pti.write(jsCoverage, { + includeHostname: false, + storagePath: './.nyc_output' + }); + + // Slight adjustment of coverage files to point to original files + const coveragePath = path.join( + __dirname, '..', '..', '.nyc_output', 'out.json' + ); + fs.readFile(coveragePath, 'utf8', function(err, data) { + if (err) { + return console.log(err); + } + const result = data.replace( + /\.nyc_output\/resources/g, + 'static/resources' + ); + + fs.writeFile(coveragePath, result, 'utf8', function(err) { + if (err) return console.log(err); + }); + }); } assert.equal(report.stats.failures, 0); From 76d9041ba7e0ebdefc36ccb55e45b049ae12620c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 19:55:16 -0700 Subject: [PATCH 086/243] Add clean command --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 338e66572..ae8c4b0ef 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "prepare": "if [ -d node_modules/puppeteer ]; then cd node_modules/puppeteer && PUPPETEER_PRODUCT=firefox node install.js; fi", "lint": "eslint .", "lint-fix": "eslint --fix .", + "clean": "rm -rf .nyc_output coverage generated MANIFEST.json", "build": "node build.js", "gcp-build": "npm run build", "deploy": "gcloud app deploy", From b26298d3e10763c7615c1efe1d92c5d52fa32688 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 20:02:37 -0700 Subject: [PATCH 087/243] Update readme --- README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bda0977e0..a239e69fc 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,10 @@ See [DESIGN.md](./DESIGN.md) for details of how this service works. ## Setup +```sh npm install npm run build +``` Before you can run or deploy, copy `secrets.sample.json` to `secrets.json`. @@ -19,19 +21,25 @@ Before you can run or deploy, copy `secrets.sample.json` to `secrets.json`. ## Running locally +```sh npm start +``` ## Deploying to App Engine +```sh npm run deploy +``` -(This is performed automatically when a commit is pushed to `main`.) +(This step is performed automatically when a commit is pushed to `main`.) ## Run tests via Selenium WebDriver To test using the latest deployed version, run: +```sh npm run selenium +``` You must configure your Selenium remote in `secrets.json`; local environments are not supported. You may use any testing service, such as SauceLabs, @@ -40,8 +48,24 @@ configure your WebDriver URL. You can also test just a single browser by defining the `BROWSER` environment variable: +```sh BROWSER=chrome npm run selenium +``` ## Running the unit tests and linter +```sh npm test +``` + +Code coverage reports can be viewed in a browser by running: + +```sh + npm run coverage +``` + +## Cleanup generated files + +```sh + npm run clean +``` From 35a5d3cc5729004de79f871d57469e41fc564679 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Fri, 4 Sep 2020 22:51:32 -0700 Subject: [PATCH 088/243] Add text to homepage, including list of known caveats --- static/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/static/index.html b/static/index.html index 748bb6a23..58958e8fc 100644 --- a/static/index.html +++ b/static/index.html @@ -13,6 +13,9 @@ +

mdn-bcd-collector

+

Data collection service for mdn/browser-compat-data. This website provides automatic feature detection for Web APIs and CSS properties, to assist in obtaining data for the BCD project.

+
- -
- -
- + - - -

Note: this website is in beta; not all feature detection is accurate yet. If you find any errors, please file an issue on the GitHub page.

-

Known caveats:

-
    -
  • Detection for features under alternative names is not yet supported
  • -
  • In older browsers, some attributes aren't initialized in the API prototypes, resulting in false negatives
  • -
  • Some APIs are accessed through other APIs and aren't exposed on their own; custom tests have not been written for them all
  • -
- -

Source on GitHub

- + getTests(); + + diff --git a/static/resources/style.css b/static/resources/style.css new file mode 100644 index 000000000..44d60e1c7 --- /dev/null +++ b/static/resources/style.css @@ -0,0 +1,51 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto&family=Roboto+Mono&display=swap'); + +body { + font-family: 'Roboto', Arial, sans-serif; +} + +code { + font-family: 'Roboto Mono', monospace; + font-size: 12px; +} + +button, select { + background-color: #3d8a3f; + border: none; + color: white; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 14px; + transition: background-color 0.2s; +} + +button { + padding: 8px 8px 8px 16px; +} + +select { + padding: 7px 16px 7px 8px; + margin-left: -2px; +} + +button:hover, select:hover { + cursor: pointer; + background-color: #4caf50; +} + +button:disabled, button:disabled:hover, select:disabled:hover { + cursor: not-allowed; + background-color: #636363; +} + +@media (prefers-color-scheme: dark) { + body { + background-color: #111; + color: white; + } + + a { + color: #99f; + } +} \ No newline at end of file diff --git a/static/results/index.html b/static/results/index.html index a82bc8019..f318c88f9 100644 --- a/static/results/index.html +++ b/static/results/index.html @@ -1,48 +1,49 @@ - - - - - - -
- Loading page... -
- - - - + - + exportGitHub(); + + \ No newline at end of file diff --git a/tests.js b/tests.js index 586965875..25058e7f7 100644 --- a/tests.js +++ b/tests.js @@ -99,6 +99,7 @@ class Tests { '', '', '', + '', '', '', '

Running tests...

', From 4485fad74786b94adff649ba2becdef6ef95f737 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sat, 5 Sep 2020 14:36:56 -0700 Subject: [PATCH 106/243] Load custom CSS after test completion --- static/index.html | 2 +- static/resources/harness.js | 6 ++++++ static/results/index.html | 2 +- tests.js | 9 ++++++++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/static/index.html b/static/index.html index 34e42a19d..a8fc56516 100644 --- a/static/index.html +++ b/static/index.html @@ -10,7 +10,7 @@ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--> - +

mdn-bcd-collector

diff --git a/static/resources/harness.js b/static/resources/harness.js index 755c3eb75..4f07e8e86 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -334,6 +334,12 @@ } function finishAndDisplay(results) { + var css = document.createElement('link'); + css.rel = 'stylesheet'; + css.type = 'text/css'; + css.href = '/resources/style.css'; + document.head.appendChild(css); + var response = ''; for (var i=0; i - +
diff --git a/tests.js b/tests.js index 25058e7f7..bcf4b0932 100644 --- a/tests.js +++ b/tests.js @@ -99,7 +99,14 @@ class Tests { '', '', '', - '', + '', '', '', '

Running tests...

', From a1a0402e9d13785861f025967df1adc28d324ed0 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sat, 5 Sep 2020 20:37:50 -0700 Subject: [PATCH 107/243] Add find-missing script to find what's covered in BCD but not here --- find-missing.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 ++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 find-missing.js diff --git a/find-missing.js b/find-missing.js new file mode 100644 index 000000000..735263cca --- /dev/null +++ b/find-missing.js @@ -0,0 +1,54 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const bcd = require('mdn-browser-compat-data'); +const tests = require('./generated/tests.json'); + +function traverseFeatures(obj, identifier) { + const features = []; + + for (const i in obj) { + if ( + !!obj[i] && + typeof obj[i] == 'object' && + i !== '__compat' + ) { + if (obj.__compat) { + features.push(`${identifier}${i}`); + } + + features.push(...traverseFeatures(obj[i], identifier + i + '.')); + } + } + + return features; +} + +function findMissing() { + const bcdEntries = [ + ...traverseFeatures(bcd.api, 'api.'), + ...traverseFeatures(bcd.css, 'css.') + ]; + const collectorEntries = Object.keys(tests); + const missingEntries = []; + + for (const entry of bcdEntries) { + if (!collectorEntries.includes(entry)) { + missingEntries.push(entry); + } + } + + return missingEntries; +} + +function main() { + console.log(findMissing().join('\n')); +} + +/* istanbul ignore if */ +if (require.main === module) { + main(); +} else { + module.exports = {}; +} diff --git a/package.json b/package.json index 0ee44c7dc..43e6fff11 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "coverage": "nyc report -r lcov && open-cli coverage/lcov-report/index.html", "test": "npm run lint && npm run unittest", "selenium": "mocha selenium", - "update-bcd": "node update-bcd.js" + "update-bcd": "node update-bcd.js", + "find-missing": "node find-missing.js" }, "dependencies": { "@google-cloud/logging-winston": "4.0.0", From 46c78a4af3dff8ab8f90acf8998892578140a2ef Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sat, 5 Sep 2020 20:45:14 -0700 Subject: [PATCH 108/243] Fix ESLint issues --- find-missing.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/find-missing.js b/find-missing.js index 735263cca..c7753193d 100644 --- a/find-missing.js +++ b/find-missing.js @@ -1,7 +1,5 @@ 'use strict'; -const fs = require('fs'); -const path = require('path'); const bcd = require('mdn-browser-compat-data'); const tests = require('./generated/tests.json'); @@ -10,9 +8,9 @@ function traverseFeatures(obj, identifier) { for (const i in obj) { if ( - !!obj[i] && - typeof obj[i] == 'object' && - i !== '__compat' + !!obj[i] && + typeof obj[i] == 'object' && + i !== '__compat' ) { if (obj.__compat) { features.push(`${identifier}${i}`); From 8f4e075c8332b7366887f4b6c0f2087efc4948fa Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sat, 5 Sep 2020 22:59:17 -0700 Subject: [PATCH 109/243] Ignore if CSS doesn't load properly after tests --- static/resources/harness.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index 4f07e8e86..f59ec4027 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -338,7 +338,11 @@ css.rel = 'stylesheet'; css.type = 'text/css'; css.href = '/resources/style.css'; - document.head.appendChild(css); + try { + document.head.appendChild(css); + } catch(e) { + // If the CSS fails to load, oh well + } var response = ''; for (var i=0; i Date: Sat, 5 Sep 2020 23:01:27 -0700 Subject: [PATCH 110/243] Fix ESLint issues --- static/resources/harness.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index f59ec4027..2a698e169 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -340,7 +340,7 @@ css.href = '/resources/style.css'; try { document.head.appendChild(css); - } catch(e) { + } catch (e) { // If the CSS fails to load, oh well } From 64db80a81dafceaaa25c268055a99aad194da642 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 12:49:15 -0700 Subject: [PATCH 111/243] Map api.console to api.Console --- build.js | 16 ++++++++++++++-- unittest/unit/build.js | 13 +++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/build.js b/build.js index 9ef389477..338a30ccd 100644 --- a/build.js +++ b/build.js @@ -323,6 +323,17 @@ function getExposureSet(node) { return globals; } +function getName(node) { + if (!('name' in node)) return false; + + switch (node.name) { + case 'console': + return 'Console'; + default: + return node.name; + } +} + function allowDuplicates(dfn, member) { switch (dfn.name) { // TODO: sort this out spec-side @@ -411,7 +422,7 @@ function buildIDLTests(ast) { const isGlobal = !!getExtAttr(iface, 'Global'); const customIfaceTest = getCustomTestAPI(iface.name); - tests[`api.${iface.name}`] = compileTest({ + tests[`api.${getName(iface)}`] = compileTest({ 'raw': { 'code': customIfaceTest || {property: iface.name, scope: 'self'}, 'combinator': '&&' @@ -481,7 +492,7 @@ function buildIDLTests(ast) { } } - tests[`api.${iface.name}.${member.name}`] = compileTest({ + tests[`api.${getName(iface)}.${member.name}`] = compileTest({ 'raw': { 'code': expr, 'combinator': '&&' @@ -703,6 +714,7 @@ if (require.main === module) { collectExtraIDL, flattenIDL, getExposureSet, + getName, buildIDLTests, buildIDL, validateIDL, diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 04739be2f..e2825ee52 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -29,6 +29,7 @@ const { writeFile, flattenIDL, getExposureSet, + getName, collectExtraIDL, validateIDL, buildIDLTests, @@ -533,6 +534,18 @@ describe('build', () => { }); }); + describe('getName', () => { + it('main', () => { + const node = {name: 'foobar'}; + assert.equal(getName(node), 'foobar'); + }); + + it('console', () => { + const node = {name: 'console'}; + assert.equal(getName(node), 'Console'); + }); + }); + describe('buildIDLTests', () => { it('interface with attribute', () => { const ast = WebIDL2.parse(`interface Attr { attribute any name; };`); From 8bb29112ed54b265d38e1f6371f95e453ee2a855 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 13:38:50 -0700 Subject: [PATCH 112/243] Don't pre-generate /tests prefix --- app.js | 12 +++++++---- build.js | 12 +++++------ tests.js | 22 +++++++++++--------- unittest/unit/build.js | 20 +++++++++--------- unittest/unit/tests.js | 46 +++++++++++++++++++++--------------------- 5 files changed, 59 insertions(+), 53 deletions(-) diff --git a/app.js b/app.js index cbd0f92a3..bb1d69152 100644 --- a/app.js +++ b/app.js @@ -138,11 +138,15 @@ app.post('/api/results/export/github', (req, res) => { .catch(/* istanbul ignore next */ (err) => catchError(err, res)); }); -for (const endpoint of tests.listAllEndpoints()) { - app.get(endpoint, (req, res) => { +app.all('/tests/*', (req, res) => { + const endpoint = `/${req.params['0']}`; + + if (tests.listAllEndpoints().includes(endpoint)) { res.send(tests.generateTestPage(endpoint)); - }); -} + } else { + res.status(404).end(); + } +}); /* istanbul ignore if */ if (require.main === module) { diff --git a/build.js b/build.js index 338a30ccd..9c1d2e122 100644 --- a/build.js +++ b/build.js @@ -640,17 +640,17 @@ function buildManifest(tests) { let endpoint = ''; switch (scope) { case 'Window': - endpoint = '/tests/api/interfaces'; + endpoint = '/api/interfaces'; break; case 'Worker': case 'DedicatedWorker': - endpoint = '/tests/api/workerinterfaces'; + endpoint = '/api/workerinterfaces'; break; case 'ServiceWorker': - endpoint = '/tests/api/serviceworkerinterfaces'; + endpoint = '/api/serviceworkerinterfaces'; break; case 'CSS': - endpoint = '/tests/css/properties'; + endpoint = '/css/properties'; break; } @@ -668,11 +668,11 @@ function buildManifest(tests) { } } - let url = '/tests'; + let url = ''; for (const part of ident.split('.')) { url += '/' + part; - if (['/tests/api', '/tests/css', '/tests/css/properties'].includes(url)) { + if (['/api', '/css', '/css/properties'].includes(url)) { // Ignore things tested in main endpoints continue; } diff --git a/tests.js b/tests.js index bcf4b0932..d41c83ea6 100644 --- a/tests.js +++ b/tests.js @@ -23,20 +23,22 @@ class Tests { this.httpOnly = options.httpOnly; } - listMainEndpoints() { - return Object.keys(this.endpoints); + listMainEndpoints(urlPrefix = '') { + return Object.keys(this.endpoints).map((item) => ( + `${urlPrefix}${item}` + )); } - listIndividual() { + listIndividual(urlPrefix = '') { return Object.keys(this.individualEndpoints).map((item) => ( - [item.substr(1).replace('tests/', '').replace(/\//g, '.'), item] + [item.substr(1).replace(/\//g, '.'), `${urlPrefix}${item}`] )); } - listAllEndpoints() { + listAllEndpoints(urlPrefix = '') { return [ - ...this.listMainEndpoints(), - ...this.listIndividual().map((item) => (item[1])) + ...this.listMainEndpoints(urlPrefix), + ...this.listIndividual(urlPrefix).map((item) => (item[1])) ]; } @@ -47,7 +49,7 @@ class Tests { } else { const endpoints = this.listMainEndpoints(); const index = endpoints.findIndex((item) => { - return item === afterURL.pathname; + return item === afterURL.pathname.replace('/tests', ''); }) + 1; if (index >= endpoints.length) { @@ -55,7 +57,7 @@ class Tests { } if (this.endpoints[endpoints[index]].httpsOnly) { - const newUrl = `https://${this.host}${endpoints[index]}`; + const newUrl = `https://${this.host}/tests${endpoints[index]}`; if (this.httpOnly) { // Skip this endpoint and go to the next return this.next(newUrl); @@ -64,7 +66,7 @@ class Tests { } } - return `http://${this.host}${endpoints[index]}`; + return `http://${this.host}/tests${endpoints[index]}`; } } diff --git a/unittest/unit/build.js b/unittest/unit/build.js index e2825ee52..647fa8fe6 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -2699,40 +2699,40 @@ describe('build', () => { }; const expectedManifest = { 'main': { - '/tests/api/interfaces': { + '/api/interfaces': { 'entries': ['api.Attr', 'api.Attr.name'], 'httpsOnly': false, 'scope': 'Window' }, - '/tests/api/serviceworkerinterfaces': { + '/api/serviceworkerinterfaces': { 'entries': ['api.Attr'], 'httpsOnly': true, 'scope': 'ServiceWorker' }, - '/tests/api/workerinterfaces': { + '/api/workerinterfaces': { 'entries': ['api.Attr', 'api.Attr.name'], 'httpsOnly': false, 'scope': 'Worker' }, - '/tests/css/properties': { + '/css/properties': { 'entries': ['css.properties.font-family'], 'httpsOnly': false, 'scope': 'CSS' } }, 'individual': { - '/tests/api/Attr': ['api.Attr', 'api.Attr.name'], - '/tests/api/Attr/name': ['api.Attr.name'], - '/tests/css/properties/font-family': [ + '/api/Attr': ['api.Attr', 'api.Attr.name'], + '/api/Attr/name': ['api.Attr.name'], + '/css/properties/font-family': [ 'css.properties.font-family' ], - '/tests/javascript': [ + '/javascript': [ 'javascript.builtins.array' ], - '/tests/javascript/builtins': [ + '/javascript/builtins': [ 'javascript.builtins.array' ], - '/tests/javascript/builtins/array': [ + '/javascript/builtins/array': [ 'javascript.builtins.array' ] } diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index 5ec1e2848..5c919cd51 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -36,7 +36,7 @@ const testDatabase = { }; const MANIFEST = { main: { - '/tests/api/interfaces': { + ' /api/interfaces': { scope: 'Window', httpsOnly: false, entries: [ @@ -44,30 +44,30 @@ const MANIFEST = { 'api.AbortController.signal' ] }, - '/tests/api/workerinterfaces': { + ' /api/workerinterfaces': { scope: 'Worker', httpsOnly: false, entries: [ 'api.AbortController' ] }, - '/tests/api/serviceworkerinterfaces': { + ' /api/serviceworkerinterfaces': { scope: 'ServiceWorker', httpsOnly: true, entries: [] }, - '/tests/css/properties': { + ' /css/properties': { scope: 'CSS', httpsOnly: false, entries: [] } }, individual: { - '/tests/api/AbortController': [ + ' /api/AbortController': [ 'api.AbortController', 'api.AbortController.signal' ], - '/tests/api/AbortController/signal': [ + ' /api/AbortController/signal': [ 'api.AbortController.signal' ] } @@ -126,33 +126,33 @@ describe('Tests', () => { it('listMainEndpoints', () => { assert.deepEqual(tests.listMainEndpoints(), [ - '/tests/api/interfaces', - '/tests/api/workerinterfaces', - '/tests/api/serviceworkerinterfaces', - '/tests/css/properties' + '/api/interfaces', + '/api/workerinterfaces', + '/api/serviceworkerinterfaces', + '/css/properties' ]); }); it('listIndividual', () => { assert.deepEqual(tests.listIndividual(), [ - ['api.AbortController', '/tests/api/AbortController'], - ['api.AbortController.signal', '/tests/api/AbortController/signal'] + ['api.AbortController', '/api/AbortController'], + ['api.AbortController.signal', '/api/AbortController/signal'] ]); }); it('listAllEndpoints', () => { assert.deepEqual(tests.listAllEndpoints(), [ - '/tests/api/interfaces', - '/tests/api/workerinterfaces', - '/tests/api/serviceworkerinterfaces', - '/tests/css/properties', - '/tests/api/AbortController', - '/tests/api/AbortController/signal' + '/api/interfaces', + '/api/workerinterfaces', + '/api/serviceworkerinterfaces', + '/css/properties', + '/api/AbortController', + '/api/AbortController/signal' ]); }); it('getTests', () => { - assert.deepEqual(tests.getTests('/tests/api/interfaces'), { + assert.deepEqual(tests.getTests('/api/interfaces'), { 'api.AbortController': { 'code': '"AbortController" in self', 'scope': ['Window', 'Worker'] @@ -162,7 +162,7 @@ describe('Tests', () => { 'scope': ['Window', 'Worker'] } }); - assert.deepEqual(tests.getTests('/tests/api/workerinterfaces'), { + assert.deepEqual(tests.getTests('/api/workerinterfaces'), { 'api.AbortController': { 'code': '"AbortController" in self', 'scope': ['Window', 'Worker'] @@ -171,8 +171,8 @@ describe('Tests', () => { }); it('getScope', () => { - assert.equal(tests.getScope('/tests/api/interfaces'), 'Window'); - assert.equal(tests.getScope('/tests/api/serviceworkerinterfaces'), 'ServiceWorker'); - assert.equal(tests.getScope('/tests/api/dummy'), ''); + assert.equal(tests.getScope('/api/interfaces'), 'Window'); + assert.equal(tests.getScope('/api/serviceworkerinterfaces'), 'ServiceWorker'); + assert.equal(tests.getScope('/api/dummy'), ''); }); }); From bdffea32b640b2772839922b9cecfbca31e13da1 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 13:39:07 -0700 Subject: [PATCH 113/243] Only send one array for /api/tests --- app.js | 5 ++++- static/index.html | 11 +++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app.js b/app.js index bb1d69152..9f65b1a5a 100644 --- a/app.js +++ b/app.js @@ -74,7 +74,10 @@ app.use(express.static('static')); app.use(express.static('generated')); app.get('/api/tests', (req, res) => { - res.json([tests.listMainEndpoints(), tests.listIndividual()]); + res.json([ + ['All Tests', tests.listMainEndpoints('/tests')[0]], + ...tests.listIndividual('/tests') + ]); }); app.post('/api/results', (req, res) => { diff --git a/static/index.html b/static/index.html index a8fc56516..5e1347d90 100644 --- a/static/index.html +++ b/static/index.html @@ -52,19 +52,14 @@

mdn-bcd-collector

dropdown.add(c); } else { var response = JSON.parse(client.responseText); - var tests = response[0]; - var individualItems = response[1]; + var tests = response; dropdown.removeAttribute('disabled'); dropdown.remove(0); button.removeAttribute('disabled'); button.textContent = 'Run'; - var c = document.createElement("option"); - c.text = "All Tests"; - c.value = tests[0]; - dropdown.add(c); - for (var i=0; i Date: Sun, 6 Sep 2020 13:48:40 -0700 Subject: [PATCH 114/243] Improve Tests.next() --- tests.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests.js b/tests.js index d41c83ea6..4f3071397 100644 --- a/tests.js +++ b/tests.js @@ -47,17 +47,17 @@ class Tests { if (!this.httpOnly && afterURL.protocol === 'http:') { return `https://${this.host}${afterURL.pathname}`; } else { - const endpoints = this.listMainEndpoints(); + const endpoints = this.listMainEndpoints('/tests'); const index = endpoints.findIndex((item) => { - return item === afterURL.pathname.replace('/tests', ''); + return item === afterURL.pathname; }) + 1; if (index >= endpoints.length) { return null; } - if (this.endpoints[endpoints[index]].httpsOnly) { - const newUrl = `https://${this.host}/tests${endpoints[index]}`; + if (this.endpoints[endpoints[index].replace('/tests', '')].httpsOnly) { + const newUrl = `https://${this.host}${endpoints[index]}`; if (this.httpOnly) { // Skip this endpoint and go to the next return this.next(newUrl); @@ -66,7 +66,7 @@ class Tests { } } - return `http://${this.host}/tests${endpoints[index]}`; + return `http://${this.host}${endpoints[index]}`; } } From a4bfcaa71efc80b51df26113b20d738ae63562e4 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 13:48:48 -0700 Subject: [PATCH 115/243] Fix unittests --- unittest/app/app.js | 19 +++++++++++-------- unittest/unit/tests.js | 12 ++++++------ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/unittest/app/app.js b/unittest/app/app.js index 1fbfd848c..bd819c717 100644 --- a/unittest/app/app.js +++ b/unittest/app/app.js @@ -46,8 +46,8 @@ describe('/api/results', () => { assert.deepEqual(res.body, {}); }); - const testURL = `http://localhost:8080${mainEndpoints[0][0]}`; - const testURL2 = `https://host.test${mainEndpoints[mainEndpoints.length - 1][0]}`; + const testURL = `http://localhost:8080/tests${mainEndpoints[0][0]}`; + const testURL2 = `https://host.test/tests${mainEndpoints[mainEndpoints.length - 1][0]}`; it('submit valid results', async () => { const res = await agent.post('/api/results') @@ -55,7 +55,7 @@ describe('/api/results', () => { .send({x: 1}); assert.equal(res.status, 201); assert.deepEqual(res.body, { - 'next': `http://localhost:8080${mainEndpoints[1][0]}` + 'next': `http://localhost:8080/tests${mainEndpoints[1][0]}` }); }); @@ -115,22 +115,25 @@ describe('/api/tests', () => { const res = await agent.get('/api/tests'); assert.equal(res.status, 200); assert.isArray(res.body); - assert.isArray(res.body[0]); - assert.isArray(res.body[1]); - assert.equal(res.body.length, 2); + assert.equal(res.body.length, individualEndpoints.length + 1); }); }); describe('/tests/', () => { it('get a main test', async () => { - const res = await agent.get(mainEndpoints[0][0]); + const res = await agent.get(`/tests${mainEndpoints[0][0]}`); assert.equal(res.status, 200); }); it('get an individual test', async () => { - const res = await agent.get(individualEndpoints[0][0]); + const res = await agent.get(`/tests${individualEndpoints[0][0]}`); assert.equal(res.status, 200); }); + + it('get a non-existent tests', async () => { + const res = await agent.get(`/tests/dummy/test`); + assert.equal(res.status, 404); + }); }); after(() => agent.close()); diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index 5c919cd51..cda183a3a 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -36,7 +36,7 @@ const testDatabase = { }; const MANIFEST = { main: { - ' /api/interfaces': { + '/api/interfaces': { scope: 'Window', httpsOnly: false, entries: [ @@ -44,30 +44,30 @@ const MANIFEST = { 'api.AbortController.signal' ] }, - ' /api/workerinterfaces': { + '/api/workerinterfaces': { scope: 'Worker', httpsOnly: false, entries: [ 'api.AbortController' ] }, - ' /api/serviceworkerinterfaces': { + '/api/serviceworkerinterfaces': { scope: 'ServiceWorker', httpsOnly: true, entries: [] }, - ' /css/properties': { + '/css/properties': { scope: 'CSS', httpsOnly: false, entries: [] } }, individual: { - ' /api/AbortController': [ + '/api/AbortController': [ 'api.AbortController', 'api.AbortController.signal' ], - ' /api/AbortController/signal': [ + '/api/AbortController/signal': [ 'api.AbortController.signal' ] } From 665ecaf3628cf8a72c8f3aa52c0b5923f9bee9e9 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 13:51:42 -0700 Subject: [PATCH 116/243] Add a little bit of extra logging on non-found tests --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 9f65b1a5a..8250377e6 100644 --- a/app.js +++ b/app.js @@ -147,7 +147,7 @@ app.all('/tests/*', (req, res) => { if (tests.listAllEndpoints().includes(endpoint)) { res.send(tests.generateTestPage(endpoint)); } else { - res.status(404).end(); + res.status(404).send(`Could not find tests for ${endpoint}`); } }); From 006ace63b427d3bc36467c4c7678664ffd495e00 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 14:28:38 -0700 Subject: [PATCH 117/243] Add toString when [Serializable] is present --- build.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.js b/build.js index 9c1d2e122..59ac9e934 100644 --- a/build.js +++ b/build.js @@ -287,9 +287,14 @@ function flattenMembers(iface) { break; } } + + // Add members from ExtAttrs if (getExtAttr(iface, 'Constructor')) { members.push({name: iface.name, type: 'constructor'}); } + if (getExtAttr(iface, 'Serializable')) { + members.push({name: 'toString', type: 'operation'}); + } return members.sort((a, b) => a.name.localeCompare(b.name)); } From 36e60020ec5460ccad7fe1918580cb62cca722e3 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 14:28:48 -0700 Subject: [PATCH 118/243] Fix a typo in non-standard.idl --- non-standard.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/non-standard.idl b/non-standard.idl index 30f7d198b..0e821f70c 100644 --- a/non-standard.idl +++ b/non-standard.idl @@ -350,7 +350,7 @@ partial interface Document { partial interface DOMMatrixReadOnly { void scaleNonUniformSelf(optional unrestricted double scaleX = 1, optional unrestricted double scaleY = 1); - void tranform(); + void transform(); }; partial interface Element { From b498c977ccd190b52fd22deb621e2e0c41f6a400 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 19:33:25 -0700 Subject: [PATCH 119/243] Add subtest support --- DESIGN.md | 12 +++- build.js | 45 ++++++++++++-- unittest/unit/build.js | 129 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+), 6 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index dd443aee0..cca958c30 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -32,7 +32,7 @@ Each API interface is written in the following structure: You can define a custom method to test the interface instance itself via `__test`. The `__test` should be a return statement that returns `true` or `false`. If no `__test` is defined, it will default to `return !!instance`. -Each member can have a custom test by defining a property as the member name. Like `__test`, it should be a return statement that returns `true` or `false`. If no custom test is defined, it will default to `return instance && 'MEMBER' in instance`. +Each member can have a custom test by defining a property as the member name. Like `__test`, it should be a return statement that returns `true` or `false`. If no custom test is defined, it will default to `return instance && 'MEMBER' in instance`. The member tests can also be an object that includes a `__test` string and various other strings for behavioral subtests (such as arguments to constructors). Each test will compile into a function as follows: `function() {__base + __test/MEMBER}` @@ -47,6 +47,12 @@ The following JSON... "__base": "var canvas = document.createElement('canvas'); var gl = canvas.getContext('webgl'); var instance = gl.getExtension('ANGLE_instanced_arrays');", "__test": "return canvas && instance;", "drawArraysInstancedANGLE": "return true && instance && 'drawArraysInstancedANGLE' in instance;" + }, + "Console": { + "log": { + "__test": "return console.log", + "substitution_strings": "console.log('Hello, %s.', 'Bob')" + } } }, "css": { @@ -64,6 +70,10 @@ bcd.addTest('api.ANGLE_instanced_arrays.drawElementsInstancedANGLE', "(function( bcd.addTest('api.ANGLE_instanced_arrays.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE', "(function() {var canvas = document.createElement('canvas'); var gl = canvas.getContext('webgl'); var instance = gl.getExtension('ANGLE_instanced_arrays');return instance && 'VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE' in instance;})()", 'Window'); bcd.addTest('api.ANGLE_instanced_arrays.vertexAttribDivisorANGLE', "(function() {var canvas = document.createElement('canvas'); var gl = canvas.getContext('webgl'); var instance = gl.getExtension('ANGLE_instanced_arrays');return instance && 'vertexAttribDivisorANGLE' in instance;})()", 'Window'); bcd.addTest('api.Animation', {"property":"Animation","scope":"self"}, 'Window'); +... +bcd.addTest('api.Console', {"property":"console","scope":"self"}, 'Window'); +bcd.addTest('api.Console.log', "(function() {return console.log;})()", 'Window'); +bcd.addTest('api.Console.log.substitution_strings', "(function() {console.log('Hello, %s.', 'Bob')})()", 'Window'); ``` Tips: make sure to implement thorough feature checking as to not raise exceptions. diff --git a/build.js b/build.js index 59ac9e934..d366c085b 100644 --- a/build.js +++ b/build.js @@ -58,7 +58,13 @@ function getCustomTestAPI(name, member) { } } else { if (member in customTests.api[name]) { - test = testbase + customTests.api[name][member]; + if (typeof customTests.api[name][member] === 'object') { + if ('__test' in customTests.api[name][member]) { + test = testbase + customTests.api[name][member].__test; + } + } else { + test = testbase + customTests.api[name][member]; + } } else { test = testbase ? testbase + `return instance && '${member}' in instance;` : @@ -74,6 +80,25 @@ function getCustomTestAPI(name, member) { return test; } +function getCustomSubtestsAPI(name, member) { + const subtests = {}; + + if (name in customTests.api) { + const testbase = customTests.api[name].__base || ''; + if ( + member in customTests.api[name] && + typeof customTests.api[name][member] === 'object' + ) { + for (const subtest of Object.entries(customTests.api[name][member])) { + if (subtest[0] == '__test') continue; + subtests[subtest[0]] = `(function() {${testbase}${subtest[1]}})()`; + } + } + } + + return subtests; +} + function getCustomTestCSS(name) { return 'properties' in customTests.css && name in customTests.css.properties && @@ -425,9 +450,10 @@ function buildIDLTests(ast) { const exposureSet = getExposureSet(iface); const isGlobal = !!getExtAttr(iface, 'Global'); - const customIfaceTest = getCustomTestAPI(iface.name); + const adjustedIfaceName = getName(iface); + const customIfaceTest = getCustomTestAPI(adjustedIfaceName); - tests[`api.${getName(iface)}`] = compileTest({ + tests[`api.${adjustedIfaceName}`] = compileTest({ 'raw': { 'code': customIfaceTest || {property: iface.name, scope: 'self'}, 'combinator': '&&' @@ -446,7 +472,7 @@ function buildIDLTests(ast) { } let expr; - const customTestMember = getCustomTestAPI(iface.name, member.name); + const customTestMember = getCustomTestAPI(adjustedIfaceName, member.name); if (customTestMember) { expr = customIfaceTest ? @@ -497,7 +523,7 @@ function buildIDLTests(ast) { } } - tests[`api.${getName(iface)}.${member.name}`] = compileTest({ + tests[`api.${adjustedIfaceName}.${member.name}`] = compileTest({ 'raw': { 'code': expr, 'combinator': '&&' @@ -505,6 +531,14 @@ function buildIDLTests(ast) { 'scope': Array.from(exposureSet) }); handledMemberNames.add(member.name); + + const subtests = getCustomSubtestsAPI(adjustedIfaceName, member.name); + for (const subtest of Object.entries(subtests)) { + tests[`api.${adjustedIfaceName}.${member.name}.${subtest[0]}`] = { + 'tests': [{'code': subtest[1], 'prefix': ''}], + 'scope': Array.from(exposureSet) + }; + } } } @@ -715,6 +749,7 @@ if (require.main === module) { module.exports = { writeFile, getCustomTestAPI, + getCustomSubtestsAPI, getCustomTestCSS, collectExtraIDL, flattenIDL, diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 647fa8fe6..0a1315825 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -186,6 +186,33 @@ describe('build', () => { }); }); + describe('custom test for member with subtests', () => { + const {getCustomTestAPI} = proxyquire('../../build', { + './custom-tests.json': { + api: { + 'foo': { + 'bar': { + '__test': 'return 1 + 1;', + 'multiple': 'return 1 + 1 + 1;', + 'one': 'return 1;' + } + } + } + } + }); + + it('interface', () => { + assert.equal(getCustomTestAPI('foo'), false); + }); + + it('member', () => { + assert.equal( + getCustomTestAPI('foo', 'bar'), + '(function() {return 1 + 1;})()' + ); + }); + }); + describe('custom test for interface and member', () => { const {getCustomTestAPI} = proxyquire('../../build', { './custom-tests.json': { @@ -215,6 +242,32 @@ describe('build', () => { }); }); + describe('getCustomSubtestAPI', () => { + it('get subtests', () => { + const {getCustomSubtestsAPI} = proxyquire('../../build', { + './custom-tests.json': { + api: { + 'foo': { + 'bar': { + '__test': 'return 1 + 1;', + 'multiple': 'return 1 + 1 + 1;', + 'one': 'return 1;' + } + } + } + } + }); + + assert.deepEqual( + getCustomSubtestsAPI('foo', 'bar'), + { + 'multiple': '(function() {return 1 + 1 + 1;})()', + 'one': '(function() {return 1;})()' + } + ); + }); + }); + describe('getCustomTestCSS', () => { it('no custom tests', () => { const {getCustomTestCSS} = proxyquire('../../build', { @@ -830,6 +883,10 @@ describe('build', () => { GLintptr offset, GLsizei primcoun ); + }; + + interface Body { + readonly attribute boolean loaded; };`); const {buildIDLTests} = proxyquire('../../build', { './custom-tests.json': { @@ -838,6 +895,11 @@ describe('build', () => { '__base': 'var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');', '__test': 'return !!instance;', 'drawArraysInstancedANGLE': 'return true && instance && \'drawArraysInstancedANGLE\' in instance;' + }, + 'Body': { + 'loaded': { + 'loaded_is_boolean': 'return typeof body.loaded === "boolean";' + } } } } @@ -870,6 +932,73 @@ describe('build', () => { } ], 'scope': ['Window'] + }, + 'api.Body': { + 'tests': [ + { + 'code': '"Body" in self', + 'prefix': '' + }, + { + 'code': '"webkitBody" in self', + 'prefix': 'webkit' + }, + { + 'code': '"WebKitBody" in self', + 'prefix': 'WebKit' + } + ], + 'scope': ['Window'] + }, + 'api.Body.loaded': { + 'tests': [ + { + 'code': '"Body" in self && "loaded" in Body.prototype', + 'prefix': '' + }, + { + 'code': '"Body" in self && "webkitLoaded" in Body.prototype', + 'prefix': 'webkit' + }, + { + 'code': '"Body" in self && "WebKitLoaded" in Body.prototype', + 'prefix': 'WebKit' + }, + { + 'code': '"webkitBody" in self && "loaded" in webkitBody.prototype', + 'prefix': '' + }, + { + 'code': '"webkitBody" in self && "webkitLoaded" in webkitBody.prototype', + 'prefix': 'webkit' + }, + { + 'code': '"webkitBody" in self && "WebKitLoaded" in webkitBody.prototype', + 'prefix': 'WebKit' + }, + { + 'code': '"WebKitBody" in self && "loaded" in WebKitBody.prototype', + 'prefix': '' + }, + { + 'code': '"WebKitBody" in self && "webkitLoaded" in WebKitBody.prototype', + 'prefix': 'webkit' + }, + { + 'code': '"WebKitBody" in self && "WebKitLoaded" in WebKitBody.prototype', + 'prefix': 'WebKit' + } + ], + 'scope': ['Window'] + }, + 'api.Body.loaded.loaded_is_boolean': { + 'tests': [ + { + 'code': '(function() {return typeof body.loaded === "boolean";})()', + 'prefix': '' + } + ], + 'scope': ['Window'] } }); }); From d57c068cbdd921fbffe1ecae653b4c18403c8e33 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 21:54:54 -0700 Subject: [PATCH 120/243] Reduce prefixes used in unittests --- build.js | 2 +- unittest/unit/build.js | 740 ----------------------------------------- 2 files changed, 1 insertion(+), 741 deletions(-) diff --git a/build.js b/build.js index d366c085b..6bc5b904b 100644 --- a/build.js +++ b/build.js @@ -26,7 +26,7 @@ const generatedDir = path.join(__dirname, 'generated'); const prefixes = process.env.NODE_ENV === 'test' ? { // Shortened in tests for convenience - api: ['', 'webkit', 'WebKit'], + api: ['', 'WebKit'], css: ['', 'webkit'] } : { api: ['', 'moz', 'Moz', 'webkit', 'WebKit', 'webKit', 'ms', 'MS'], diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 0a1315825..d71cae4fe 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -609,10 +609,6 @@ describe('build', () => { 'code': '"Attr" in self', 'prefix': '' }, - { - 'code': '"webkitAttr" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitAttr" in self', 'prefix': 'WebKit' @@ -626,34 +622,14 @@ describe('build', () => { 'code': '"Attr" in self && "name" in Attr.prototype', 'prefix': '' }, - { - 'code': '"Attr" in self && "webkitName" in Attr.prototype', - 'prefix': 'webkit' - }, { 'code': '"Attr" in self && "WebKitName" in Attr.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitAttr" in self && "name" in webkitAttr.prototype', - 'prefix': '' - }, - { - 'code': '"webkitAttr" in self && "webkitName" in webkitAttr.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitAttr" in self && "WebKitName" in webkitAttr.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitAttr" in self && "name" in WebKitAttr.prototype', 'prefix': '' }, - { - 'code': '"WebKitAttr" in self && "webkitName" in WebKitAttr.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitAttr" in self && "WebKitName" in WebKitAttr.prototype', 'prefix': 'WebKit' @@ -676,10 +652,6 @@ describe('build', () => { 'code': '"Node" in self', 'prefix': '' }, - { - 'code': '"webkitNode" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitNode" in self', 'prefix': 'WebKit' @@ -693,34 +665,14 @@ describe('build', () => { 'code': '"Node" in self && "contains" in Node.prototype', 'prefix': '' }, - { - 'code': '"Node" in self && "webkitContains" in Node.prototype', - 'prefix': 'webkit' - }, { 'code': '"Node" in self && "WebKitContains" in Node.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitNode" in self && "contains" in webkitNode.prototype', - 'prefix': '' - }, - { - 'code': '"webkitNode" in self && "webkitContains" in webkitNode.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitNode" in self && "WebKitContains" in webkitNode.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitNode" in self && "contains" in WebKitNode.prototype', 'prefix': '' }, - { - 'code': '"WebKitNode" in self && "webkitContains" in WebKitNode.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitNode" in self && "WebKitContains" in WebKitNode.prototype', 'prefix': 'WebKit' @@ -744,10 +696,6 @@ describe('build', () => { 'code': '"MediaSource" in self', 'prefix': '' }, - { - 'code': '"webkitMediaSource" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitMediaSource" in self', 'prefix': 'WebKit' @@ -761,34 +709,14 @@ describe('build', () => { 'code': '"MediaSource" in self && "isTypeSupported" in MediaSource', 'prefix': '' }, - { - 'code': '"MediaSource" in self && "webkitIsTypeSupported" in MediaSource', - 'prefix': 'webkit' - }, { 'code': '"MediaSource" in self && "WebKitIsTypeSupported" in MediaSource', 'prefix': 'WebKit' }, - { - 'code': '"webkitMediaSource" in self && "isTypeSupported" in webkitMediaSource', - 'prefix': '' - }, - { - 'code': '"webkitMediaSource" in self && "webkitIsTypeSupported" in webkitMediaSource', - 'prefix': 'webkit' - }, - { - 'code': '"webkitMediaSource" in self && "WebKitIsTypeSupported" in webkitMediaSource', - 'prefix': 'WebKit' - }, { 'code': '"WebKitMediaSource" in self && "isTypeSupported" in WebKitMediaSource', 'prefix': '' }, - { - 'code': '"WebKitMediaSource" in self && "webkitIsTypeSupported" in WebKitMediaSource', - 'prefix': 'webkit' - }, { 'code': '"WebKitMediaSource" in self && "WebKitIsTypeSupported" in WebKitMediaSource', 'prefix': 'WebKit' @@ -812,10 +740,6 @@ describe('build', () => { 'code': '"Window" in self', 'prefix': '' }, - { - 'code': '"webkitWindow" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitWindow" in self', 'prefix': 'WebKit' @@ -829,34 +753,14 @@ describe('build', () => { 'code': '"Window" in self && "isWindow" in Window', 'prefix': '' }, - { - 'code': '"Window" in self && "webkitIsWindow" in Window', - 'prefix': 'webkit' - }, { 'code': '"Window" in self && "WebKitIsWindow" in Window', 'prefix': 'WebKit' }, - { - 'code': '"webkitWindow" in self && "isWindow" in webkitWindow', - 'prefix': '' - }, - { - 'code': '"webkitWindow" in self && "webkitIsWindow" in webkitWindow', - 'prefix': 'webkit' - }, - { - 'code': '"webkitWindow" in self && "WebKitIsWindow" in webkitWindow', - 'prefix': 'WebKit' - }, { 'code': '"WebKitWindow" in self && "isWindow" in WebKitWindow', 'prefix': '' }, - { - 'code': '"WebKitWindow" in self && "webkitIsWindow" in WebKitWindow', - 'prefix': 'webkit' - }, { 'code': '"WebKitWindow" in self && "WebKitIsWindow" in WebKitWindow', 'prefix': 'WebKit' @@ -939,10 +843,6 @@ describe('build', () => { 'code': '"Body" in self', 'prefix': '' }, - { - 'code': '"webkitBody" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitBody" in self', 'prefix': 'WebKit' @@ -956,34 +856,14 @@ describe('build', () => { 'code': '"Body" in self && "loaded" in Body.prototype', 'prefix': '' }, - { - 'code': '"Body" in self && "webkitLoaded" in Body.prototype', - 'prefix': 'webkit' - }, { 'code': '"Body" in self && "WebKitLoaded" in Body.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitBody" in self && "loaded" in webkitBody.prototype', - 'prefix': '' - }, - { - 'code': '"webkitBody" in self && "webkitLoaded" in webkitBody.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitBody" in self && "WebKitLoaded" in webkitBody.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitBody" in self && "loaded" in WebKitBody.prototype', 'prefix': '' }, - { - 'code': '"WebKitBody" in self && "webkitLoaded" in WebKitBody.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitBody" in self && "WebKitLoaded" in WebKitBody.prototype', 'prefix': 'WebKit' @@ -1022,10 +902,6 @@ describe('build', () => { 'code': '"WindowOrWorkerGlobalScope" in self', 'prefix': '' }, - { - 'code': '"webkitWindowOrWorkerGlobalScope" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitWindowOrWorkerGlobalScope" in self', 'prefix': 'WebKit' @@ -1039,10 +915,6 @@ describe('build', () => { 'code': '"active" in self', 'prefix': '' }, - { - 'code': '"webkitActive" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitActive" in self', 'prefix': 'WebKit' @@ -1056,10 +928,6 @@ describe('build', () => { 'code': '"isLoaded" in self', 'prefix': '' }, - { - 'code': '"webkitIsLoaded" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitIsLoaded" in self', 'prefix': 'WebKit' @@ -1082,10 +950,6 @@ describe('build', () => { 'code': '"Number" in self', 'prefix': '' }, - { - 'code': '"webkitNumber" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitNumber" in self', 'prefix': 'WebKit' @@ -1099,10 +963,6 @@ describe('build', () => { 'code': '"Number" in self && bcd.testConstructor("Number")', 'prefix': '' }, - { - 'code': '"webkitNumber" in self && bcd.testConstructor("webkitNumber")', - 'prefix': 'webkit' - }, { 'code': '"WebKitNumber" in self && bcd.testConstructor("WebKitNumber")', 'prefix': 'WebKit' @@ -1123,10 +983,6 @@ describe('build', () => { 'code': '"Number" in self', 'prefix': '' }, - { - 'code': '"webkitNumber" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitNumber" in self', 'prefix': 'WebKit' @@ -1140,10 +996,6 @@ describe('build', () => { 'code': '"Number" in self && bcd.testConstructor("Number")', 'prefix': '' }, - { - 'code': '"webkitNumber" in self && bcd.testConstructor("webkitNumber")', - 'prefix': 'webkit' - }, { 'code': '"WebKitNumber" in self && bcd.testConstructor("WebKitNumber")', 'prefix': 'WebKit' @@ -1165,10 +1017,6 @@ describe('build', () => { 'code': '"DoubleList" in self', 'prefix': '' }, - { - 'code': '"webkitDoubleList" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleList" in self', 'prefix': 'WebKit' @@ -1182,10 +1030,6 @@ describe('build', () => { 'code': '"DoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in DoubleList.prototype', 'prefix': '' }, - { - 'code': '"webkitDoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in webkitDoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in WebKitDoubleList.prototype', 'prefix': 'WebKit' @@ -1199,34 +1043,14 @@ describe('build', () => { 'code': '"DoubleList" in self && "entries" in DoubleList.prototype', 'prefix': '' }, - { - 'code': '"DoubleList" in self && "webkitEntries" in DoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleList" in self && "WebKitEntries" in DoubleList.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleList" in self && "entries" in webkitDoubleList.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleList" in self && "webkitEntries" in webkitDoubleList.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleList" in self && "WebKitEntries" in webkitDoubleList.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleList" in self && "entries" in WebKitDoubleList.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleList" in self && "webkitEntries" in WebKitDoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleList" in self && "WebKitEntries" in WebKitDoubleList.prototype', 'prefix': 'WebKit' @@ -1240,34 +1064,14 @@ describe('build', () => { 'code': '"DoubleList" in self && "forEach" in DoubleList.prototype', 'prefix': '' }, - { - 'code': '"DoubleList" in self && "webkitForEach" in DoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleList" in self && "WebKitForEach" in DoubleList.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleList" in self && "forEach" in webkitDoubleList.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleList" in self && "webkitForEach" in webkitDoubleList.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleList" in self && "WebKitForEach" in webkitDoubleList.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleList" in self && "forEach" in WebKitDoubleList.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleList" in self && "webkitForEach" in WebKitDoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleList" in self && "WebKitForEach" in WebKitDoubleList.prototype', 'prefix': 'WebKit' @@ -1281,34 +1085,14 @@ describe('build', () => { 'code': '"DoubleList" in self && "keys" in DoubleList.prototype', 'prefix': '' }, - { - 'code': '"DoubleList" in self && "webkitKeys" in DoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleList" in self && "WebKitKeys" in DoubleList.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleList" in self && "keys" in webkitDoubleList.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleList" in self && "webkitKeys" in webkitDoubleList.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleList" in self && "WebKitKeys" in webkitDoubleList.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleList" in self && "keys" in WebKitDoubleList.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleList" in self && "webkitKeys" in WebKitDoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleList" in self && "WebKitKeys" in WebKitDoubleList.prototype', 'prefix': 'WebKit' @@ -1322,34 +1106,14 @@ describe('build', () => { 'code': '"DoubleList" in self && "values" in DoubleList.prototype', 'prefix': '' }, - { - 'code': '"DoubleList" in self && "webkitValues" in DoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleList" in self && "WebKitValues" in DoubleList.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleList" in self && "values" in webkitDoubleList.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleList" in self && "webkitValues" in webkitDoubleList.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleList" in self && "WebKitValues" in webkitDoubleList.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleList" in self && "values" in WebKitDoubleList.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleList" in self && "webkitValues" in WebKitDoubleList.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleList" in self && "WebKitValues" in WebKitDoubleList.prototype', 'prefix': 'WebKit' @@ -1371,10 +1135,6 @@ describe('build', () => { 'code': '"DoubleMap" in self', 'prefix': '' }, - { - 'code': '"webkitDoubleMap" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self', 'prefix': 'WebKit' @@ -1388,34 +1148,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "clear" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitClear" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitClear" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "clear" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitClear" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitClear" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "clear" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitClear" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitClear" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1429,34 +1169,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "delete" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitDelete" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitDelete" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "delete" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitDelete" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitDelete" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "delete" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitDelete" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitDelete" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1470,34 +1190,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "entries" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitEntries" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitEntries" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "entries" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitEntries" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitEntries" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "entries" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitEntries" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitEntries" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1511,34 +1211,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "forEach" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitForEach" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitForEach" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "forEach" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitForEach" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitForEach" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "forEach" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitForEach" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitForEach" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1552,34 +1232,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "get" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitGet" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitGet" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "get" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitGet" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitGet" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "get" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitGet" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitGet" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1593,34 +1253,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "has" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitHas" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitHas" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "has" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitHas" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitHas" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "has" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitHas" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitHas" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1634,34 +1274,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "keys" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitKeys" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitKeys" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "keys" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitKeys" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitKeys" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "keys" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitKeys" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitKeys" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1675,34 +1295,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "set" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitSet" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitSet" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "set" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitSet" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitSet" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "set" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitSet" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitSet" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1716,34 +1316,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "size" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitSize" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitSize" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "size" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitSize" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitSize" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "size" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitSize" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitSize" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1757,34 +1337,14 @@ describe('build', () => { 'code': '"DoubleMap" in self && "values" in DoubleMap.prototype', 'prefix': '' }, - { - 'code': '"DoubleMap" in self && "webkitValues" in DoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleMap" in self && "WebKitValues" in DoubleMap.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleMap" in self && "values" in webkitDoubleMap.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleMap" in self && "webkitValues" in webkitDoubleMap.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleMap" in self && "WebKitValues" in webkitDoubleMap.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleMap" in self && "values" in WebKitDoubleMap.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleMap" in self && "webkitValues" in WebKitDoubleMap.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleMap" in self && "WebKitValues" in WebKitDoubleMap.prototype', 'prefix': 'WebKit' @@ -1806,10 +1366,6 @@ describe('build', () => { 'code': '"DoubleSet" in self', 'prefix': '' }, - { - 'code': '"webkitDoubleSet" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self', 'prefix': 'WebKit' @@ -1823,34 +1379,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "add" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitAdd" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitAdd" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "add" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitAdd" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitAdd" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "add" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitAdd" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitAdd" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -1864,34 +1400,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "clear" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitClear" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitClear" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "clear" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitClear" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitClear" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "clear" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitClear" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitClear" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -1905,34 +1421,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "delete" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitDelete" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitDelete" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "delete" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitDelete" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitDelete" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "delete" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitDelete" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitDelete" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -1946,34 +1442,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "entries" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitEntries" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitEntries" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "entries" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitEntries" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitEntries" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "entries" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitEntries" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitEntries" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -1987,34 +1463,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "has" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitHas" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitHas" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "has" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitHas" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitHas" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "has" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitHas" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitHas" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -2028,34 +1484,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "keys" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitKeys" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitKeys" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "keys" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitKeys" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitKeys" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "keys" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitKeys" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitKeys" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -2069,34 +1505,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "size" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitSize" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitSize" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "size" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitSize" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitSize" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "size" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitSize" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitSize" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -2110,34 +1526,14 @@ describe('build', () => { 'code': '"DoubleSet" in self && "values" in DoubleSet.prototype', 'prefix': '' }, - { - 'code': '"DoubleSet" in self && "webkitValues" in DoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"DoubleSet" in self && "WebKitValues" in DoubleSet.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitDoubleSet" in self && "values" in webkitDoubleSet.prototype', - 'prefix': '' - }, - { - 'code': '"webkitDoubleSet" in self && "webkitValues" in webkitDoubleSet.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitDoubleSet" in self && "WebKitValues" in webkitDoubleSet.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitDoubleSet" in self && "values" in WebKitDoubleSet.prototype', 'prefix': '' }, - { - 'code': '"WebKitDoubleSet" in self && "webkitValues" in WebKitDoubleSet.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitDoubleSet" in self && "WebKitValues" in WebKitDoubleSet.prototype', 'prefix': 'WebKit' @@ -2160,10 +1556,6 @@ describe('build', () => { 'code': '"GetMe" in self', 'prefix': '' }, - { - 'code': '"webkitGetMe" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitGetMe" in self', 'prefix': 'WebKit' @@ -2188,10 +1580,6 @@ describe('build', () => { 'code': '"CSS" in self', 'prefix': '' }, - { - 'code': '"webkitCSS" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitCSS" in self', 'prefix': 'WebKit' @@ -2205,10 +1593,6 @@ describe('build', () => { 'code': '"MessageChannel" in self', 'prefix': '' }, - { - 'code': '"webkitMessageChannel" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitMessageChannel" in self', 'prefix': 'WebKit' @@ -2222,10 +1606,6 @@ describe('build', () => { 'code': '"Worker" in self', 'prefix': '' }, - { - 'code': '"webkitWorker" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitWorker" in self', 'prefix': 'WebKit' @@ -2239,10 +1619,6 @@ describe('build', () => { 'code': '"WorkerSync" in self', 'prefix': '' }, - { - 'code': '"webkitWorkerSync" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitWorkerSync" in self', 'prefix': 'WebKit' @@ -2268,10 +1644,6 @@ describe('build', () => { 'code': '"AudioNode" in self', 'prefix': '' }, - { - 'code': '"webkitAudioNode" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitAudioNode" in self', 'prefix': 'WebKit' @@ -2285,34 +1657,14 @@ describe('build', () => { 'code': '"AudioNode" in self && "disconnect" in AudioNode.prototype', 'prefix': '' }, - { - 'code': '"AudioNode" in self && "webkitDisconnect" in AudioNode.prototype', - 'prefix': 'webkit' - }, { 'code': '"AudioNode" in self && "WebKitDisconnect" in AudioNode.prototype', 'prefix': 'WebKit' }, - { - 'code': '"webkitAudioNode" in self && "disconnect" in webkitAudioNode.prototype', - 'prefix': '' - }, - { - 'code': '"webkitAudioNode" in self && "webkitDisconnect" in webkitAudioNode.prototype', - 'prefix': 'webkit' - }, - { - 'code': '"webkitAudioNode" in self && "WebKitDisconnect" in webkitAudioNode.prototype', - 'prefix': 'WebKit' - }, { 'code': '"WebKitAudioNode" in self && "disconnect" in WebKitAudioNode.prototype', 'prefix': '' }, - { - 'code': '"WebKitAudioNode" in self && "webkitDisconnect" in WebKitAudioNode.prototype', - 'prefix': 'webkit' - }, { 'code': '"WebKitAudioNode" in self && "WebKitDisconnect" in WebKitAudioNode.prototype', 'prefix': 'WebKit' @@ -2335,10 +1687,6 @@ describe('build', () => { 'code': '"CSS" in self', 'prefix': '' }, - { - 'code': '"webkitCSS" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitCSS" in self', 'prefix': 'WebKit' @@ -2352,34 +1700,14 @@ describe('build', () => { 'code': '"CSS" in self && "paintWorklet" in CSS', 'prefix': '' }, - { - 'code': '"CSS" in self && "webkitPaintWorklet" in CSS', - 'prefix': 'webkit' - }, { 'code': '"CSS" in self && "WebKitPaintWorklet" in CSS', 'prefix': 'WebKit' }, - { - 'code': '"webkitCSS" in self && "paintWorklet" in webkitCSS', - 'prefix': '' - }, - { - 'code': '"webkitCSS" in self && "webkitPaintWorklet" in webkitCSS', - 'prefix': 'webkit' - }, - { - 'code': '"webkitCSS" in self && "WebKitPaintWorklet" in webkitCSS', - 'prefix': 'WebKit' - }, { 'code': '"WebKitCSS" in self && "paintWorklet" in WebKitCSS', 'prefix': '' }, - { - 'code': '"WebKitCSS" in self && "webkitPaintWorklet" in WebKitCSS', - 'prefix': 'webkit' - }, { 'code': '"WebKitCSS" in self && "WebKitPaintWorklet" in WebKitCSS', 'prefix': 'WebKit' @@ -2402,10 +1730,6 @@ describe('build', () => { 'code': '"CSS" in self', 'prefix': '' }, - { - 'code': '"webkitCSS" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitCSS" in self', 'prefix': 'WebKit' @@ -2419,34 +1743,14 @@ describe('build', () => { 'code': '"CSS" in self && "supports" in CSS', 'prefix': '' }, - { - 'code': '"CSS" in self && "webkitSupports" in CSS', - 'prefix': 'webkit' - }, { 'code': '"CSS" in self && "WebKitSupports" in CSS', 'prefix': 'WebKit' }, - { - 'code': '"webkitCSS" in self && "supports" in webkitCSS', - 'prefix': '' - }, - { - 'code': '"webkitCSS" in self && "webkitSupports" in webkitCSS', - 'prefix': 'webkit' - }, - { - 'code': '"webkitCSS" in self && "WebKitSupports" in webkitCSS', - 'prefix': 'WebKit' - }, { 'code': '"WebKitCSS" in self && "supports" in WebKitCSS', 'prefix': '' }, - { - 'code': '"WebKitCSS" in self && "webkitSupports" in WebKitCSS', - 'prefix': 'webkit' - }, { 'code': '"WebKitCSS" in self && "WebKitSupports" in WebKitCSS', 'prefix': 'WebKit' @@ -2510,10 +1814,6 @@ describe('build', () => { 'code': '"ElementRegistrationOptions" in self', 'prefix': '' }, - { - 'code': '"webkitElementRegistrationOptions" in self', - 'prefix': 'webkit' - }, { 'code': '"WebKitElementRegistrationOptions" in self', 'prefix': 'WebKit' @@ -2527,34 +1827,14 @@ describe('build', () => { 'code': '"ElementRegistrationOptions" in self && "extends" in ElementRegistrationOptions', 'prefix': '' }, - { - 'code': '"ElementRegistrationOptions" in self && "webkitExtends" in ElementRegistrationOptions', - 'prefix': 'webkit' - }, { 'code': '"ElementRegistrationOptions" in self && "WebKitExtends" in ElementRegistrationOptions', 'prefix': 'WebKit' }, - { - 'code': '"webkitElementRegistrationOptions" in self && "extends" in webkitElementRegistrationOptions', - 'prefix': '' - }, - { - 'code': '"webkitElementRegistrationOptions" in self && "webkitExtends" in webkitElementRegistrationOptions', - 'prefix': 'webkit' - }, - { - 'code': '"webkitElementRegistrationOptions" in self && "WebKitExtends" in webkitElementRegistrationOptions', - 'prefix': 'WebKit' - }, { 'code': '"WebKitElementRegistrationOptions" in self && "extends" in WebKitElementRegistrationOptions', 'prefix': '' }, - { - 'code': '"WebKitElementRegistrationOptions" in self && "webkitExtends" in WebKitElementRegistrationOptions', - 'prefix': 'webkit' - }, { 'code': '"WebKitElementRegistrationOptions" in self && "WebKitExtends" in WebKitElementRegistrationOptions', 'prefix': 'WebKit' @@ -2568,34 +1848,14 @@ describe('build', () => { 'code': '"ElementRegistrationOptions" in self && "prototype" in ElementRegistrationOptions', 'prefix': '' }, - { - 'code': '"ElementRegistrationOptions" in self && "webkitPrototype" in ElementRegistrationOptions', - 'prefix': 'webkit' - }, { 'code': '"ElementRegistrationOptions" in self && "WebKitPrototype" in ElementRegistrationOptions', 'prefix': 'WebKit' }, - { - 'code': '"webkitElementRegistrationOptions" in self && "prototype" in webkitElementRegistrationOptions', - 'prefix': '' - }, - { - 'code': '"webkitElementRegistrationOptions" in self && "webkitPrototype" in webkitElementRegistrationOptions', - 'prefix': 'webkit' - }, - { - 'code': '"webkitElementRegistrationOptions" in self && "WebKitPrototype" in webkitElementRegistrationOptions', - 'prefix': 'WebKit' - }, { 'code': '"WebKitElementRegistrationOptions" in self && "prototype" in WebKitElementRegistrationOptions', 'prefix': '' }, - { - 'code': '"WebKitElementRegistrationOptions" in self && "webkitPrototype" in WebKitElementRegistrationOptions', - 'prefix': 'webkit' - }, { 'code': '"WebKitElementRegistrationOptions" in self && "WebKitPrototype" in WebKitElementRegistrationOptions', 'prefix': 'WebKit' From 8ef18ea21d4257e54f6a1d24ea7fc40374a4fa3b Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 22:05:58 -0700 Subject: [PATCH 121/243] Add no-else-return as ESLint error --- .eslintrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.json b/.eslintrc.json index e47ec3714..5b88a9759 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,6 +7,7 @@ "rules": { "comma-dangle": ["error", "never"], "require-jsdoc": "off", + "no-else-return": "error", "no-unused-vars": ["error", {"varsIgnorePattern": "^_$"}], "max-len": ["error", { "code": 80, From 28cc3870c10fdbce9e4c800c0aed00dd17254d16 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 22:06:17 -0700 Subject: [PATCH 122/243] Remove redundant else statements after return statements --- build.js | 43 ++++++++++++++++++++++--------------------- tests.js | 34 ++++++++++++++++------------------ 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/build.js b/build.js index 6bc5b904b..1c2199af7 100644 --- a/build.js +++ b/build.js @@ -108,28 +108,29 @@ function getCustomTestCSS(name) { function compileTestCode(test, prefix = '', scopePrefix = '') { if (typeof(test) === 'string') { return test.replace(/PREFIX/g, prefix); - } else { - const property = prefix ? - prefix + test.property.charAt(0).toUpperCase() + - test.property.slice(1) : test.property; - const scopeAsProperty = prefix ? - prefix + test.scope.charAt(0).toUpperCase() + - test.scope.slice(1) : test.scope; - const scope = scopePrefix ? - scopePrefix + test.scope.charAt(0).toUpperCase() + - test.scope.slice(1) : test.scope; - - if (test.property == 'constructor') { - return `"${scopeAsProperty}" in self && bcd.testConstructor("${scopeAsProperty}")`; - } else if (test.scope === 'CSS.supports') { - const thisPrefix = prefix ? `-${prefix}-` : ''; - return `CSS.supports("${thisPrefix}${test.property}", "inherit")`; - } else if (test.property.startsWith('Symbol.')) { - return `"${scopeAsProperty}" in self && "Symbol" in self && "${test.property.replace('Symbol.', '')}" in Symbol && ${test.property} in ${scopeAsProperty}.prototype`; - } else { - return `"${property}" in ${scope}`; - } } + + const property = prefix ? + prefix + test.property.charAt(0).toUpperCase() + + test.property.slice(1) : test.property; + const scopeAsProperty = prefix ? + prefix + test.scope.charAt(0).toUpperCase() + + test.scope.slice(1) : test.scope; + const scope = scopePrefix ? + scopePrefix + test.scope.charAt(0).toUpperCase() + + test.scope.slice(1) : test.scope; + + if (test.property == 'constructor') { + return `"${scopeAsProperty}" in self && bcd.testConstructor("${scopeAsProperty}")`; + } + if (test.scope === 'CSS.supports') { + const thisPrefix = prefix ? `-${prefix}-` : ''; + return `CSS.supports("${thisPrefix}${test.property}", "inherit")`; + } + if (test.property.startsWith('Symbol.')) { + return `"${scopeAsProperty}" in self && "Symbol" in self && "${test.property.replace('Symbol.', '')}" in Symbol && ${test.property} in ${scopeAsProperty}.prototype`; + } + return `"${property}" in ${scope}`; } function compileTest(test) { diff --git a/tests.js b/tests.js index 4f3071397..8a95ae71f 100644 --- a/tests.js +++ b/tests.js @@ -46,28 +46,26 @@ class Tests { const afterURL = new URL(after); if (!this.httpOnly && afterURL.protocol === 'http:') { return `https://${this.host}${afterURL.pathname}`; - } else { - const endpoints = this.listMainEndpoints('/tests'); - const index = endpoints.findIndex((item) => { - return item === afterURL.pathname; - }) + 1; + } + const endpoints = this.listMainEndpoints('/tests'); + const index = endpoints.findIndex((item) => { + return item === afterURL.pathname; + }) + 1; - if (index >= endpoints.length) { - return null; - } + if (index >= endpoints.length) { + return null; + } - if (this.endpoints[endpoints[index].replace('/tests', '')].httpsOnly) { - const newUrl = `https://${this.host}${endpoints[index]}`; - if (this.httpOnly) { - // Skip this endpoint and go to the next - return this.next(newUrl); - } else { - return newUrl; - } + if (this.endpoints[endpoints[index].replace('/tests', '')].httpsOnly) { + const newUrl = `https://${this.host}${endpoints[index]}`; + if (this.httpOnly) { + // Skip this endpoint and go to the next + return this.next(newUrl); } - - return `http://${this.host}${endpoints[index]}`; + return newUrl; } + + return `http://${this.host}${endpoints[index]}`; } getTests(endpoint) { From 62987c955174c4a2fa741043a11638450b1b2a10 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 22:06:34 -0700 Subject: [PATCH 123/243] Improve unittest for collectExtraIDL() --- unittest/unit/build.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/unittest/unit/build.js b/unittest/unit/build.js index d71cae4fe..fa14d5ef3 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -420,7 +420,14 @@ describe('build', () => { }); it('collectExtraIDL', () => { - assert.typeOf(collectExtraIDL(), 'array'); + const idl = 'interface Dummy {};'; + mockFs({ + 'non-standard.idl': idl + }); + + assert.deepEqual(collectExtraIDL(), WebIDL2.parse(idl)); + + mockFs.restore(); }); it('buildIDL', () => { From f02e4a5b62e313f8d6379e50d6e5167fd0bc3a3a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 23:17:49 -0700 Subject: [PATCH 124/243] Fix prefix capitalization for string tests --- build.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.js b/build.js index 1c2199af7..76ed76515 100644 --- a/build.js +++ b/build.js @@ -107,7 +107,9 @@ function getCustomTestCSS(name) { function compileTestCode(test, prefix = '', scopePrefix = '') { if (typeof(test) === 'string') { - return test.replace(/PREFIX/g, prefix); + return test.replace(/PREFIX(.)/g, (_, p1) => ( + `${prefix}${prefix ? p1.toUpperCase() : p1}` + )); } const property = prefix ? From 0d40d5810f9d6ce9f92cb909bf8f9c05d83f0b84 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 23:53:04 -0700 Subject: [PATCH 125/243] Improve compiled code de-duping --- build.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.js b/build.js index 76ed76515..964705dea 100644 --- a/build.js +++ b/build.js @@ -147,7 +147,7 @@ function compileTest(test) { for (const prefix of prefixesToTest) { const code = compileTestCode(test.raw.code, prefix); - if (!newTest.tests.length || code !== newTest.tests[0].code) { + if (!newTest.tests.map((item) => (item.code)).includes(code)) { newTest.tests.push({ code: code, prefix: prefix @@ -162,7 +162,7 @@ function compileTest(test) { test.raw.code[1], prefix )}`); - if (!newTest.tests.length || code !== newTest.tests[0].code) { + if (!newTest.tests.map((item) => (item.code)).includes(code)) { newTest.tests.push({ code: code, prefix: prefix @@ -177,7 +177,7 @@ function compileTest(test) { const childCode = compileTestCode(test.raw.code[1], prefix2, prefix1); const code = (`${parentCode} ${test.raw.combinator} ${childCode}`); - if (!newTest.tests.length || code !== newTest.tests[0].code) { + if (!newTest.tests.map((item) => (item.code)).includes(code)) { newTest.tests.push({ code: code, prefix: prefix2 From a8af5ba02c0bb72fa8ebb5cfba99d8a005efd3c3 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 23:53:18 -0700 Subject: [PATCH 126/243] Add unittests for compileTest[Code]() --- build.js | 2 + unittest/unit/build.js | 210 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) diff --git a/build.js b/build.js index 964705dea..73f3ce058 100644 --- a/build.js +++ b/build.js @@ -754,6 +754,8 @@ if (require.main === module) { getCustomTestAPI, getCustomSubtestsAPI, getCustomTestCSS, + compileTestCode, + compileTest, collectExtraIDL, flattenIDL, getExposureSet, diff --git a/unittest/unit/build.js b/unittest/unit/build.js index fa14d5ef3..c8502fcd7 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -30,6 +30,8 @@ const { flattenIDL, getExposureSet, getName, + compileTestCode, + compileTest, collectExtraIDL, validateIDL, buildIDLTests, @@ -292,6 +294,214 @@ describe('build', () => { }); }); + describe('compileTestCode', () => { + describe('string', () => { + const test = 'PREFIXfoo'; + + it('normal', () => { + assert.equal(compileTestCode(test), 'foo'); + }); + + it('prefix', () => { + assert.equal(compileTestCode(test, 'webkit'), 'webkitFoo'); + }); + }); + + describe('constructor', () => { + const test = {property: 'constructor', scope: 'AudioContext'}; + + it('normal', () => { + assert.equal(compileTestCode(test), '"AudioContext" in self && bcd.testConstructor("AudioContext")'); + }); + + it('prefix', () => { + assert.equal(compileTestCode(test, 'moz'), '"mozAudioContext" in self && bcd.testConstructor("mozAudioContext")'); + }); + }); + + describe('CSS.supports', () => { + const test = {property: 'font-weight', scope: 'CSS.supports'}; + + it('normal', () => { + assert.equal(compileTestCode(test), 'CSS.supports("font-weight", "inherit")'); + }); + + it('prefix', () => { + assert.equal(compileTestCode(test, 'webkit'), 'CSS.supports("-webkit-font-weight", "inherit")'); + }); + }); + + describe('Symbol', () => { + const test = {property: 'Symbol.iterator', scope: 'DOMMatrixReadOnly'}; + + it('normal', () => { + assert.equal(compileTestCode(test), '"DOMMatrixReadOnly" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in DOMMatrixReadOnly.prototype'); + }); + + it('prefix', () => { + assert.equal(compileTestCode(test, 'moz'), '"mozDOMMatrixReadOnly" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in mozDOMMatrixReadOnly.prototype'); + }); + }); + + describe('other', () => { + const test = {property: 'log', scope: 'console'}; + + it('normal', () => { + assert.equal(compileTestCode(test), '"log" in console'); + }); + + it('prefix', () => { + assert.equal(compileTestCode(test, 'webkit'), '"webkitLog" in console'); + }); + + it('scope prefix', () => { + assert.equal(compileTestCode(test, '', 'moz'), '"log" in mozConsole'); + }); + + it('prefix + scope prefix', () => { + assert.equal(compileTestCode(test, 'webkit', 'moz'), '"webkitLog" in mozConsole'); + }); + }); + }); + + describe('compileTest', () => { + it('main', () => { + const rawTest = { + 'raw': { + 'code': [ + {property: 'Document', scope: 'self'}, + {property: 'body', scope: `Document.prototype`} + ], + 'combinator': '&&' + }, + 'scope': ['Window'] + }; + + assert.deepEqual(compileTest(rawTest), { + 'tests': [ + { + 'code': '"Document" in self && "body" in Document.prototype', + 'prefix': '' + }, + { + 'code': '"Document" in self && "WebKitBody" in Document.prototype', + 'prefix': 'WebKit' + }, + { + 'code': '"WebKitDocument" in self && "body" in WebKitDocument.prototype', + 'prefix': '' + }, + { + 'code': '"WebKitDocument" in self && "WebKitBody" in WebKitDocument.prototype', + 'prefix': 'WebKit' + } + ], + 'scope': ['Window'] + }); + }); + + it('ignore already compiled', () => { + const test = { + 'tests': [ + { + 'code': 'true', + 'prefix': '' + } + ], + 'scope': ['Window'] + }; + + assert.deepEqual(compileTest(test), test); + }); + + it('no-repeated test code', () => { + const rawTests = [ + { + 'raw': { + 'code': 'true', + 'combinator': '&&' + }, + 'scope': ['Window'] + }, + { + 'raw': { + 'code': [ + 'true', + 'true' + ], + 'combinator': '||' + }, + 'scope': ['CSS'] + }, + { + 'raw': { + 'code': [ + 'true', + 'true' + ], + 'combinator': '&&' + }, + 'scope': ['Worker'] + } + ]; + + assert.deepEqual(compileTest(rawTests[0]), { + 'tests': [ + { + 'code': 'true', + 'prefix': '' + } + ], + 'scope': ['Window'] + }); + assert.deepEqual(compileTest(rawTests[1]), { + 'tests': [ + { + 'code': 'true || true', + 'prefix': '' + } + ], + 'scope': ['CSS'] + }); + assert.deepEqual(compileTest(rawTests[2]), { + 'tests': [ + { + 'code': 'true && true', + 'prefix': '' + } + ], + 'scope': ['Worker'] + }); + }); + + it('CSS scope', () => { + const rawTest = { + 'raw': { + 'code': [ + {property: 'fontFamily', scope: 'document.body.style'}, + {property: 'font-family', scope: 'CSS.supports'} + ], + 'combinator': '||' + }, + 'scope': ['CSS'] + }; + + assert.deepEqual(compileTest(rawTest), { + 'tests': [ + { + 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', + 'prefix': '' + }, + { + 'code': '"webkitFontFamily" in document.body.style || CSS.supports("-webkit-font-family", "inherit")', + 'prefix': 'webkit' + } + ], + 'scope': ['CSS'] + }); + }); + }); + describe('collectCSSPropertiesFromBCD', () => { it('simple supported', () => { const bcd = { From ba7da9e2721a0d5ab3fd1f7051993e9d85d8000b Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Sun, 6 Sep 2020 23:57:10 -0700 Subject: [PATCH 127/243] Add quote-props ESLint rule (and fix) --- .eslintrc.json | 3 +- build.js | 30 +- selenium.js | 10 +- unittest/app/app.js | 8 +- unittest/unit/build.js | 1304 +++++++++++++++++++-------------------- unittest/unit/github.js | 2 +- unittest/unit/tests.js | 20 +- 7 files changed, 689 insertions(+), 688 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 5b88a9759..0ff6b0350 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -17,7 +17,8 @@ "ignoreRegExpLiterals": true, "ignoreUrls": true, "ignorePattern": "goog.(module|require)" - }] + }], + "quote-props": ["error", "as-needed"] }, "env": { "es6": true, diff --git a/build.js b/build.js index 73f3ce058..4c1a30008 100644 --- a/build.js +++ b/build.js @@ -138,7 +138,7 @@ function compileTestCode(test, prefix = '', scopePrefix = '') { function compileTest(test) { if (!('raw' in test) && 'tests' in test) return test; - const newTest = {'tests': [], 'scope': test.scope}; + const newTest = {tests: [], scope: test.scope}; const prefixesToTest = test.scope[0] == ['CSS'] ? prefixes.css : prefixes.api; @@ -457,11 +457,11 @@ function buildIDLTests(ast) { const customIfaceTest = getCustomTestAPI(adjustedIfaceName); tests[`api.${adjustedIfaceName}`] = compileTest({ - 'raw': { - 'code': customIfaceTest || {property: iface.name, scope: 'self'}, - 'combinator': '&&' + raw: { + code: customIfaceTest || {property: iface.name, scope: 'self'}, + combinator: '&&' }, - 'scope': Array.from(exposureSet) + scope: Array.from(exposureSet) }); const members = flattenMembers(iface); @@ -527,19 +527,19 @@ function buildIDLTests(ast) { } tests[`api.${adjustedIfaceName}.${member.name}`] = compileTest({ - 'raw': { - 'code': expr, - 'combinator': '&&' + raw: { + code: expr, + combinator: '&&' }, - 'scope': Array.from(exposureSet) + scope: Array.from(exposureSet) }); handledMemberNames.add(member.name); const subtests = getCustomSubtestsAPI(adjustedIfaceName, member.name); for (const subtest of Object.entries(subtests)) { tests[`api.${adjustedIfaceName}.${member.name}.${subtest[0]}`] = { - 'tests': [{'code': subtest[1], 'prefix': ''}], - 'scope': Array.from(exposureSet) + tests: [{code: subtest[1], prefix: ''}], + scope: Array.from(exposureSet) }; } } @@ -619,14 +619,14 @@ function buildCSS(webref, bcd) { for (const name of Array.from(propertySet).sort()) { const attrName = cssPropertyToIDLAttribute(name, name.startsWith('-')); tests[`css.properties.${name}`] = compileTest({ - 'raw': { - 'code': getCustomTestCSS(name) || [ + raw: { + code: getCustomTestCSS(name) || [ {property: attrName, scope: 'document.body.style'}, {property: name, scope: 'CSS.supports'} ], - 'combinator': '||' + combinator: '||' }, - 'scope': ['CSS'] + scope: ['CSS'] }); } diff --git a/selenium.js b/selenium.js index dd707d7bd..8621a56fb 100644 --- a/selenium.js +++ b/selenium.js @@ -39,11 +39,11 @@ const filterVersions = (data, earliestVersion) => { // TODO: IE and pre-Blink Edge have issues with automated runtime let browsersToTest = { - 'chrome': filterVersions(bcd.browsers.chrome.releases, 40), - 'edge': filterVersions(bcd.browsers.edge.releases, 12), - 'firefox': filterVersions(bcd.browsers.firefox.releases, 35), - 'ie': filterVersions(bcd.browsers.ie.releases, 11), - 'safari': filterVersions(bcd.browsers.safari.releases, 9) + chrome: filterVersions(bcd.browsers.chrome.releases, 40), + edge: filterVersions(bcd.browsers.edge.releases, 12), + firefox: filterVersions(bcd.browsers.firefox.releases, 35), + ie: filterVersions(bcd.browsers.ie.releases, 11), + safari: filterVersions(bcd.browsers.safari.releases, 9) }; if (process.env.BROWSER) { diff --git a/unittest/app/app.js b/unittest/app/app.js index bd819c717..5c86127aa 100644 --- a/unittest/app/app.js +++ b/unittest/app/app.js @@ -55,7 +55,7 @@ describe('/api/results', () => { .send({x: 1}); assert.equal(res.status, 201); assert.deepEqual(res.body, { - 'next': `http://localhost:8080/tests${mainEndpoints[1][0]}` + next: `http://localhost:8080/tests${mainEndpoints[1][0]}` }); }); @@ -63,7 +63,7 @@ describe('/api/results', () => { const res = await agent.get('/api/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { - '__version': version, + __version: version, [testURL]: {x: 1} }); }); @@ -79,7 +79,7 @@ describe('/api/results', () => { const res = await agent.get('/api/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { - '__version': version, + __version: version, [testURL]: {x: 2} }); }); @@ -96,7 +96,7 @@ describe('/api/results', () => { const res = await agent.get('/api/results'); assert.equal(res.status, 200); assert.deepEqual(res.body, { - '__version': version, + __version: version, [testURL]: {x: 2}, [testURL2]: {y: 3} }); diff --git a/unittest/unit/build.js b/unittest/unit/build.js index c8502fcd7..c86ff0144 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -42,7 +42,7 @@ const { buildCSS, buildManifest } = proxyquire('../../build', { - './custom-tests.json': {'api': {}, 'css': {}} + './custom-tests.json': {api: {}, css: {}} }); describe('build', () => { @@ -52,7 +52,7 @@ describe('build', () => { beforeEach(() => { mockFs({ '.testtmp': '', - './custom-tests.json': {'api': {}, 'css': {}} + './custom-tests.json': {api: {}, css: {}} }); }); @@ -67,7 +67,7 @@ describe('build', () => { }); it('dictionary', async () => { - await writeFile(filepath, {'foo': ['bar', 'baz']}); + await writeFile(filepath, {foo: ['bar', 'baz']}); assert.fileContent(filepath, '{\n "foo": [\n "bar",\n "baz"\n ]\n}\n'); }); @@ -95,9 +95,9 @@ describe('build', () => { const {getCustomTestAPI} = proxyquire('../../build', { './custom-tests.json': { api: { - 'foo': { - '__base': 'var a = 1;', - '__test': 'return a;' + foo: { + __base: 'var a = 1;', + __test: 'return a;' } } } @@ -122,8 +122,8 @@ describe('build', () => { const {getCustomTestAPI} = proxyquire('../../build', { './custom-tests.json': { api: { - 'foo': { - '__test': 'return 1;' + foo: { + __test: 'return 1;' } } } @@ -142,9 +142,9 @@ describe('build', () => { const {getCustomTestAPI} = proxyquire('../../build', { './custom-tests.json': { api: { - 'foo': { - '__base': 'var a = 1;', - 'bar': 'return a + 1;' + foo: { + __base: 'var a = 1;', + bar: 'return a + 1;' } } } @@ -169,8 +169,8 @@ describe('build', () => { const {getCustomTestAPI} = proxyquire('../../build', { './custom-tests.json': { api: { - 'foo': { - 'bar': 'return 1 + 1;' + foo: { + bar: 'return 1 + 1;' } } } @@ -192,11 +192,11 @@ describe('build', () => { const {getCustomTestAPI} = proxyquire('../../build', { './custom-tests.json': { api: { - 'foo': { - 'bar': { - '__test': 'return 1 + 1;', - 'multiple': 'return 1 + 1 + 1;', - 'one': 'return 1;' + foo: { + bar: { + __test: 'return 1 + 1;', + multiple: 'return 1 + 1 + 1;', + one: 'return 1;' } } } @@ -219,10 +219,10 @@ describe('build', () => { const {getCustomTestAPI} = proxyquire('../../build', { './custom-tests.json': { api: { - 'foo': { - '__base': 'var a = 1;', - '__test': 'return a;', - 'bar': 'return a + 1;' + foo: { + __base: 'var a = 1;', + __test: 'return a;', + bar: 'return a + 1;' } } } @@ -249,11 +249,11 @@ describe('build', () => { const {getCustomSubtestsAPI} = proxyquire('../../build', { './custom-tests.json': { api: { - 'foo': { - 'bar': { - '__test': 'return 1 + 1;', - 'multiple': 'return 1 + 1 + 1;', - 'one': 'return 1;' + foo: { + bar: { + __test: 'return 1 + 1;', + multiple: 'return 1 + 1 + 1;', + one: 'return 1;' } } } @@ -263,8 +263,8 @@ describe('build', () => { assert.deepEqual( getCustomSubtestsAPI('foo', 'bar'), { - 'multiple': '(function() {return 1 + 1 + 1;})()', - 'one': '(function() {return 1;})()' + multiple: '(function() {return 1 + 1 + 1;})()', + one: '(function() {return 1;})()' } ); }); @@ -367,48 +367,48 @@ describe('build', () => { describe('compileTest', () => { it('main', () => { const rawTest = { - 'raw': { - 'code': [ + raw: { + code: [ {property: 'Document', scope: 'self'}, {property: 'body', scope: `Document.prototype`} ], - 'combinator': '&&' + combinator: '&&' }, - 'scope': ['Window'] + scope: ['Window'] }; assert.deepEqual(compileTest(rawTest), { - 'tests': [ + tests: [ { - 'code': '"Document" in self && "body" in Document.prototype', - 'prefix': '' + code: '"Document" in self && "body" in Document.prototype', + prefix: '' }, { - 'code': '"Document" in self && "WebKitBody" in Document.prototype', - 'prefix': 'WebKit' + code: '"Document" in self && "WebKitBody" in Document.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDocument" in self && "body" in WebKitDocument.prototype', - 'prefix': '' + code: '"WebKitDocument" in self && "body" in WebKitDocument.prototype', + prefix: '' }, { - 'code': '"WebKitDocument" in self && "WebKitBody" in WebKitDocument.prototype', - 'prefix': 'WebKit' + code: '"WebKitDocument" in self && "WebKitBody" in WebKitDocument.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }); }); it('ignore already compiled', () => { const test = { - 'tests': [ + tests: [ { - 'code': 'true', - 'prefix': '' + code: 'true', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }; assert.deepEqual(compileTest(test), test); @@ -417,87 +417,87 @@ describe('build', () => { it('no-repeated test code', () => { const rawTests = [ { - 'raw': { - 'code': 'true', - 'combinator': '&&' + raw: { + code: 'true', + combinator: '&&' }, - 'scope': ['Window'] + scope: ['Window'] }, { - 'raw': { - 'code': [ + raw: { + code: [ 'true', 'true' ], - 'combinator': '||' + combinator: '||' }, - 'scope': ['CSS'] + scope: ['CSS'] }, { - 'raw': { - 'code': [ + raw: { + code: [ 'true', 'true' ], - 'combinator': '&&' + combinator: '&&' }, - 'scope': ['Worker'] + scope: ['Worker'] } ]; assert.deepEqual(compileTest(rawTests[0]), { - 'tests': [ + tests: [ { - 'code': 'true', - 'prefix': '' + code: 'true', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }); assert.deepEqual(compileTest(rawTests[1]), { - 'tests': [ + tests: [ { - 'code': 'true || true', - 'prefix': '' + code: 'true || true', + prefix: '' } ], - 'scope': ['CSS'] + scope: ['CSS'] }); assert.deepEqual(compileTest(rawTests[2]), { - 'tests': [ + tests: [ { - 'code': 'true && true', - 'prefix': '' + code: 'true && true', + prefix: '' } ], - 'scope': ['Worker'] + scope: ['Worker'] }); }); it('CSS scope', () => { const rawTest = { - 'raw': { - 'code': [ + raw: { + code: [ {property: 'fontFamily', scope: 'document.body.style'}, {property: 'font-family', scope: 'CSS.supports'} ], - 'combinator': '||' + combinator: '||' }, - 'scope': ['CSS'] + scope: ['CSS'] }; assert.deepEqual(compileTest(rawTest), { - 'tests': [ + tests: [ { - 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', - 'prefix': '' + code: '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', + prefix: '' }, { - 'code': '"webkitFontFamily" in document.body.style || CSS.supports("-webkit-font-family", "inherit")', - 'prefix': 'webkit' + code: '"webkitFontFamily" in document.body.style || CSS.supports("-webkit-font-family", "inherit")', + prefix: 'webkit' } ], - 'scope': ['CSS'] + scope: ['CSS'] }); }); }); @@ -612,7 +612,7 @@ describe('build', () => { }, 'css-grid': { properties: { - 'grid': {} + grid: {} } } } @@ -821,38 +821,38 @@ describe('build', () => { const ast = WebIDL2.parse(`interface Attr { attribute any name; };`); assert.deepEqual(buildIDLTests(ast), { 'api.Attr': { - 'tests': [ + tests: [ { - 'code': '"Attr" in self', - 'prefix': '' + code: '"Attr" in self', + prefix: '' }, { - 'code': '"WebKitAttr" in self', - 'prefix': 'WebKit' + code: '"WebKitAttr" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Attr.name': { - 'tests': [ + tests: [ { - 'code': '"Attr" in self && "name" in Attr.prototype', - 'prefix': '' + code: '"Attr" in self && "name" in Attr.prototype', + prefix: '' }, { - 'code': '"Attr" in self && "WebKitName" in Attr.prototype', - 'prefix': 'WebKit' + code: '"Attr" in self && "WebKitName" in Attr.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitAttr" in self && "name" in WebKitAttr.prototype', - 'prefix': '' + code: '"WebKitAttr" in self && "name" in WebKitAttr.prototype', + prefix: '' }, { - 'code': '"WebKitAttr" in self && "WebKitName" in WebKitAttr.prototype', - 'prefix': 'WebKit' + code: '"WebKitAttr" in self && "WebKitName" in WebKitAttr.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -864,38 +864,38 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.Node': { - 'tests': [ + tests: [ { - 'code': '"Node" in self', - 'prefix': '' + code: '"Node" in self', + prefix: '' }, { - 'code': '"WebKitNode" in self', - 'prefix': 'WebKit' + code: '"WebKitNode" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Node.contains': { - 'tests': [ + tests: [ { - 'code': '"Node" in self && "contains" in Node.prototype', - 'prefix': '' + code: '"Node" in self && "contains" in Node.prototype', + prefix: '' }, { - 'code': '"Node" in self && "WebKitContains" in Node.prototype', - 'prefix': 'WebKit' + code: '"Node" in self && "WebKitContains" in Node.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitNode" in self && "contains" in WebKitNode.prototype', - 'prefix': '' + code: '"WebKitNode" in self && "contains" in WebKitNode.prototype', + prefix: '' }, { - 'code': '"WebKitNode" in self && "WebKitContains" in WebKitNode.prototype', - 'prefix': 'WebKit' + code: '"WebKitNode" in self && "WebKitContains" in WebKitNode.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -908,38 +908,38 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.MediaSource': { - 'tests': [ + tests: [ { - 'code': '"MediaSource" in self', - 'prefix': '' + code: '"MediaSource" in self', + prefix: '' }, { - 'code': '"WebKitMediaSource" in self', - 'prefix': 'WebKit' + code: '"WebKitMediaSource" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.MediaSource.isTypeSupported': { - 'tests': [ + tests: [ { - 'code': '"MediaSource" in self && "isTypeSupported" in MediaSource', - 'prefix': '' + code: '"MediaSource" in self && "isTypeSupported" in MediaSource', + prefix: '' }, { - 'code': '"MediaSource" in self && "WebKitIsTypeSupported" in MediaSource', - 'prefix': 'WebKit' + code: '"MediaSource" in self && "WebKitIsTypeSupported" in MediaSource', + prefix: 'WebKit' }, { - 'code': '"WebKitMediaSource" in self && "isTypeSupported" in WebKitMediaSource', - 'prefix': '' + code: '"WebKitMediaSource" in self && "isTypeSupported" in WebKitMediaSource', + prefix: '' }, { - 'code': '"WebKitMediaSource" in self && "WebKitIsTypeSupported" in WebKitMediaSource', - 'prefix': 'WebKit' + code: '"WebKitMediaSource" in self && "WebKitIsTypeSupported" in WebKitMediaSource', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -952,38 +952,38 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Window': { - 'tests': [ + tests: [ { - 'code': '"Window" in self', - 'prefix': '' + code: '"Window" in self', + prefix: '' }, { - 'code': '"WebKitWindow" in self', - 'prefix': 'WebKit' + code: '"WebKitWindow" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Window.isWindow': { - 'tests': [ + tests: [ { - 'code': '"Window" in self && "isWindow" in Window', - 'prefix': '' + code: '"Window" in self && "isWindow" in Window', + prefix: '' }, { - 'code': '"Window" in self && "WebKitIsWindow" in Window', - 'prefix': 'WebKit' + code: '"Window" in self && "WebKitIsWindow" in Window', + prefix: 'WebKit' }, { - 'code': '"WebKitWindow" in self && "isWindow" in WebKitWindow', - 'prefix': '' + code: '"WebKitWindow" in self && "isWindow" in WebKitWindow', + prefix: '' }, { - 'code': '"WebKitWindow" in self && "WebKitIsWindow" in WebKitWindow', - 'prefix': 'WebKit' + code: '"WebKitWindow" in self && "WebKitIsWindow" in WebKitWindow', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1011,15 +1011,15 @@ describe('build', () => { };`); const {buildIDLTests} = proxyquire('../../build', { './custom-tests.json': { - 'api': { - 'ANGLE_instanced_arrays': { - '__base': 'var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');', - '__test': 'return !!instance;', - 'drawArraysInstancedANGLE': 'return true && instance && \'drawArraysInstancedANGLE\' in instance;' - }, - 'Body': { - 'loaded': { - 'loaded_is_boolean': 'return typeof body.loaded === "boolean";' + api: { + ANGLE_instanced_arrays: { + __base: 'var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');', + __test: 'return !!instance;', + drawArraysInstancedANGLE: 'return true && instance && \'drawArraysInstancedANGLE\' in instance;' + }, + Body: { + loaded: { + loaded_is_boolean: 'return typeof body.loaded === "boolean";' } } } @@ -1028,74 +1028,74 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.ANGLE_instanced_arrays': { - 'tests': [ + tests: [ { - 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', - 'prefix': '' + code: '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.ANGLE_instanced_arrays.drawArraysInstancedANGLE': { - 'tests': [ + tests: [ { - 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return true && instance && \'drawArraysInstancedANGLE\' in instance;})()', - 'prefix': '' + code: '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return true && instance && \'drawArraysInstancedANGLE\' in instance;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.ANGLE_instanced_arrays.drawElementsInstancedANGLE': { - 'tests': [ + tests: [ { - 'code': '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()', - 'prefix': '' + code: '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Body': { - 'tests': [ + tests: [ { - 'code': '"Body" in self', - 'prefix': '' + code: '"Body" in self', + prefix: '' }, { - 'code': '"WebKitBody" in self', - 'prefix': 'WebKit' + code: '"WebKitBody" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Body.loaded': { - 'tests': [ + tests: [ { - 'code': '"Body" in self && "loaded" in Body.prototype', - 'prefix': '' + code: '"Body" in self && "loaded" in Body.prototype', + prefix: '' }, { - 'code': '"Body" in self && "WebKitLoaded" in Body.prototype', - 'prefix': 'WebKit' + code: '"Body" in self && "WebKitLoaded" in Body.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitBody" in self && "loaded" in WebKitBody.prototype', - 'prefix': '' + code: '"WebKitBody" in self && "loaded" in WebKitBody.prototype', + prefix: '' }, { - 'code': '"WebKitBody" in self && "WebKitLoaded" in WebKitBody.prototype', - 'prefix': 'WebKit' + code: '"WebKitBody" in self && "WebKitLoaded" in WebKitBody.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Body.loaded.loaded_is_boolean': { - 'tests': [ + tests: [ { - 'code': '(function() {return typeof body.loaded === "boolean";})()', - 'prefix': '' + code: '(function() {return typeof body.loaded === "boolean";})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1114,43 +1114,43 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.WindowOrWorkerGlobalScope': { - 'tests': [ + tests: [ { - 'code': '"WindowOrWorkerGlobalScope" in self', - 'prefix': '' + code: '"WindowOrWorkerGlobalScope" in self', + prefix: '' }, { - 'code': '"WebKitWindowOrWorkerGlobalScope" in self', - 'prefix': 'WebKit' + code: '"WebKitWindowOrWorkerGlobalScope" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.WindowOrWorkerGlobalScope.active': { - 'tests': [ + tests: [ { - 'code': '"active" in self', - 'prefix': '' + code: '"active" in self', + prefix: '' }, { - 'code': '"WebKitActive" in self', - 'prefix': 'WebKit' + code: '"WebKitActive" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.WindowOrWorkerGlobalScope.isLoaded': { - 'tests': [ + tests: [ { - 'code': '"isLoaded" in self', - 'prefix': '' + code: '"isLoaded" in self', + prefix: '' }, { - 'code': '"WebKitIsLoaded" in self', - 'prefix': 'WebKit' + code: '"WebKitIsLoaded" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1162,30 +1162,30 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.Number': { - 'tests': [ + tests: [ { - 'code': '"Number" in self', - 'prefix': '' + code: '"Number" in self', + prefix: '' }, { - 'code': '"WebKitNumber" in self', - 'prefix': 'WebKit' + code: '"WebKitNumber" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Number.Number': { - 'tests': [ + tests: [ { - 'code': '"Number" in self && bcd.testConstructor("Number")', - 'prefix': '' + code: '"Number" in self && bcd.testConstructor("Number")', + prefix: '' }, { - 'code': '"WebKitNumber" in self && bcd.testConstructor("WebKitNumber")', - 'prefix': 'WebKit' + code: '"WebKitNumber" in self && bcd.testConstructor("WebKitNumber")', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1195,30 +1195,30 @@ describe('build', () => { interface Number {};`); assert.deepEqual(buildIDLTests(ast), { 'api.Number': { - 'tests': [ + tests: [ { - 'code': '"Number" in self', - 'prefix': '' + code: '"Number" in self', + prefix: '' }, { - 'code': '"WebKitNumber" in self', - 'prefix': 'WebKit' + code: '"WebKitNumber" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.Number.Number': { - 'tests': [ + tests: [ { - 'code': '"Number" in self && bcd.testConstructor("Number")', - 'prefix': '' + code: '"Number" in self && bcd.testConstructor("Number")', + prefix: '' }, { - 'code': '"WebKitNumber" in self && bcd.testConstructor("WebKitNumber")', - 'prefix': 'WebKit' + code: '"WebKitNumber" in self && bcd.testConstructor("WebKitNumber")', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1229,114 +1229,114 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.DoubleList': { - 'tests': [ + tests: [ { - 'code': '"DoubleList" in self', - 'prefix': '' + code: '"DoubleList" in self', + prefix: '' }, { - 'code': '"WebKitDoubleList" in self', - 'prefix': 'WebKit' + code: '"WebKitDoubleList" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleList.@@iterator': { - 'tests': [ + tests: [ { - 'code': '"DoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in DoubleList.prototype', - 'prefix': '' + code: '"DoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in DoubleList.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in WebKitDoubleList.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleList" in self && "Symbol" in self && "iterator" in Symbol && Symbol.iterator in WebKitDoubleList.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleList.entries': { - 'tests': [ + tests: [ { - 'code': '"DoubleList" in self && "entries" in DoubleList.prototype', - 'prefix': '' + code: '"DoubleList" in self && "entries" in DoubleList.prototype', + prefix: '' }, { - 'code': '"DoubleList" in self && "WebKitEntries" in DoubleList.prototype', - 'prefix': 'WebKit' + code: '"DoubleList" in self && "WebKitEntries" in DoubleList.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleList" in self && "entries" in WebKitDoubleList.prototype', - 'prefix': '' + code: '"WebKitDoubleList" in self && "entries" in WebKitDoubleList.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleList" in self && "WebKitEntries" in WebKitDoubleList.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleList" in self && "WebKitEntries" in WebKitDoubleList.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleList.forEach': { - 'tests': [ + tests: [ { - 'code': '"DoubleList" in self && "forEach" in DoubleList.prototype', - 'prefix': '' + code: '"DoubleList" in self && "forEach" in DoubleList.prototype', + prefix: '' }, { - 'code': '"DoubleList" in self && "WebKitForEach" in DoubleList.prototype', - 'prefix': 'WebKit' + code: '"DoubleList" in self && "WebKitForEach" in DoubleList.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleList" in self && "forEach" in WebKitDoubleList.prototype', - 'prefix': '' + code: '"WebKitDoubleList" in self && "forEach" in WebKitDoubleList.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleList" in self && "WebKitForEach" in WebKitDoubleList.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleList" in self && "WebKitForEach" in WebKitDoubleList.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleList.keys': { - 'tests': [ + tests: [ { - 'code': '"DoubleList" in self && "keys" in DoubleList.prototype', - 'prefix': '' + code: '"DoubleList" in self && "keys" in DoubleList.prototype', + prefix: '' }, { - 'code': '"DoubleList" in self && "WebKitKeys" in DoubleList.prototype', - 'prefix': 'WebKit' + code: '"DoubleList" in self && "WebKitKeys" in DoubleList.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleList" in self && "keys" in WebKitDoubleList.prototype', - 'prefix': '' + code: '"WebKitDoubleList" in self && "keys" in WebKitDoubleList.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleList" in self && "WebKitKeys" in WebKitDoubleList.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleList" in self && "WebKitKeys" in WebKitDoubleList.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleList.values': { - 'tests': [ + tests: [ { - 'code': '"DoubleList" in self && "values" in DoubleList.prototype', - 'prefix': '' + code: '"DoubleList" in self && "values" in DoubleList.prototype', + prefix: '' }, { - 'code': '"DoubleList" in self && "WebKitValues" in DoubleList.prototype', - 'prefix': 'WebKit' + code: '"DoubleList" in self && "WebKitValues" in DoubleList.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleList" in self && "values" in WebKitDoubleList.prototype', - 'prefix': '' + code: '"WebKitDoubleList" in self && "values" in WebKitDoubleList.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleList" in self && "WebKitValues" in WebKitDoubleList.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleList" in self && "WebKitValues" in WebKitDoubleList.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1347,227 +1347,227 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.DoubleMap': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self', - 'prefix': '' + code: '"DoubleMap" in self', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.clear': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "clear" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "clear" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitClear" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitClear" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "clear" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "clear" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitClear" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitClear" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.delete': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "delete" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "delete" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitDelete" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitDelete" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "delete" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "delete" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitDelete" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitDelete" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.entries': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "entries" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "entries" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitEntries" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitEntries" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "entries" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "entries" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitEntries" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitEntries" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.forEach': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "forEach" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "forEach" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitForEach" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitForEach" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "forEach" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "forEach" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitForEach" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitForEach" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.get': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "get" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "get" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitGet" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitGet" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "get" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "get" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitGet" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitGet" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.has': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "has" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "has" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitHas" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitHas" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "has" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "has" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitHas" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitHas" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.keys': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "keys" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "keys" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitKeys" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitKeys" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "keys" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "keys" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitKeys" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitKeys" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.set': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "set" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "set" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitSet" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitSet" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "set" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "set" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitSet" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitSet" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.size': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "size" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "size" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitSize" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitSize" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "size" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "size" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitSize" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitSize" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleMap.values': { - 'tests': [ + tests: [ { - 'code': '"DoubleMap" in self && "values" in DoubleMap.prototype', - 'prefix': '' + code: '"DoubleMap" in self && "values" in DoubleMap.prototype', + prefix: '' }, { - 'code': '"DoubleMap" in self && "WebKitValues" in DoubleMap.prototype', - 'prefix': 'WebKit' + code: '"DoubleMap" in self && "WebKitValues" in DoubleMap.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleMap" in self && "values" in WebKitDoubleMap.prototype', - 'prefix': '' + code: '"WebKitDoubleMap" in self && "values" in WebKitDoubleMap.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleMap" in self && "WebKitValues" in WebKitDoubleMap.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleMap" in self && "WebKitValues" in WebKitDoubleMap.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1578,185 +1578,185 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.DoubleSet': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self', - 'prefix': '' + code: '"DoubleSet" in self', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.add': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "add" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "add" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitAdd" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitAdd" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "add" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "add" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitAdd" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitAdd" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.clear': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "clear" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "clear" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitClear" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitClear" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "clear" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "clear" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitClear" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitClear" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.delete': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "delete" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "delete" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitDelete" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitDelete" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "delete" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "delete" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitDelete" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitDelete" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.entries': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "entries" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "entries" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitEntries" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitEntries" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "entries" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "entries" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitEntries" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitEntries" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.has': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "has" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "has" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitHas" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitHas" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "has" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "has" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitHas" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitHas" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.keys': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "keys" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "keys" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitKeys" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitKeys" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "keys" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "keys" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitKeys" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitKeys" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.size': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "size" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "size" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitSize" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitSize" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "size" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "size" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitSize" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitSize" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.DoubleSet.values': { - 'tests': [ + tests: [ { - 'code': '"DoubleSet" in self && "values" in DoubleSet.prototype', - 'prefix': '' + code: '"DoubleSet" in self && "values" in DoubleSet.prototype', + prefix: '' }, { - 'code': '"DoubleSet" in self && "WebKitValues" in DoubleSet.prototype', - 'prefix': 'WebKit' + code: '"DoubleSet" in self && "WebKitValues" in DoubleSet.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitDoubleSet" in self && "values" in WebKitDoubleSet.prototype', - 'prefix': '' + code: '"WebKitDoubleSet" in self && "values" in WebKitDoubleSet.prototype', + prefix: '' }, { - 'code': '"WebKitDoubleSet" in self && "WebKitValues" in WebKitDoubleSet.prototype', - 'prefix': 'WebKit' + code: '"WebKitDoubleSet" in self && "WebKitValues" in WebKitDoubleSet.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1768,17 +1768,17 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.GetMe': { - 'tests': [ + tests: [ { - 'code': '"GetMe" in self', - 'prefix': '' + code: '"GetMe" in self', + prefix: '' }, { - 'code': '"WebKitGetMe" in self', - 'prefix': 'WebKit' + code: '"WebKitGetMe" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1792,56 +1792,56 @@ describe('build', () => { `); assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'tests': [ + tests: [ { - 'code': '"CSS" in self', - 'prefix': '' + code: '"CSS" in self', + prefix: '' }, { - 'code': '"WebKitCSS" in self', - 'prefix': 'WebKit' + code: '"WebKitCSS" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.MessageChannel': { - 'tests': [ + tests: [ { - 'code': '"MessageChannel" in self', - 'prefix': '' + code: '"MessageChannel" in self', + prefix: '' }, { - 'code': '"WebKitMessageChannel" in self', - 'prefix': 'WebKit' + code: '"WebKitMessageChannel" in self', + prefix: 'WebKit' } ], - 'scope': ['Window', 'Worker'] + scope: ['Window', 'Worker'] }, 'api.Worker': { - 'tests': [ + tests: [ { - 'code': '"Worker" in self', - 'prefix': '' + code: '"Worker" in self', + prefix: '' }, { - 'code': '"WebKitWorker" in self', - 'prefix': 'WebKit' + code: '"WebKitWorker" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.WorkerSync': { - 'tests': [ + tests: [ { - 'code': '"WorkerSync" in self', - 'prefix': '' + code: '"WorkerSync" in self', + prefix: '' }, { - 'code': '"WebKitWorkerSync" in self', - 'prefix': 'WebKit' + code: '"WebKitWorkerSync" in self', + prefix: 'WebKit' } ], - 'scope': ['Worker'] + scope: ['Worker'] } }); }); @@ -1856,38 +1856,38 @@ describe('build', () => { `); assert.deepEqual(buildIDLTests(ast), { 'api.AudioNode': { - 'tests': [ + tests: [ { - 'code': '"AudioNode" in self', - 'prefix': '' + code: '"AudioNode" in self', + prefix: '' }, { - 'code': '"WebKitAudioNode" in self', - 'prefix': 'WebKit' + code: '"WebKitAudioNode" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.AudioNode.disconnect': { - 'tests': [ + tests: [ { - 'code': '"AudioNode" in self && "disconnect" in AudioNode.prototype', - 'prefix': '' + code: '"AudioNode" in self && "disconnect" in AudioNode.prototype', + prefix: '' }, { - 'code': '"AudioNode" in self && "WebKitDisconnect" in AudioNode.prototype', - 'prefix': 'WebKit' + code: '"AudioNode" in self && "WebKitDisconnect" in AudioNode.prototype', + prefix: 'WebKit' }, { - 'code': '"WebKitAudioNode" in self && "disconnect" in WebKitAudioNode.prototype', - 'prefix': '' + code: '"WebKitAudioNode" in self && "disconnect" in WebKitAudioNode.prototype', + prefix: '' }, { - 'code': '"WebKitAudioNode" in self && "WebKitDisconnect" in WebKitAudioNode.prototype', - 'prefix': 'WebKit' + code: '"WebKitAudioNode" in self && "WebKitDisconnect" in WebKitAudioNode.prototype', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1899,38 +1899,38 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'tests': [ + tests: [ { - 'code': '"CSS" in self', - 'prefix': '' + code: '"CSS" in self', + prefix: '' }, { - 'code': '"WebKitCSS" in self', - 'prefix': 'WebKit' + code: '"WebKitCSS" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.CSS.paintWorklet': { - 'tests': [ + tests: [ { - 'code': '"CSS" in self && "paintWorklet" in CSS', - 'prefix': '' + code: '"CSS" in self && "paintWorklet" in CSS', + prefix: '' }, { - 'code': '"CSS" in self && "WebKitPaintWorklet" in CSS', - 'prefix': 'WebKit' + code: '"CSS" in self && "WebKitPaintWorklet" in CSS', + prefix: 'WebKit' }, { - 'code': '"WebKitCSS" in self && "paintWorklet" in WebKitCSS', - 'prefix': '' + code: '"WebKitCSS" in self && "paintWorklet" in WebKitCSS', + prefix: '' }, { - 'code': '"WebKitCSS" in self && "WebKitPaintWorklet" in WebKitCSS', - 'prefix': 'WebKit' + code: '"WebKitCSS" in self && "WebKitPaintWorklet" in WebKitCSS', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1942,38 +1942,38 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'tests': [ + tests: [ { - 'code': '"CSS" in self', - 'prefix': '' + code: '"CSS" in self', + prefix: '' }, { - 'code': '"WebKitCSS" in self', - 'prefix': 'WebKit' + code: '"WebKitCSS" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.CSS.supports': { - 'tests': [ + tests: [ { - 'code': '"CSS" in self && "supports" in CSS', - 'prefix': '' + code: '"CSS" in self && "supports" in CSS', + prefix: '' }, { - 'code': '"CSS" in self && "WebKitSupports" in CSS', - 'prefix': 'WebKit' + code: '"CSS" in self && "WebKitSupports" in CSS', + prefix: 'WebKit' }, { - 'code': '"WebKitCSS" in self && "supports" in WebKitCSS', - 'prefix': '' + code: '"WebKitCSS" in self && "supports" in WebKitCSS', + prefix: '' }, { - 'code': '"WebKitCSS" in self && "WebKitSupports" in WebKitCSS', - 'prefix': 'WebKit' + code: '"WebKitCSS" in self && "WebKitSupports" in WebKitCSS', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -1986,11 +1986,11 @@ describe('build', () => { const {buildIDLTests} = proxyquire('../../build', { './custom-tests.json': { - 'api': { - 'CSS': { - '__base': 'var css = CSS;', - '__test': 'return !!css;', - 'paintWorklet': 'return css && \'paintWorklet\' in css;' + api: { + CSS: { + __base: 'var css = CSS;', + __test: 'return !!css;', + paintWorklet: 'return css && \'paintWorklet\' in css;' } } } @@ -1998,22 +1998,22 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.CSS': { - 'tests': [ + tests: [ { - 'code': '(function() {var css = CSS;return !!css;})()', - 'prefix': '' + code: '(function() {var css = CSS;return !!css;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.CSS.paintWorklet': { - 'tests': [ + tests: [ { - 'code': '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()', - 'prefix': '' + code: '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -2026,59 +2026,59 @@ describe('build', () => { };`); assert.deepEqual(buildIDLTests(ast), { 'api.ElementRegistrationOptions': { - 'tests': [ + tests: [ { - 'code': '"ElementRegistrationOptions" in self', - 'prefix': '' + code: '"ElementRegistrationOptions" in self', + prefix: '' }, { - 'code': '"WebKitElementRegistrationOptions" in self', - 'prefix': 'WebKit' + code: '"WebKitElementRegistrationOptions" in self', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.ElementRegistrationOptions.extends': { - 'tests': [ + tests: [ { - 'code': '"ElementRegistrationOptions" in self && "extends" in ElementRegistrationOptions', - 'prefix': '' + code: '"ElementRegistrationOptions" in self && "extends" in ElementRegistrationOptions', + prefix: '' }, { - 'code': '"ElementRegistrationOptions" in self && "WebKitExtends" in ElementRegistrationOptions', - 'prefix': 'WebKit' + code: '"ElementRegistrationOptions" in self && "WebKitExtends" in ElementRegistrationOptions', + prefix: 'WebKit' }, { - 'code': '"WebKitElementRegistrationOptions" in self && "extends" in WebKitElementRegistrationOptions', - 'prefix': '' + code: '"WebKitElementRegistrationOptions" in self && "extends" in WebKitElementRegistrationOptions', + prefix: '' }, { - 'code': '"WebKitElementRegistrationOptions" in self && "WebKitExtends" in WebKitElementRegistrationOptions', - 'prefix': 'WebKit' + code: '"WebKitElementRegistrationOptions" in self && "WebKitExtends" in WebKitElementRegistrationOptions', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.ElementRegistrationOptions.prototype': { - 'tests': [ + tests: [ { - 'code': '"ElementRegistrationOptions" in self && "prototype" in ElementRegistrationOptions', - 'prefix': '' + code: '"ElementRegistrationOptions" in self && "prototype" in ElementRegistrationOptions', + prefix: '' }, { - 'code': '"ElementRegistrationOptions" in self && "WebKitPrototype" in ElementRegistrationOptions', - 'prefix': 'WebKit' + code: '"ElementRegistrationOptions" in self && "WebKitPrototype" in ElementRegistrationOptions', + prefix: 'WebKit' }, { - 'code': '"WebKitElementRegistrationOptions" in self && "prototype" in WebKitElementRegistrationOptions', - 'prefix': '' + code: '"WebKitElementRegistrationOptions" in self && "prototype" in WebKitElementRegistrationOptions', + prefix: '' }, { - 'code': '"WebKitElementRegistrationOptions" in self && "WebKitPrototype" in WebKitElementRegistrationOptions', - 'prefix': 'WebKit' + code: '"WebKitElementRegistrationOptions" in self && "WebKitPrototype" in WebKitElementRegistrationOptions', + prefix: 'WebKit' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -2091,9 +2091,9 @@ describe('build', () => { };`); const {buildIDLTests} = proxyquire('../../build', { './custom-tests.json': { - 'api': { - 'ElementRegistrationOptions': { - '__base': 'var instance = ElementRegistrationOptions;' + api: { + ElementRegistrationOptions: { + __base: 'var instance = ElementRegistrationOptions;' } } } @@ -2101,31 +2101,31 @@ describe('build', () => { assert.deepEqual(buildIDLTests(ast), { 'api.ElementRegistrationOptions': { - 'tests': [ + tests: [ { - 'code': '(function() {var instance = ElementRegistrationOptions;return !!instance;})()', - 'prefix': '' + code: '(function() {var instance = ElementRegistrationOptions;return !!instance;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.ElementRegistrationOptions.extends': { - 'tests': [ + tests: [ { - 'code': '(function() {var instance = ElementRegistrationOptions;return instance && \'extends\' in instance;})()', - 'prefix': '' + code: '(function() {var instance = ElementRegistrationOptions;return instance && \'extends\' in instance;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] }, 'api.ElementRegistrationOptions.prototype': { - 'tests': [ + tests: [ { - 'code': '(function() {var instance = ElementRegistrationOptions;return instance && \'prototype\' in instance;})()', - 'prefix': '' + code: '(function() {var instance = ElementRegistrationOptions;return instance && \'prototype\' in instance;})()', + prefix: '' } ], - 'scope': ['Window'] + scope: ['Window'] } }); }); @@ -2222,7 +2222,7 @@ describe('build', () => { }, 'css-grid': { properties: { - 'grid': {} + grid: {} } } } @@ -2230,56 +2230,56 @@ describe('build', () => { assert.deepEqual(buildCSS(webref, bcd), { 'css.properties.appearance': { - 'tests': [ + tests: [ { - 'code': '"appearance" in document.body.style || CSS.supports("appearance", "inherit")', - 'prefix': '' + code: '"appearance" in document.body.style || CSS.supports("appearance", "inherit")', + prefix: '' }, { - 'code': '"webkitAppearance" in document.body.style || CSS.supports("-webkit-appearance", "inherit")', - 'prefix': 'webkit' + code: '"webkitAppearance" in document.body.style || CSS.supports("-webkit-appearance", "inherit")', + prefix: 'webkit' } ], - 'scope': ['CSS'] + scope: ['CSS'] }, 'css.properties.font-family': { - 'tests': [ + tests: [ { - 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', - 'prefix': '' + code: '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', + prefix: '' }, { - 'code': '"webkitFontFamily" in document.body.style || CSS.supports("-webkit-font-family", "inherit")', - 'prefix': 'webkit' + code: '"webkitFontFamily" in document.body.style || CSS.supports("-webkit-font-family", "inherit")', + prefix: 'webkit' } ], - 'scope': ['CSS'] + scope: ['CSS'] }, 'css.properties.font-weight': { - 'tests': [ + tests: [ { - 'code': '"fontWeight" in document.body.style || CSS.supports("font-weight", "inherit")', - 'prefix': '' + code: '"fontWeight" in document.body.style || CSS.supports("font-weight", "inherit")', + prefix: '' }, { - 'code': '"webkitFontWeight" in document.body.style || CSS.supports("-webkit-font-weight", "inherit")', - 'prefix': 'webkit' + code: '"webkitFontWeight" in document.body.style || CSS.supports("-webkit-font-weight", "inherit")', + prefix: 'webkit' } ], - 'scope': ['CSS'] + scope: ['CSS'] }, 'css.properties.grid': { - 'tests': [ + tests: [ { - 'code': '"grid" in document.body.style || CSS.supports("grid", "inherit")', - 'prefix': '' + code: '"grid" in document.body.style || CSS.supports("grid", "inherit")', + prefix: '' }, { - 'code': '"webkitGrid" in document.body.style || CSS.supports("-webkit-grid", "inherit")', - 'prefix': 'webkit' + code: '"webkitGrid" in document.body.style || CSS.supports("-webkit-grid", "inherit")', + prefix: 'webkit' } ], - 'scope': ['CSS'] + scope: ['CSS'] } }); }); @@ -2287,46 +2287,46 @@ describe('build', () => { it('buildManifest', () => { const tests = { 'api.Attr': { - 'code': '"Attr" in self', - 'scope': ['Window', 'Worker', 'ServiceWorker'] + code: '"Attr" in self', + scope: ['Window', 'Worker', 'ServiceWorker'] }, 'api.Attr.name': { - 'code': '"Attr" in self && "name" in Attr.prototype', - 'scope': ['Window', 'Worker'] + code: '"Attr" in self && "name" in Attr.prototype', + scope: ['Window', 'Worker'] }, 'css.properties.font-family': { - 'code': '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', - 'scope': ['CSS'] + code: '"fontFamily" in document.body.style || CSS.supports("font-family", "inherit")', + scope: ['CSS'] }, 'javascript.builtins.array': { - 'code': '[1, 2, 3]', - 'scope': ['JavaScript'] + code: '[1, 2, 3]', + scope: ['JavaScript'] } }; const expectedManifest = { - 'main': { + main: { '/api/interfaces': { - 'entries': ['api.Attr', 'api.Attr.name'], - 'httpsOnly': false, - 'scope': 'Window' + entries: ['api.Attr', 'api.Attr.name'], + httpsOnly: false, + scope: 'Window' }, '/api/serviceworkerinterfaces': { - 'entries': ['api.Attr'], - 'httpsOnly': true, - 'scope': 'ServiceWorker' + entries: ['api.Attr'], + httpsOnly: true, + scope: 'ServiceWorker' }, '/api/workerinterfaces': { - 'entries': ['api.Attr', 'api.Attr.name'], - 'httpsOnly': false, - 'scope': 'Worker' + entries: ['api.Attr', 'api.Attr.name'], + httpsOnly: false, + scope: 'Worker' }, '/css/properties': { - 'entries': ['css.properties.font-family'], - 'httpsOnly': false, - 'scope': 'CSS' + entries: ['css.properties.font-family'], + httpsOnly: false, + scope: 'CSS' } }, - 'individual': { + individual: { '/api/Attr': ['api.Attr', 'api.Attr.name'], '/api/Attr/name': ['api.Attr.name'], '/css/properties/font-family': [ diff --git a/unittest/unit/github.js b/unittest/unit/github.js index da9ed8731..008e3faa0 100644 --- a/unittest/unit/github.js +++ b/unittest/unit/github.js @@ -27,7 +27,7 @@ const REPORT = { }; const RESULT = { - 'html_url': 'https://github.com/foolip/mdn-bcd-results/pull/42' + html_url: 'https://github.com/foolip/mdn-bcd-results/pull/42' }; describe('GitHub export', () => { diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index cda183a3a..dc91cea92 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -19,15 +19,15 @@ const Tests = require('../../tests'); const testDatabase = { 'api.AbortController': { - 'code': '"AbortController" in self', - 'scope': [ + code: '"AbortController" in self', + scope: [ 'Window', 'Worker' ] }, 'api.AbortController.signal': { - 'code': '"AbortController" in self && "signal" in AbortController', - 'scope': [ + code: '"AbortController" in self && "signal" in AbortController', + scope: [ 'Window', 'Worker' ] @@ -154,18 +154,18 @@ describe('Tests', () => { it('getTests', () => { assert.deepEqual(tests.getTests('/api/interfaces'), { 'api.AbortController': { - 'code': '"AbortController" in self', - 'scope': ['Window', 'Worker'] + code: '"AbortController" in self', + scope: ['Window', 'Worker'] }, 'api.AbortController.signal': { - 'code': '"AbortController" in self && "signal" in AbortController', - 'scope': ['Window', 'Worker'] + code: '"AbortController" in self && "signal" in AbortController', + scope: ['Window', 'Worker'] } }); assert.deepEqual(tests.getTests('/api/workerinterfaces'), { 'api.AbortController': { - 'code': '"AbortController" in self', - 'scope': ['Window', 'Worker'] + code: '"AbortController" in self', + scope: ['Window', 'Worker'] } }); }); From bd95266ac17d4f9dad0ddc450af2db55b6efff9c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 00:00:29 -0700 Subject: [PATCH 128/243] Sort ESLint rules --- .eslintrc.json | 8 ++++---- static/.eslintrc.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 0ff6b0350..ddcbb0d8f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,9 +6,6 @@ }, "rules": { "comma-dangle": ["error", "never"], - "require-jsdoc": "off", - "no-else-return": "error", - "no-unused-vars": ["error", {"varsIgnorePattern": "^_$"}], "max-len": ["error", { "code": 80, "tabWidth": 2, @@ -18,7 +15,10 @@ "ignoreUrls": true, "ignorePattern": "goog.(module|require)" }], - "quote-props": ["error", "as-needed"] + "no-else-return": "error", + "no-unused-vars": ["error", {"varsIgnorePattern": "^_$"}], + "quote-props": ["error", "as-needed"], + "require-jsdoc": "off" }, "env": { "es6": true, diff --git a/static/.eslintrc.json b/static/.eslintrc.json index ba3dda857..f2a2ecb4a 100644 --- a/static/.eslintrc.json +++ b/static/.eslintrc.json @@ -5,10 +5,7 @@ }, "rules": { "comma-dangle": ["error", "never"], - "require-jsdoc": "off", - "no-var": "off", "guard-for-in": "off", - "no-invalid-this": "off", "max-len": ["error", { "code": 80, "tabWidth": 2, @@ -17,7 +14,10 @@ "ignoreRegExpLiterals": true, "ignoreUrls": true, "ignorePattern": "goog.(module|require)" - }] + }], + "no-invalid-this": "off", + "no-var": "off", + "require-jsdoc": "off" }, "root": true } From 2e752559b9df93977a346378d36969600787eff2 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 00:53:32 -0700 Subject: [PATCH 129/243] Prefer arrow functions --- .eslintrc.json | 2 + app.js | 8 +-- build.js | 104 +++++++++++++++++----------------- find-missing.js | 17 +++--- github.js | 4 +- logger.js | 4 +- package-lock.json | 6 ++ package.json | 1 + selenium.js | 6 +- static/.eslintrc.json | 1 + unittest/puppeteer/harness.js | 4 +- unittest/unit/github.js | 2 + update-bcd.js | 96 +++++++++++++++---------------- webref.js | 4 +- 14 files changed, 137 insertions(+), 122 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index ddcbb0d8f..a67d2c53a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,5 +1,6 @@ { "extends": ["eslint:recommended", "google"], + "plugins": ["prefer-arrow"], "parser": "babel-eslint", "parserOptions": { "ecmaVersion": 8 @@ -17,6 +18,7 @@ }], "no-else-return": "error", "no-unused-vars": ["error", {"varsIgnorePattern": "^_$"}], + "prefer-arrow/prefer-arrow-functions": "error", "quote-props": ["error", "as-needed"], "require-jsdoc": "off" }, diff --git a/app.js b/app.js index 8250377e6..43af60137 100644 --- a/app.js +++ b/app.js @@ -51,20 +51,20 @@ const tests = new Tests({ httpOnly: process.env.NODE_ENV !== 'production' }); -function cookieSession(req, res, next) { +const cookieSession = (req, res, next) => { req.sessionID = req.cookies.sid; if (!req.sessionID) { req.sessionID = uniqueString(); res.cookie('sid', req.sessionID); } next(); -} +}; /* istanbul ignore next */ -function catchError(err, res) { +const catchError = (err, res) => { logger.error(err); res.status(500).end(); -} +}; const app = express(); app.use(cookieParser()); diff --git a/build.js b/build.js index 4c1a30008..01b568510 100644 --- a/build.js +++ b/build.js @@ -33,7 +33,7 @@ const prefixes = process.env.NODE_ENV === 'test' ? { css: ['', 'khtml', 'webkit', 'moz', 'ms'] }; -async function writeFile(filename, content) { +const writeFile = async (filename, content) => { if (Array.isArray(content)) { content = content.join('\n'); } else if (typeof content === 'object') { @@ -43,9 +43,9 @@ async function writeFile(filename, content) { await fs.ensureDir(path.dirname(filename)); await fs.writeFile(filename, content, 'utf8'); -} +}; -function getCustomTestAPI(name, member) { +const getCustomTestAPI = (name, member) => { let test = false; if (name in customTests.api) { @@ -78,9 +78,9 @@ function getCustomTestAPI(name, member) { } return test; -} +}; -function getCustomSubtestsAPI(name, member) { +const getCustomSubtestsAPI = (name, member) => { const subtests = {}; if (name in customTests.api) { @@ -97,15 +97,15 @@ function getCustomSubtestsAPI(name, member) { } return subtests; -} +}; -function getCustomTestCSS(name) { +const getCustomTestCSS = (name) => { return 'properties' in customTests.css && name in customTests.css.properties && `(function() {${customTests.css.properties[name]}})()`; -} +}; -function compileTestCode(test, prefix = '', scopePrefix = '') { +const compileTestCode = (test, prefix = '', scopePrefix = '') => { if (typeof(test) === 'string') { return test.replace(/PREFIX(.)/g, (_, p1) => ( `${prefix}${prefix ? p1.toUpperCase() : p1}` @@ -133,9 +133,9 @@ function compileTestCode(test, prefix = '', scopePrefix = '') { return `"${scopeAsProperty}" in self && "Symbol" in self && "${test.property.replace('Symbol.', '')}" in Symbol && ${test.property} in ${scopeAsProperty}.prototype`; } return `"${property}" in ${scope}`; -} +}; -function compileTest(test) { +const compileTest = (test) => { if (!('raw' in test) && 'tests' in test) return test; const newTest = {tests: [], scope: test.scope}; @@ -188,14 +188,14 @@ function compileTest(test) { } return newTest; -} +}; -function collectExtraIDL() { +const collectExtraIDL = () => { const idl = fs.readFileSync('./non-standard.idl', 'utf8'); return WebIDL2.parse(idl); -} +}; -function mergeMembers(target, source) { +const mergeMembers = (target, source) => { // Check for operation overloads across partials/mixins. const targetOperations = new Set(); for (const {type, name} of target.members) { @@ -210,9 +210,9 @@ function mergeMembers(target, source) { } // Now merge members. target.members.push(...source.members); -} +}; -function flattenIDL(specIDLs, collectExtraIDL) { +const flattenIDL = (specIDLs, collectExtraIDL) => { let ast = []; for (const idl of Object.values(specIDLs)) { @@ -266,9 +266,9 @@ function flattenIDL(specIDLs, collectExtraIDL) { dfn.type !== 'interface mixin'); return ast; -} +}; -function flattenMembers(iface) { +const flattenMembers = (iface) => { const members = iface.members.filter((member) => member.name); for (const member of iface.members.filter((member) => !member.name)) { switch (member.type) { @@ -325,14 +325,14 @@ function flattenMembers(iface) { } return members.sort((a, b) => a.name.localeCompare(b.name)); -} +}; -function getExtAttr(node, name) { +const getExtAttr = (node, name) => { return node.extAttrs && node.extAttrs.find((i) => i.name === name); -} +}; // https://heycam.github.io/webidl/#dfn-exposure-set -function getExposureSet(node) { +const getExposureSet = (node) => { // step 6-8 const attr = getExtAttr(node, 'Exposed'); if (!attr) { @@ -354,9 +354,9 @@ function getExposureSet(node) { throw new Error(`Unexpected RHS for Exposed extended attribute`); } return globals; -} +}; -function getName(node) { +const getName = (node) => { if (!('name' in node)) return false; switch (node.name) { @@ -365,9 +365,9 @@ function getName(node) { default: return node.name; } -} +}; -function allowDuplicates(dfn, member) { +const allowDuplicates = (dfn, member) => { switch (dfn.name) { // TODO: sort this out spec-side case 'SVGAElement': @@ -378,9 +378,9 @@ function allowDuplicates(dfn, member) { return member.name === 'canvas'; } return false; -} +}; -function validateIDL(ast) { +const validateIDL = (ast) => { const ignoreRules = new Set([ 'constructor-member', 'dict-arg-default', @@ -431,9 +431,9 @@ function validateIDL(ast) { } return true; -} +}; -function buildIDLTests(ast) { +const buildIDLTests = (ast) => { const tests = {}; const interfaces = ast.filter((dfn) => @@ -546,15 +546,15 @@ function buildIDLTests(ast) { } return tests; -} +}; -function buildIDL(webref) { +const buildIDL = (webref) => { const ast = flattenIDL(webref.idl, collectExtraIDL()); validateIDL(ast); return buildIDLTests(ast); -} +}; -function collectCSSPropertiesFromBCD(bcd, propertySet) { +const collectCSSPropertiesFromBCD = (bcd, propertySet) => { for (const [prop, data] of Object.entries(bcd.css.properties)) { propertySet.add(prop); if (!data.__compat) { @@ -566,7 +566,7 @@ function collectCSSPropertiesFromBCD(bcd, propertySet) { continue; } // eslint-disable-next-line no-inner-declarations - function process(statement) { + const process = (statement) => { if (Array.isArray(statement)) { statement.forEach(process); return; @@ -574,23 +574,23 @@ function collectCSSPropertiesFromBCD(bcd, propertySet) { if (statement.alternative_name) { propertySet.add(statement.alternative_name); } - } + }; for (const statement of Object.values(support)) { process(statement); } } -} +}; -function collectCSSPropertiesFromWebref(webref, propertySet) { +const collectCSSPropertiesFromWebref = (webref, propertySet) => { for (const data of Object.values(webref.css)) { for (const prop of Object.keys(data.properties)) { propertySet.add(prop); } } -} +}; // https://drafts.csswg.org/cssom/#css-property-to-idl-attribute -function cssPropertyToIDLAttribute(property, lowercaseFirst) { +const cssPropertyToIDLAttribute = (property, lowercaseFirst) => { let output = ''; let uppercaseNext = false; if (lowercaseFirst) { @@ -607,9 +607,9 @@ function cssPropertyToIDLAttribute(property, lowercaseFirst) { } } return output; -} +}; -function buildCSS(webref, bcd) { +const buildCSS = (webref, bcd) => { const propertySet = new Set; collectCSSPropertiesFromBCD(bcd, propertySet); collectCSSPropertiesFromWebref(webref, propertySet); @@ -631,10 +631,10 @@ function buildCSS(webref, bcd) { } return tests; -} +}; /* istanbul ignore next */ -async function copyResources() { +const copyResources = async () => { const resources = [ ['json3/lib/json3.min.js', 'resources'], ['core-js-bundle/minified.js', 'resources', 'core.js'], @@ -656,7 +656,7 @@ async function copyResources() { // Fix source mapping in core-js const corejsPath = path.join(generatedDir, 'resources', 'core.js'); - await fs.readFile(corejsPath, 'utf8', function(err, data) { + await fs.readFile(corejsPath, 'utf8', (err, data) => { if (err) { return console.log(err); } @@ -665,13 +665,13 @@ async function copyResources() { 'sourceMappingURL=core.js.map' ); - fs.writeFileSync(corejsPath, result, 'utf8', function(err) { + fs.writeFileSync(corejsPath, result, 'utf8', (err) => { if (err) return console.log(err); }); }); -} +}; -function buildManifest(tests) { +const buildManifest = (tests) => { const manifest = { main: {}, individual: {} @@ -729,10 +729,10 @@ function buildManifest(tests) { } return manifest; -} +}; /* istanbul ignore next */ -async function build(webref, bcd) { +const build = async (webref, bcd) => { const IDLTests = buildIDL(webref); const CSSTests = buildCSS(webref, bcd); const tests = Object.assign(IDLTests, CSSTests); @@ -740,7 +740,7 @@ async function build(webref, bcd) { await writeFile(path.join(generatedDir, 'tests.json'), tests); await writeFile(path.join(generatedDir, 'manifest.json'), buildManifest(tests)); await copyResources(); -} +}; /* istanbul ignore if */ if (require.main === module) { diff --git a/find-missing.js b/find-missing.js index c7753193d..2b952f02c 100644 --- a/find-missing.js +++ b/find-missing.js @@ -3,7 +3,7 @@ const bcd = require('mdn-browser-compat-data'); const tests = require('./generated/tests.json'); -function traverseFeatures(obj, identifier) { +const traverseFeatures = (obj, identifier) => { const features = []; for (const i in obj) { @@ -21,9 +21,9 @@ function traverseFeatures(obj, identifier) { } return features; -} +}; -function findMissing() { +const findMissing = () => { const bcdEntries = [ ...traverseFeatures(bcd.api, 'api.'), ...traverseFeatures(bcd.css, 'css.') @@ -38,15 +38,18 @@ function findMissing() { } return missingEntries; -} +}; -function main() { +const main = () => { console.log(findMissing().join('\n')); -} +}; /* istanbul ignore if */ if (require.main === module) { main(); } else { - module.exports = {}; + module.exports = { + traverseFeatures, + findMissing + }; } diff --git a/github.js b/github.js index 165d13dce..c307871a4 100644 --- a/github.js +++ b/github.js @@ -25,7 +25,7 @@ const appversion = require('./package.json').version; module.exports = (options) => { const octokit = new Octokit(options); - async function exportAsPR(report) { + const exportAsPR = async (report) => { const json = stringify(report, {space: ' '}) + '\n'; const buffer = Buffer.from(json); // like https://github.com/web-platform-tests/wpt.fyi/blob/26805a0122ea01076ac22c0a96313c1cf5cc30d6/results-processor/wptreport.py#L79 @@ -71,7 +71,7 @@ module.exports = (options) => { }); return data; - } + }; return {exportAsPR}; }; diff --git a/logger.js b/logger.js index 00b5ae813..b5551e35b 100644 --- a/logger.js +++ b/logger.js @@ -17,7 +17,7 @@ const winston = require('winston'); const {LoggingWinston} = require('@google-cloud/logging-winston'); -function getTransport() { +const getTransport = () => { /* istanbul ignore if */ if (process.env.NODE_ENV === 'production' || process.env.GOOGLE_APPLICATION_CREDENTIALS) { @@ -29,7 +29,7 @@ function getTransport() { winston.format.simple() ) }); -} +}; const logger = winston.createLogger({ level: 'info', diff --git a/package-lock.json b/package-lock.json index 8a9d1d131..48cc77e62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1993,6 +1993,12 @@ "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", "dev": true }, + "eslint-plugin-prefer-arrow": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.2.tgz", + "integrity": "sha512-C8YMhL+r8RMeMdYAw/rQtE6xNdMulj+zGWud/qIGnlmomiPRaLDGLMeskZ3alN6uMBojmooRimtdrXebLN4svQ==", + "dev": true + }, "eslint-scope": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", diff --git a/package.json b/package.json index 43e6fff11..6cc2560ea 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "compare-versions": "^3.6.0", "eslint": "7.8.0", "eslint-config-google": "0.14.0", + "eslint-plugin-prefer-arrow": "^1.2.2", "mocha": "8.1.1", "mock-fs": "^4.13.0", "nyc": "15.1.0", diff --git a/selenium.js b/selenium.js index 8621a56fb..f739824a5 100644 --- a/selenium.js +++ b/selenium.js @@ -71,7 +71,7 @@ for (const browser in browsersToTest) { describe(`${bcd.browsers[browser].name} ${version}`, () => { let driver; - beforeEach(function() { + beforeEach(() => { const capabilities = new Capabilities(); capabilities.set( Capability.BROWSER_NAME, @@ -83,11 +83,11 @@ for (const browser in browsersToTest) { .withCapabilities(capabilities).build(); }); - afterEach(async function() { + afterEach(async () => { await driver.quit(); }); - it('run', async function() { + it('run', async () => { await driver.get(host); await driver.wait( until.elementIsEnabled( diff --git a/static/.eslintrc.json b/static/.eslintrc.json index f2a2ecb4a..cf7f64502 100644 --- a/static/.eslintrc.json +++ b/static/.eslintrc.json @@ -17,6 +17,7 @@ }], "no-invalid-this": "off", "no-var": "off", + "prefer-arrow/prefer-arrow-functions": "off", "require-jsdoc": "off" }, "root": true diff --git a/unittest/puppeteer/harness.js b/unittest/puppeteer/harness.js index 0aa6d65a7..5bef16eb4 100644 --- a/unittest/puppeteer/harness.js +++ b/unittest/puppeteer/harness.js @@ -69,7 +69,7 @@ describe('harness.js', () => { const coveragePath = path.join( __dirname, '..', '..', '.nyc_output', 'out.json' ); - fs.readFile(coveragePath, 'utf8', function(err, data) { + fs.readFile(coveragePath, 'utf8', (err, data) => { if (err) { return console.log(err); } @@ -78,7 +78,7 @@ describe('harness.js', () => { 'static/resources' ); - fs.writeFile(coveragePath, result, 'utf8', function(err) { + fs.writeFile(coveragePath, result, 'utf8', (err) => { if (err) return console.log(err); }); }); diff --git a/unittest/unit/github.js b/unittest/unit/github.js index 008e3faa0..e7c2cf5da 100644 --- a/unittest/unit/github.js +++ b/unittest/unit/github.js @@ -37,6 +37,7 @@ describe('GitHub export', () => { let octokit; const github = proxyquire('../../github', { '@octokit/rest': { + /* eslint-disable-next-line prefer-arrow/prefer-arrow-functions */ Octokit: function(options) { assert(octokit === undefined); octokit = new Octokit(options); @@ -86,6 +87,7 @@ describe('GitHub export', () => { it('no auth token', async () => { const github = proxyquire('../../github', { '@octokit/rest': { + /* eslint-disable-next-line prefer-arrow/prefer-arrow-functions */ Octokit: function(options) { return new Octokit(options); } diff --git a/update-bcd.js b/update-bcd.js index cb3c13a6c..1f2d07b91 100644 --- a/update-bcd.js +++ b/update-bcd.js @@ -7,24 +7,24 @@ const uaParser = require('ua-parser-js'); const overrides = require('./overrides').filter(Array.isArray); -function findEntry(bcd, path) { +const findEntry = (bcd, path) => { const keys = path.split('.'); let entry = bcd; while (entry && keys.length) { entry = entry[keys.shift()]; } return entry; -} +}; -function isDirectory(fp) { +const isDirectory = (fp) => { try { return fs.statSync(fp).isDirectory(); } catch (e) { return false; } -} +}; -function isEquivalent(a, b) { +const isEquivalent = (a, b) => { // Create arrays of property names const aProps = Object.getOwnPropertyNames(a); const bProps = Object.getOwnPropertyNames(b); @@ -46,41 +46,41 @@ function isEquivalent(a, b) { // If we made it this far, objects // are considered equivalent return true; -} +}; // https://github.com/mdn/browser-compat-data/issues/3617 -function save(bcd, bcdDir) { - function processObject(object, keypath) { - if (keypath.length && !['api', 'css'].includes(keypath[0])) { - return; - } - for (const [key, value] of Object.entries(object)) { - const candidate = path.join(bcdDir, ...keypath, key); - - if (isDirectory(candidate)) { - // If the path is a directory, recurse. - processObject(value, keypath.concat(key)); - } else { - // Otherwise, write data to file. - const filepath = `${candidate}.json`; - // Add wrapping objects with keys as in keypath. - let wrappedValue = value; - const keys = keypath.concat(key).reverse(); - for (const key of keys) { - const wrapper = {}; - wrapper[key] = wrappedValue; - wrappedValue = wrapper; - } - const json = JSON.stringify(wrappedValue, null, ' ') + '\n'; - fs.writeFileSync(filepath, json); +const processObject = (object, keypath, bcdDir) => { + if (keypath.length && !['api', 'css'].includes(keypath[0])) { + return; + } + for (const [key, value] of Object.entries(object)) { + const candidate = path.join(bcdDir, ...keypath, key); + + if (isDirectory(candidate)) { + // If the path is a directory, recurse. + processObject(value, keypath.concat(key), bcdDir); + } else { + // Otherwise, write data to file. + const filepath = `${candidate}.json`; + // Add wrapping objects with keys as in keypath. + let wrappedValue = value; + const keys = keypath.concat(key).reverse(); + for (const key of keys) { + const wrapper = {}; + wrapper[key] = wrappedValue; + wrappedValue = wrapper; } + const json = JSON.stringify(wrappedValue, null, ' ') + '\n'; + fs.writeFileSync(filepath, json); } } +}; - processObject(bcd, []); -} +const save = (bcd, bcdDir) => { + processObject(bcd, [], bcdDir); +}; -function getBrowserAndVersion(userAgent, browsers) { +const getBrowserAndVersion = (userAgent, browsers) => { const ua = uaParser(userAgent); let browser = ua.browser.name.toLowerCase(); @@ -104,11 +104,11 @@ function getBrowserAndVersion(userAgent, browsers) { } return [browser, version]; -} +}; // Get support map from BCD path to test result(null/true/false) for a single // report. -function getSupportMap(report) { +const getSupportMap = (report) => { // Transform `report` to map from test name (BCD path) to array of results. const testMap = new Map; for (const [url, results] of Object.entries(report.results)) { @@ -153,11 +153,11 @@ function getSupportMap(report) { supportMap.set(name, supported); } return supportMap; -} +}; // Load all reports and build a map from BCD path to browser + version // and test result (null/true/false) for that version. -function getSupportMatrix(bcd, reports) { +const getSupportMatrix = (bcd, reports) => { // TODO catch prefixed support const supportMatrix = new Map; @@ -218,9 +218,9 @@ function getSupportMatrix(bcd, reports) { } return supportMatrix; -} +}; -function inferSupportStatements(versionMap) { +const inferSupportStatements = (versionMap) => { const versions = Array.from(versionMap.keys()).sort(compareVersions); const statements = []; @@ -283,9 +283,9 @@ function inferSupportStatements(versionMap) { } return statements; -} +}; -function update(bcd, supportMatrix) { +const update = (bcd, supportMatrix) => { for (const [path, browserMap] of supportMatrix.entries()) { const entry = findEntry(bcd, path); if (!entry || !entry.__compat) { @@ -350,18 +350,18 @@ function update(bcd, supportMatrix) { } } } -} +}; -function loadFile(reportFile) { +const loadFile = (reportFile) => { try { return JSON.parse(fs.readFileSync(reportFile)); } catch (e) { console.warn(`Could not parse ${reportFile}; skipping`); return null; } -} +}; -function loadFiles(files, root = '') { +const loadFiles = (files, root = '') => { const reports = []; for (const filename of files) { @@ -386,9 +386,9 @@ function loadFiles(files, root = '') { } return reports; -} +}; -function main(reportFiles) { +const main = (reportFiles) => { const BCD_DIR = process.env.BCD_DIR || `../browser-compat-data`; const bcd = require(BCD_DIR); @@ -396,7 +396,7 @@ function main(reportFiles) { const supportMatrix = getSupportMatrix(bcd, reports); update(bcd, supportMatrix); save(bcd, BCD_DIR); -} +}; /* istanbul ignore if */ if (require.main === module) { diff --git a/webref.js b/webref.js index e49c8fabf..2cb49ae89 100644 --- a/webref.js +++ b/webref.js @@ -23,7 +23,7 @@ const reportsDir = path.dirname(require.resolve('webref/package.json')); // Load text (UTF-8) files from a directory and return an object mapping each // name (sans extension) to the parsed result of that text. -function loadTextFiles(relativeDir, extension, parse) { +const loadTextFiles = (relativeDir, extension, parse) => { const dir = path.join(reportsDir, relativeDir); const files = fs.readdirSync(dir); files.sort(); @@ -38,7 +38,7 @@ function loadTextFiles(relativeDir, extension, parse) { results[name] = parse(text); } return results; -} +}; module.exports = { css: loadTextFiles('ed/css', '.json', JSON.parse), From e27517275831bf43cd24c5f563c1604cbd93aa7e Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 01:21:47 -0700 Subject: [PATCH 130/243] Upgrade subtest structure to allow for non-members --- DESIGN.md | 18 +++++++++++------- build.js | 36 ++++++++++++++++-------------------- unittest/unit/build.js | 17 ++++++++--------- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index cca958c30..9bb08f6d9 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -24,7 +24,10 @@ Each API interface is written in the following structure: "INTERFACE_NAME": { "__base": "CODE_TO_REPEAT_FOR_EVERY_TEST", "__test": "CODE_SPECIFIC_TO_TEST_THE_INTERFACE", - "MEMBER": "CODE_TO_TEST_THE_MEMBER" + "MEMBER": "CODE_TO_TEST_THE_MEMBER", + "__additional": { + "SUBFEATURE": "CODE_TO_TEST_SUBFEATURE" + } } ``` @@ -32,9 +35,11 @@ Each API interface is written in the following structure: You can define a custom method to test the interface instance itself via `__test`. The `__test` should be a return statement that returns `true` or `false`. If no `__test` is defined, it will default to `return !!instance`. -Each member can have a custom test by defining a property as the member name. Like `__test`, it should be a return statement that returns `true` or `false`. If no custom test is defined, it will default to `return instance && 'MEMBER' in instance`. The member tests can also be an object that includes a `__test` string and various other strings for behavioral subtests (such as arguments to constructors). +Each member can have a custom test by defining a property as the member name. Like `__test`, it should be a return statement that returns `true` or `false`. If no custom test is defined, it will default to `return instance && 'MEMBER' in instance`. + +Additional members and submembers can be defined using the `__additional` property. If there is a subfeature to an API or one of its members, such as "api.AudioContext.AudioContext.latencyHint", that simply cannot be defined within IDL, you can include this object and specify tests for such subfeatures. -Each test will compile into a function as follows: `function() {__base + __test/MEMBER}` +Each test will compile into a function as follows: `function() {__base + __test/MEMBER/SUBFEATURE}` Example: @@ -49,9 +54,8 @@ The following JSON... "drawArraysInstancedANGLE": "return true && instance && 'drawArraysInstancedANGLE' in instance;" }, "Console": { - "log": { - "__test": "return console.log", - "substitution_strings": "console.log('Hello, %s.', 'Bob')" + "__additional": { + "log.substitution_strings": "console.log('Hello, %s.', 'Bob')" } } }, @@ -72,7 +76,7 @@ bcd.addTest('api.ANGLE_instanced_arrays.vertexAttribDivisorANGLE', "(function() bcd.addTest('api.Animation', {"property":"Animation","scope":"self"}, 'Window'); ... bcd.addTest('api.Console', {"property":"console","scope":"self"}, 'Window'); -bcd.addTest('api.Console.log', "(function() {return console.log;})()", 'Window'); +bcd.addTest('api.Console.log', [{"property":"console","scope":"self"},{"property":"log","scope":"console"}], 'Window'); bcd.addTest('api.Console.log.substitution_strings', "(function() {console.log('Hello, %s.', 'Bob')})()", 'Window'); ``` diff --git a/build.js b/build.js index 01b568510..17e97f41c 100644 --- a/build.js +++ b/build.js @@ -58,13 +58,7 @@ const getCustomTestAPI = (name, member) => { } } else { if (member in customTests.api[name]) { - if (typeof customTests.api[name][member] === 'object') { - if ('__test' in customTests.api[name][member]) { - test = testbase + customTests.api[name][member].__test; - } - } else { - test = testbase + customTests.api[name][member]; - } + test = testbase + customTests.api[name][member]; } else { test = testbase ? testbase + `return instance && '${member}' in instance;` : @@ -80,16 +74,15 @@ const getCustomTestAPI = (name, member) => { return test; }; -const getCustomSubtestsAPI = (name, member) => { +const getCustomSubtestsAPI = (name) => { const subtests = {}; if (name in customTests.api) { const testbase = customTests.api[name].__base || ''; - if ( - member in customTests.api[name] && - typeof customTests.api[name][member] === 'object' - ) { - for (const subtest of Object.entries(customTests.api[name][member])) { + if ('__additional' in customTests.api[name]) { + for ( + const subtest of Object.entries(customTests.api[name].__additional) + ) { if (subtest[0] == '__test') continue; subtests[subtest[0]] = `(function() {${testbase}${subtest[1]}})()`; } @@ -534,14 +527,17 @@ const buildIDLTests = (ast) => { scope: Array.from(exposureSet) }); handledMemberNames.add(member.name); + } - const subtests = getCustomSubtestsAPI(adjustedIfaceName, member.name); - for (const subtest of Object.entries(subtests)) { - tests[`api.${adjustedIfaceName}.${member.name}.${subtest[0]}`] = { - tests: [{code: subtest[1], prefix: ''}], - scope: Array.from(exposureSet) - }; - } + const subtests = getCustomSubtestsAPI(adjustedIfaceName); + for (const subtest of Object.entries(subtests)) { + tests[`api.${adjustedIfaceName}.${subtest[0]}`] = compileTest({ + raw: { + code: subtest[1], + combinator: '&&' + }, + scope: Array.from(exposureSet) + }); } } diff --git a/unittest/unit/build.js b/unittest/unit/build.js index c86ff0144..e76a21601 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -193,8 +193,8 @@ describe('build', () => { './custom-tests.json': { api: { foo: { - bar: { - __test: 'return 1 + 1;', + bar: 'return 1 + 1;', + __additional: { multiple: 'return 1 + 1 + 1;', one: 'return 1;' } @@ -244,16 +244,15 @@ describe('build', () => { }); }); - describe('getCustomSubtestAPI', () => { + describe('getCustomSubtestsAPI', () => { it('get subtests', () => { const {getCustomSubtestsAPI} = proxyquire('../../build', { './custom-tests.json': { api: { foo: { - bar: { - __test: 'return 1 + 1;', + __additional: { multiple: 'return 1 + 1 + 1;', - one: 'return 1;' + 'one.only': 'return 1;' } } } @@ -264,7 +263,7 @@ describe('build', () => { getCustomSubtestsAPI('foo', 'bar'), { multiple: '(function() {return 1 + 1 + 1;})()', - one: '(function() {return 1;})()' + 'one.only': '(function() {return 1;})()' } ); }); @@ -1018,8 +1017,8 @@ describe('build', () => { drawArraysInstancedANGLE: 'return true && instance && \'drawArraysInstancedANGLE\' in instance;' }, Body: { - loaded: { - loaded_is_boolean: 'return typeof body.loaded === "boolean";' + __additional: { + 'loaded.loaded_is_boolean': 'return typeof body.loaded === "boolean";' } } } From 7fb0be2d9cda9c0fa33d759da13b76cd947767df Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 01:41:09 -0700 Subject: [PATCH 131/243] Limit find-missing to CSS properties --- find-missing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/find-missing.js b/find-missing.js index 2b952f02c..53af542b2 100644 --- a/find-missing.js +++ b/find-missing.js @@ -26,7 +26,7 @@ const traverseFeatures = (obj, identifier) => { const findMissing = () => { const bcdEntries = [ ...traverseFeatures(bcd.api, 'api.'), - ...traverseFeatures(bcd.css, 'css.') + ...traverseFeatures(bcd.css.properties, 'css.properties.') ]; const collectorEntries = Object.keys(tests); const missingEntries = []; From 83df42ad66de614431fcf48c069a762e9034b2f6 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 02:10:03 -0700 Subject: [PATCH 132/243] Fix find-missing --- find-missing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/find-missing.js b/find-missing.js index 53af542b2..d1a398c38 100644 --- a/find-missing.js +++ b/find-missing.js @@ -12,7 +12,7 @@ const traverseFeatures = (obj, identifier) => { typeof obj[i] == 'object' && i !== '__compat' ) { - if (obj.__compat) { + if (obj[i].__compat) { features.push(`${identifier}${i}`); } From 6129d1637dce3f6c6fd9d44e480bbdbb8593cf12 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 02:25:17 -0700 Subject: [PATCH 133/243] Add additional non-standard IDL --- non-standard.idl | 138 +++++++++++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 53 deletions(-) diff --git a/non-standard.idl b/non-standard.idl index 0e821f70c..60c5f6595 100644 --- a/non-standard.idl +++ b/non-standard.idl @@ -28,6 +28,34 @@ partial interface Document { attribute EventHandler onbeforecut; attribute EventHandler onbeforepaste; attribute EventHandler onsearch; + + boolean contains(); + Touch createTouch(); + TouchList createTouchList(); + readonly attribute nsIURI documentURIObject; + void enableStyleSheetsForSet(DOMString? name); + boolean execCommandShowHelp(DOMString name); + readonly attribute long fileSize; + nsIBoxObject getBoxObjectFor(DOMElement element); + readonly attribute long height; + readonly attribute DOMString? lastStyleSheetSet; + void loadOverlay(DOMString url, nsIObserver observer); + void mozSetImageElement(DOMString imageElementId, DOMElement imageElement); + readonly attribute boolean mozSyntheticDocument; + void normalizeDocument(); + attribute EventHandler onafterscriptexecute; + attribute EventHandler onbeforescriptexecute; + readonly attribute DOMString? origin; + readonly attribute Node? popupNode; + readonly attribute DOMString? preferredStyleSheetSet; + void queryCommandText(); + void releaseCapture(); + void routeEvent(); + readonly attribute DOMString? selectedStyleSheetSet; + readonly attribute FrozenArray styleSheetSets; + readonly attribute XULTooltip tooltipNode; + attribute UndoManager undoManager; + readonly attribute long width; }; partial interface Element { @@ -43,10 +71,25 @@ partial interface Element { attribute EventHandler onbeforepaste; attribute EventHandler onsearch; attribute EventHandler onbeforematch; + + readonly attribute DOMString? accessKey; + readonly attribute DOMString? attributeStyleMap; + readonly attribute DOMString? currentStyle; + readonly attribute DOMString? name; + readonly attribute boolean openOrClosedShadowRoot; + readonly attribute DOMString? runtimeStyle; + readonly attribute Number? scrollLeftMax; + void setCapture(optional boolean retargetToElement); + readonly attribute boolean tabStop; }; partial interface Event { readonly attribute object path; + readonly attribute Element? explicitOriginalTarget; + boolean getPreventDefault(); + readonly attribute Element? originalTarget; + attribute boolean preventBubble; + attribute boolean preventCapture; }; partial interface File { @@ -312,68 +355,47 @@ partial interface DataTransfer { void addElement(Element el); }; -[Exposed=Window] -interface DirectoryEntrySync {}; - -[Exposed=Window] -interface DirectoryReaderSync {}; - -partial interface Document { - boolean contains(); - Touch createTouch(); - TouchList createTouchList(); - readonly attribute nsIURI documentURIObject; - void enableStyleSheetsForSet(DOMString? name); - boolean execCommandShowHelp(DOMString name); - readonly attribute long fileSize; - nsIBoxObject getBoxObjectFor(DOMElement element); - readonly attribute long height; - readonly attribute DOMString? lastStyleSheetSet; - void loadOverlay(DOMString url, nsIObserver observer); - void mozSetImageElement(DOMString imageElementId, DOMElement imageElement); - readonly attribute boolean mozSyntheticDocument; - void normalizeDocument(); - attribute EventHandler onafterscriptexecute; - attribute EventHandler onbeforescriptexecute; - readonly attribute DOMString? origin; - readonly attribute Node? popupNode; - readonly attribute DOMString? preferredStyleSheetSet; - void queryCommandText(); - void releaseCapture(); - void routeEvent(); - readonly attribute DOMString? selectedStyleSheetSet; - readonly attribute FrozenArray styleSheetSets; - readonly attribute XULTooltip tooltipNode; - attribute UndoManager undoManager; - readonly attribute long width; -}; +[Exposed=Window] interface DirectoryEntrySync {}; +[Exposed=Window] interface DirectoryReaderSync {}; partial interface DOMMatrixReadOnly { void scaleNonUniformSelf(optional unrestricted double scaleX = 1, optional unrestricted double scaleY = 1); void transform(); }; -partial interface Element { - readonly attribute DOMString? accessKey; - readonly attribute DOMString? attributeStyleMap; - readonly attribute DOMString? currentStyle; - readonly attribute DOMString? name; - readonly attribute boolean openOrClosedShadowRoot; - readonly attribute DOMString? runtimeStyle; - readonly attribute Number? scrollLeftMax; - void setCapture(optional boolean retargetToElement); - readonly attribute boolean tabStop; +[Exposed=Window] interface EntrySync {}; + +partial interface FetchEvent { + readonly attribute Client client; + readonly attribute boolean isReload; + Promise navigationPreload(); + readonly attribute DOMString targetClientId; }; -[Exposed=Window] -interface EntrySync {}; +partial interface File { + readonly attribute DOMString type; +}; -partial interface Event { - readonly attribute Element? explicitOriginalTarget; - boolean getPreventDefault(); - readonly attribute Element? originalTarget; - attribute boolean preventBubble; - attribute boolean preventCapture; +[Exposed=Window] interface FileEntrySync {}; +[Exposed=Window] interface FileError {}; +[Exposed=Window] interface FileException {}; + +partial interface FileSystemEntry { + void getMetadata(MetadataCallback successCallback, optional ErrorCallback? errorCallback); + void moveTo(DirectoryEntry parent, optional DOMString? name, optional EntryCallback? successCallback, optional ErrorCallback? errorCallback); + void copyTo(DirectoryEntry parent, optional DOMString? name, optional EntryCallback? successCallback, optional ErrorCallback? errorCallback); + DOMString toURL(); + void remove(VoidCallback successCallback, optional ErrorCallback? errorCallback); +}; + +partial interface FileSystemFileEntry { + void createWriter(FileWriterCallback successCallback, + optional ErrorCallback? errorCallback); +}; + +[Exposed=Window] interface FileSystemSync { + readonly attribute DOMString name; + readonly attribute DirectoryEntry root; }; // https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/modules/payments/abort_payment_event.idl;drc=c2e7d4f0b24814b0d1c51a964db34ec5b4930756 @@ -769,3 +791,13 @@ interface UserDataHandler { void handle(unsigned short operation, DOMString key, DOMUserData data, Node src, Node dst); }; + +// https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/core/feature_policy/feature_policy.idl;drc=56a02023a0c4c3d513bf7cd972cf616eb25f73bc + +[Exposed=Window] +interface FeaturePolicy { + [MeasureAs=FeaturePolicyJSAPI, CallWith=ScriptState] boolean allowsFeature(DOMString feature, optional DOMString origin); + [HighEntropy=Direct, MeasureAs=FeaturePolicyJSAPI, CallWith=ScriptState] sequence features(); + [MeasureAs=FeaturePolicyJSAPI, CallWith=ScriptState] sequence allowedFeatures(); + [MeasureAs=FeaturePolicyJSAPI, CallWith=ScriptState] sequence getAllowlistForFeature(DOMString feature); +}; From be3913fd68ebeaf1631e53d2795327c2846ea48c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 13:53:20 -0700 Subject: [PATCH 134/243] Simplify max-len rule --- .eslintrc.json | 6 +----- build.js | 3 +-- github.js | 1 + static/.eslintrc.json | 6 +----- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index a67d2c53a..75a32366d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -8,13 +8,9 @@ "rules": { "comma-dangle": ["error", "never"], "max-len": ["error", { - "code": 80, - "tabWidth": 2, "ignoreStrings": true, "ignoreTemplateLiterals": true, - "ignoreRegExpLiterals": true, - "ignoreUrls": true, - "ignorePattern": "goog.(module|require)" + "ignoreRegExpLiterals": true }], "no-else-return": "error", "no-unused-vars": ["error", {"varsIgnorePattern": "^_$"}], diff --git a/build.js b/build.js index 17e97f41c..ae7162261 100644 --- a/build.js +++ b/build.js @@ -61,8 +61,7 @@ const getCustomTestAPI = (name, member) => { test = testbase + customTests.api[name][member]; } else { test = testbase ? - testbase + `return instance && '${member}' in instance;` : - false; + testbase + `return instance && '${member}' in instance;` : false; } } } diff --git a/github.js b/github.js index c307871a4..9e146773e 100644 --- a/github.js +++ b/github.js @@ -28,6 +28,7 @@ module.exports = (options) => { const exportAsPR = async (report) => { const json = stringify(report, {space: ' '}) + '\n'; const buffer = Buffer.from(json); + /* eslint-disable-next-line max-len */ // like https://github.com/web-platform-tests/wpt.fyi/blob/26805a0122ea01076ac22c0a96313c1cf5cc30d6/results-processor/wptreport.py#L79 const hash = crypto.createHash('sha1'); const digest = hash.update(buffer).digest('hex').substr(0, 10); diff --git a/static/.eslintrc.json b/static/.eslintrc.json index cf7f64502..eb418acf1 100644 --- a/static/.eslintrc.json +++ b/static/.eslintrc.json @@ -7,13 +7,9 @@ "comma-dangle": ["error", "never"], "guard-for-in": "off", "max-len": ["error", { - "code": 80, - "tabWidth": 2, "ignoreStrings": true, "ignoreTemplateLiterals": true, - "ignoreRegExpLiterals": true, - "ignoreUrls": true, - "ignorePattern": "goog.(module|require)" + "ignoreRegExpLiterals": true }], "no-invalid-this": "off", "no-var": "off", From 6f2cd26ef1bdef04c510aad34eedbb5889ce92ec Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 14:18:15 -0700 Subject: [PATCH 135/243] Address issues in code review --- .nycrc.json | 2 +- README.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.nycrc.json b/.nycrc.json index 66f767946..3af4a97e1 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -6,4 +6,4 @@ "**/coverage/**", "**/json3.min.js" ] -} \ No newline at end of file +} diff --git a/README.md b/README.md index a239e69fc..1a44087be 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,13 @@ Before you can run or deploy, copy `secrets.sample.json` to `secrets.json`. ## Running locally ```sh - npm start +npm start ``` ## Deploying to App Engine ```sh - npm run deploy +npm run deploy ``` (This step is performed automatically when a commit is pushed to `main`.) @@ -38,7 +38,7 @@ Before you can run or deploy, copy `secrets.sample.json` to `secrets.json`. To test using the latest deployed version, run: ```sh - npm run selenium +npm run selenium ``` You must configure your Selenium remote in `secrets.json`; local environments @@ -49,23 +49,23 @@ configure your WebDriver URL. You can also test just a single browser by defining the `BROWSER` environment variable: ```sh - BROWSER=chrome npm run selenium +BROWSER=chrome npm run selenium ``` ## Running the unit tests and linter ```sh - npm test +npm test ``` Code coverage reports can be viewed in a browser by running: ```sh - npm run coverage +npm run coverage ``` ## Cleanup generated files ```sh - npm run clean +npm run clean ``` From 90e9371cd67f9e0de6ac4aa77d63b85f511f5fde Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 15:16:30 -0700 Subject: [PATCH 136/243] Move manifest files to their own folder --- .gitignore | 1 + app.js | 4 ++-- build.js | 5 +++-- package.json | 2 +- tests.js | 4 ++-- unittest/app/app.js | 2 +- unittest/unit/tests.js | 4 ++-- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 805f0cf3f..d3bcb59a9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ coverage.lcov coverage/ generated/ +manifest/ node_modules/ secrets.json .testtmp diff --git a/app.js b/app.js index 43af60137..b0d8b3c45 100644 --- a/app.js +++ b/app.js @@ -45,8 +45,8 @@ const github = require('./github')( const Tests = require('./tests'); const tests = new Tests({ - tests: require('./generated/tests.json'), - manifest: require('./generated/manifest.json'), + tests: require('./manifest/tests.json'), + endpoints: require('./manifest/endpoints.json'), host: host, httpOnly: process.env.NODE_ENV !== 'production' }); diff --git a/build.js b/build.js index ae7162261..b8eff51ed 100644 --- a/build.js +++ b/build.js @@ -23,6 +23,7 @@ const customTests = require('./custom-tests.json'); const webref = require('./webref'); const generatedDir = path.join(__dirname, 'generated'); +const manifestDir = path.join(__dirname, 'manifest'); const prefixes = process.env.NODE_ENV === 'test' ? { // Shortened in tests for convenience @@ -732,8 +733,8 @@ const build = async (webref, bcd) => { const CSSTests = buildCSS(webref, bcd); const tests = Object.assign(IDLTests, CSSTests); - await writeFile(path.join(generatedDir, 'tests.json'), tests); - await writeFile(path.join(generatedDir, 'manifest.json'), buildManifest(tests)); + await writeFile(path.join(manifestDir, 'tests.json'), tests); + await writeFile(path.join(manifestDir, 'endpoints.json'), buildManifest(tests)); await copyResources(); }; diff --git a/package.json b/package.json index 6cc2560ea..b2086553c 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "prepare": "if [ -d node_modules/puppeteer ]; then cd node_modules/puppeteer && PUPPETEER_PRODUCT=firefox node install.js; fi", "lint": "eslint .", "lint-fix": "eslint --fix .", - "clean": "rm -rf .nyc_output coverage generated", + "clean": "rm -rf .nyc_output coverage generated manifest", "build": "node build.js", "gcp-build": "npm run build", "deploy": "gcloud app deploy", diff --git a/tests.js b/tests.js index 8a95ae71f..5393b2491 100644 --- a/tests.js +++ b/tests.js @@ -17,8 +17,8 @@ class Tests { constructor(options) { this.tests = options.tests; - this.endpoints = options.manifest.main; - this.individualEndpoints = options.manifest.individual; + this.endpoints = options.endpoints.main; + this.individualEndpoints = options.endpoints.individual; this.host = options.host; this.httpOnly = options.httpOnly; } diff --git a/unittest/app/app.js b/unittest/app/app.js index 5c86127aa..cde28c5f9 100644 --- a/unittest/app/app.js +++ b/unittest/app/app.js @@ -18,7 +18,7 @@ const {app, version} = require('../../app'); const chai = require('chai'); const chaiHttp = require('chai-http'); -const manifest = require('../../generated/manifest.json'); +const manifest = require('../../manifest/endpoints.json'); const mainEndpoints = Object.entries(manifest.main); const individualEndpoints = Object.entries(manifest.individual); diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index dc91cea92..3785aee40 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -76,7 +76,7 @@ const MANIFEST = { describe('Tests', () => { const tests = new Tests({ tests: testDatabase, - manifest: MANIFEST, + endpoints: MANIFEST, host: 'host.test' }); @@ -103,7 +103,7 @@ describe('Tests', () => { it('HTTP only', () => { const theseTests = new Tests({ - manifest: MANIFEST, + endpoints: MANIFEST, host: 'host.test', httpOnly: true }); From fc8c27f8fc30ad8307d41f7b28e8de8c3b97e679 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 15:49:46 -0700 Subject: [PATCH 137/243] Move "All Tests" back to index.html --- app.js | 2 +- static/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index b0d8b3c45..d771cf6b5 100644 --- a/app.js +++ b/app.js @@ -75,7 +75,7 @@ app.use(express.static('generated')); app.get('/api/tests', (req, res) => { res.json([ - ['All Tests', tests.listMainEndpoints('/tests')[0]], + ['', tests.listMainEndpoints('/tests')[0]], ...tests.listIndividual('/tests') ]); }); diff --git a/static/index.html b/static/index.html index 5e1347d90..c04239c94 100644 --- a/static/index.html +++ b/static/index.html @@ -61,7 +61,7 @@

mdn-bcd-collector

for (var i=0; i Date: Mon, 7 Sep 2020 15:57:08 -0700 Subject: [PATCH 138/243] Fix callbacks/promises in copyResources --- build.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/build.js b/build.js index b8eff51ed..287790099 100644 --- a/build.js +++ b/build.js @@ -652,18 +652,15 @@ const copyResources = async () => { // Fix source mapping in core-js const corejsPath = path.join(generatedDir, 'resources', 'core.js'); - await fs.readFile(corejsPath, 'utf8', (err, data) => { - if (err) { - return console.log(err); - } + await fs.readFile(corejsPath, 'utf8').then((data) => { const result = data.replace( /sourceMappingURL=minified\.js\.map/g, 'sourceMappingURL=core.js.map' ); - fs.writeFileSync(corejsPath, result, 'utf8', (err) => { - if (err) return console.log(err); - }); + fs.writeFile(corejsPath, result, 'utf8'); + }).catch((err) => { + console.error(err); }); }; From dfb6171c0b4d2d787242ba782302d77124e37244 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 16:34:32 -0700 Subject: [PATCH 139/243] Address review comments --- build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.js b/build.js index 287790099..0e235c47d 100644 --- a/build.js +++ b/build.js @@ -728,7 +728,7 @@ const buildManifest = (tests) => { const build = async (webref, bcd) => { const IDLTests = buildIDL(webref); const CSSTests = buildCSS(webref, bcd); - const tests = Object.assign(IDLTests, CSSTests); + const tests = Object.assign({}, IDLTests, CSSTests); await writeFile(path.join(manifestDir, 'tests.json'), tests); await writeFile(path.join(manifestDir, 'endpoints.json'), buildManifest(tests)); From 554f6c045c83d207e3e4d8164ee2fcb6b01c2edb Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 17:38:27 -0700 Subject: [PATCH 140/243] Delete redundant file --- test/unit/build.js | 1326 -------------------------------------------- 1 file changed, 1326 deletions(-) delete mode 100644 test/unit/build.js diff --git a/test/unit/build.js b/test/unit/build.js deleted file mode 100644 index b724cd7b4..000000000 --- a/test/unit/build.js +++ /dev/null @@ -1,1326 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -const chai = require('chai'); -const chaiSubset = require('chai-subset'); -const chaiFs = require('chai-fs'); -chai.use(chaiSubset).use(chaiFs); -const assert = chai.assert; -const expect = chai.expect; - -const WebIDL2 = require('webidl2'); -const fs = require('fs'); - -const { - writeText, - loadCustomTests, - getCustomTestAPI, - getCustomTestCSS, - collectCSSPropertiesFromBCD, - collectCSSPropertiesFromReffy, - cssPropertyToIDLAttribute, - flattenIDL, - getExposureSet, - buildIDLTests, - validateIDL -} = require('../../build'); - -describe('build', () => { - describe('writeText', () => { - const filepath = '.testtmp'; - - it('simple supported', () => { - writeText(filepath, 'foo\nbar'); - assert.fileContent(filepath, 'foo\nbar\n'); - }); - - it('array', () => { - writeText(filepath, ['foo', 'bar', 'baz']); - assert.fileContent(filepath, 'foo\nbar\nbaz\n'); - }); - - afterEach(() => { - fs.unlinkSync(filepath); - }); - }); - - describe('getCustomTestAPI', () => { - describe('no custom tests', () => { - beforeEach(() => { - loadCustomTests({api: {}, css: {}}); - }); - - it('interface', () => { - assert.equal(getCustomTestAPI('foo'), false); - }); - - it('member', () => { - assert.equal(getCustomTestAPI('foo', 'bar'), false); - }); - }); - - describe('custom test for interface only', () => { - beforeEach(() => { - loadCustomTests({ - api: { - foo: { - __base: 'var a = 1;', - __test: 'return a;' - } - }, - css: {} - }); - }); - - it('interface', () => { - assert.equal( - getCustomTestAPI('foo'), - '(function() {var a = 1;return a;})()' - ); - }); - - it('member', () => { - assert.equal( - getCustomTestAPI('foo', 'bar'), - '(function() {var a = 1;return instance && \'bar\' in instance;})()' - ); - }); - }); - - describe('custom test for interface only, no base', () => { - beforeEach(() => { - loadCustomTests({ - api: { - foo: { - __test: 'return 1;' - } - }, - css: {} - }); - }); - - it('interface', () => { - assert.equal(getCustomTestAPI('foo'), '(function() {return 1;})()'); - }); - - it('member', () => { - assert.equal(getCustomTestAPI('foo', 'bar'), false); - }); - }); - - describe('custom test for member only', () => { - beforeEach(() => { - loadCustomTests({ - api: { - foo: { - __base: 'var a = 1;', - bar: 'return a + 1;' - } - }, - css: {} - }); - }); - - it('interface', () => { - assert.equal( - getCustomTestAPI('foo'), - '(function() {var a = 1;return !!instance;})()' - ); - }); - - it('member', () => { - assert.equal( - getCustomTestAPI('foo', 'bar'), - '(function() {var a = 1;return a + 1;})()' - ); - }); - }); - - describe('custom test for member only, no __base', () => { - beforeEach(() => { - loadCustomTests({ - api: { - foo: { - bar: 'return 1 + 1;' - } - }, - css: {} - }); - }); - - it('interface', () => { - assert.equal(getCustomTestAPI('foo'), false); - }); - - it('member', () => { - assert.equal( - getCustomTestAPI('foo', 'bar'), - '(function() {return 1 + 1;})()' - ); - }); - }); - - describe('custom test for interface and member', () => { - beforeEach(() => { - loadCustomTests({ - api: { - foo: { - __base: 'var a = 1;', - __test: 'return a;', - bar: 'return a + 1;' - } - }, - css: {} - }); - }); - - it('interface', () => { - assert.equal( - getCustomTestAPI('foo'), - '(function() {var a = 1;return a;})()' - ); - }); - - it('member', () => { - assert.equal( - getCustomTestAPI('foo', 'bar'), - '(function() {var a = 1;return a + 1;})()' - ); - }); - }); - }); - - describe('getCustomTestCSS', () => { - it('no custom tests', () => { - loadCustomTests({api: {}, css: {}}); - assert.equal(getCustomTestCSS('foo'), false); - }); - - it('custom test for property', () => { - loadCustomTests({ - api: {}, - css: { - properties: { - foo: 'return 1;' - } - } - }); - - assert.equal(getCustomTestCSS('foo'), '(function() {return 1;})()'); - }); - }); - - describe('collectCSSPropertiesFromBCD', () => { - it('simple supported', () => { - const bcd = { - css: { - properties: { - appearance: { - __compat: { - support: {} - } - } - } - } - }; - const propertySet = new Set(); - collectCSSPropertiesFromBCD(bcd, propertySet); - const properties = Array.from(propertySet); - assert.deepEqual(properties, ['appearance']); - }); - - it('aliased support', () => { - const bcd = { - css: { - properties: { - 'font-smooth': { - __compat: { - support: { - safari: { - alternative_name: '-webkit-font-smoothing' - } - } - } - } - } - } - }; - const propertySet = new Set(); - collectCSSPropertiesFromBCD(bcd, propertySet); - const properties = Array.from(propertySet); - assert.deepEqual(properties, ['font-smooth', '-webkit-font-smoothing']); - }); - - it('support array', () => { - const bcd = { - css: { - properties: { - 'font-smooth': { - __compat: { - support: { - safari: [ - { - prefix: '-webkit-' - }, - { - alternative_name: '-webkit-font-smoothing' - } - ] - } - } - } - } - } - }; - const propertySet = new Set(); - collectCSSPropertiesFromBCD(bcd, propertySet); - const properties = Array.from(propertySet); - assert.deepEqual(properties, ['font-smooth', '-webkit-font-smoothing']); - }); - - it('no __compat statement', () => { - const bcd = { - css: { - properties: { - appearance: {} - } - } - }; - const propertySet = new Set(); - collectCSSPropertiesFromBCD(bcd, propertySet); - const properties = Array.from(propertySet); - assert.deepEqual(properties, ['appearance']); - }); - - it('no __compat.support statement', () => { - const bcd = { - css: { - properties: { - appearance: { - __compat: {} - } - } - } - }; - const propertySet = new Set(); - collectCSSPropertiesFromBCD(bcd, propertySet); - const properties = Array.from(propertySet); - assert.deepEqual(properties, ['appearance']); - }); - }); - - it('collectCSSPropertiesFromReffy', () => { - const webref = { - css: { - 'css-fonts': { - properties: { - 'font-family': {}, - 'font-weight': {} - } - }, - 'css-grid': { - properties: { - grid: {} - } - } - } - }; - const propertySet = new Set(); - collectCSSPropertiesFromReffy(webref, propertySet); - const properties = Array.from(propertySet); - assert.deepEqual(properties, ['font-family', 'font-weight', 'grid']); - }); - - it('cssPropertyToIDLAttribute', () => { - assert.equal(cssPropertyToIDLAttribute('line-height'), 'lineHeight'); - assert.equal(cssPropertyToIDLAttribute('-webkit-line-clamp', true), - 'webkitLineClamp'); - }); - - describe('flattenIDL', () => { - const historicalIDL = WebIDL2.parse(`interface DOMError {};`); - - it('interface + mixin', () => { - const specIDLs = { - first: WebIDL2.parse(`interface DummyError : Error { - readonly attribute boolean imadumdum; - };`), - secnd: WebIDL2.parse( - `interface mixin DummyErrorHelper { - DummyError geterror(); - }; - - DummyError includes DummyErrorHelper;`) - }; - const ast = flattenIDL(specIDLs, historicalIDL); - - const interfaces = ast.filter((dfn) => dfn.type === 'interface'); - assert.lengthOf(interfaces, 2); - - assert.equal(interfaces[0].name, 'DummyError'); - assert.lengthOf(interfaces[0].members, 2); - assert.containSubset(interfaces[0].members[0], { - type: 'attribute', - name: 'imadumdum' - }); - assert.containSubset(interfaces[0].members[1], { - type: 'operation', - name: 'geterror' - }); - - assert.equal(interfaces[1].name, 'DOMError'); - }); - - it('namespace + partial namespace', () => { - const specIDLs = { - cssom: WebIDL2.parse(`namespace CSS { boolean supports(); };`), - paint: WebIDL2.parse( - `partial namespace CSS { - readonly attribute any paintWorklet; - };`) - }; - const ast = flattenIDL(specIDLs, historicalIDL); - - const namespaces = ast.filter((dfn) => dfn.type === 'namespace'); - assert.lengthOf(namespaces, 1); - const [namespace] = namespaces; - assert.equal(namespace.name, 'CSS'); - assert.lengthOf(namespace.members, 2); - assert.containSubset(namespace.members[0], { - type: 'operation', - name: 'supports' - }); - assert.containSubset(namespace.members[1], { - type: 'attribute', - name: 'paintWorklet' - }); - - const interfaces = ast.filter((dfn) => dfn.type === 'interface'); - assert.lengthOf(interfaces, 1); - assert.equal(interfaces[0].name, 'DOMError'); - }); - - it('mixin missing', () => { - const specIDLs = { - first: WebIDL2.parse(`interface mixin DummyErrorHelper { - DummyError geterror(); - };`), - secnd: WebIDL2.parse(`DummyError includes DummyErrorHelper;`) - }; - - expect(() => { - flattenIDL(specIDLs, historicalIDL); - // eslint-disable-next-line max-len - }).to.throw('Target DummyError not found for interface mixin DummyErrorHelper'); - }); - - it('interface missing', () => { - const specIDLs = { - first: WebIDL2.parse(`interface DummyError : Error { - readonly attribute boolean imadumdum; - };`), - secnd: WebIDL2.parse(`DummyError includes DummyErrorHelper;`) - }; - - expect(() => { - flattenIDL(specIDLs, historicalIDL); - // eslint-disable-next-line max-len - }).to.throw('Interface mixin DummyErrorHelper not found for target DummyError'); - }); - - it('Operation overloading', () => { - const specIDLs = { - cssom: WebIDL2.parse(`namespace CSS { boolean supports(); };`), - paint: WebIDL2.parse( - `partial namespace CSS { - readonly attribute any paintWorklet; - };`), - paint2: WebIDL2.parse( - `partial namespace CSS { - boolean supports(); - };`) - }; - expect(() => { - flattenIDL(specIDLs, historicalIDL); - // eslint-disable-next-line max-len - }).to.throw('Operation overloading across partials/mixins for CSS.supports'); - }); - - it('Partial missing main', () => { - const specIDLs = { - paint: WebIDL2.parse( - `partial namespace CSS { - readonly attribute any paintWorklet; - };`) - }; - expect(() => { - flattenIDL(specIDLs, historicalIDL); - }).to.throw('Original definition not found for partial namespace CSS'); - }); - }); - - describe('getExposureSet', () => { - const historicalIDL = WebIDL2.parse(`interface DOMError {};`); - - it('no defined exposure set', () => { - const specIDLs = { - first: WebIDL2.parse(`interface Dummy { - readonly attribute boolean imadumdum; - };`) - }; - const ast = flattenIDL(specIDLs, historicalIDL); - const interfaces = ast.filter((dfn) => dfn.type === 'interface'); - const exposureSet = getExposureSet(interfaces[0]); - assert.hasAllKeys(exposureSet, ['Window']); - }); - - it('single exposure', () => { - const specIDLs = { - first: WebIDL2.parse(`[Exposed=Worker] interface Dummy { - readonly attribute boolean imadumdum; - };`) - }; - const ast = flattenIDL(specIDLs, historicalIDL); - const interfaces = ast.filter((dfn) => dfn.type === 'interface'); - const exposureSet = getExposureSet(interfaces[0]); - assert.hasAllKeys(exposureSet, ['Worker']); - }); - - it('multiple exposure', () => { - const specIDLs = { - first: WebIDL2.parse(`[Exposed=(Window,Worker)] interface Dummy { - readonly attribute boolean imadumdum; - };`) - }; - const ast = flattenIDL(specIDLs, historicalIDL); - const interfaces = ast.filter((dfn) => dfn.type === 'interface'); - const exposureSet = getExposureSet(interfaces[0]); - assert.hasAllKeys(exposureSet, ['Window', 'Worker']); - }); - }); - - describe('buildIDLTests', () => { - it('interface with attribute', () => { - const ast = WebIDL2.parse(`interface Attr { attribute any name; };`); - assert.deepEqual(buildIDLTests(ast), [ - ['Attr', {property: 'Attr', scope: 'self'}, new Set(['Window']), [ - ['name', [ - {property: 'Attr', scope: 'self'}, - {property: 'name', scope: 'Attr.prototype'} - ]] - ] - ]]); - }); - - it('interface with method', () => { - const ast = WebIDL2.parse( - `interface Node { - boolean contains(Node? other); - };`); - assert.deepEqual(buildIDLTests(ast), [ - ['Node', {property: 'Node', scope: 'self'}, new Set(['Window']), [ - ['contains', [ - {property: 'Node', scope: 'self'}, - {property: 'contains', scope: 'Node.prototype'} - ]] - ] - ]]); - }); - - it('interface with static method', () => { - const ast = WebIDL2.parse( - `interface MediaSource { - static boolean isTypeSupported(DOMString type); - };`); - assert.deepEqual(buildIDLTests(ast), [ - ['MediaSource', {property: 'MediaSource', scope: 'self'}, - new Set(['Window']), [ - ['isTypeSupported', [ - {property: 'MediaSource', scope: 'self'}, - {property: 'isTypeSupported', scope: 'MediaSource'} - ]] - ] - ]]); - }); - - it('interface with const', () => { - const ast = WebIDL2.parse( - `interface Window { - const boolean isWindow = true; - };`); - assert.deepEqual(buildIDLTests(ast), [ - ['Window', {property: 'Window', scope: 'self'}, new Set(['Window']), [ - ['isWindow', [ - {property: 'Window', scope: 'self'}, - {property: 'isWindow', scope: 'Window'} - ]] - ] - ]]); - }); - - it('interface with custom test', () => { - const ast = WebIDL2.parse( - `interface ANGLE_instanced_arrays { - void drawArraysInstancedANGLE( - GLenum mode, - GLint first, - GLsizei count, - GLsizei primcount - ); - void drawElementsInstancedANGLE( - GLenum mode, - GLsizei count, - GLenum type, - GLintptr offset, - GLsizei primcoun - ); - };`); - loadCustomTests({ - api: { - ANGLE_instanced_arrays: { - // eslint-disable-next-line max-len - __base: 'var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');', - __test: 'return !!instance;', - // eslint-disable-next-line max-len - drawArraysInstancedANGLE: 'return instance && \'drawArraysInstancedANGLE\' in instance;' - } - }, - css: {} - }); - assert.deepEqual(buildIDLTests(ast), [ - // eslint-disable-next-line max-len - ['ANGLE_instanced_arrays', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return !!instance;})()', new Set(['Window']), [ - // eslint-disable-next-line max-len - ['drawArraysInstancedANGLE', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawArraysInstancedANGLE\' in instance;})()'], - // eslint-disable-next-line max-len - ['drawElementsInstancedANGLE', '(function() {var canvas = document.createElement(\'canvas\'); var gl = canvas.getContext(\'webgl\'); var instance = gl.getExtension(\'ANGLE_instanced_arrays\');return instance && \'drawElementsInstancedANGLE\' in instance;})()'] - ] - ]]); - }); - - it('interface with legacy namespace', () => { - const ast = WebIDL2.parse(`[LegacyNamespace] interface Legacy {};`); - assert.deepEqual(buildIDLTests(ast), []); - }); - - it('global interface', () => { - const ast = WebIDL2.parse(`[Global=(Window,Worker)] - interface WindowOrWorkerGlobalScope { - attribute boolean isLoaded; - const boolean active = true; - };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'WindowOrWorkerGlobalScope', - { - property: 'WindowOrWorkerGlobalScope', - scope: 'self' - }, - new Set(['Window']), - [ - [ - 'active', - { - property: 'active', - scope: 'self' - } - ], - [ - 'isLoaded', - { - property: 'isLoaded', - scope: 'self' - } - ] - ] - ] - ]); - }); - - it('interface with constructor operation', () => { - const ast = WebIDL2.parse(`interface Number { - constructor(optional any value); - };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'Number', - { - property: 'Number', - scope: 'self' - }, - new Set(['Window']), - [ - [ - 'Number', - [ - { - property: 'Number', - scope: 'self' - }, - { - property: 'constructor', - scope: 'Number' - } - ] - ] - ] - ] - ]); - }); - - it('interface with constructor in ExtAttr', () => { - const ast = WebIDL2.parse(`[Constructor(optional any value)] - interface Number {};`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'Number', - { - property: 'Number', - scope: 'self' - }, - new Set(['Window']), - [ - [ - 'Number', - [ - { - property: 'Number', - scope: 'self' - }, - { - property: 'constructor', - scope: 'Number' - } - ] - ] - ] - ] - ]); - }); - - it('iterable interface', () => { - const ast = WebIDL2.parse(`interface DoubleList { - iterable; - };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'DoubleList', - { - property: 'DoubleList', - scope: 'self' - }, - new Set(['Window']), - [ - [ - '@@iterator', - [ - { - property: 'DoubleList', - scope: 'self' - }, - { - property: 'Symbol', - scope: 'self' - }, - { - property: 'iterator', - scope: 'Symbol' - }, - { - property: 'Symbol.iterator', - scope: 'DoubleList.prototype' - } - ] - ], - [ - 'entries', - [ - { - property: 'DoubleList', - scope: 'self' - }, - { - property: 'entries', - scope: 'DoubleList.prototype' - } - ] - ], - [ - 'forEach', - [ - { - property: 'DoubleList', - scope: 'self' - }, - { - property: 'forEach', - scope: 'DoubleList.prototype' - } - ] - ], - [ - 'keys', - [ - { - property: 'DoubleList', - scope: 'self' - }, - { - property: 'keys', - scope: 'DoubleList.prototype' - } - ] - ], - [ - 'values', - [ - { - property: 'DoubleList', - scope: 'self' - }, - { - property: 'values', - scope: 'DoubleList.prototype' - } - ] - ] - ] - ] - ]); - }); - - it('maplike interface', () => { - const ast = WebIDL2.parse(`interface DoubleMap { - maplike; - };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'DoubleMap', - { - property: 'DoubleMap', - scope: 'self' - }, - new Set(['Window']), - [ - [ - 'clear', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'clear', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'delete', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'delete', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'entries', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'entries', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'forEach', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'forEach', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'get', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'get', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'has', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'has', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'keys', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'keys', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'set', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'set', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'size', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'size', - scope: 'DoubleMap.prototype' - } - ] - ], - [ - 'values', - [ - { - property: 'DoubleMap', - scope: 'self' - }, - { - property: 'values', - scope: 'DoubleMap.prototype' - } - ] - ] - ] - ] - ]); - }); - - it('setlike interface', () => { - const ast = WebIDL2.parse(`interface DoubleSet { - setlike; - };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'DoubleSet', - { - property: 'DoubleSet', - scope: 'self' - }, - new Set(['Window']), - [ - [ - 'add', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'add', - scope: 'DoubleSet.prototype' - } - ] - ], - [ - 'clear', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'clear', - scope: 'DoubleSet.prototype' - } - ] - ], - [ - 'delete', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'delete', - scope: 'DoubleSet.prototype' - } - ] - ], - [ - 'entries', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'entries', - scope: 'DoubleSet.prototype' - } - ] - ], - [ - 'has', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'has', - scope: 'DoubleSet.prototype' - } - ] - ], - [ - 'keys', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'keys', - scope: 'DoubleSet.prototype' - } - ] - ], - [ - 'size', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'size', - scope: 'DoubleSet.prototype' - } - ] - ], - [ - 'values', - [ - { - property: 'DoubleSet', - scope: 'self' - }, - { - property: 'values', - scope: 'DoubleSet.prototype' - } - ] - ] - ] - ] - ]); - }); - - it('interface with getter/setter', () => { - const ast = WebIDL2.parse(`interface GetMe { - getter GetMe (unsigned long index); - setter void (GetMe data, optional unsigned long index); - };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'GetMe', - { - property: 'GetMe', - scope: 'self' - }, - new Set(['Window']), - [] - ] - ]); - }); - - it('varied scopes', () => { - const ast = WebIDL2.parse(` - [Exposed=Window] interface Worker {}; - [Exposed=Worker] interface WorkerSync {}; - [Exposed=(Window,Worker)] interface MessageChannel {}; - namespace CSS {}; - `); - assert.deepEqual(buildIDLTests(ast), [ - ['CSS', {property: 'CSS', scope: 'self'}, new Set(['Window']), []], - [ - 'MessageChannel', - {property: 'MessageChannel', scope: 'self'}, - new Set(['Window', 'Worker']), - [] - ], - [ - 'Worker', - {property: 'Worker', scope: 'self'}, - new Set(['Window']), - [] - ], - [ - 'WorkerSync', - {property: 'WorkerSync', scope: 'self'}, - new Set(['Worker']), - [] - ] - ]); - }); - - it('operator variations', () => { - const ast = WebIDL2.parse(` - interface AudioNode : EventTarget { - void disconnect (); - void disconnect (unsigned long output); - void disconnect (AudioNode destinationNode); - }; - `); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'AudioNode', - {property: 'AudioNode', scope: 'self'}, - new Set(['Window']), - [ - ['disconnect', [ - {property: 'AudioNode', scope: 'self'}, - {property: 'disconnect', scope: 'AudioNode.prototype'} - ]] - ] - ] - ]); - }); - - it('namespace with attribute', () => { - const ast = WebIDL2.parse( - `namespace CSS { - readonly attribute any paintWorklet; - };`); - assert.deepEqual(buildIDLTests(ast), [ - ['CSS', {property: 'CSS', scope: 'self'}, new Set(['Window']), [ - ['paintWorklet', [ - {property: 'CSS', scope: 'self'}, - {property: 'paintWorklet', scope: 'CSS'} - ]] - ] - ]]); - }); - - it('namespace with method', () => { - const ast = WebIDL2.parse( - `namespace CSS { - boolean supports(CSSOMString property, CSSOMString value); - };`); - assert.deepEqual(buildIDLTests(ast), [ - ['CSS', {property: 'CSS', scope: 'self'}, new Set(['Window']), [ - ['supports', [ - {property: 'CSS', scope: 'self'}, - {property: 'supports', scope: 'CSS'} - ]] - ] - ]]); - }); - - it('namespace with custom test', () => { - const ast = WebIDL2.parse( - `namespace CSS { - readonly attribute any paintWorklet; - };`); - loadCustomTests({ - api: { - CSS: { - __base: 'var css = CSS;', - __test: 'return !!css;', - paintWorklet: 'return css && \'paintWorklet\' in css;' - } - }, - css: {} - }); - assert.deepEqual(buildIDLTests(ast), [ - // eslint-disable-next-line max-len - [ - 'CSS', - '(function() {var css = CSS;return !!css;})()', - new Set(['Window']), - [ - // eslint-disable-next-line max-len - ['paintWorklet', '(function() {var css = CSS;return css && \'paintWorklet\' in css;})()'] - ] - ] - ]); - }); - - it('dictionary', () => { - const ast = WebIDL2.parse( - `dictionary ElementRegistrationOptions { - object? prototype = null; - DOMString? extends = null; - };`); - assert.deepEqual(buildIDLTests(ast), [ - [ - 'ElementRegistrationOptions', - {property: 'ElementRegistrationOptions', scope: 'self'}, - new Set(['Window']), - [ - ['extends', [ - {property: 'ElementRegistrationOptions', scope: 'self'}, - {property: 'extends', scope: 'ElementRegistrationOptions'} - ]], - ['prototype', [ - {property: 'ElementRegistrationOptions', scope: 'self'}, - {property: 'prototype', scope: 'ElementRegistrationOptions'} - ]] - ] - ] - ]); - }); - - it('dictionary with custom test', () => { - const ast = WebIDL2.parse( - `dictionary ElementRegistrationOptions { - object? prototype = null; - DOMString? extends = null; - };`); - loadCustomTests({ - api: { - ElementRegistrationOptions: { - __base: 'var ers = ElementRegistrationOptions;', - __test: 'return !!ers;', - extends: 'return ers && \'extends\' in ers;', - prototype: 'return ers && \'prototype\' in ers;' - } - }, - css: {} - }); - assert.deepEqual(buildIDLTests(ast), [ - // eslint-disable-next-line max-len - ['ElementRegistrationOptions', '(function() {var ers = ElementRegistrationOptions;return !!ers;})()', new Set(['Window']), [ - // eslint-disable-next-line max-len - ['extends', '(function() {var ers = ElementRegistrationOptions;return ers && \'extends\' in ers;})()'], - // eslint-disable-next-line max-len - ['prototype', '(function() {var ers = ElementRegistrationOptions;return ers && \'prototype\' in ers;})()'] - ] - ]]); - }); - }); - - describe('validateIDL', () => { - it('valid idl', () => { - const ast = WebIDL2.parse(`interface Node { - boolean contains(Node otherNode); - };`); - expect(() => { - validateIDL(ast); - }).to.not.throw(); - }); - - it('no members', () => { - const ast = WebIDL2.parse(`interface Node {};`); - expect(() => { - validateIDL(ast); - }).to.not.throw(); - }); - - it('overloaded operator', () => { - const ast = WebIDL2.parse(`interface Node { - boolean contains(Node otherNode); - boolean contains(Node otherNode, boolean deepEqual); - };`); - expect(() => { - validateIDL(ast); - }).to.not.throw(); - }); - - it('nameless member', () => { - const ast = WebIDL2.parse(`interface Node { - iterable; - };`); - expect(() => { - validateIDL(ast); - }).to.not.throw(); - }); - - /* Remove when issues are resolved spec-side */ - it('allowed duplicates', () => { - const ast = WebIDL2.parse(`interface SVGAElement { - attribute DOMString href; - attribute DOMString href; - }; - - interface WebGLRenderingContext { - attribute Canvas canvas; - attribute Canvas canvas; - }; - - interface WebGL2RenderingContext { - attribute Canvas canvas; - attribute Canvas canvas; - };`); - expect(() => { - validateIDL(ast); - }).to.not.throw(); - }); - - it('disallowed duplicates', () => { - const ast = WebIDL2.parse(`interface Node { - attribute DOMString type; - attribute DOMString type; - };`); - expect(() => { - validateIDL(ast); - }).to.throw(); - }); - }); -}); From 5211ae8a662fb5d98806e873bc2570cb690496b5 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 20:26:36 -0700 Subject: [PATCH 141/243] Fix toString tests --- build.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build.js b/build.js index 0e235c47d..00062dcf7 100644 --- a/build.js +++ b/build.js @@ -304,7 +304,11 @@ const flattenMembers = (iface) => { ); break; case 'operation': - // We don't care about setter/getter functions + switch (member.special) { + case 'stringifier': + members.push({name: 'toString', type: 'operation'}); + break; + } break; } } @@ -313,9 +317,6 @@ const flattenMembers = (iface) => { if (getExtAttr(iface, 'Constructor')) { members.push({name: iface.name, type: 'constructor'}); } - if (getExtAttr(iface, 'Serializable')) { - members.push({name: 'toString', type: 'operation'}); - } return members.sort((a, b) => a.name.localeCompare(b.name)); }; From 6db60a95709dbe84e46db25a9847e9187f70265c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 22:13:06 -0700 Subject: [PATCH 142/243] Simplify manifest (remove "individual" points, leave only main) --- build.js | 34 ++++++++-------------------------- tests.js | 19 ++++++++++++------- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/build.js b/build.js index 00062dcf7..74be54fc9 100644 --- a/build.js +++ b/build.js @@ -666,14 +666,12 @@ const copyResources = async () => { }; const buildManifest = (tests) => { - const manifest = { - main: {}, - individual: {} - }; + const manifest = {}; for (const [ident, test] of Object.entries(tests)) { for (const scope of test.scope) { let endpoint = ''; + let httpsOnly = false; switch (scope) { case 'Window': endpoint = '/api/interfaces'; @@ -684,6 +682,7 @@ const buildManifest = (tests) => { break; case 'ServiceWorker': endpoint = '/api/serviceworkerinterfaces'; + httpsOnly = true; break; case 'CSS': endpoint = '/css/properties'; @@ -691,35 +690,18 @@ const buildManifest = (tests) => { } if (endpoint) { - if (!(endpoint in manifest.main)) { - manifest.main[endpoint] = { + if (!(endpoint in manifest)) { + manifest[endpoint] = { scope: scope, - httpsOnly: scope === 'ServiceWorker', + httpsOnly: httpsOnly, entries: [] }; } - if (!(ident in manifest.main[endpoint].entries)) { - manifest.main[endpoint].entries.push(ident); + if (!(ident in manifest[endpoint].entries)) { + manifest[endpoint].entries.push(ident); } } } - - let url = ''; - for (const part of ident.split('.')) { - url += '/' + part; - - if (['/api', '/css', '/css/properties'].includes(url)) { - // Ignore things tested in main endpoints - continue; - } - - if (!(url in manifest.individual)) { - manifest.individual[url] = []; - } - if (!(ident in manifest.individual[url])) { - manifest.individual[url].push(ident); - } - } } return manifest; diff --git a/tests.js b/tests.js index 5393b2491..2af5d58e5 100644 --- a/tests.js +++ b/tests.js @@ -17,8 +17,7 @@ class Tests { constructor(options) { this.tests = options.tests; - this.endpoints = options.endpoints.main; - this.individualEndpoints = options.endpoints.individual; + this.endpoints = options.endpoints; this.host = options.host; this.httpOnly = options.httpOnly; } @@ -30,8 +29,8 @@ class Tests { } listIndividual(urlPrefix = '') { - return Object.keys(this.individualEndpoints).map((item) => ( - [item.substr(1).replace(/\//g, '.'), `${urlPrefix}${item}`] + return Object.keys(this.tests).map((item) => ( + [item, `${urlPrefix}/${item.replace(/\./g, '/')}`] )); } @@ -69,9 +68,15 @@ class Tests { } getTests(endpoint) { - const idents = this.endpoints[endpoint] ? - this.endpoints[endpoint].entries : - this.individualEndpoints[endpoint]; + let idents = []; + if (endpoint in this.endpoints) { + idents = this.endpoints[endpoint].entries; + } else { + idents = Object.keys(this.tests).filter( + (ident) => ident.startsWith(endpoint.substr(1).replace(/\//g, '.')) + ); + }; + const tests = {}; for (const ident of idents) { From 523749223bf8917c04b9257b8bd19d5ae11bd318 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 22:13:24 -0700 Subject: [PATCH 143/243] Fix Tests.next() --- app.js | 12 +++--------- tests.js | 10 ++++++---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/app.js b/app.js index d771cf6b5..26b9474a6 100644 --- a/app.js +++ b/app.js @@ -97,15 +97,9 @@ app.post('/api/results', (req, res) => { const response = {}; // Include next test in response as a convenience. - try { - const next = tests.next(forURL); - if (next) { - response.next = next; - } - } catch (err) { - /* istanbul ignore next */ - logger.warn(`Results submitted for URL not in manifest: ${forURL}`); - // note: indistinguishable from finishing last test to client + const next = tests.next(forURL); + if (next) { + response.next = next; } Promise.all([ diff --git a/tests.js b/tests.js index 2af5d58e5..8a1f5c85c 100644 --- a/tests.js +++ b/tests.js @@ -48,15 +48,17 @@ class Tests { } const endpoints = this.listMainEndpoints('/tests'); const index = endpoints.findIndex((item) => { - return item === afterURL.pathname; + return item[1] === afterURL.pathname; }) + 1; if (index >= endpoints.length) { return null; } - if (this.endpoints[endpoints[index].replace('/tests', '')].httpsOnly) { - const newUrl = `https://${this.host}${endpoints[index]}`; + const endpoint = endpoints[index][1]; + + if (this.endpoints[endpoint.replace('/tests', '')].httpsOnly) { + const newUrl = `https://${this.host}${endpoint}`; if (this.httpOnly) { // Skip this endpoint and go to the next return this.next(newUrl); @@ -64,7 +66,7 @@ class Tests { return newUrl; } - return `http://${this.host}${endpoints[index]}`; + return `http://${this.host}${endpoint}`; } getTests(endpoint) { From 4bc3b0368c767333789beaedcc861c4e40930a6c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 22:14:33 -0700 Subject: [PATCH 144/243] Simplify endpoint listing functions --- app.js | 4 ++-- tests.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 26b9474a6..c54e4d923 100644 --- a/app.js +++ b/app.js @@ -75,7 +75,7 @@ app.use(express.static('generated')); app.get('/api/tests', (req, res) => { res.json([ - ['', tests.listMainEndpoints('/tests')[0]], + tests.listMainEndpoints('/tests')[0], ...tests.listIndividual('/tests') ]); }); @@ -138,7 +138,7 @@ app.post('/api/results/export/github', (req, res) => { app.all('/tests/*', (req, res) => { const endpoint = `/${req.params['0']}`; - if (tests.listAllEndpoints().includes(endpoint)) { + if (tests.listAllEndpoints().map((item) => (item[1])).includes(endpoint)) { res.send(tests.generateTestPage(endpoint)); } else { res.status(404).send(`Could not find tests for ${endpoint}`); diff --git a/tests.js b/tests.js index 8a1f5c85c..9bb1fe953 100644 --- a/tests.js +++ b/tests.js @@ -24,7 +24,7 @@ class Tests { listMainEndpoints(urlPrefix = '') { return Object.keys(this.endpoints).map((item) => ( - `${urlPrefix}${item}` + ['', `${urlPrefix}${item}`] )); } @@ -37,7 +37,7 @@ class Tests { listAllEndpoints(urlPrefix = '') { return [ ...this.listMainEndpoints(urlPrefix), - ...this.listIndividual(urlPrefix).map((item) => (item[1])) + ...this.listIndividual(urlPrefix) ]; } From bb2f51c75b3957fd7a4eb0d188b3c30da9c18718 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 22:15:27 -0700 Subject: [PATCH 145/243] Rename buildManifest to buildEndpoints --- build.js | 9 ++++++--- unittest/unit/build.js | 10 +++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/build.js b/build.js index 74be54fc9..ce53d1d85 100644 --- a/build.js +++ b/build.js @@ -665,7 +665,7 @@ const copyResources = async () => { }); }; -const buildManifest = (tests) => { +const buildEndpoints = (tests) => { const manifest = {}; for (const [ident, test] of Object.entries(tests)) { @@ -714,7 +714,10 @@ const build = async (webref, bcd) => { const tests = Object.assign({}, IDLTests, CSSTests); await writeFile(path.join(manifestDir, 'tests.json'), tests); - await writeFile(path.join(manifestDir, 'endpoints.json'), buildManifest(tests)); + await writeFile( + path.join(manifestDir, 'endpoints.json'), + buildEndpoints(tests) + ); await copyResources(); }; @@ -743,6 +746,6 @@ if (require.main === module) { collectCSSPropertiesFromWebref, cssPropertyToIDLAttribute, buildCSS, - buildManifest + buildEndpoints }; } diff --git a/unittest/unit/build.js b/unittest/unit/build.js index e76a21601..65d18c41a 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -40,7 +40,7 @@ const { collectCSSPropertiesFromWebref, cssPropertyToIDLAttribute, buildCSS, - buildManifest + buildEndpoints } = proxyquire('../../build', { './custom-tests.json': {api: {}, css: {}} }); @@ -2283,7 +2283,7 @@ describe('build', () => { }); }); - it('buildManifest', () => { + it('buildEndpoints', () => { const tests = { 'api.Attr': { code: '"Attr" in self', @@ -2302,7 +2302,6 @@ describe('build', () => { scope: ['JavaScript'] } }; - const expectedManifest = { main: { '/api/interfaces': { entries: ['api.Attr', 'api.Attr.name'], @@ -2324,6 +2323,7 @@ describe('build', () => { httpsOnly: false, scope: 'CSS' } + const expectedEndpoints = { }, individual: { '/api/Attr': ['api.Attr', 'api.Attr.name'], @@ -2343,8 +2343,8 @@ describe('build', () => { } }; - const manifest = buildManifest(tests); + const endpoints = buildEndpoints(tests); - assert.deepEqual(manifest, expectedManifest); + assert.deepEqual(endpoints, expectedEndpoints); }); }); From da94ee5238f3c5c7a181ba7257c69ec5f28b8ceb Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 22:30:10 -0700 Subject: [PATCH 146/243] Fix ESLint issues --- build.js | 4 ++-- tests.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.js b/build.js index ce53d1d85..96e2dd290 100644 --- a/build.js +++ b/build.js @@ -715,8 +715,8 @@ const build = async (webref, bcd) => { await writeFile(path.join(manifestDir, 'tests.json'), tests); await writeFile( - path.join(manifestDir, 'endpoints.json'), - buildEndpoints(tests) + path.join(manifestDir, 'endpoints.json'), + buildEndpoints(tests) ); await copyResources(); }; diff --git a/tests.js b/tests.js index 9bb1fe953..e476457b8 100644 --- a/tests.js +++ b/tests.js @@ -75,9 +75,9 @@ class Tests { idents = this.endpoints[endpoint].entries; } else { idents = Object.keys(this.tests).filter( - (ident) => ident.startsWith(endpoint.substr(1).replace(/\//g, '.')) + (ident) => ident.startsWith(endpoint.substr(1).replace(/\//g, '.')) ); - }; + } const tests = {}; From f70877ef4c8f94a0067b3ef5601864f96b7beb8f Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 22:33:28 -0700 Subject: [PATCH 147/243] Update unittests --- unittest/app/app.js | 19 +++++----- unittest/unit/build.js | 54 +++++++++------------------ unittest/unit/tests.js | 83 +++++++++++++++++++----------------------- 3 files changed, 65 insertions(+), 91 deletions(-) diff --git a/unittest/app/app.js b/unittest/app/app.js index cde28c5f9..fa53f56d5 100644 --- a/unittest/app/app.js +++ b/unittest/app/app.js @@ -18,9 +18,8 @@ const {app, version} = require('../../app'); const chai = require('chai'); const chaiHttp = require('chai-http'); -const manifest = require('../../manifest/endpoints.json'); -const mainEndpoints = Object.entries(manifest.main); -const individualEndpoints = Object.entries(manifest.individual); +const endpoints = Object.entries(require('../../manifest/endpoints.json')); +const tests = Object.entries(require('../../manifest/tests.json')); chai.use(chaiHttp); const agent = chai.request.agent(app); @@ -46,8 +45,8 @@ describe('/api/results', () => { assert.deepEqual(res.body, {}); }); - const testURL = `http://localhost:8080/tests${mainEndpoints[0][0]}`; - const testURL2 = `https://host.test/tests${mainEndpoints[mainEndpoints.length - 1][0]}`; + const testURL = `http://localhost:8080/tests${endpoints[0][0]}`; + const testURL2 = `https://host.test/tests${endpoints[endpoints.length - 1][0]}`; it('submit valid results', async () => { const res = await agent.post('/api/results') @@ -55,7 +54,7 @@ describe('/api/results', () => { .send({x: 1}); assert.equal(res.status, 201); assert.deepEqual(res.body, { - next: `http://localhost:8080/tests${mainEndpoints[1][0]}` + next: `http://localhost:8080/tests${endpoints[1][0]}` }); }); @@ -115,18 +114,20 @@ describe('/api/tests', () => { const res = await agent.get('/api/tests'); assert.equal(res.status, 200); assert.isArray(res.body); - assert.equal(res.body.length, individualEndpoints.length + 1); + assert.equal(res.body.length, tests.length + 1); }); }); describe('/tests/', () => { it('get a main test', async () => { - const res = await agent.get(`/tests${mainEndpoints[0][0]}`); + const res = await agent.get(`/tests${endpoints[0][0]}`); assert.equal(res.status, 200); }); it('get an individual test', async () => { - const res = await agent.get(`/tests${individualEndpoints[0][0]}`); + const res = await agent.get(`/tests/${ + tests[1][0].replace(/\./g, '/') + }`); assert.equal(res.status, 200); }); diff --git a/unittest/unit/build.js b/unittest/unit/build.js index 65d18c41a..5f62676f5 100644 --- a/unittest/unit/build.js +++ b/unittest/unit/build.js @@ -2302,44 +2302,26 @@ describe('build', () => { scope: ['JavaScript'] } }; - main: { - '/api/interfaces': { - entries: ['api.Attr', 'api.Attr.name'], - httpsOnly: false, - scope: 'Window' - }, - '/api/serviceworkerinterfaces': { - entries: ['api.Attr'], - httpsOnly: true, - scope: 'ServiceWorker' - }, - '/api/workerinterfaces': { - entries: ['api.Attr', 'api.Attr.name'], - httpsOnly: false, - scope: 'Worker' - }, - '/css/properties': { - entries: ['css.properties.font-family'], - httpsOnly: false, - scope: 'CSS' - } const expectedEndpoints = { + '/api/interfaces': { + entries: ['api.Attr', 'api.Attr.name'], + httpsOnly: false, + scope: 'Window' }, - individual: { - '/api/Attr': ['api.Attr', 'api.Attr.name'], - '/api/Attr/name': ['api.Attr.name'], - '/css/properties/font-family': [ - 'css.properties.font-family' - ], - '/javascript': [ - 'javascript.builtins.array' - ], - '/javascript/builtins': [ - 'javascript.builtins.array' - ], - '/javascript/builtins/array': [ - 'javascript.builtins.array' - ] + '/api/serviceworkerinterfaces': { + entries: ['api.Attr'], + httpsOnly: true, + scope: 'ServiceWorker' + }, + '/api/workerinterfaces': { + entries: ['api.Attr', 'api.Attr.name'], + httpsOnly: false, + scope: 'Worker' + }, + '/css/properties': { + entries: ['css.properties.font-family'], + httpsOnly: false, + scope: 'CSS' } }; diff --git a/unittest/unit/tests.js b/unittest/unit/tests.js index 3785aee40..bdf731af6 100644 --- a/unittest/unit/tests.js +++ b/unittest/unit/tests.js @@ -34,49 +34,38 @@ const testDatabase = { }, 'api.FooBar': null }; -const MANIFEST = { - main: { - '/api/interfaces': { - scope: 'Window', - httpsOnly: false, - entries: [ - 'api.AbortController', - 'api.AbortController.signal' - ] - }, - '/api/workerinterfaces': { - scope: 'Worker', - httpsOnly: false, - entries: [ - 'api.AbortController' - ] - }, - '/api/serviceworkerinterfaces': { - scope: 'ServiceWorker', - httpsOnly: true, - entries: [] - }, - '/css/properties': { - scope: 'CSS', - httpsOnly: false, - entries: [] - } - }, - individual: { - '/api/AbortController': [ +const endpoints = { + '/api/interfaces': { + scope: 'Window', + httpsOnly: false, + entries: [ 'api.AbortController', 'api.AbortController.signal' - ], - '/api/AbortController/signal': [ - 'api.AbortController.signal' ] + }, + '/api/workerinterfaces': { + scope: 'Worker', + httpsOnly: false, + entries: [ + 'api.AbortController' + ] + }, + '/api/serviceworkerinterfaces': { + scope: 'ServiceWorker', + httpsOnly: true, + entries: [] + }, + '/css/properties': { + scope: 'CSS', + httpsOnly: false, + entries: [] } }; describe('Tests', () => { const tests = new Tests({ tests: testDatabase, - endpoints: MANIFEST, + endpoints: endpoints, host: 'host.test' }); @@ -103,7 +92,7 @@ describe('Tests', () => { it('HTTP only', () => { const theseTests = new Tests({ - endpoints: MANIFEST, + endpoints: endpoints, host: 'host.test', httpOnly: true }); @@ -126,28 +115,30 @@ describe('Tests', () => { it('listMainEndpoints', () => { assert.deepEqual(tests.listMainEndpoints(), [ - '/api/interfaces', - '/api/workerinterfaces', - '/api/serviceworkerinterfaces', - '/css/properties' + ['', '/api/interfaces'], + ['', '/api/workerinterfaces'], + ['', '/api/serviceworkerinterfaces'], + ['', '/css/properties'] ]); }); it('listIndividual', () => { assert.deepEqual(tests.listIndividual(), [ ['api.AbortController', '/api/AbortController'], - ['api.AbortController.signal', '/api/AbortController/signal'] + ['api.AbortController.signal', '/api/AbortController/signal'], + ['api.FooBar', '/api/FooBar'] ]); }); it('listAllEndpoints', () => { assert.deepEqual(tests.listAllEndpoints(), [ - '/api/interfaces', - '/api/workerinterfaces', - '/api/serviceworkerinterfaces', - '/css/properties', - '/api/AbortController', - '/api/AbortController/signal' + ['', '/api/interfaces'], + ['', '/api/workerinterfaces'], + ['', '/api/serviceworkerinterfaces'], + ['', '/css/properties'], + ['api.AbortController', '/api/AbortController'], + ['api.AbortController.signal', '/api/AbortController/signal'], + ['api.FooBar', '/api/FooBar'] ]); }); From 93bdfd3d79a683f56ca9b022a25d733f66f88a9c Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 22:51:10 -0700 Subject: [PATCH 148/243] Run all scopes each test --- static/resources/harness.js | 232 +++++++++++++++++------------------- tests.js | 15 +-- 2 files changed, 114 insertions(+), 133 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index 2a698e169..a93779a7b 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -139,36 +139,31 @@ return result; } - function runCSS(callback) { - var results = []; - + function runCSS(callback, results) { var length = pending.length; for (var i = 0; i < length; i++) { - updateStatus('Testing ' + pending[i].name); - results.push(test(pending[i])); + if (pending[i].scope == 'CSS') { + updateStatus('Testing ' + pending[i].name); + results.push(test(pending[i])); + } } - pending = []; - callback(results); } - function runWindow(callback) { - var results = []; - + function runWindow(callback, results) { var length = pending.length; for (var i = 0; i < length; i++) { - updateStatus('Testing ' + pending[i].name); - results.push(test(pending[i])); + if (pending[i].scope == 'Window') { + updateStatus('Testing ' + pending[i].name); + results.push(test(pending[i])); + } } - pending = []; - callback(results); } - function runWorker(callback) { - var results = []; + function runWorker(callback, results) { var length = pending.length; var i; @@ -183,20 +178,20 @@ }; for (i = 0; i < length; i++) { - promises.push(new Promise(function(resolve) { - updateStatus('Testing ' + pending[i].name); - myWorker.postMessage(pending[i]); - - testhandlers[pending[i].name] = function(message) { - results.push(message); - resolve(); - }; - })); + if (pending[i].scope == 'Worker') { + promises.push(new Promise(function(resolve) { + updateStatus('Testing ' + pending[i].name); + myWorker.postMessage(pending[i]); + + testhandlers[pending[i].name] = function(message) { + results.push(message); + resolve(); + }; + })); + } } Promise.allSettled(promises).then(function() { - pending = []; - callback(results); }); } else { @@ -204,28 +199,26 @@ updateStatus('No worker support, skipping'); for (i = 0; i < length; i++) { - var result = { - name: pending[i].name, - result: false, - message: 'No worker support' - }; - - if (pending[i].info !== undefined) { - result.info = pending[i].info; - } + if (pending[i].scope == 'Worker') { + var result = { + name: pending[i].name, + result: false, + message: 'No worker support' + }; - results.push(result); - } + if (pending[i].info !== undefined) { + result.info = pending[i].info; + } - pending = []; + results.push(result); + } + } callback(results); } } - function runServiceWorker(callback) { - var results = []; - + function runServiceWorker(callback, results) { if ('serviceWorker' in navigator) { window.__workerCleanup().then(function() { navigator.serviceWorker.register('/resources/serviceworker.js', { @@ -242,21 +235,21 @@ var length = pending.length; for (var i = 0; i < length; i++) { - promises.push(new Promise(function(resolve) { - updateStatus('Testing ' + pending[i].name); - - reg.active.postMessage(pending[i]); - - testhandlers[pending[i].name] = function(message) { - results.push(message); - resolve(); - }; - })); + if (pending[i].scope == 'ServiceWorker') { + promises.push(new Promise(function(resolve) { + updateStatus('Testing ' + pending[i].name); + + reg.active.postMessage(pending[i]); + + testhandlers[pending[i].name] = function(message) { + results.push(message); + resolve(); + }; + })); + } } Promise.allSettled(promises).then(function() { - pending = []; - window.__workerCleanup().then(function() { callback(results); }); @@ -269,90 +262,83 @@ var length = pending.length; for (var i = 0; i < length; i++) { - var result = { - name: pending[i].name, - result: false, - message: 'No service worker support' - }; - - if (pending[i].info !== undefined) { - result.info = pending[i].info; - } + if (pending[i].scope == 'ServiceWorker') { + var result = { + name: pending[i].name, + result: false, + message: 'No service worker support' + }; - results.push(result); - } + if (pending[i].info !== undefined) { + result.info = pending[i].info; + } - pending = []; + results.push(result); + } + } callback(results); } } - function run(scope, callback) { + function run(callback) { var timeout = setTimeout(function() { updateStatus('
This test seems to be taking a long time; ' + 'it may have crashed. Check the console for errors.', true); }, 10000); - var onfinish = function(results) { - clearTimeout(timeout); - - if (callback) { - callback(results); - } else { - report(results); - } - }; - - if (scope === 'CSS') { - runCSS(onfinish); - } else if (scope === 'Window') { - runWindow(onfinish); - } else if (scope === 'Worker') { - runWorker(onfinish); - } else if (scope === 'ServiceWorker') { - runServiceWorker(onfinish); - } else { - console.error('Unknown scope specified: ' + scope); - } + runWindow(function(results) { + runWorker(function(results) { + runServiceWorker(function(results) { + runCSS(function(results) { + clearTimeout(timeout); + callback(results); + }, results); + }, results); + }, results); + }, []); } - function report(results) { - var body = JSON.stringify(results); - var client = new XMLHttpRequest(); - client.open('POST', '/api/results?for='+encodeURIComponent(location.href)); - client.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); - client.send(body); - client.onreadystatechange = function() { - if (client.readyState == 4) { - var response = JSON.parse(client.responseText); - // Navigate to the next page, or /results/ if none. - var nextURL = response.next || '/results/'; - window.location = nextURL; - } - }; + function runAndReport() { + run(function(results) { + var body = JSON.stringify(results); + var client = new XMLHttpRequest(); + client.open('POST', '/api/results?for='+encodeURIComponent(location.href)); + client.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); + client.send(body); + client.onreadystatechange = function() { + if (client.readyState == 4) { + var response = JSON.parse(client.responseText); + // Navigate to the next page, or /results/ if none. + var nextURL = response.next || '/results/'; + window.location = nextURL; + } + }; + }); } - function finishAndDisplay(results) { - var css = document.createElement('link'); - css.rel = 'stylesheet'; - css.type = 'text/css'; - css.href = '/resources/style.css'; - try { - document.head.appendChild(css); - } catch (e) { - // If the CSS fails to load, oh well - } + function runAndDisplay() { + run(function(results) { + var css = document.createElement('link'); + css.rel = 'stylesheet'; + css.type = 'text/css'; + css.href = '/resources/style.css'; + try { + document.head.appendChild(css); + } catch (e) { + // If the CSS fails to load, oh well + } - var response = ''; - for (var i=0; i' + result.result; - if (result.prefix) response += ' (' + result.prefix + ' prefix)'; - if (result.message) response += ' (' + result.message + ')'; - response += '\n' + result.info.code + ';\n\n'; - } - updateStatus(response.replace(/\n/g, '
')); + var response = ''; + for (var i=0; i' + result.result; + if (result.prefix) response += ' (' + result.prefix + ' prefix)'; + if (result.message) response += ' (' + result.message + ')'; + response += '\n' + result.info.code + ';\n\n'; + } + updateStatus(response.replace(/\n/g, '
')); + }); } // Service Worker helpers @@ -415,7 +401,7 @@ testConstructor: testConstructor, addTest: addTest, test: test, - run: run, - finishAndDisplay: finishAndDisplay + runAndDisplay: runAndDisplay, + runAndReport: runAndReport }; })(this); diff --git a/tests.js b/tests.js index e476457b8..3e92a63ce 100644 --- a/tests.js +++ b/tests.js @@ -95,8 +95,8 @@ class Tests { generateTestPage(endpoint) { const theseTests = this.getTests(endpoint); - let testScope = this.getScope(endpoint); - let individual = false; + const testScope = this.getScope(endpoint); + const individual = !(endpoint in this.endpoints); const lines = [ '', @@ -122,21 +122,16 @@ class Tests { for (const [ident, test] of Object.entries(theseTests)) { for (const scope of test.scope) { - if (!testScope) { - // Set scope to the first found scope if it's an individual test - testScope = scope; - individual = true; - } - if (scope == testScope) { + if (!testScope || scope == testScope) { lines.push(`bcd.addTest("${ident}", ${JSON.stringify(test.tests)}, "${scope}");`); } } } if (individual) { - lines.push(`bcd.run('${testScope}', bcd.finishAndDisplay);`); + lines.push(`bcd.runAndDisplay();`); } else { - lines.push(`bcd.run('${testScope}');`); + lines.push(`bcd.runAndReport();`); } lines.push('', '', ''); From f4f2ca98de0f72562f17158b490177ce5b4bd409 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 23:01:58 -0700 Subject: [PATCH 149/243] Display scope when showing results --- static/resources/harness.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index a93779a7b..837516eb7 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -203,11 +203,14 @@ var result = { name: pending[i].name, result: false, - message: 'No worker support' + message: 'No worker support', + info: { + scope: 'Worker' + } }; if (pending[i].info !== undefined) { - result.info = pending[i].info; + result.info = Object.assign({}, result.info, pending[i].info); } results.push(result); @@ -266,11 +269,14 @@ var result = { name: pending[i].name, result: false, - message: 'No service worker support' + message: 'No service worker support', + info: { + scope: 'ServiceWorker' + } }; if (pending[i].info !== undefined) { - result.info = pending[i].info; + result.info = Object.assign({}, result.info, pending[i].info); } results.push(result); @@ -332,7 +338,8 @@ var response = ''; for (var i=0; i' + result.result; + response += result.name + ' (' + result.info.scope + + ' scope): ' + result.result; if (result.prefix) response += ' (' + result.prefix + ' prefix)'; if (result.message) response += ' (' + result.message + ')'; response += '\n' + result.info.code + ';\n\n'; From 65cb6a2f9c664c87ac43b117b0e400a90fe4798a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 23:04:25 -0700 Subject: [PATCH 150/243] Update unittests --- static/resources/harness.js | 3 ++ static/unittest/test.js | 55 ++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/static/resources/harness.js b/static/resources/harness.js index 837516eb7..00629e23d 100644 --- a/static/resources/harness.js +++ b/static/resources/harness.js @@ -297,6 +297,8 @@ runWorker(function(results) { runServiceWorker(function(results) { runCSS(function(results) { + pending = []; + clearTimeout(timeout); callback(results); }, results); @@ -408,6 +410,7 @@ testConstructor: testConstructor, addTest: addTest, test: test, + run: run, runAndDisplay: runAndDisplay, runAndReport: runAndReport }; diff --git a/static/unittest/test.js b/static/unittest/test.js index dab4ef9bf..8eb58b355 100644 --- a/static/unittest/test.js +++ b/static/unittest/test.js @@ -26,44 +26,44 @@ var assert = chai.assert; describe('harness.js', function() { it('no tests', function(done) { - bcd.run('Window', function(results) { + bcd.run(function(results) { assert.isEmpty(results); done(); }); }); it('return true', function(done) { - bcd.addTest('name', [{code: 'true'}], 'test'); - bcd.run('Window', function(results) { + bcd.addTest('name', [{code: 'true'}], 'Window'); + bcd.run(function(results) { assert.deepStrictEqual(results, [{ name: 'name', result: true, - info: {code: 'true', scope: 'test'} + info: {code: 'true', scope: 'Window'} }]); done(); }); }); it('return false', function(done) { - bcd.addTest('name', [{code: 'false'}], 'test'); - bcd.run('Window', function(results) { + bcd.addTest('name', [{code: 'false'}], 'Window'); + bcd.run(function(results) { assert.deepStrictEqual(results, [{ name: 'name', result: false, - info: {code: 'false', scope: 'test'} + info: {code: 'false', scope: 'Window'} }]); done(); }); }); it('return null', function(done) { - bcd.addTest('name', [{code: 'null'}], 'test'); - bcd.run('Window', function(results) { + bcd.addTest('name', [{code: 'null'}], 'Window'); + bcd.run(function(results) { assert.deepStrictEqual(results, [{ name: 'name', result: null, message: 'returned null', - info: {code: 'null', scope: 'test'} + info: {code: 'null', scope: 'Window'} }]); done(); }); @@ -73,67 +73,66 @@ describe('harness.js', function() { if (typeof Symbol === 'undefined') { this.skip(); } - bcd.addTest('name', [{code: 'Symbol(\'bar\')'}], 'test'); - bcd.run('Window', function(results) { + bcd.addTest('name', [{code: 'Symbol(\'bar\')'}], 'Window'); + bcd.run(function(results) { assert.deepStrictEqual(results, [{ name: 'name', result: null, message: 'returned Symbol(bar)', - info: {code: 'Symbol(\'bar\')', scope: 'test'} + info: {code: 'Symbol(\'bar\')', scope: 'Window'} }]); done(); }); }); it('return undefined', function(done) { - bcd.addTest('name', [{code: 'undefined'}], 'test'); - bcd.run('Window', function(results) { + bcd.addTest('name', [{code: 'undefined'}], 'Window'); + bcd.run(function(results) { assert.deepStrictEqual(results, [{ name: 'name', result: null, message: 'returned undefined', - info: {code: 'undefined', scope: 'test'} + info: {code: 'undefined', scope: 'Window'} }]); done(); }); }); it('throw error', function(done) { - bcd.addTest('name', [{code: 'throw new Error(\'something went wrong\')'}], 'test'); - bcd.run('Window', function(results) { + bcd.addTest('name', [{code: 'throw new Error(\'something went wrong\')'}], 'Window'); + bcd.run(function(results) { assert.deepStrictEqual(results, [{ name: 'name', result: null, message: 'threw Error: something went wrong', - info: {code: 'throw new Error(\'something went wrong\')', scope: 'test'} + info: {code: 'throw new Error(\'something went wrong\')', scope: 'Window'} }]); done(); }); }); it('include info', function(done) { - var info = {'extra': 'stuff'}; - bcd.addTest('ctx', [{code: 'true'}], 'test', info); - bcd.run('Window', function(results) { + bcd.addTest('ctx', [{code: 'true'}], 'Window', {'extra': 'stuff'}); + bcd.run(function(results) { assert.deepStrictEqual(results[0].info, { - extra: 'stuff', code: 'true', scope: 'test' + extra: 'stuff', code: 'true', scope: 'Window' }); done(); }); }); it('two tests', function(done) { - bcd.addTest('first', [{code: 'true'}], 'test', {a: 1}); - bcd.addTest('second', [{code: 'false'}], 'test', {b: 2}); - bcd.run('Window', function(results) { + bcd.addTest('first', [{code: 'true'}], 'Window', {a: 1}); + bcd.addTest('second', [{code: 'false'}], 'Window', {b: 2}); + bcd.run(function(results) { assert.deepEqual(results, [{ name: 'first', result: true, - info: {code: 'true', scope: 'test', a: 1} + info: {code: 'true', scope: 'Window', a: 1} }, { name: 'second', result: false, - info: {code: 'false', scope: 'test', b: 2} + info: {code: 'false', scope: 'Window', b: 2} }]); done(); }); From b6d5e51afdfb84d07117047b891cdcdf6fdf5d36 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 23:14:13 -0700 Subject: [PATCH 151/243] Simplify code --- tests.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests.js b/tests.js index 3e92a63ce..afd3a5337 100644 --- a/tests.js +++ b/tests.js @@ -128,12 +128,7 @@ class Tests { } } - if (individual) { - lines.push(`bcd.runAndDisplay();`); - } else { - lines.push(`bcd.runAndReport();`); - } - + lines.push(individual ? 'bcd.runAndDisplay();' : 'bcd.runAndReport();'); lines.push('', '', ''); return lines.join('\n'); From e0e55c52c0346a1df9ed8bd683a6289bd930e343 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 23:53:47 -0700 Subject: [PATCH 152/243] Add additional istanbul ignore statements --- app.js | 4 ++++ build.js | 1 + 2 files changed, 5 insertions(+) diff --git a/app.js b/app.js index c54e4d923..0dcd97dfc 100644 --- a/app.js +++ b/app.js @@ -23,20 +23,24 @@ const logger = require('./logger'); const appversion = require('./package.json').version; const PORT = process.env.PORT || 8080; +/* istanbul ignore next */ const host = process.env.NODE_ENV === 'production' ? 'mdn-bcd-collector.appspot.com' : `localhost:${PORT}`; +/* istanbul ignore next */ const secrets = process.env.NODE_ENV === 'test' ? require('./secrets.sample.json') : require('./secrets.json'); // TODO: none of this setup is pretty const {CloudStorage, MemoryStorage} = require('./storage'); +/* istanbul ignore next */ const storage = process.env.NODE_ENV === 'production' ? new CloudStorage : new MemoryStorage; +/* istanbul ignore next */ const github = require('./github')( secrets.github.token ? {auth: `token ${secrets.github.token}`} : diff --git a/build.js b/build.js index 96e2dd290..e68b24ebc 100644 --- a/build.js +++ b/build.js @@ -25,6 +25,7 @@ const webref = require('./webref'); const generatedDir = path.join(__dirname, 'generated'); const manifestDir = path.join(__dirname, 'manifest'); +/* istanbul ignore next */ const prefixes = process.env.NODE_ENV === 'test' ? { // Shortened in tests for convenience api: ['', 'WebKit'], From b20b14d343ac76fd669062c8e9fa82468fe7edde Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Mon, 7 Sep 2020 23:54:00 -0700 Subject: [PATCH 153/243] Remove redundant if clause --- build.js | 1 - 1 file changed, 1 deletion(-) diff --git a/build.js b/build.js index e68b24ebc..9424e55ee 100644 --- a/build.js +++ b/build.js @@ -84,7 +84,6 @@ const getCustomSubtestsAPI = (name) => { for ( const subtest of Object.entries(customTests.api[name].__additional) ) { - if (subtest[0] == '__test') continue; subtests[subtest[0]] = `(function() {${testbase}${subtest[1]}})()`; } } From 92f132efd44d92181f1b90d446686c58000d80db Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Tue, 8 Sep 2020 00:27:09 -0700 Subject: [PATCH 154/243] Add "use HTTPS" checkbox for individual tests --- static/index.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/static/index.html b/static/index.html index c04239c94..b210c0a2a 100644 --- a/static/index.html +++ b/static/index.html @@ -21,6 +21,10 @@

mdn-bcd-collector

+
+

Note: this website is in beta; not all feature detection is accurate yet. If you find any errors, please file an issue on the GitHub page.

@@ -38,6 +42,8 @@

mdn-bcd-collector

function getTests() { var button = document.getElementById('start'); var dropdown = document.getElementById('tests'); + var secureContext = document.getElementById('secureContext'); + var secureContextBox = document.getElementById('secureContextBox'); var client = new XMLHttpRequest(); client.open('GET', '/api/tests', true); client.send(); @@ -66,8 +72,20 @@

mdn-bcd-collector

dropdown.add(option); } + dropdown.onchange = function() { + if (dropdown.selectedIndex == 0) { + secureContextBox.style.display = "none"; + } else { + secureContextBox.style.display = "block"; + } + } + button.onclick = function() { var newUrl = dropdown.options[dropdown.selectedIndex].value; + if (dropdown.selectedIndex > 0) { + var protocol = secureContext.checked ? 'https:' : 'http:'; + newUrl = protocol + '//' + window.location.host + newUrl; + } if (newUrl) window.location = newUrl; } } From f5d5141f58333caef1972fd094d6ef9e81f4c124 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Tue, 8 Sep 2020 00:30:10 -0700 Subject: [PATCH 155/243] Use Nodemon to auto-reload server on file changes --- package-lock.json | 639 ++++++++++++++++++++++++++++++++++++++++++---- package.json | 3 +- 2 files changed, 594 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index 48cc77e62..10816abba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -747,6 +747,11 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -792,6 +797,14 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, "@tokenizer/token": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", @@ -812,8 +825,7 @@ "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, "@types/cookiejar": { "version": "2.1.1", @@ -869,6 +881,11 @@ "@types/node": "*" } }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -928,6 +945,14 @@ "uri-js": "^4.2.2" } }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "requires": { + "string-width": "^3.0.0" + } + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -937,8 +962,7 @@ "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { "version": "3.2.1", @@ -953,7 +977,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1085,8 +1108,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { "version": "1.3.1", @@ -1106,8 +1128,7 @@ "binary-extensions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" }, "bit-mask": { "version": "1.0.2", @@ -1174,11 +1195,96 @@ } } }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1188,7 +1294,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -1230,6 +1335,27 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + } + } + }, "caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -1257,8 +1383,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-keys": { "version": "6.2.2", @@ -1378,7 +1503,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", - "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -1396,12 +1520,22 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -1436,6 +1570,14 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "color": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", @@ -1519,8 +1661,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "2.0.0", @@ -1682,6 +1823,14 @@ } } }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -1691,6 +1840,11 @@ "type-detect": "^4.0.0" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1706,6 +1860,11 @@ "strip-bom": "^4.0.0" } }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1765,6 +1924,11 @@ "is-obj": "^2.0.0" } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -1800,8 +1964,7 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "enabled": { "version": "2.0.0", @@ -1923,6 +2086,11 @@ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2269,7 +2437,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -2468,7 +2635,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, "optional": true }, "function-bind": { @@ -2566,7 +2732,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, "requires": { "pump": "^3.0.0" } @@ -2589,7 +2754,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -2600,6 +2764,14 @@ "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "dev": true }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "requires": { + "ini": "^1.3.5" + } + }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -2725,6 +2897,34 @@ "node-forge": "^0.9.0" } }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + } + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -2765,8 +2965,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.1", @@ -2774,6 +2973,11 @@ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, "hash-stream-validation": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", @@ -2820,6 +3024,11 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -2878,6 +3087,11 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" + }, "immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -2894,6 +3108,11 @@ "resolve-from": "^4.0.0" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -2920,6 +3139,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, "ip-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", @@ -2951,7 +3175,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "requires": { "binary-extensions": "^2.0.0" } @@ -2968,6 +3191,14 @@ "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", "dev": true }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", @@ -2983,24 +3214,30 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, "is-ip": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz", @@ -3016,11 +3253,15 @@ "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", "dev": true }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-obj": { "version": "2.0.0", @@ -3033,6 +3274,11 @@ "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", "dev": true }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==" + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -3104,6 +3350,11 @@ "is-docker": "^2.0.0" } }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3318,6 +3569,11 @@ "bignumber.js": "^9.0.0" } }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -3409,6 +3665,14 @@ "safe-buffer": "^5.0.1" } }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "requires": { + "json-buffer": "3.0.0" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -3420,6 +3684,14 @@ "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "requires": { + "package-json": "^6.3.0" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3536,6 +3808,11 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3640,6 +3917,11 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -3650,7 +3932,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3658,8 +3939,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minimist-options": { "version": "4.1.0", @@ -3837,6 +4117,46 @@ "process-on-spawn": "^1.0.0" } }, + "nodemon": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", + "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==", + "requires": { + "chokidar": "^3.2.2", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^4.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -3860,8 +4180,12 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" }, "nyc": { "version": "15.1.0", @@ -4113,6 +4437,11 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, "p-limit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", @@ -4167,6 +4496,17 @@ "release-zalgo": "^1.0.0" } }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + } + }, "pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -4249,8 +4589,7 @@ "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pkg-dir": { "version": "4.2.0", @@ -4267,6 +4606,11 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4346,6 +4690,11 @@ "resolve": "^1.11.1" } }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4394,6 +4743,14 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "pupa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", + "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", + "requires": { + "escape-goat": "^2.0.0" + } + }, "puppeteer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.2.1.tgz", @@ -4596,6 +4953,24 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } + } + }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -4670,7 +5045,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", - "dev": true, "requires": { "picomatch": "^2.0.7" } @@ -4691,6 +5065,22 @@ "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true }, + "registry-auth-token": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", + "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "requires": { + "rc": "^1.2.8" + } + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -4727,6 +5117,14 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "retry-request": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.1.1.tgz", @@ -4778,6 +5176,14 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "requires": { + "semver": "^6.3.0" + } + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -5068,7 +5474,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -5078,14 +5483,12 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -5124,7 +5527,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -5205,7 +5607,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -5299,6 +5700,11 @@ } } }, + "term-size": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", + "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==" + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -5356,11 +5762,15 @@ "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", "integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo=" }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -5396,6 +5806,14 @@ "ieee754": "^1.1.13" } }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + } + }, "trim-newlines": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", @@ -5464,6 +5882,29 @@ "through": "^2.3.8" } }, + "undefsafe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", + "requires": { + "debug": "^2.2.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -5487,6 +5928,72 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "update-notifier": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.1.tgz", + "integrity": "sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg==", + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", @@ -5496,6 +6003,14 @@ "punycode": "^2.1.0" } }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5603,6 +6118,36 @@ } } }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + } + } + }, "winston": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", diff --git a/package.json b/package.json index b2086553c..197325e5b 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "build": "node build.js", "gcp-build": "npm run build", "deploy": "gcloud app deploy", - "start": "node app.js", + "start": "nodemon app.js", "unittest": "NODE_ENV=test nyc mocha --recursive unittest", "coverage": "nyc report -r lcov && open-cli coverage/lcov-report/index.html", "test": "npm run lint && npm run unittest", @@ -38,6 +38,7 @@ "json-stable-stringify": "1.0.1", "json3": "3.3.3", "mdn-browser-compat-data": "1.0.35", + "nodemon": "^2.0.4", "slugify": "1.4.5", "ua-parser-js": "0.7.21", "unique-string": "2.0.0", From 4e3db82f05f188aa23b03bfc5ce0fdb303989d25 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Tue, 8 Sep 2020 00:39:56 -0700 Subject: [PATCH 156/243] Add Nodemon config --- nodemon.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 nodemon.json diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 000000000..445fc8c13 --- /dev/null +++ b/nodemon.json @@ -0,0 +1,4 @@ +{ + "verbose": true, + "ignore": ["static/*", "coverage/*", ".nyc_output/*"], +} From 1560873255d5d89917c3b97ccfd2831f72346aa1 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Tue, 8 Sep 2020 00:40:04 -0700 Subject: [PATCH 157/243] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 197325e5b..106350105 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "slugify": "1.4.5", "ua-parser-js": "0.7.21", "unique-string": "2.0.0", - "webref": "git://github.com/foolip/webref.git#mdn-bcd-updater-fixes", "webidl2": "23.13.0", + "webref": "git://github.com/foolip/webref.git#mdn-bcd-updater-fixes", "winston": "3.3.3" }, "devDependencies": { From a5e37b3e759421bd8f66f18312147316b0aa68d1 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Tue, 8 Sep 2020 00:40:44 -0700 Subject: [PATCH 158/243] Allow limitation of scope via scope argument --- app.js | 2 +- tests.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 0dcd97dfc..14d796d53 100644 --- a/app.js +++ b/app.js @@ -143,7 +143,7 @@ app.all('/tests/*', (req, res) => { const endpoint = `/${req.params['0']}`; if (tests.listAllEndpoints().map((item) => (item[1])).includes(endpoint)) { - res.send(tests.generateTestPage(endpoint)); + res.send(tests.generateTestPage(endpoint, req.query.scope)); } else { res.status(404).send(`Could not find tests for ${endpoint}`); } diff --git a/tests.js b/tests.js index afd3a5337..935791f11 100644 --- a/tests.js +++ b/tests.js @@ -93,11 +93,14 @@ class Tests { return e ? e.scope : ''; } - generateTestPage(endpoint) { + generateTestPage(endpoint, testScope) { const theseTests = this.getTests(endpoint); - const testScope = this.getScope(endpoint); const individual = !(endpoint in this.endpoints); + if (!testScope) { + testScope = individual ? '' : this.getScope(endpoint); + } + const lines = [ '', '', From c9bfdb0cbaa9b450e1aa12cb65fa8c5bcdae293a Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Tue, 8 Sep 2020 00:59:37 -0700 Subject: [PATCH 159/243] Add scope limitation dropdown --- static/index.html | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/static/index.html b/static/index.html index b210c0a2a..6c06c8bbb 100644 --- a/static/index.html +++ b/static/index.html @@ -22,8 +22,16 @@

mdn-bcd-collector


-