diff --git a/packages/vite/index.d.ts b/packages/vite/index.d.ts index 848505af54..6661eff57b 100644 --- a/packages/vite/index.d.ts +++ b/packages/vite/index.d.ts @@ -6,3 +6,4 @@ export * from './src/template-tag.js'; export * from './src/optimize-deps.js'; export * from './src/assets.js'; export * from './src/build.js'; +export * from './src/content-for.js'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4522d99c77..21fc37a807 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1992,159 +1992,6 @@ importers: specifier: workspace:* version: link:../../packages/addon-shim - tests/vite-app: - devDependencies: - '@babel/core': - specifier: ^7.23.6 - version: 7.23.9 - '@babel/eslint-parser': - specifier: ^7.22.5 - version: 7.23.10(@babel/core@7.23.9)(eslint@8.57.0) - '@babel/plugin-proposal-decorators': - specifier: ^7.23.6 - version: 7.23.9(@babel/core@7.23.9) - '@ember/optional-features': - specifier: ^2.0.0 - version: 2.1.0 - '@ember/string': - specifier: ^3.1.1 - version: 3.1.1 - '@ember/test-helpers': - specifier: ^3.0.3 - version: 3.3.0(ember-source@5.7.0-beta.1) - '@embroider/compat': - specifier: workspace:* - version: link:../../packages/compat - '@embroider/core': - specifier: workspace:* - version: link:../../packages/core - '@embroider/vite': - specifier: workspace:* - version: link:../../packages/vite - '@glimmer/component': - specifier: ^1.1.2 - version: 1.1.2(@babel/core@7.23.9) - '@glimmer/tracking': - specifier: ^1.1.2 - version: 1.1.2 - '@rollup/plugin-babel': - specifier: ^5.3.1 - version: 5.3.1(@babel/core@7.23.9)(rollup@3.29.4) - broccoli-asset-rev: - specifier: ^3.0.0 - version: 3.0.0 - concurrently: - specifier: ^8.2.0 - version: 8.2.2 - ember-auto-import: - specifier: ^2.6.3 - version: 2.7.2(@glint/template@1.3.0)(webpack@5.90.3) - ember-cli: - specifier: ~5.0.0 - version: 5.0.0 - ember-cli-app-version: - specifier: ^6.0.0 - version: 6.0.1(ember-source@5.7.0-beta.1) - ember-cli-babel: - specifier: ^8.2.0 - version: 8.2.0(@babel/core@7.23.9) - ember-cli-clean-css: - specifier: ^2.0.0 - version: 2.0.1 - ember-cli-dependency-checker: - specifier: ^3.3.1 - version: 3.3.2(ember-cli@5.0.0) - ember-cli-htmlbars: - specifier: ^6.2.0 - version: 6.3.0 - ember-cli-inject-live-reload: - specifier: ^2.1.0 - version: 2.1.0 - ember-cli-sri: - specifier: ^2.1.1 - version: 2.1.1 - ember-cli-terser: - specifier: ^4.0.2 - version: 4.0.2 - ember-load-initializers: - specifier: ^2.1.2 - version: 2.1.2(@babel/core@7.23.9) - ember-modifier: - specifier: ^4.1.0 - version: 4.1.0(ember-source@5.7.0-beta.1) - ember-page-title: - specifier: ^7.0.0 - version: 7.0.0 - ember-qunit: - specifier: ^7.0.0 - version: 7.0.0(@ember/test-helpers@3.3.0)(ember-source@5.7.0-beta.1)(qunit@2.20.1) - ember-resolver: - specifier: ^10.1.0 - version: 10.1.1(@ember/string@3.1.1)(ember-source@5.7.0-beta.1) - ember-source: - specifier: 5.7.0-beta.1 - version: 5.7.0-beta.1(@babel/core@7.23.9)(@glimmer/component@1.1.2) - ember-template-lint: - specifier: ^5.10.3 - version: 5.13.0 - ember-welcome-page: - specifier: ^7.0.2 - version: 7.0.2 - eslint: - specifier: ^8.42.0 - version: 8.57.0 - eslint-config-prettier: - specifier: ^8.8.0 - version: 8.10.0(eslint@8.57.0) - eslint-plugin-ember: - specifier: ^11.8.0 - version: 11.12.0(eslint@8.57.0) - eslint-plugin-n: - specifier: ^16.0.0 - version: 16.6.2(eslint@8.57.0) - eslint-plugin-prettier: - specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.57.0)(prettier@2.8.8) - eslint-plugin-qunit: - specifier: ^7.3.4 - version: 7.3.4(eslint@8.57.0) - js-reporters: - specifier: ^2.1.0 - version: 2.1.0 - loader.js: - specifier: ^4.7.0 - version: 4.7.0 - prettier: - specifier: ^2.8.8 - version: 2.8.8 - puppeteer-chromium-resolver: - specifier: ^21.0.0 - version: 21.0.0 - qunit: - specifier: ^2.19.4 - version: 2.20.1 - qunit-dom: - specifier: ^2.0.0 - version: 2.0.0 - stylelint: - specifier: ^15.7.0 - version: 15.11.0(typescript@5.2.2) - stylelint-config-standard: - specifier: ^33.0.0 - version: 33.0.0(stylelint@15.11.0) - stylelint-prettier: - specifier: ^3.0.0 - version: 3.0.0(prettier@2.8.8)(stylelint@15.11.0) - tracked-built-ins: - specifier: ^3.1.1 - version: 3.3.0 - typescript: - specifier: ^5.1.6 - version: 5.2.2 - vite: - specifier: ^5.0.9 - version: 5.1.4 - types/broccoli: {} types/broccoli-concat: @@ -5686,28 +5533,6 @@ packages: - webpack dev: true - /@ember/test-helpers@3.3.0(ember-source@5.7.0-beta.1): - resolution: {integrity: sha512-HEI28wtjnQuEj9+DstHUEEKPtqPAEVN9AAVr4EifVCd3DyEDy0m6hFT4qbap1WxAIktLja2QXGJg50lVWzZc5g==} - engines: {node: 16.* || >= 18} - peerDependencies: - ember-source: ^4.0.0 || ^5.0.0 - dependencies: - '@ember/test-waiters': 3.1.0 - '@embroider/macros': 1.13.5(@glint/template@1.3.0) - '@simple-dom/interface': 1.4.0 - broccoli-debug: 0.6.5 - broccoli-funnel: 3.0.8 - dom-element-descriptors: 0.5.0 - ember-auto-import: 2.7.2(@glint/template@1.3.0)(webpack@5.90.3) - ember-cli-babel: 7.26.11 - ember-cli-htmlbars: 6.3.0 - ember-source: 5.7.0-beta.1(@babel/core@7.23.9)(@glimmer/component@1.1.2) - transitivePeerDependencies: - - '@glint/template' - - supports-color - - webpack - dev: true - /@ember/test-waiters@3.1.0: resolution: {integrity: sha512-bb9h95ktG2wKY9+ja1sdsFBdOms2lB19VWs8wmNpzgHv1NCetonBoV5jHBV4DHt0uS1tg9z66cZqhUVlYs96KQ==} engines: {node: 10.* || 12.* || >= 14.*} @@ -13395,19 +13220,6 @@ packages: - supports-color dev: true - /ember-cli-app-version@6.0.1(ember-source@5.7.0-beta.1): - resolution: {integrity: sha512-XA1FwkWA5QytmWF0jcJqEr3jcZoiCl9Fb33TZgOVfClL7Voxe+/RwzISEprBRQgbf7j8z1xf8/RJCKfclUy3rQ==} - engines: {node: 14.* || 16.* || >= 18} - peerDependencies: - ember-source: ^3.28.0 || >= 4.0.0 - dependencies: - ember-cli-babel: 7.26.11 - ember-source: 5.7.0-beta.1(@babel/core@7.23.9)(@glimmer/component@1.1.2) - git-repo-info: 2.1.1 - transitivePeerDependencies: - - supports-color - dev: true - /ember-cli-babel-plugin-helpers@1.1.1: resolution: {integrity: sha512-sKvOiPNHr5F/60NLd7SFzMpYPte/nnGkq/tMIfXejfKHIhaiIkYFqX8Z9UFTKWLLn+V7NOaby6niNPZUdvKCRw==} engines: {node: 6.* || 8.* || >= 10.*} @@ -15494,22 +15306,6 @@ packages: - supports-color dev: true - /ember-modifier@4.1.0(ember-source@5.7.0-beta.1): - resolution: {integrity: sha512-YFCNpEYj6jdyy3EjslRb2ehNiDvaOrXTilR9+ngq+iUqSHYto2zKV0rleiA1XJQ27ELM1q8RihT29U6Lq5EyqQ==} - peerDependencies: - ember-source: '*' - peerDependenciesMeta: - ember-source: - optional: true - dependencies: - '@embroider/addon-shim': 1.8.7 - ember-cli-normalize-entity-name: 1.0.0 - ember-cli-string-utils: 1.1.0 - ember-source: 5.7.0-beta.1(@babel/core@7.23.9)(@glimmer/component@1.1.2) - transitivePeerDependencies: - - supports-color - dev: true - /ember-named-blocks-polyfill@0.2.5: resolution: {integrity: sha512-OVMxzkfqJrEvmiky7gFzmuTaImCGm7DOudHWTdMBPO7E+dQSunrcRsJMgO9ZZ56suqBIz/yXbEURrmGS+avHxA==} engines: {node: 10.* || >= 12} @@ -15697,32 +15493,6 @@ packages: - webpack dev: true - /ember-qunit@7.0.0(@ember/test-helpers@3.3.0)(ember-source@5.7.0-beta.1)(qunit@2.20.1): - resolution: {integrity: sha512-KhrndHYEXsHnXvmsGyJLJQ6VCudXaRs5dzPZBsdttZJIhsB6PmYAvq2Q+mh3GRDT/59T/sRDrB3FD3/lATS8aA==} - engines: {node: 16.* || >= 18} - peerDependencies: - '@ember/test-helpers': '>=3.0.3' - ember-source: '>=4.0.0' - qunit: ^2.13.0 - dependencies: - '@ember/test-helpers': 3.3.0(ember-source@5.7.0-beta.1) - broccoli-funnel: 3.0.8 - broccoli-merge-trees: 3.0.2 - common-tags: 1.8.2 - ember-auto-import: 2.7.2(@glint/template@1.3.0)(webpack@5.90.3) - ember-cli-babel: 7.26.11 - ember-cli-test-loader: 3.1.0 - ember-source: 5.7.0-beta.1(@babel/core@7.23.9)(@glimmer/component@1.1.2) - qunit: 2.20.1 - resolve-package-path: 4.0.3 - silent-error: 1.1.1 - validate-peer-dependencies: 2.2.0 - transitivePeerDependencies: - - '@glint/template' - - supports-color - - webpack - dev: true - /ember-qunit@8.0.2(@ember/test-helpers@3.3.0)(@glint/template@1.3.0)(ember-source@5.3.0)(qunit@2.20.1): resolution: {integrity: sha512-Rf60jeUTWNsF3Imf/FLujW/B/DFmKVXKmXO1lirTXjpertKfwRhp/3MnN8a/U/WyodTIsERkInGT1IqTtphCdQ==} peerDependencies: @@ -15814,23 +15584,6 @@ packages: - supports-color dev: true - /ember-resolver@10.1.1(@ember/string@3.1.1)(ember-source@5.7.0-beta.1): - resolution: {integrity: sha512-y1zzn6C4YGJui+tJzcCKlsf1oSOSVAkRrvmg8OwqVIKnALKKb9ihx2qLCslHg8x0wJvJgMtDMXgrczvQrZW0Lw==} - engines: {node: 14.* || 16.* || >= 18} - peerDependencies: - '@ember/string': ^3.0.1 - ember-source: ^4.8.3 || >= 5.0.0 - peerDependenciesMeta: - ember-source: - optional: true - dependencies: - '@ember/string': 3.1.1 - ember-cli-babel: 7.26.11 - ember-source: 5.7.0-beta.1(@babel/core@7.23.9)(@glimmer/component@1.1.2) - transitivePeerDependencies: - - supports-color - dev: true - /ember-resolver@11.0.1(ember-source@5.3.0): resolution: {integrity: sha512-ucBk3oM+PR+AfYoSUXeQh8cDQS1sSiEKp4Pcgbew5cFMSqPxJfqd1zyZsfQKNTuyubeGmWxBOyMVSTvX2LeCyg==} engines: {node: 14.* || 16.* || >= 18} @@ -16253,67 +16006,6 @@ packages: - webpack dev: true - /ember-source@5.7.0-beta.1(@babel/core@7.23.9)(@glimmer/component@1.1.2): - resolution: {integrity: sha512-r8Leu1ZbxiZAxmonRiZNBlvMaxhW0MR2Om97KfppRc82wAMAvqa3Qz+vyNHL2F4b00ckjNNLfanp7gO08Lq2GA==} - engines: {node: '>= 16.*'} - peerDependencies: - '@glimmer/component': ^1.1.2 - dependencies: - '@babel/helper-module-imports': 7.22.15 - '@ember/edition-utils': 1.2.0 - '@glimmer/compiler': 0.87.1 - '@glimmer/component': 1.1.2(@babel/core@7.23.9) - '@glimmer/destroyable': 0.87.1 - '@glimmer/env': 0.1.7 - '@glimmer/global-context': 0.87.1 - '@glimmer/interfaces': 0.87.1 - '@glimmer/manager': 0.87.1 - '@glimmer/node': 0.87.1 - '@glimmer/opcode-compiler': 0.87.1 - '@glimmer/owner': 0.87.1 - '@glimmer/program': 0.87.1 - '@glimmer/reference': 0.87.1 - '@glimmer/runtime': 0.87.1 - '@glimmer/syntax': 0.87.1 - '@glimmer/util': 0.87.1 - '@glimmer/validator': 0.87.1 - '@glimmer/vm': 0.87.1 - '@glimmer/vm-babel-plugins': 0.87.1(@babel/core@7.23.9) - '@simple-dom/interface': 1.4.0 - babel-plugin-debug-macros: 0.3.4(@babel/core@7.23.9) - babel-plugin-ember-template-compilation: 2.2.1 - babel-plugin-filter-imports: 4.0.0 - backburner.js: 2.8.0 - broccoli-concat: 4.2.5 - broccoli-debug: 0.6.5 - broccoli-file-creator: 2.1.1 - broccoli-funnel: 3.0.8 - broccoli-merge-trees: 4.2.0 - chalk: 4.1.2 - ember-auto-import: 2.7.2(@glint/template@1.3.0)(webpack@5.90.3) - ember-cli-babel: 7.26.11 - ember-cli-get-component-path-option: 1.0.0 - ember-cli-is-package-missing: 1.0.0 - ember-cli-normalize-entity-name: 1.0.0 - ember-cli-path-utils: 1.0.0 - ember-cli-string-utils: 1.1.0 - ember-cli-typescript-blueprint-polyfill: 0.1.0 - ember-cli-version-checker: 5.1.2 - ember-router-generator: 2.0.0 - inflection: 2.0.1 - route-recognizer: 0.3.4 - router_js: 8.0.3(route-recognizer@0.3.4) - semver: 7.6.0 - silent-error: 1.1.1 - simple-html-tokenizer: 0.5.11 - transitivePeerDependencies: - - '@babel/core' - - '@glint/template' - - rsvp - - supports-color - - webpack - dev: true - /ember-source@5.8.0-beta.1(@babel/core@7.23.9)(webpack@5.90.3): resolution: {integrity: sha512-UxvbEu7is7rl797D4SybwFOy+O6PeXNcN/IKSHcBAc4SGOoUQZ+UNFHZveWedX5SdYbnN/miziDD3lmo2rzCQg==} engines: {node: '>= 16.*'} @@ -16580,15 +16272,6 @@ packages: - supports-color dev: true - /ember-welcome-page@7.0.2: - resolution: {integrity: sha512-TyaKxFIRXhODW5BTbqD/by0Gu8Z9B9AA1ki3Bzzm6fOj2b30Qlprtt+XUG52kS0zVNmxYj/WWoT0TsKiU61VOw==} - engines: {node: 14.* || 16.* || >= 18} - dependencies: - '@embroider/addon-shim': 1.8.7 - transitivePeerDependencies: - - supports-color - dev: true - /emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} @@ -25228,7 +24911,7 @@ packages: resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true peerDependencies: - browserslist: '>= 4.21.0' + browserslist: ^4.14.0 dependencies: browserslist: 4.23.0 escalade: 3.1.2 diff --git a/tests/scenarios/vite-app-dev-test.ts b/tests/scenarios/vite-app-dev-test.ts new file mode 100644 index 0000000000..a733355540 --- /dev/null +++ b/tests/scenarios/vite-app-dev-test.ts @@ -0,0 +1,289 @@ +import { appScenarios } from './scenarios'; +import type { PreparedApp } from 'scenario-tester'; +import QUnit from 'qunit'; + +const { module: Qmodule, test } = QUnit; + +appScenarios + .map('vite-app-development', project => { + project.mergeFiles({ + scripts: { + 'run-tests.mjs': ` + import child from "child_process"; + import { resolve } from "path"; + import { readdirSync, writeFileSync, rmSync } from "fs"; + import PCR from "puppeteer-chromium-resolver"; + + const __root = process.cwd(); + + async function run() { + // eslint-disable-next-line new-cap + const { puppeteer, executablePath } = await PCR({}); + console.log("[ci] starting"); + let runvite; + + async function startVite() { + await /** @type {Promise} */ ( + new Promise((fulfill) => { + runvite = child.fork( + resolve(__root, "node_modules", "vite", "bin", "vite.js"), + ["--port", "60173", "--no-open", "--force"], + { + stdio: "pipe", + } + ); + + process.on("exit", () => runvite.kill()); + + runvite.stderr.on("data", (data) => { + console.log("stderr", String(data)); + }); + + runvite.stdout.on("data", (data) => { + const chunk = String(data); + console.log("stdout", chunk); + if (chunk.includes("Local") && chunk.includes("60173")) { + fulfill(1); + } + }); + + console.log("[ci] spawning"); + }) + ); + } + + async function runTests() { + console.log("[ci] spawned"); + + const browser = await puppeteer.launch({ + headless: "new", + executablePath, + args: ["--no-sandbox", "--disable-setuid-sandbox"], + }); + + console.log("[ci] puppeteer launched"); + let unOptimizedDeps = []; + let allUrls = new Set(); + let madeRequests = {}; + let result = await /** @type {Promise} */ ( + // eslint-disable-next-line no-async-promise-executor + new Promise(async (fulfill) => { + const page = await browser.newPage(); + + page.on("pageerror", (msg) => { + console.error(msg); + fulfill(1); + }); + + function logRequest(interceptedRequest) { + const url = interceptedRequest.url(); + const initiator = interceptedRequest.initiator().url; + madeRequests[initiator] = madeRequests[initiator] || []; + + madeRequests[initiator].push(url); + allUrls.add(url); + const allow = [ + "vite/dist/client/env.mjs", + "@babel+runtime", + ".css", + "@embroider/macros", + "ember-source/ember/index.js", + ]; + + function importerAllowedUnoptimized(importer) { + // virtual modules can contain the rewritten-app location + if (allow.some((a) => url.includes(a))) { + return true; + } + return !!( + importer.includes("node_modules") && + !importer.includes("rewritten-app") + ); + } + + if ( + url.includes("node_modules") && + !url.includes("rewritten-app") && + !url.includes(".vite/deps") && + !url.includes("embroider_virtual") && + !importerAllowedUnoptimized(initiator) + ) { + console.error("url does not use optimized dep", url, initiator); + unOptimizedDeps.push(url); + } + } + page.on("request", logRequest); + + page.on("console", (msg) => { + const text = msg.text(); + const location = msg.location(); + if (text.includes("HARNESS")) { + try { + const parsed = JSON.parse(text); + if (parsed.type === "[HARNESS] done") { + return fulfill(parsed.failed > 0 ? 1 : 0); + } + } catch (e) {} + } + if (location.url?.includes(\`/qunit.js\`)) { + console.log(text); + } else { + console.debug(text); + } + }); + + await page.goto("http://localhost:60173/tests/?hidepassed&ci"); + }) + ); + + await browser.close(); + + const optmizedDeps = readdirSync("./node_modules/.vite/deps") + .filter((f) => !f.endsWith(".map")) + .filter((f) => f !== "_metadata.json") + .filter((f) => f !== "package.json"); + const allUrlsList = [...allUrls]; + const unusedOptimzedDep = optmizedDeps.filter((o) => { + return !allUrlsList.some((url) => url.includes(o)); + }); + + if (unusedOptimzedDep.length) { + console.error("has unused optmized deps", unusedOptimzedDep); + result = 1; + } + + if (unOptimizedDeps.length) { + console.error("unoptimized deps detected", unOptimizedDeps); + result = 1; + } + + return { + result, + madeRequests, + }; + } + + async function test1() { + console.log("test1"); + await startVite(); + await runTests(); + // need also test compat for other types + const applicationHbs = \` + {{page-title "ViteApp"}} + {{outlet}} + \`; + const importsTest = \` + import { test } from 'qunit'; + import * as title from 'app-template/helpers/page-title'; + test("should work", async function (assert) { + assert.ok(title.default); + }) + \`.trim(); + writeFileSync("./app/templates/application.hbs", applicationHbs); + writeFileSync("./tests/unit/imports-test.js", importsTest); + await runTests(); + await runvite.kill(); + } + + async function test2() { + console.log("test2"); + await startVite(); + await runTests(); + const importsTest = \` + import { test } from 'qunit'; + import * as title2 from '../../helpers/page-title'; + test("should work", async function (assert) { + assert.ok(title2.default); + }) + \`.trim(); + writeFileSync("./tests/unit/imports-test.js", importsTest); + await runTests(); + await runvite.kill(); + } + + async function test3() { + console.log("test3"); + await startVite(); + await runTests(); + const importsTest = \` + import { test } from 'qunit'; + import * as title3 from 'ember-page-title/helpers/page-title'; + test("should work", async function (assert) { + assert.ok(title3.default); + }) + \`.trim(); + writeFileSync("./tests/unit/imports-test.js", importsTest); + await runTests(); + await runvite.kill(); + } + + async function test4() { + console.log("test4"); + await startVite(); + await runTests(); + const importsTest = \` + import { test } from 'qunit'; + import * as title4 from '#embroider_compat/helpers/page-title'; + test("should work", async function (assert) { + assert.ok(title4.default); + }) + \`.trim(); + writeFileSync("./tests/unit/imports-test.js", importsTest); + await runTests(); + await runvite.kill(); + } + + async function test5() { + console.log("test5"); + await startVite(); + await runTests(); + const importsTest = \` + import { test } from 'qunit'; + import * as title from 'app-template/helpers/page-title'; + import * as title2 from '../../helpers/page-title'; + import * as title3 from 'ember-page-title/helpers/page-title'; + import * as title4 from '#embroider_compat/helpers/page-title'; + + test("should work", async function (assert) { + assert.ok(title.default); + assert.ok(title2.default); + assert.ok(title3.default); + assert.ok(title.default === title2.default); + assert.ok(title.default === title3.default); + assert.ok(title.default === title4.default); + }) + \`.trim(); + writeFileSync("./tests/unit/imports-test.js", importsTest); + await runTests(); + await runvite.kill(); + } + + await test1(); + await test2(); + await test3(); + await test4(); + await test5(); + } + + await run(); + + `, + }, + }); + }) + .forEachScenario(scenario => { + Qmodule(scenario.name, function (hooks) { + let app: PreparedApp; + + hooks.before(async () => { + app = await scenario.prepare(); + }); + + test(`pnpm test:ember`, async function (assert) { + // this will only hang if there is an issue + assert.timeout(5 * 60 * 1000); + let result = await app.execute('pnpm test:ember'); + assert.equal(result.exitCode, 0, result.output); + }); + }); + });