Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/macros/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
"node": "12.* || 14.* || >= 16"
},
"ember-addon": {
"version": 2,
"type": "addon",
"main": "src/ember-addon-main.js"
}
}
394 changes: 394 additions & 0 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions tests/app-template-minimal/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file is committed to git and should not contain any secrets.
#
# Vite recommends using .env.local or .env.[mode].local if you need to manage secrets
# SEE: https://vite.dev/guide/env-and-mode.html#env-files for more information.


# Default NODE_ENV with vite build --mode=test is production
NODE_ENV=development
4 changes: 2 additions & 2 deletions tests/app-template-minimal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
"scripts": {
"build": "vite build",
"build:test": "NODE_ENV=development vite build --mode development",

@NullVoxPopuli NullVoxPopuli Jul 24, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without cross-env (or the .env file), this fails on windows if invoked directly

"build:test": "vite build --mode development",
"start": "vite",
"test": "pnpm test:ember",
"test:ember": "pnpm build:test && pnpm dist:ember:test",
Expand Down Expand Up @@ -60,4 +60,4 @@
"type": "app",
"version": 2
}
}
}
47 changes: 47 additions & 0 deletions tests/scenarios/helpers/browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import puppeteer, { type Browser } from 'puppeteer-core';
import { existsSync } from 'fs';

/**
* We use puppeteer-core (rather than full puppeteer) so we don't download a
* bundled Chromium. Instead we drive whatever Chrome/Chromium is already on the
* machine — the same browser testem uses in CI. Honor the usual env overrides
* first, then fall back to the well-known install locations per platform.
*/
export function findChrome(): string {
let fromEnv = process.env.PUPPETEER_EXECUTABLE_PATH || process.env.CHROME_BIN;
if (fromEnv && existsSync(fromEnv)) {
return fromEnv;
}

let candidates = [

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be default puppeteer behavior, tbh

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(is closer to testem)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this exists because I need to visit the app and ask the DOM questions, which I am uncomfortable with forcing testem in that role

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(because isTesting() is not (always) a compiled thing, I need to assert actual runtime output)

// macOS
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Chromium.app/Contents/MacOS/Chromium',
// Linux
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
// Windows
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
];
for (let candidate of candidates) {
if (existsSync(candidate)) {
return candidate;
}
}

throw new Error(
'Could not find a Chrome/Chromium executable to drive. ' +
'Set PUPPETEER_EXECUTABLE_PATH (or CHROME_BIN) to its path.'
);
}

export async function launchBrowser(): Promise<Browser> {
return puppeteer.launch({
executablePath: findChrome(),
headless: true,
args: ['--no-sandbox', '--disable-dev-shm-usage', '--disable-gpu', '--mute-audio'],
});
}
100 changes: 100 additions & 0 deletions tests/scenarios/macro-deep-v2-addon-compat-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { appScenarios, baseV2Addon } from './scenarios';
import type { PreparedApp } from 'scenario-tester';
import QUnit from 'qunit';
import merge from 'lodash/merge';

const { module: Qmodule, test } = QUnit;

appScenarios
.only('canary')
.map('macro-deep-v2-addon-compat-istesting', project => {
let addon = baseV2Addon();
addon.pkg.name = 'macros-consumer-addon';
// an app-js initializer that re-exports a module which imports undeclared macros
(addon.pkg as any)['ember-addon']['app-js']['./initializers/macros-consumer.js'] =
'./app/initializers/macros-consumer.js';
merge(addon.files, {
app: {
initializers: {
'macros-consumer.js': `export { default } from 'macros-consumer-addon/macros-init';`,
},
},
'macros-init.js': `
import { isTesting } from '@embroider/macros';

export const isTestingAtModuleLoad = isTesting();

export default {
name: 'macros-consumer',
initialize() {},
};
`,
});

let deep = baseV2Addon();
deep.pkg.name = 'deep-macros-addon';
merge(deep.files, {
'is-testing-at-load.js': `
import { isTesting } from '@embroider/macros';

export const isTestingAtModuleLoad = isTesting();
`,
});

let intermediate = baseV2Addon();
intermediate.pkg.name = 'intermediate-addon';
intermediate.addDependency(deep);
merge(intermediate.files, {
're-export.js': `
export { isTestingAtModuleLoad } from 'deep-macros-addon/is-testing-at-load';
`,
});

project.addDevDependency(addon);
project.addDevDependency(intermediate);
project.linkDevDependency('@embroider/macros', { baseDir: __dirname });

merge(project.files, {
tests: {
unit: {
'deep-v2-addon-istesting-test.js': `
import { module, test } from 'qunit';
import { isTestingAtModuleLoad } from 'intermediate-addon/re-export';

module('Unit | deep v2 addon | isTesting at module load (compat)', function () {
test('a second-level v2 addon sees isTesting() === true when evaluated at module load', function (assert) {
assert.true(
isTestingAtModuleLoad,
'macros test-support set isTesting before the deep v2 addon module was evaluated'
);
});
});
`,
'virtual-peer-istesting-test.js': `
import { module, test } from 'qunit';
import { isTestingAtModuleLoad } from 'macros-consumer-addon/macros-init';

module('Unit | v2 addon app-js | macros virtual peer dep', function () {
test('an undeclared @embroider/macros import from a v2 addon app-tree resolves and isTesting() is true', function (assert) {
assert.true(isTestingAtModuleLoad, 'macros rehomed to the app copy + test-support enabled isTesting');
});
});
`,
},
},
});
})
.forEachScenario(scenario => {
Qmodule(scenario.name, function (hooks) {
let app: PreparedApp;

hooks.before(async () => {
app = await scenario.prepare();
});

test('pnpm test', async function (assert) {
let result = await app.execute('pnpm test');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great that it's testing the expected behaviour of the isTesting() macro in a test 👍 but we need the other side of the equation. We need something that will run the app (not in the tests) and check that some behaviour (hand wave 👋 ) is different from the test mode.

I recommend that you use the same infra that we have for testing the vite dev mode because it will run the vite dev server and you can visit the app and the tests separately and verify the behviour that way 👍

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pushed. we had no existing infra that I could find that actually looked at the output in-browser. only the CLI.

assert.equal(result.exitCode, 0, result.output);
});
});
});
Loading
Loading