1import { describe, expect, it } from "vitest";
2import {
3 enforceNitroConfig,
4 findPresetConflict,
5 isSamePreset,
6 makeNuxtOverrides,
7 normalizePresetName,
8 presetConflictMessage,
9 type NitroConfigSlice,
10} from "../UserConfig.ts";
11
12describe("normalizePresetName / isSamePreset", () => {
13 it("treats snake, kebab, and camel spellings as the same preset", () => {
14 expect(normalizePresetName("cloudflare_module")).toBe("cloudflare-module");
15 expect(normalizePresetName("cloudflare-module")).toBe("cloudflare-module");
16 expect(normalizePresetName("cloudflareModule")).toBe("cloudflare-module");
17 expect(isSamePreset("cloudflare_module", "cloudflare-module")).toBe(true);
18 expect(isSamePreset("cloudflareModule", "cloudflare_module")).toBe(true);
19 });
20
21 it("distinguishes genuinely different presets", () => {
22 expect(isSamePreset("cloudflare_module", "cloudflare_pages")).toBe(false);
23 expect(isSamePreset("cloudflare_module", "cloudflare_durable")).toBe(false);
24 expect(isSamePreset("cloudflare_module", "vercel")).toBe(false);
25 });
26});
27
28describe("makeNuxtOverrides", () => {
29 it("injects the target preset into the nitro overrides", () => {
30 const overrides = makeNuxtOverrides({ nitroPreset: "cloudflare_module" });
31 expect(overrides).toEqual({
32 vite: { logLevel: "warn" },
33 nitro: { preset: "cloudflare_module" },
34 });
35 });
36
37 it("lets integration-level vite config override the reporter-safe defaults", () => {
38 const overrides = makeNuxtOverrides({
39 nuxtConfig: { vite: { logLevel: "info", clearScreen: false } },
40 });
41 expect(overrides["vite"]).toEqual({ logLevel: "info", clearScreen: false });
42 });
43
44 it("merges integration-level nuxt config, with the preset winning over its nitro slice", () => {
45 const overrides = makeNuxtOverrides({
46 nitroPreset: "cloudflare_module",
47 nuxtConfig: {
48 ssr: true,
49 nitro: { preset: "vercel", minify: false },
50 },
51 });
52 expect(overrides["ssr"]).toBe(true);
53 expect(overrides["nitro"]).toEqual({
54 preset: "cloudflare_module",
55 minify: false,
56 });
57 });
58
59 it("appends nitro plugins after integration-declared ones", () => {
60 const overrides = makeNuxtOverrides({
61 nitroPreset: "cloudflare_module",
62 nuxtConfig: { nitro: { plugins: ["a-plugin.ts"] } },
63 nitroPlugins: ["/abs/dev-bridge.ts"],
64 });
65 expect((overrides["nitro"] as { plugins: Array<string> }).plugins).toEqual([
66 "a-plugin.ts",
67 "/abs/dev-bridge.ts",
68 ]);
69 });
70
71 it("omits the preset for dev-shaped overrides (no nitroPreset) while still appending plugins", () => {
72 const overrides = makeNuxtOverrides({
73 nuxtConfig: { telemetry: false },
74 nitroPlugins: ["/abs/dev-bridge.ts"],
75 });
76 expect(overrides["telemetry"]).toBe(false);
77 expect(overrides["nitro"]).toEqual({ plugins: ["/abs/dev-bridge.ts"] });
78 });
79
80 it("merges injected runtimeConfig over the integration overrides' runtimeConfig", () => {
81 const overrides = makeNuxtOverrides({
82 nuxtConfig: { runtimeConfig: { keep: "user", clobbered: "user" } },
83 runtimeConfig: {
84 clobbered: "platform",
85 injected: { url: "http://127.0.0.1:1", token: "t" },
86 },
87 });
88 expect(overrides["runtimeConfig"]).toEqual({
89 keep: "user",
90 clobbered: "platform",
91 injected: { url: "http://127.0.0.1:1", token: "t" },
92 });
93 });
94
95 it("adds no runtimeConfig key when none is injected", () => {
96 const overrides = makeNuxtOverrides({ nitroPreset: "cloudflare_module" });
97 expect("runtimeConfig" in overrides).toBe(false);
98 });
99
100 it("adds no plugins key when none are given", () => {
101 const overrides = makeNuxtOverrides({ nitroPreset: "cloudflare_module" });
102 expect("plugins" in (overrides["nitro"] as Record<string, unknown>)).toBe(
103 false,
104 );
105 });
106});
107
108describe("findPresetConflict", () => {
109 const layer = (preset: string | undefined, cwd = "/project") => ({
110 cwd,
111 config: preset !== undefined ? { nitro: { preset } } : {},
112 });
113
114 it("returns undefined when no layer sets a preset", () => {
115 expect(
116 findPresetConflict([layer(undefined)], "cloudflare_module"),
117 ).toBeUndefined();
118 expect(findPresetConflict([], "cloudflare_module")).toBeUndefined();
119 expect(findPresetConflict(undefined, "cloudflare_module")).toBeUndefined();
120 });
121
122 it("accepts the target preset and its spelling aliases", () => {
123 expect(
124 findPresetConflict([layer("cloudflare_module")], "cloudflare_module"),
125 ).toBeUndefined();
126 expect(
127 findPresetConflict([layer("cloudflare-module")], "cloudflare_module"),
128 ).toBeUndefined();
129 expect(
130 findPresetConflict([layer("cloudflareModule")], "cloudflare_module"),
131 ).toBeUndefined();
132 });
133
134 it("surfaces a foreign preset from any layer", () => {
135 expect(findPresetConflict([layer("vercel")], "cloudflare_module")).toBe(
136 "vercel",
137 );
138 expect(
139 findPresetConflict(
140 [layer(undefined), layer("cloudflare_pages", "/project/base")],
141 "cloudflare_module",
142 ),
143 ).toBe("cloudflare_pages");
144 });
145
146 it("ignores empty-string presets", () => {
147 expect(
148 findPresetConflict([layer("")], "cloudflare_module"),
149 ).toBeUndefined();
150 });
151});
152
153describe("presetConflictMessage", () => {
154 it("names both presets and the fix", () => {
155 const message = presetConflictMessage("vercel", "cloudflare_module");
156 expect(message).toContain('"vercel"');
157 expect(message).toContain('"cloudflare_module"');
158 expect(message).toContain("nitro.preset");
159 });
160});
161
162describe("enforceNitroConfig", () => {
163 it("enforces the preset as the last word", () => {
164 const config: NitroConfigSlice = { preset: "node-server" };
165 enforceNitroConfig(config, { preset: "cloudflare_module" });
166 expect(config.preset).toBe("cloudflare_module");
167 });
168
169 it("runs the target's configure pass after the preset is set", () => {
170 const config: NitroConfigSlice = {};
171 const seen: Array<string | undefined> = [];
172 enforceNitroConfig(config, {
173 preset: "cloudflare_module",
174 configure: (nitroConfig) => {
175 seen.push(nitroConfig.preset);
176 nitroConfig.cloudflare = { deployConfig: false };
177 },
178 });
179 expect(seen).toEqual(["cloudflare_module"]);
180 expect(config.cloudflare).toEqual({ deployConfig: false });
181 });
182});