diff --git a/package.json b/package.json index e8feff1f..258a4474 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "scripts": { "test": "cross-env TS_NODE_SKIP_PROJECT=true node ./bin/c8.js mocha --timeout=10000 ./test/*.js", + "test-loader": "cross-env TS_NODE_SKIP_PROJECT=true node ./bin/c8.js mocha --timeout=10000 ./test/source-resolved-from-loader.js", "coverage": "cross-env TS_NODE_SKIP_PROJECT=true node ./bin/c8.js --check-coverage mocha --timeout=10000 ./test/*.js", "test:snap": "cross-env CHAI_JEST_SNAPSHOT_UPDATE_ALL=true npm test", "fix": "standard --fix", diff --git a/test/fixtures/all/vanilla/main.querystring-import.mjs b/test/fixtures/all/vanilla/main.querystring-import.mjs new file mode 100644 index 00000000..17e7c33d --- /dev/null +++ b/test/fixtures/all/vanilla/main.querystring-import.mjs @@ -0,0 +1,38 @@ +import module from 'node:module' + +async function resolve (moduleId, context, next) { + const result = await next(moduleId, context); + const url = new URL(result.url) + url.searchParams.set('randomSeed', Math.random()); + result.url = url.href; + return result; +} + +function load(url, context, next) { + if (url.includes('main.js')) { + const loadedId = url.replace('main.js', 'loaded.js') + + return { + shortCircuit: true, + format: 'module', + source: `import loaded from "${loadedId}";loaded()`, + }; + } + + if (url.includes('loaded.js')) { + return { + shortCircuit: true, + format: 'module', + source: 'export default () => true', + }; + } + + return next(url, context); +} + +module.register && module.register(` +data:text/javascript, +export ${encodeURIComponent(load)} +export ${encodeURIComponent(resolve)}`.slice(1)) + +export default import('./main.js?qs=1') diff --git a/test/source-resolved-from-loader.js b/test/source-resolved-from-loader.js new file mode 100644 index 00000000..ec44a08d --- /dev/null +++ b/test/source-resolved-from-loader.js @@ -0,0 +1,50 @@ +/* global describe, before, beforeEach, it */ + +const { spawnSync } = require('child_process') +const c8Path = require.resolve('../bin/c8') +const nodePath = process.execPath +const tsNodePath = './node_modules/.bin/ts-node' +const chaiJestSnapshot = require('chai-jest-snapshot') +const rimraf = require('rimraf') +const nodemodule = require('node:module') + +require('chai') + .use(chaiJestSnapshot) + .should() + +before(cb => rimraf('tmp', cb)) + +beforeEach(function () { + chaiJestSnapshot.configureUsingMochaContext(this) +}) + +;[false, true].forEach((mergeAsync) => { + const title = mergeAsync ? 'c8+loader mergeAsync' : 'c8+loader' + describe(title, () => { + if (nodemodule.register) { + it('reports coverage for query-loaded js files, with accuracy', async () => { + const { output } = spawnSync(nodePath, [ + c8Path, + '--temp-directory=tmp/vanilla-all', + '--clean=false', + '--all=true', + '--include=test/fixtures/all/vanilla/**/*.js', + '--exclude=**/*.ts', // add an exclude to avoid default excludes of test/** + `--merge-async=${mergeAsync}`, + nodePath, + '--experimental-default-type=module', + require.resolve('./fixtures/all/vanilla/main.querystring-import.mjs') + ]) + + // test fails if loaded row looks like this + // loaded.js | 100 | 100 | 100 | 100 | + output.toString('utf8') + .split('\n') + .filter(l => l.includes(' loaded.js'))[0] + .split('|').filter(l => /\d/.test(l)) + .every(l => !l.includes(100)) + .should.equal(true) + }) + } + }) +})