1import { describe, expect, it } from "vitest";
2import {
3 findPresetConflict,
4 hasForeignNitroPlugin,
5 isSamePreset,
6 markInjectedPlugins,
7 NITRO_PLUGIN_NAME,
8 normalizePresetName,
9 resolveNitroConfig,
10 resolveNitroOutputDirs,
11 type NitroConfigSlice,
12} from "../UserConfig.ts";
13
14const resolve = (...segments: Array<string>): string =>
15 segments.reduce((acc, segment) =>
16 segment.startsWith("/") ? segment : `${acc}/${segment}`,
17 );
18
19describe("normalizePresetName / isSamePreset", () => {
20 it("treats kebab, snake, and camel spellings as the same preset", () => {
21 expect(normalizePresetName("awsLambda")).toBe("aws-lambda");
22 expect(normalizePresetName("aws_lambda")).toBe("aws-lambda");
23 expect(isSamePreset("aws-lambda", "awsLambda")).toBe(true);
24 expect(isSamePreset("aws-lambda", "node-server")).toBe(false);
25 });
26});
27
28describe("findPresetConflict", () => {
29 it("returns undefined when no preset is given or it matches the target", () => {
30 expect(findPresetConflict(undefined, "aws-lambda")).toBeUndefined();
31 expect(findPresetConflict({}, "aws-lambda")).toBeUndefined();
32 expect(
33 findPresetConflict({ preset: "aws_lambda" }, "aws-lambda"),
34 ).toBeUndefined();
35 });
36
37 it("surfaces a foreign preset so the build can fail actionably", () => {
38 expect(findPresetConflict({ preset: "netlify" }, "aws-lambda")).toBe(
39 "netlify",
40 );
41 });
42});
43
44describe("resolveNitroConfig", () => {
45 it("enforces the target's preset and rootDir over the caller's overrides", () => {
46 const config = resolveNitroConfig({
47 preset: "aws-lambda",
48 rootDir: "/project",
49 nitro: {
50 preset: "node-server",
51 rootDir: "/elsewhere",
52 prerender: { crawlLinks: true },
53 },
54 });
55 expect(config.preset).toBe("aws-lambda");
56 expect(config.rootDir).toBe("/project");
57 expect(config.buildDir).toBe("/project/.nitro");
58 // Everything the integration does not own is preserved.
59 expect(config["prerender"]).toEqual({ crawlLinks: true });
60 });
61
62 it("runs the target's configure pass after the preset is enforced", () => {
63 const config = resolveNitroConfig({
64 preset: "aws-lambda",
65 rootDir: "/project",
66 nitro: { awsLambda: { foo: 1 } },
67 configure: (nitroConfig: NitroConfigSlice) => {
68 nitroConfig.awsLambda = {
69 ...(nitroConfig.awsLambda as Record<string, unknown>),
70 streaming: true,
71 };
72 },
73 });
74 expect(config.awsLambda).toEqual({ foo: 1, streaming: true });
75 });
76});
77
78describe("resolveNitroOutputDirs", () => {
79 it("mirrors nitro's defaults", () => {
80 expect(resolveNitroOutputDirs({}, "/project", resolve)).toEqual({
81 dir: "/project/.output",
82 serverDir: "/project/.output/server",
83 publicDir: "/project/.output/public",
84 });
85 });
86
87 it("honors an output override on the nitro config", () => {
88 expect(
89 resolveNitroOutputDirs(
90 { output: { dir: "build", serverDir: "fn", publicDir: "static" } },
91 "/project",
92 resolve,
93 ),
94 ).toEqual({
95 dir: "/project/build",
96 serverDir: "/project/build/fn",
97 publicDir: "/project/build/static",
98 });
99 });
100});
101
102describe("hasForeignNitroPlugin", () => {
103 it("ignores the plugin instances this integration created", () => {
104 const injected = markInjectedPlugins([
105 { name: "alchemy:solidstart-nitro-conflict" },
106 [{ name: NITRO_PLUGIN_NAME }, false],
107 ]);
108 expect(hasForeignNitroPlugin(injected)).toBe(false);
109 });
110
111 it("detects a project-registered nitro plugin, however nested", () => {
112 const injected = markInjectedPlugins([{ name: NITRO_PLUGIN_NAME }]);
113 expect(
114 hasForeignNitroPlugin([
115 [{ name: "solid-start:config" }, [{ name: NITRO_PLUGIN_NAME }]],
116 injected,
117 ]),
118 ).toBe(true);
119 });
120
121 it("tolerates falsy and non-plugin entries", () => {
122 expect(hasForeignNitroPlugin([false, null, undefined, "x"])).toBe(false);
123 expect(hasForeignNitroPlugin(undefined)).toBe(false);
124 });
125});