Skip to content

Commit

Permalink
Merge pull request #1807 from BlueCutOfficial/virtualize-implicit-tes…
Browse files Browse the repository at this point in the history
…t-scripts

Module resolver: virtualize test-support.js
  • Loading branch information
ef4 authored Apr 4, 2024
2 parents b5fd677 + 20503b1 commit 2afc470
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 49 deletions.
51 changes: 2 additions & 49 deletions packages/compat/src/compat-app-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,32 +361,6 @@ export class CompatAppBuilder {
});
}

if (type === 'implicit-test-scripts') {
// this is the traditional test-support-suffix.js
result.push({
kind: 'in-memory',
relativePath: '_testing_suffix_.js',
source: `
var runningTests=true;
if (typeof Testem !== 'undefined' && (typeof QUnit !== 'undefined' || typeof Mocha !== 'undefined')) {
Testem.hookIntoTestFramework();
}`,
});

// whether or not anybody was actually using @embroider/macros
// explicitly as an addon, we ensure its test-support file is always
// present.
if (!result.find(s => s.kind === 'on-disk' && s.sourcePath.endsWith('embroider-macros-test-support.js'))) {
result.unshift({
kind: 'on-disk',
sourcePath: require.resolve('@embroider/macros/src/vendor/embroider-macros-test-support'),
mtime: 0,
size: 0,
relativePath: 'embroider-macros-test-support.js',
});
}
}

return result;
}

