UNPKG

assetgraph

Version:

An auto discovery dependency graph based optimization framework for web pages and applications

201 lines (188 loc) 6.01 kB
const urlModule = require('url'); const urlTools = require('urltools'); const parseJavaScript = require('../lib/parseJavaScript'); const escodegen = require('escodegen'); module.exports = { name: 'unexpected-assetgraph', installInto(expect) { expect.addType({ name: 'AssetGraph.asset', base: 'object', identify(obj) { return obj && obj.isAsset && obj.constructor !== Object; }, equal(a, b) { return ( a.type === b.type && a.urlOrDescription === b.urlOrDescription && (a.isText ? a.text : a.rawSrc) === (b.isText ? b.text : b.rawSrc) // && same outgoing relations ); }, inspect(asset, depth, output) { return output .text(`${asset.type}(`) .text(asset.urlOrDescription) .text(')'); }, getKeys(value) { return ['type', 'url', 'isLoaded', 'isInline', 'isRedirect']; } }); expect.addType({ name: 'AssetGraph', base: 'object', identify(obj) { return obj && obj.isAssetGraph && obj.constructor !== Object; }, inspect(assetGraph, depth, output) { output.text('AssetGraph(').nl(); assetGraph.findAssets({ isInline: false }).forEach(function(asset) { output .text( `${asset.isLoaded ? ' ' : '!'} ${urlTools.buildRelativeUrl( assetGraph.root, asset.url )}` ) .nl(); }); return output.text(')'); } }); expect.addType({ name: 'AssetGraph.relation', base: 'object', identify(obj) { return obj && obj.isRelation && obj.constructor !== Object; }, equal(a, b) { return a === b; }, inspect(relation, depth, output) { return output .text(`${relation.type}(`) .text(relation.toString()) .text(')'); }, getKeys(value) { return ['type', 'hrefType', 'href', 'crossorigin', 'canonical']; } }); expect.addAssertion( [ '<AssetGraph> to contain [no] (asset|assets) <string|object|number?>', '<AssetGraph> to contain [no] (asset|assets) <string|object|number> <number?>' ], (expect, subject, value, number) => { expect.errorMode = 'nested'; if (typeof value === 'string') { value = { type: value }; } else if (typeof value === 'number') { number = value; value = {}; } if (expect.flags.no) { return expect(subject.findAssets(value), 'to satisfy', []); } else if (typeof number === 'undefined') { number = 1; } const foundAssets = subject.findAssets(value); expect(foundAssets, 'to have length', number); if (number === 1) { return foundAssets[0]; } else { return foundAssets; } } ); expect.addAssertion( '<AssetGraph> to contain (url|urls) <string|array?>', function(expect, subject, urls) { if (!Array.isArray(urls)) { urls = [urls]; } urls = urls.map(url => new urlModule.URL(url, subject.root).toString()); expect.errorMode = 'nested'; urls.forEach(function(url) { expect(subject.findAssets({ url }), 'to have length', 1); }); } ); expect.addAssertion( '<AssetGraph> to contain [no] (relation|relations) <string|object|number?>', function(expect, subject, queryObj) { let number; if (typeof queryObj === 'string') { queryObj = { type: queryObj }; } else if (typeof queryObj === 'number') { number = queryObj; queryObj = {}; } if (expect.flags.no) { number = 0; } else if (typeof number === 'undefined') { number = 1; } expect.errorMode = 'nested'; const foundRelations = subject.findRelations(queryObj); expect(foundRelations, 'to have length', number); if (number === 1) { return foundRelations[0]; } else { return foundRelations; } } ); expect.addAssertion( '<AssetGraph> to contain [no] (relation|relations) [including unresolved] <string|object|number> <number?>', function(expect, subject, queryObj, number) { if (typeof queryObj === 'string') { queryObj = { type: queryObj }; } else if (typeof queryObj === 'number') { number = queryObj; queryObj = {}; } if (expect.flags.no) { number = 0; } else if (typeof number === 'undefined') { number = 1; } expect.errorMode = 'nested'; expect( subject.findRelations(queryObj, expect.flags['including unresolved']), 'to have length', number ); } ); function toAst(stringOrAssetOrFunctionOrAst) { if (typeof stringOrAssetOrFunctionOrAst === 'string') { return parseJavaScript(stringOrAssetOrFunctionOrAst); } else if (stringOrAssetOrFunctionOrAst.isAsset) { return stringOrAssetOrFunctionOrAst.parseTree; } else if (typeof stringOrAssetOrFunctionOrAst === 'function') { return { type: 'Program', body: parseJavaScript(`!${stringOrAssetOrFunctionOrAst.toString()}`) .body[0].expression.argument.body.body }; } else { return stringOrAssetOrFunctionOrAst; } } function prettyPrintAst(ast) { return escodegen.generate(ast); } expect.addAssertion( '<object|string|function|AssetGraph.asset> [not] to have the same AST as <object|string|function|AssetGraph.asset>', function(expect, subject, value) { expect( prettyPrintAst(toAst(subject)), '[not] to equal', prettyPrintAst(toAst(value)) ); } ); } };