ember.nvp 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.release-plan.json +37 -5
- package/CHANGELOG.md +31 -0
- package/README.md +28 -0
- package/package.json +2 -1
- package/packages/rolldown/package.json +2 -2
- package/packages/rolldown/src/transform.test.ts +3 -3
- package/packages/vite/package.json +4 -4
- package/packages/vite/src/ember.test.ts +38 -0
- package/packages/vite/src/ember.ts +38 -5
- package/src/bases/minimal-app/files/package.json +2 -2
- package/src/bases/minimal-extension/files/package.json +2 -2
- package/src/cli/generator.js +10 -0
- package/src/cli/index.js +19 -2
- package/src/cli/questions/layers.js +3 -2
- package/src/cli/questions/migration.js +69 -0
- package/src/index.js +1 -0
- package/src/layers/qunit/index.js +1 -1
- package/src/migration-from/addons.js +154 -0
- package/src/migration-from/app.js +1117 -0
- package/src/migration-from/at-ember/addon-blueprint/index.js +515 -0
- package/src/migration-from/at-ember/addon-blueprint/rollup.js +188 -0
- package/src/migration-from/at-ember/app-blueprint/index.js +60 -0
- package/src/migration-from/at-ember-tooling/classic-build-addon-blueprint/index.js +601 -0
- package/src/migration-from/at-ember-tooling/classic-build-app-blueprint/index.js +118 -0
- package/src/migration-from/babel.js +207 -0
- package/src/migration-from/ember-cli-build.js +238 -0
- package/src/migration-from/files.js +120 -0
- package/src/migration-from/findings.js +69 -0
- package/src/migration-from/index.js +81 -0
- package/src/migration-from/javascript.js +217 -0
- package/src/migration-from/layers.js +170 -0
- package/src/migration-from/library.js +311 -0
- package/src/utils/types.ts +69 -0
- package/test/ember.nvp/migration-from-fixtures.ts +506 -0
- package/test/ember.nvp/migration-from.test.ts +475 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import { describe, it, expect, afterAll } from "vitest";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { rm } from "node:fs/promises";
|
|
6
|
+
import { stripVTControlCharacters } from "node:util";
|
|
7
|
+
import { packageJson } from "ember-apply";
|
|
8
|
+
import { checkMigration, detectMigration, formatFindings, MigrationError } from "#migration-from";
|
|
9
|
+
import { Project } from "#utils/project.js";
|
|
10
|
+
import { cli, generate, mktemp } from "#test-helpers";
|
|
11
|
+
import type { ProjectType } from "#types";
|
|
12
|
+
import {
|
|
13
|
+
addonBlueprint,
|
|
14
|
+
appBlueprint,
|
|
15
|
+
classicAddon,
|
|
16
|
+
classicApp,
|
|
17
|
+
} from "./migration-from-fixtures.ts";
|
|
18
|
+
|
|
19
|
+
const FIXTURES = {
|
|
20
|
+
"addon-blueprint": addonBlueprint,
|
|
21
|
+
"app-blueprint": appBlueprint,
|
|
22
|
+
"classic-build-app-blueprint": classicApp,
|
|
23
|
+
"classic-build-addon-blueprint": classicAddon,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const dirs: string[] = [];
|
|
27
|
+
|
|
28
|
+
afterAll(async () => {
|
|
29
|
+
if (process.env.CI) return;
|
|
30
|
+
|
|
31
|
+
for (const dir of dirs) {
|
|
32
|
+
await rm(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
async function fixture(name: keyof typeof FIXTURES, files: Record<string, string> = {}) {
|
|
37
|
+
let dir = await mktemp(`migration-from-${name}`);
|
|
38
|
+
dirs.push(dir);
|
|
39
|
+
|
|
40
|
+
for (let [file, contents] of Object.entries({ ...FIXTURES[name], ...files })) {
|
|
41
|
+
await mkdir(dirname(join(dir, file)), { recursive: true });
|
|
42
|
+
await writeFile(join(dir, file), contents);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return dir;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function migrate(directory: string, type: ProjectType, layers: string[]) {
|
|
49
|
+
let { name } = await packageJson.read(directory);
|
|
50
|
+
|
|
51
|
+
return generate({ directory, name, type, layers });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @returns the titles of the unsupported findings, or undefined when the migration succeeds
|
|
56
|
+
*/
|
|
57
|
+
async function unsupported(directory: string, type: ProjectType) {
|
|
58
|
+
try {
|
|
59
|
+
await migrate(directory, type, []);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (error instanceof MigrationError) {
|
|
62
|
+
return error.findings.map((finding) => finding.title);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function read(directory: string, file: string) {
|
|
70
|
+
return readFile(join(directory, file), "utf-8");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
describe("detectMigration", () => {
|
|
74
|
+
const cases = {
|
|
75
|
+
"addon-blueprint": "@ember/addon-blueprint",
|
|
76
|
+
"app-blueprint": "@ember/app-blueprint",
|
|
77
|
+
"classic-build-app-blueprint": "@ember-tooling/classic-build-app-blueprint",
|
|
78
|
+
"classic-build-addon-blueprint": "@ember-tooling/classic-build-addon-blueprint",
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
for (let [name, label] of Object.entries(cases)) {
|
|
82
|
+
it(`detects ${label}`, async () => {
|
|
83
|
+
let dir = await fixture(name as keyof typeof FIXTURES);
|
|
84
|
+
|
|
85
|
+
expect(detectMigration(dir)?.label).toBe(label);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (let type of ["app", "library"] as const) {
|
|
90
|
+
it(`detects nothing in a ${type} that ember.nvp generates`, async () => {
|
|
91
|
+
let project = await generate({ type });
|
|
92
|
+
dirs.push(project.directory);
|
|
93
|
+
|
|
94
|
+
expect(detectMigration(project.directory)).toBe(undefined);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe("@ember/addon-blueprint", () => {
|
|
100
|
+
it("moves the build to tsdown", async () => {
|
|
101
|
+
let dir = await fixture("addon-blueprint");
|
|
102
|
+
|
|
103
|
+
await migrate(dir, "library", ["typescript", "qunit"]);
|
|
104
|
+
|
|
105
|
+
for (let file of [
|
|
106
|
+
"rollup.config.mjs",
|
|
107
|
+
"babel.config.cjs",
|
|
108
|
+
"babel.publish.config.cjs",
|
|
109
|
+
"tsconfig.publish.json",
|
|
110
|
+
"testem.cjs",
|
|
111
|
+
"index.html",
|
|
112
|
+
"demo-app",
|
|
113
|
+
"unpublished-development-types",
|
|
114
|
+
]) {
|
|
115
|
+
expect(existsSync(join(dir, file)), file).toBe(false);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let config = await read(dir, "tsdown.config.js");
|
|
119
|
+
|
|
120
|
+
expect(config).toContain(`"./src/**/*.{js,ts,gjs,gts}"`);
|
|
121
|
+
expect(config).toContain(
|
|
122
|
+
`appReexports(["components/**/*.js", "helpers/**/*.js", "modifiers/**/*.js", "services/**/*.js"])`,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
let manifest = await packageJson.read(dir);
|
|
126
|
+
|
|
127
|
+
expect(manifest.type).toBe("module");
|
|
128
|
+
expect(manifest.scripts.build).toBe("tsdown");
|
|
129
|
+
expect(manifest.exports["."].types).toBe("./dist/index.d.ts");
|
|
130
|
+
expect(manifest.files).not.toContain("declarations");
|
|
131
|
+
expect(manifest["ember-addon"].main).toBe("addon-main.cjs");
|
|
132
|
+
expect(manifest.devDependencies).not.toHaveProperty("@embroider/addon-dev");
|
|
133
|
+
expect(manifest.devDependencies).not.toHaveProperty("rollup");
|
|
134
|
+
expect(manifest.devDependencies).toHaveProperty("tsdown");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("stops at .hbs templates and public assets, and changes nothing", async () => {
|
|
138
|
+
let dir = await fixture("addon-blueprint", {
|
|
139
|
+
"src/components/greeting.hbs": "Hello",
|
|
140
|
+
"src/components/greeting.js": "export default class Greeting {}",
|
|
141
|
+
});
|
|
142
|
+
let rollup = await read(dir, "rollup.config.mjs");
|
|
143
|
+
|
|
144
|
+
await writeFile(
|
|
145
|
+
join(dir, "rollup.config.mjs"),
|
|
146
|
+
rollup.replace("addon.clean(),", "addon.clean(),\n addon.publicAssets('public'),"),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
expect(await unsupported(dir, "library")).toEqual(["Templates in .hbs files", "Public assets"]);
|
|
150
|
+
expect(existsSync(join(dir, "rollup.config.mjs"))).toBe(true);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe("@ember/app-blueprint", () => {
|
|
155
|
+
it("moves the app off @embroider/compat", async () => {
|
|
156
|
+
let dir = await fixture("app-blueprint");
|
|
157
|
+
|
|
158
|
+
await migrate(dir, "app", ["typescript", "qunit"]);
|
|
159
|
+
|
|
160
|
+
for (let file of [
|
|
161
|
+
"ember-cli-build.mjs",
|
|
162
|
+
"babel.config.mjs",
|
|
163
|
+
"config/environment.js",
|
|
164
|
+
"config/optional-features.json",
|
|
165
|
+
"app/config/environment.ts",
|
|
166
|
+
]) {
|
|
167
|
+
expect(existsSync(join(dir, file)), file).toBe(false);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let html = await read(dir, "index.html");
|
|
171
|
+
|
|
172
|
+
expect(html).not.toContain("content-for");
|
|
173
|
+
expect(html).not.toContain("@embroider/virtual");
|
|
174
|
+
expect(html).toContain(`<link rel="stylesheet" href="/app/styles/app.css" />`);
|
|
175
|
+
expect(html).toContain(`import Application from "#app/app";`);
|
|
176
|
+
|
|
177
|
+
let app = await read(dir, "app/app.ts");
|
|
178
|
+
|
|
179
|
+
expect(app).toContain(`import "@warp-drive/ember/install";`);
|
|
180
|
+
expect(app).toContain(`"./services/page-title": PageTitleService`);
|
|
181
|
+
expect(app).toContain(`importSync("./deprecation-workflow");`);
|
|
182
|
+
|
|
183
|
+
expect(await read(dir, "app/router.ts")).toContain(`import config from '#config';`);
|
|
184
|
+
expect(await read(dir, "babel.config.js")).toContain("setConfig(config, {");
|
|
185
|
+
|
|
186
|
+
let manifest = await packageJson.read(dir);
|
|
187
|
+
|
|
188
|
+
expect(manifest.scripts.build).toBe("vite build");
|
|
189
|
+
expect(manifest.devDependencies).not.toHaveProperty("ember-cli");
|
|
190
|
+
expect(manifest.devDependencies).not.toHaveProperty("@embroider/compat");
|
|
191
|
+
expect(manifest.devDependencies).toHaveProperty("@nullvoxpopuli/ember-vite");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("stops at compat features, and changes nothing", async () => {
|
|
195
|
+
let dir = await fixture("app-blueprint", {
|
|
196
|
+
"app/components/greeting.hbs": "Hello",
|
|
197
|
+
"vendor/legacy.js": "window.legacy = true;",
|
|
198
|
+
});
|
|
199
|
+
let build = await read(dir, "ember-cli-build.mjs");
|
|
200
|
+
|
|
201
|
+
await writeFile(
|
|
202
|
+
join(dir, "ember-cli-build.mjs"),
|
|
203
|
+
build.replace("// Add options here", "sassOptions: {},"),
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
expect(await unsupported(dir, "app")).toEqual([
|
|
207
|
+
"Templates in .hbs files",
|
|
208
|
+
"Build settings in ember-cli-build",
|
|
209
|
+
"Files in vendor/",
|
|
210
|
+
]);
|
|
211
|
+
expect(existsSync(join(dir, "ember-cli-build.mjs"))).toBe(true);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("reads the top level of node_modules, when there is one", async () => {
|
|
215
|
+
let dir = await fixture("app-blueprint", {
|
|
216
|
+
"node_modules/ember-cli-mirage/package.json": JSON.stringify({
|
|
217
|
+
name: "ember-cli-mirage",
|
|
218
|
+
version: "3.0.4",
|
|
219
|
+
keywords: ["ember-addon"],
|
|
220
|
+
}),
|
|
221
|
+
// installed, but not a dependency of the app
|
|
222
|
+
"node_modules/ember-fetch/package.json": JSON.stringify({
|
|
223
|
+
name: "ember-fetch",
|
|
224
|
+
version: "8.1.2",
|
|
225
|
+
keywords: ["ember-addon"],
|
|
226
|
+
}),
|
|
227
|
+
"node_modules/@acme/session/package.json": JSON.stringify({
|
|
228
|
+
name: "@acme/session",
|
|
229
|
+
version: "1.0.0",
|
|
230
|
+
keywords: ["ember-addon"],
|
|
231
|
+
exports: { "./*": "./dist/*.js" },
|
|
232
|
+
"ember-addon": {
|
|
233
|
+
version: 2,
|
|
234
|
+
"app-js": { "./services/session.js": "./dist/_app_/services/session.js" },
|
|
235
|
+
},
|
|
236
|
+
}),
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
await packageJson.addDevDependencies({ "@acme/session": "link:../session" }, dir);
|
|
240
|
+
|
|
241
|
+
let project = new Project(dir, {
|
|
242
|
+
name: "my-app",
|
|
243
|
+
type: "app",
|
|
244
|
+
path: dir,
|
|
245
|
+
layers: [],
|
|
246
|
+
packageManager: "pnpm",
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
expect((await checkMigration(project))?.report.unsupported).toEqual([]);
|
|
250
|
+
|
|
251
|
+
await packageJson.addDevDependencies({ "ember-cli-mirage": "^3.0.0" }, dir);
|
|
252
|
+
|
|
253
|
+
let report = (await checkMigration(project))?.report;
|
|
254
|
+
|
|
255
|
+
expect(report?.unsupported.map((finding) => finding.where)).toEqual([
|
|
256
|
+
["ember-cli-mirage@3.0.4"],
|
|
257
|
+
]);
|
|
258
|
+
|
|
259
|
+
await packageJson.removeDevDependencies(["ember-cli-mirage"], dir);
|
|
260
|
+
await migrate(dir, "app", ["typescript"]);
|
|
261
|
+
|
|
262
|
+
let app = await read(dir, "app/app.ts");
|
|
263
|
+
|
|
264
|
+
expect(app).toContain(`import SessionService from "@acme/session/_app_/services/session";`);
|
|
265
|
+
expect(app).toContain(`"./services/session": SessionService,`);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it("stops at an ember-source older than 7.2", async () => {
|
|
269
|
+
let dir = await fixture("app-blueprint");
|
|
270
|
+
|
|
271
|
+
await packageJson.modify((json) => {
|
|
272
|
+
json.devDependencies["ember-source"] = "~6.4.0";
|
|
273
|
+
}, dir);
|
|
274
|
+
|
|
275
|
+
expect(await unsupported(dir, "app")).toEqual(["An ember-source older than 7.2"]);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
describe("@ember-tooling/classic-build-app-blueprint", () => {
|
|
280
|
+
it("moves the app from ember-cli to Vite", async () => {
|
|
281
|
+
let dir = await fixture("classic-build-app-blueprint");
|
|
282
|
+
|
|
283
|
+
await migrate(dir, "app", ["typescript", "qunit"]);
|
|
284
|
+
|
|
285
|
+
for (let file of ["ember-cli-build.js", "app/index.html", "testem.js", "types/global.d.ts"]) {
|
|
286
|
+
expect(existsSync(join(dir, file)), file).toBe(false);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
let html = await read(dir, "index.html");
|
|
290
|
+
|
|
291
|
+
expect(html).not.toContain("{{");
|
|
292
|
+
expect(html).not.toContain("assets/vendor");
|
|
293
|
+
expect(html).toContain(`<link rel="icon" href="/assets/favicon.png">`);
|
|
294
|
+
expect(html).toContain(`import Application from "#app/app";`);
|
|
295
|
+
|
|
296
|
+
expect(await read(dir, "tsconfig.json")).toContain("@ember/app-tsconfig");
|
|
297
|
+
|
|
298
|
+
let manifest = await packageJson.read(dir);
|
|
299
|
+
|
|
300
|
+
expect(manifest.devDependencies).not.toHaveProperty("ember-cli-app-version");
|
|
301
|
+
expect(manifest.devDependencies).not.toHaveProperty("@tsconfig/ember");
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
describe("testem configs", () => {
|
|
306
|
+
it("lists browser flags that differ from the new testem config", async () => {
|
|
307
|
+
let dir = await fixture("classic-build-app-blueprint", {
|
|
308
|
+
"testem.js": classicApp["testem.js"]!.replace(
|
|
309
|
+
"'--disable-software-rasterizer',",
|
|
310
|
+
"'--use-gl=angle',",
|
|
311
|
+
),
|
|
312
|
+
});
|
|
313
|
+
let project = new Project(dir, {
|
|
314
|
+
name: "my-classic-app",
|
|
315
|
+
type: "app",
|
|
316
|
+
path: dir,
|
|
317
|
+
layers: [],
|
|
318
|
+
packageManager: "pnpm",
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
let todo = (await checkMigration(project))?.report.todo ?? [];
|
|
322
|
+
let flags = todo.find((finding) => finding.title.startsWith("Browser flags"));
|
|
323
|
+
|
|
324
|
+
expect(flags?.where).toEqual([
|
|
325
|
+
"--use-gl=angle: only in testem.js",
|
|
326
|
+
"--disable-software-rasterizer: only in testem.cjs",
|
|
327
|
+
]);
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
describe("@ember-tooling/classic-build-addon-blueprint", () => {
|
|
332
|
+
it("makes a v2 addon that builds with tsdown", async () => {
|
|
333
|
+
let dir = await fixture("classic-build-addon-blueprint", {
|
|
334
|
+
"addon/components/greeting.gjs": "<template>Hello</template>",
|
|
335
|
+
"addon/utils/shout.js":
|
|
336
|
+
"import { quiet } from 'my-classic-addon/utils/quiet';\n\nexport const shout = (text) => quiet(text).toUpperCase();\n",
|
|
337
|
+
"addon/utils/quiet.js": "export const quiet = (text) => text;\n",
|
|
338
|
+
"addon-test-support/index.js": "export function setupGreeting() {}\n",
|
|
339
|
+
"app/components/greeting.js":
|
|
340
|
+
"export { default } from 'my-classic-addon/components/greeting';\n",
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
await migrate(dir, "library", ["qunit"]);
|
|
344
|
+
|
|
345
|
+
for (let file of [
|
|
346
|
+
"index.js",
|
|
347
|
+
"ember-cli-build.js",
|
|
348
|
+
"addon",
|
|
349
|
+
"app",
|
|
350
|
+
".npmignore",
|
|
351
|
+
"tests/dummy",
|
|
352
|
+
]) {
|
|
353
|
+
expect(existsSync(join(dir, file)), file).toBe(false);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
expect(await read(dir, "src/components/greeting.gjs")).toBe("<template>Hello</template>");
|
|
357
|
+
expect(await read(dir, "src/utils/shout.js")).toContain(`from "./quiet.js";`);
|
|
358
|
+
expect(existsSync(join(dir, "src/test-support/index.js"))).toBe(true);
|
|
359
|
+
expect(await read(dir, "addon-main.cjs")).toContain("addonV1Shim");
|
|
360
|
+
expect(existsSync(join(dir, ".prettierrc.cjs"))).toBe(true);
|
|
361
|
+
expect(await read(dir, "tsdown.config.js")).toContain(
|
|
362
|
+
`appReexports(["components/greeting.js"])`,
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
let manifest = await packageJson.read(dir);
|
|
366
|
+
|
|
367
|
+
expect(manifest["ember-addon"]).toEqual({ version: 2, type: "addon", main: "addon-main.cjs" });
|
|
368
|
+
expect(manifest.exports["./test-support"]).toBe("./dist/test-support/index.js");
|
|
369
|
+
expect(manifest.dependencies).toHaveProperty("@embroider/addon-shim");
|
|
370
|
+
expect(manifest.dependencies).not.toHaveProperty("ember-cli-babel");
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it("keeps a dummy app with a demo of its own, and lists it", async () => {
|
|
374
|
+
let dir = await fixture("classic-build-addon-blueprint", {
|
|
375
|
+
"tests/dummy/app/router.js": `Router.map(function () {\n this.route("docs");\n});\n`,
|
|
376
|
+
});
|
|
377
|
+
let project = new Project(dir, {
|
|
378
|
+
name: "my-classic-addon",
|
|
379
|
+
type: "library",
|
|
380
|
+
path: dir,
|
|
381
|
+
layers: [],
|
|
382
|
+
packageManager: "pnpm",
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
let result = await checkMigration(project);
|
|
386
|
+
|
|
387
|
+
expect(result?.report.todo.map((finding) => finding.title)).toContain("A dummy app");
|
|
388
|
+
|
|
389
|
+
await migrate(dir, "library", []);
|
|
390
|
+
|
|
391
|
+
expect(existsSync(join(dir, "tests/dummy/app/router.js"))).toBe(true);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it("stops at ember-cli hooks, and changes nothing", async () => {
|
|
395
|
+
let dir = await fixture("classic-build-addon-blueprint", {
|
|
396
|
+
"index.js": `'use strict';\n\nmodule.exports = {\n name: require('./package').name,\n included() {},\n contentFor() {},\n};\n`,
|
|
397
|
+
"addon/styles/addon.css": ".greeting {}",
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
expect(await unsupported(dir, "library")).toEqual([
|
|
401
|
+
"ember-cli hooks in the addon's main file",
|
|
402
|
+
"Styles that ember-cli merges into the app",
|
|
403
|
+
]);
|
|
404
|
+
expect(existsSync(join(dir, "index.js"))).toBe(true);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
describe("the type question", () => {
|
|
409
|
+
it("stops when the selected type differs from the blueprint's", async () => {
|
|
410
|
+
let dir = await fixture("addon-blueprint");
|
|
411
|
+
|
|
412
|
+
expect(await unsupported(dir, "app")).toEqual(["A library from @ember/addon-blueprint"]);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
describe("formatFindings", () => {
|
|
417
|
+
it("numbers the findings and shortens long lists", () => {
|
|
418
|
+
let where = Array.from({ length: 10 }, (_, i) => `app/components/c${i}.hbs`);
|
|
419
|
+
|
|
420
|
+
expect(
|
|
421
|
+
formatFindings([
|
|
422
|
+
{ title: "Templates in .hbs files", where, action: "Convert them.\nThe build needs it." },
|
|
423
|
+
{ title: "Public assets", action: "Import them." },
|
|
424
|
+
]),
|
|
425
|
+
).toMatchInlineSnapshot(`
|
|
426
|
+
"1. Templates in .hbs files
|
|
427
|
+
- app/components/c0.hbs
|
|
428
|
+
- app/components/c1.hbs
|
|
429
|
+
- app/components/c2.hbs
|
|
430
|
+
- app/components/c3.hbs
|
|
431
|
+
- app/components/c4.hbs
|
|
432
|
+
- app/components/c5.hbs
|
|
433
|
+
- app/components/c6.hbs
|
|
434
|
+
- app/components/c7.hbs
|
|
435
|
+
- and 2 more
|
|
436
|
+
Convert them.
|
|
437
|
+
The build needs it.
|
|
438
|
+
|
|
439
|
+
2. Public assets
|
|
440
|
+
Import them."
|
|
441
|
+
`);
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
describe("the CLI", () => {
|
|
446
|
+
it("lists what to change, and writes nothing", async () => {
|
|
447
|
+
let dir = await fixture("app-blueprint", { "app/components/greeting.hbs": "Hello" });
|
|
448
|
+
let args = [
|
|
449
|
+
"--name",
|
|
450
|
+
"my-vite-app",
|
|
451
|
+
"--path",
|
|
452
|
+
dir,
|
|
453
|
+
"--replaceOrUpdate",
|
|
454
|
+
"update",
|
|
455
|
+
"--type",
|
|
456
|
+
"app",
|
|
457
|
+
"--layers",
|
|
458
|
+
"qunit",
|
|
459
|
+
"--packageManager",
|
|
460
|
+
"pnpm",
|
|
461
|
+
"--confirm",
|
|
462
|
+
"yes",
|
|
463
|
+
];
|
|
464
|
+
|
|
465
|
+
let result = await cli(args)
|
|
466
|
+
.execaPromise.then((res) => res)
|
|
467
|
+
.catch((error) => error);
|
|
468
|
+
let output = stripVTControlCharacters(`${result.stdout}\n${result.stderr}`);
|
|
469
|
+
|
|
470
|
+
expect(result.exitCode).toBe(1);
|
|
471
|
+
expect(output).toContain("ember.nvp cannot migrate this project yet");
|
|
472
|
+
expect(output).toContain("app/components/greeting.hbs");
|
|
473
|
+
expect(existsSync(join(dir, "ember-cli-build.mjs"))).toBe(true);
|
|
474
|
+
});
|
|
475
|
+
});
|