Expand Down Expand Up @@ -556,10 +530,8 @@ export class CompatAppBuilder {
let testJS = this.testJSEntrypoint(appFiles, prepared);
html.insertScriptTag(html.testJavascript, testJS.relativePath, { type: 'module' });

let implicitTestScriptsAsset = this.implicitTestScriptsAsset(prepared, parentEngine);
if (implicitTestScriptsAsset) {
html.insertScriptTag(html.implicitTestScripts, implicitTestScriptsAsset.relativePath);
}
// virtual test-support.js
html.insertScriptTag(html.implicitTestScripts, '@embroider/core/test-support.js');

let implicitTestStylesAsset = this.implicitTestStylesAsset(prepared, parentEngine);
if (implicitTestStylesAsset) {
Expand Down Expand Up @@ -596,25 +568,6 @@ export class CompatAppBuilder {
return asset;
}

private implicitTestScriptsAsset(
prepared: Map<string, InternalAsset>,
application: AppFiles
): InternalAsset | undefined {
let testSupportJS = prepared.get('assets/test-support.js');
if (!testSupportJS) {
let implicitTestScripts = this.impliedAssets('implicit-test-scripts', application);
if (implicitTestScripts.length > 0) {
testSupportJS = new ConcatenatedAsset(
'assets/test-support.js',
implicitTestScripts,
this.resolvableExtensionsPattern
);
prepared.set(testSupportJS.relativePath, testSupportJS);
}
}
return testSupportJS;
}

private implicitTestStylesAsset(
prepared: Map<string, InternalAsset>,
application: AppFiles
Expand Down
23 changes: 23 additions & 0 deletions packages/core/src/module-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ export class Resolver {
request = this.handleFastbootSwitch(request);
request = await this.handleGlobalsCompat(request);
request = this.handleImplicitModules(request);
request = this.handleImplicitTestScripts(request);
request = this.handleRenaming(request);
// we expect the specifier to be app relative at this point - must be after handleRenaming
request = this.generateFastbootSwitch(request);
Expand Down Expand Up @@ -421,6 +422,28 @@ export class Resolver {
}
}

private handleImplicitTestScripts<R extends ModuleRequest>(request: R): R {
//TODO move the extra forwardslash handling out into the vite plugin
const candidates = [
'@embroider/core/test-support.js',
'/@embroider/core/test-support.js',
'./@embroider/core/test-support.js',
];

if (!candidates.includes(request.specifier)) {
return request;
}

let pkg = this.packageCache.ownerOfFile(request.fromFile);
if (pkg?.root !== this.options.engines[0].root) {
throw new Error(
`bug: found an import of ${request.specifier} in ${request.fromFile}, but this is not the top-level Ember app. The top-level Ember app is the only one that has support for @embroider/core/test-support.js. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`
);
}

return logTransition('test-support', request, request.virtualize(resolve(pkg.root, '-embroider-test-support.js')));
}

private async handleGlobalsCompat<R extends ModuleRequest>(request: R): Promise<R> {
if (isTerminal(request)) {
return request;
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/virtual-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { dirname, basename, resolve, posix, sep, join } from 'path';
import type { Resolver, AddonPackage, Package } from '.';
import { explicitRelative, extensionsPattern } from '.';
import { compile } from './js-handlebars';
import { decodeImplicitTestScripts, renderImplicitTestScripts } from './virtual-test-support';

const externalESPrefix = '/@embroider/ext-es/';
const externalCJSPrefix = '/@embroider/ext-cjs/';
Expand Down Expand Up @@ -40,6 +41,11 @@ export function virtualContent(filename: string, resolver: Resolver): VirtualCon
return renderImplicitModules(im, resolver);
}

let isImplicitTestScripts = decodeImplicitTestScripts(filename);
if (isImplicitTestScripts) {
return renderImplicitTestScripts(filename, resolver);
}

throw new Error(`not an @embroider/core virtual file: ${filename}`);
}

Expand Down
78 changes: 78 additions & 0 deletions packages/core/src/virtual-test-support.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { Package } from '@embroider/shared-internals';
import type { V2AddonPackage } from '@embroider/shared-internals/src/package';
import { readFileSync } from 'fs';
import resolve from 'resolve';
import type { Engine } from './app-files';
import type { Resolver } from './module-resolver';
import type { VirtualContentResult } from './virtual-content';

export function decodeImplicitTestScripts(filename: string): boolean {
return filename.endsWith('-embroider-test-support.js');
}

export function renderImplicitTestScripts(filename: string, resolver: Resolver): VirtualContentResult {
const owner = resolver.packageCache.ownerOfFile(filename);
if (!owner) {
throw new Error(`Failed to find a valid owner for ${filename}`);
}
return { src: getTestSupport(owner, resolver), watches: [] };
}

function getTestSupport(owner: Package, resolver: Resolver): string {
let engineConfig = resolver.owningEngine(owner);
let engine: Engine = {
package: owner,
addons: new Map(
engineConfig.activeAddons.map(addon => [
resolver.packageCache.get(addon.root) as V2AddonPackage,
addon.canResolveFromFile,
])
),
isApp: true,
modulePrefix: resolver.options.modulePrefix,
appRelativePath: 'NOT_USED_DELETE_ME',
};

return generateTestSupport(engine);
}

function generateTestSupport(engine: Engine): string {
// Add classic addons test-support
let result: string[] = impliedAddonTestSupport(engine);
let hasEmbroiderMacrosTestSupport = result.find(sourcePath =>
sourcePath.endsWith('embroider-macros-test-support.js')
);
result = result.map((sourcePath: string): string => {
let source = readFileSync(sourcePath);
return `${source}`;
});

// Add _testing_suffix_.js
result.push(`
var runningTests=true;
if (typeof Testem !== 'undefined' && (typeof QUnit !== 'undefined' || typeof Mocha !== 'undefined')) {
Testem.hookIntoTestFramework();
}`);

// whether or not anybody was actually using @embroider/macros explicitly
// as an addon, we ensure its test-support file is always present.
if (!hasEmbroiderMacrosTestSupport) {
result.unshift(`${readFileSync(require.resolve('@embroider/macros/src/vendor/embroider-macros-test-support'))}`);
}

return result.join('') as string;
}

function impliedAddonTestSupport(engine: Engine): string[] {
let result: Array<string> = [];
for (let addon of Array.from(engine.addons.keys())) {
let implicitScripts = addon.meta['implicit-test-scripts'];
if (implicitScripts) {
let options = { basedir: addon.root };
for (let mod of implicitScripts) {
result.push(resolve.sync(mod, options));
}
}
}
return result;
}
11 changes: 11 additions & 0 deletions packages/vite/src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { virtualContent, ResolverLoader } from '@embroider/core';
import { RollupModuleRequest, virtualPrefix } from './request';
import assertNever from 'assert-never';
import makeDebug from 'debug';
import { resolve } from 'path';

const debug = makeDebug('embroider:vite');

Expand Down Expand Up @@ -59,5 +60,15 @@ export function resolver(): Plugin {
return src;
}
},
buildEnd() {
this.emitFile({
type: 'asset',
fileName: '@embroider/core/test-support.js',
source: virtualContent(
resolve(resolverLoader.resolver.options.engines[0].root, '-embroider-test-support.js'),
resolverLoader.resolver
).src,
});
},
};
}

0 comments on commit 2afc470

Please sign in to comment.