From c8cea5ae83143ebd16c149ed7823b7cd9b4a5350 Mon Sep 17 00:00:00 2001 From: Chris Manson Date: Sat, 30 Aug 2025 17:50:37 +0100 Subject: [PATCH 1/6] codemod --- app/app.js | 6 +- app/config/environment.js | 3 + babel.config.cjs | 43 + ember-cli-build.js | 16 +- app/index.html => index.html | 17 +- package.json | 32 +- pnpm-lock.yaml | 1804 ++++++++++++++++------------------ testem.js | 47 +- tests/index.html | 21 +- vite.config.mjs | 17 + 10 files changed, 975 insertions(+), 1031 deletions(-) create mode 100644 app/config/environment.js create mode 100644 babel.config.cjs rename app/index.html => index.html (80%) create mode 100644 vite.config.mjs diff --git a/app/app.js b/app/app.js index 0680f1c7778..9d2d2526fb3 100644 --- a/app/app.js +++ b/app/app.js @@ -8,6 +8,8 @@ import * as Sentry from './sentry'; import './app.css'; +import compatModules from "@embroider/virtual/compat-modules"; + // eslint-disable-next-line unicorn/prefer-add-event-listener window.onerror = undefined; Sentry.init(); @@ -15,7 +17,7 @@ Sentry.init(); export default class App extends Application { modulePrefix = config.modulePrefix; podModulePrefix = config.podModulePrefix; - Resolver = Resolver; + Resolver = Resolver.withModules(compatModules); customEvents = { // prevent non-passive listeners for touchstart/touchmove events @@ -24,4 +26,4 @@ export default class App extends Application { }; } -loadInitializers(App, config.modulePrefix); +loadInitializers(App, config.modulePrefix, compatModules); diff --git a/app/config/environment.js b/app/config/environment.js new file mode 100644 index 00000000000..3dd074bf1df --- /dev/null +++ b/app/config/environment.js @@ -0,0 +1,3 @@ +import loadConfigFromMeta from '@embroider/config-meta-loader'; + +export default loadConfigFromMeta('crates-io'); diff --git a/babel.config.cjs b/babel.config.cjs new file mode 100644 index 00000000000..46f9be988ae --- /dev/null +++ b/babel.config.cjs @@ -0,0 +1,43 @@ +const { + babelCompatSupport, + templateCompatSupport, +} = require('@embroider/compat/babel'); +const scopedCSS = require("ember-scoped-css/build"); + +module.exports = { + plugins: [ + [ + 'babel-plugin-ember-template-compilation', + { + compilerPath: 'ember-source/dist/ember-template-compiler.js', + enableLegacyModules: [ + 'ember-cli-htmlbars', + 'ember-cli-htmlbars-inline-precompile', + 'htmlbars-inline-precompile', + ], + transforms: [...templateCompatSupport(), scopedCSS.templatePlugin({})], + }, + ], + [ + 'module:decorator-transforms', + { + runtime: { + import: require.resolve('decorator-transforms/runtime-esm'), + }, + }, + ], + [ + '@babel/plugin-transform-runtime', + { + absoluteRuntime: __dirname, + useESModules: true, + regenerator: false, + }, + ], + ...babelCompatSupport(), + ], + + generatorOpts: { + compact: false, + }, +}; diff --git a/ember-cli-build.js b/ember-cli-build.js index a231bd84d37..a998e5822c6 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -1,8 +1,15 @@ -'use strict'; - +'use strict';; const EmberApp = require('ember-cli/lib/broccoli/ember-app'); -module.exports = function (defaults) { +const { + compatBuild +} = require("@embroider/compat"); + +module.exports = async function(defaults) { + const { + buildOnce + } = await import("@embroider/vite"); + let env = EmberApp.env(); let isProd = env === 'production'; @@ -66,8 +73,7 @@ module.exports = function (defaults) { // app.import('node_modules/normalize.css/normalize.css'); app.import('vendor/qunit.css', { type: 'test' }); - const { Webpack } = require('@embroider/webpack'); - return require('@embroider/compat').compatBuild(app, Webpack, { + return compatBuild(app, buildOnce, { extraPublicTrees, staticAddonTrees: true, staticAddonTestSupportTrees: true, diff --git a/app/index.html b/index.html similarity index 80% rename from app/index.html rename to index.html index d87a0a03689..198cd3d66db 100644 --- a/app/index.html +++ b/index.html @@ -9,8 +9,8 @@ {{content-for 'head'}} - - + + @@ -28,7 +28,9 @@ - + - {{content-for 'body'}} + {{content-for "body"}} @@ -49,6 +49,6 @@ Application.create(environment.APP); - {{content-for 'body-footer'}} + {{content-for "body-footer"}} From da7feac01e5ad317dd1a89c056a101022b9e6327 Mon Sep 17 00:00:00 2001 From: Chris Manson Date: Sat, 30 Aug 2025 18:19:30 +0100 Subject: [PATCH 4/6] get tests running --- tests/acceptance/read-only-mode-test.js | 2 +- tests/components/download-graph-test.gjs | 6 ++-- tests/test-helper.js | 37 ++++++++++++++---------- tests/utils/license-test.js | 2 +- tests/utils/search-test.js | 2 +- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/tests/acceptance/read-only-mode-test.js b/tests/acceptance/read-only-mode-test.js index bca05656beb..1159742c460 100644 --- a/tests/acceptance/read-only-mode-test.js +++ b/tests/acceptance/read-only-mode-test.js @@ -5,7 +5,7 @@ import { http, HttpResponse } from 'msw'; import { setupApplicationTest } from 'crates-io/tests/helpers'; -import { AjaxError } from '../../utils/ajax'; +import { AjaxError } from 'crates-io/utils/ajax'; module('Acceptance | Read-only Mode', function (hooks) { setupApplicationTest(hooks); diff --git a/tests/components/download-graph-test.gjs b/tests/components/download-graph-test.gjs index 4ea36e0b2f9..3a4bf074866 100644 --- a/tests/components/download-graph-test.gjs +++ b/tests/components/download-graph-test.gjs @@ -11,9 +11,9 @@ import { setupWindowMock } from 'ember-window-mock/test-support'; import DownloadGraph from 'crates-io/components/download-graph'; import { setupRenderingTest } from 'crates-io/tests/helpers'; -import { toChartData } from '../../components/download-graph'; -import ChartJsLoader from '../../services/chartjs'; -import { setupFakeTimers } from '../helpers/fake-timers'; +import { toChartData } from 'crates-io/components/download-graph'; +import ChartJsLoader from 'crates-io/services/chartjs'; +import { setupFakeTimers } from '../helpers/fake-timers.js'; module('Component | DownloadGraph', function (hooks) { setupRenderingTest(hooks); diff --git a/tests/test-helper.js b/tests/test-helper.js index 0e41823d0aa..89bc5c548dd 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -1,22 +1,27 @@ -import { setApplication } from '@ember/test-helpers'; -import start from 'ember-exam/test-support/start'; -import * as QUnit from 'qunit'; - +// TODO re-enable ember exam +import emberExamStart from 'ember-exam/test-support/start'; import { forceModulesToBeLoaded, sendCoverage } from 'ember-cli-code-coverage/test-support'; -import { setup } from 'qunit-dom'; - -import Application from '../app'; -import config from '../config/environment'; import registerMatchJsonAssertion from './helpers/match-json'; -setup(QUnit.assert); -registerMatchJsonAssertion(QUnit.assert); -setApplication(Application.create(config.APP)); +import Application from 'crates-io/app'; +import config from 'crates-io/config/environment'; +import * as QUnit from 'qunit'; +import { setApplication } from '@ember/test-helpers'; +import { setup } from 'qunit-dom'; +import { start as qunitStart, setupEmberOnerrorValidation } from 'ember-qunit'; + +export function start() { + setApplication(Application.create(config.APP)); + + setup(QUnit.assert); + registerMatchJsonAssertion(QUnit.assert); + setupEmberOnerrorValidation(); -QUnit.done(async function () { - forceModulesToBeLoaded(); - await sendCoverage(); -}); + QUnit.done(async function () { + forceModulesToBeLoaded(); + await sendCoverage(); + }); -start(); + qunitStart(); +} diff --git a/tests/utils/license-test.js b/tests/utils/license-test.js index c1514e02141..796c864d894 100644 --- a/tests/utils/license-test.js +++ b/tests/utils/license-test.js @@ -1,6 +1,6 @@ import { module, test } from 'qunit'; -import { parseLicense } from '../../utils/license'; +import { parseLicense } from 'crates-io/utils/license'; module('parseLicense()', function () { const TESTS = [ diff --git a/tests/utils/search-test.js b/tests/utils/search-test.js index ba59b68ac1d..c551f9e0e79 100644 --- a/tests/utils/search-test.js +++ b/tests/utils/search-test.js @@ -1,6 +1,6 @@ import { module, test } from 'qunit'; -import { processSearchQuery } from '../../utils/search'; +import { processSearchQuery } from 'crates-io/utils/search'; module('processSearchQuery()', function () { const TESTS = [ From 6131c86401568cf9f4b69921d2b26de520837709 Mon Sep 17 00:00:00 2001 From: Chris Manson Date: Sun, 31 Aug 2025 11:42:28 +0100 Subject: [PATCH 5/6] fix lint --- app/app.js | 3 +-- app/components/version-list/row.gjs | 1 + babel.config.cjs | 7 ++----- ember-cli-build.js | 13 ++++--------- eslint.config.mjs | 14 ++------------ package.json | 2 -- pnpm-lock.yaml | 3 --- tests/acceptance/read-only-mode-test.js | 1 - tests/components/download-graph-test.gjs | 4 ++-- vite.config.mjs | 4 ++-- 10 files changed, 14 insertions(+), 38 deletions(-) diff --git a/app/app.js b/app/app.js index 9d2d2526fb3..007bc581fa7 100644 --- a/app/app.js +++ b/app/app.js @@ -1,5 +1,6 @@ import Application from '@ember/application'; +import compatModules from '@embroider/virtual/compat-modules'; import loadInitializers from 'ember-load-initializers'; import Resolver from 'ember-resolver'; @@ -8,8 +9,6 @@ import * as Sentry from './sentry'; import './app.css'; -import compatModules from "@embroider/virtual/compat-modules"; - // eslint-disable-next-line unicorn/prefer-add-event-listener window.onerror = undefined; Sentry.init(); diff --git a/app/components/version-list/row.gjs b/app/components/version-list/row.gjs index 0d558133f9b..372935c66eb 100644 --- a/app/components/version-list/row.gjs +++ b/app/components/version-list/row.gjs @@ -27,6 +27,7 @@ import prettyBytes from 'crates-io/helpers/pretty-bytes'; // TODO fix this - throws a vite error // import styles from './row.css'; +const styles = {}; export default class VersionRow extends Component { @service session; diff --git a/babel.config.cjs b/babel.config.cjs index 46f9be988ae..078f3496df1 100644 --- a/babel.config.cjs +++ b/babel.config.cjs @@ -1,8 +1,5 @@ -const { - babelCompatSupport, - templateCompatSupport, -} = require('@embroider/compat/babel'); -const scopedCSS = require("ember-scoped-css/build"); +const { babelCompatSupport, templateCompatSupport } = require('@embroider/compat/babel'); +const scopedCSS = require('ember-scoped-css/build'); module.exports = { plugins: [ diff --git a/ember-cli-build.js b/ember-cli-build.js index a998e5822c6..54f05817cb4 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -1,14 +1,9 @@ -'use strict';; +'use strict'; +const { compatBuild } = require('@embroider/compat'); const EmberApp = require('ember-cli/lib/broccoli/ember-app'); -const { - compatBuild -} = require("@embroider/compat"); - -module.exports = async function(defaults) { - const { - buildOnce - } = await import("@embroider/vite"); +module.exports = async function (defaults) { + const { buildOnce } = await import('@embroider/vite'); let env = EmberApp.env(); let isProd = env === 'production'; diff --git a/eslint.config.mjs b/eslint.config.mjs index 5333c53b257..6a1572b86c5 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -72,17 +72,6 @@ export default [ parserOptions: { requireConfigFile: false, - - babelOptions: { - plugins: [ - [ - '@babel/plugin-proposal-decorators', - { - decoratorsBeforeExport: true, - }, - ], - ], - }, }, }, @@ -180,7 +169,8 @@ export default [ 'eslint.config.mjs', '**/.template-lintrc.js', '**/ember-cli-build.js', - '**/testem.js', + '**/testem.cjs', + '**/babel.config.cjs', 'blueprints/*/index.js', 'config/**/*.js', 'lib/*/index.js', diff --git a/package.json b/package.json index 9959a90a32b..e60420dcbfd 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "@axe-core/playwright": "4.10.2", "@babel/core": "7.28.3", "@babel/eslint-parser": "7.28.0", - "@babel/plugin-proposal-decorators": "7.28.0", "@babel/plugin-transform-runtime": "^7.26.9", "@crates-io/msw": "workspace:*", "@ember/optional-features": "2.2.0", @@ -201,7 +200,6 @@ "./tests/*": "./tests/*", "./*": "./app/*" }, - "packageManager": "pnpm@10.15.0+sha512.486ebc259d3e999a4e8691ce03b5cac4a71cbeca39372a9b762cb500cfdf0873e2cb16abe3d951b1ee2cf012503f027b98b6584e4df22524e0c7450d9ec7aa7b", "ember-addon": { "type": "app", "version": 2 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 860af80f8e9..aab9b7fe6a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,9 +56,6 @@ importers: '@babel/eslint-parser': specifier: 7.28.0 version: 7.28.0(@babel/core@7.28.3)(eslint@9.34.0(jiti@1.21.7)) - '@babel/plugin-proposal-decorators': - specifier: 7.28.0 - version: 7.28.0(@babel/core@7.28.3) '@babel/plugin-transform-runtime': specifier: ^7.26.9 version: 7.28.3(@babel/core@7.28.3) diff --git a/tests/acceptance/read-only-mode-test.js b/tests/acceptance/read-only-mode-test.js index 1159742c460..1248ddf0f1d 100644 --- a/tests/acceptance/read-only-mode-test.js +++ b/tests/acceptance/read-only-mode-test.js @@ -4,7 +4,6 @@ import { module, test } from 'qunit'; import { http, HttpResponse } from 'msw'; import { setupApplicationTest } from 'crates-io/tests/helpers'; - import { AjaxError } from 'crates-io/utils/ajax'; module('Acceptance | Read-only Mode', function (hooks) { diff --git a/tests/components/download-graph-test.gjs b/tests/components/download-graph-test.gjs index 3a4bf074866..81d4f0d9045 100644 --- a/tests/components/download-graph-test.gjs +++ b/tests/components/download-graph-test.gjs @@ -9,10 +9,10 @@ import window from 'ember-window-mock'; import { setupWindowMock } from 'ember-window-mock/test-support'; import DownloadGraph from 'crates-io/components/download-graph'; -import { setupRenderingTest } from 'crates-io/tests/helpers'; - import { toChartData } from 'crates-io/components/download-graph'; import ChartJsLoader from 'crates-io/services/chartjs'; +import { setupRenderingTest } from 'crates-io/tests/helpers'; + import { setupFakeTimers } from '../helpers/fake-timers.js'; module('Component | DownloadGraph', function (hooks) { diff --git a/vite.config.mjs b/vite.config.mjs index 99d78bd0dae..02a4d520b58 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -1,7 +1,7 @@ -import { defineConfig } from 'vite'; -import { extensions, classicEmberSupport, ember } from '@embroider/vite'; +import { classicEmberSupport, ember, extensions } from '@embroider/vite'; import { babel } from '@rollup/plugin-babel'; import { scopedCSS } from 'ember-scoped-css/vite'; +import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ From d0a9140cb88f5d211fb77e21a21d581a340e1cdb Mon Sep 17 00:00:00 2001 From: Chris Manson Date: Sun, 31 Aug 2025 11:42:36 +0100 Subject: [PATCH 6/6] re-enable ember-exam --- package.json | 2 +- tests/index.html | 14 +++++++++----- tests/test-helper.js | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index e60420dcbfd..6c147c26409 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "start:live": "ember serve --proxy https://crates.io", "start:local": "ember serve --proxy http://127.0.0.1:8888", "start:staging": "ember serve --proxy https://staging-crates-io.herokuapp.com", - "test": "ember exam --split=2 --parallel", + "test": "vite build --mode development && ember exam --path dist --split=2 --parallel", "test-coverage": "COVERAGE=true npm run test && ember coverage-merge && rm -rf coverage_* coverage/coverage-summary.json && nyc report", "e2e": "playwright test", "test:ember": "vite build --mode test && ember test --path dist" diff --git a/tests/index.html b/tests/index.html index c62eb4143af..59108fcf93e 100644 --- a/tests/index.html +++ b/tests/index.html @@ -32,15 +32,19 @@ - + {{content-for "body-footer"}} - + diff --git a/tests/test-helper.js b/tests/test-helper.js index 89bc5c548dd..aafb1e20db4 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -1,17 +1,17 @@ -// TODO re-enable ember exam -import emberExamStart from 'ember-exam/test-support/start'; -import { forceModulesToBeLoaded, sendCoverage } from 'ember-cli-code-coverage/test-support'; -import registerMatchJsonAssertion from './helpers/match-json'; +import { setApplication } from '@ember/test-helpers'; +import { start as startEmberExam } from 'ember-exam/test-support'; +import { setupEmberOnerrorValidation } from 'ember-qunit'; +import * as QUnit from 'qunit'; +import { forceModulesToBeLoaded, sendCoverage } from 'ember-cli-code-coverage/test-support'; +import { setup } from 'qunit-dom'; import Application from 'crates-io/app'; import config from 'crates-io/config/environment'; -import * as QUnit from 'qunit'; -import { setApplication } from '@ember/test-helpers'; -import { setup } from 'qunit-dom'; -import { start as qunitStart, setupEmberOnerrorValidation } from 'ember-qunit'; -export function start() { +import registerMatchJsonAssertion from './helpers/match-json'; + +export async function start({ availableModules }) { setApplication(Application.create(config.APP)); setup(QUnit.assert); @@ -23,5 +23,5 @@ export function start() { await sendCoverage(); }); - qunitStart(); + await startEmberExam({ availableModules }); }