|
1 | | -import { test, expect } from "@playwright/test"; |
| 1 | +import { expect } from "@playwright/test"; |
| 2 | +import tsx from "dedent"; |
2 | 3 | import getPort from "get-port"; |
3 | 4 |
|
4 | | -import { |
5 | | - type TemplateName, |
6 | | - createProject, |
7 | | - customDev, |
8 | | - EXPRESS_SERVER, |
9 | | - viteConfig, |
10 | | -} from "./helpers/vite.js"; |
11 | | - |
12 | | -const templateNames = [ |
13 | | - "vite-6-template", |
14 | | - "rsc-vite-framework", |
15 | | -] as const satisfies TemplateName[]; |
16 | | - |
17 | | -let getFiles = async ({ |
18 | | - templateName, |
19 | | - envDir, |
20 | | - port, |
21 | | -}: { |
22 | | - templateName: TemplateName; |
23 | | - envDir?: string; |
24 | | - port: number; |
25 | | -}) => { |
26 | | - let envPath = `${envDir ? `${envDir}/` : ""}.env`; |
27 | | - |
28 | | - return { |
29 | | - "vite.config.js": await viteConfig.basic({ templateName, port, envDir }), |
30 | | - "server.mjs": EXPRESS_SERVER({ port, templateName }), |
31 | | - [envPath]: ` |
32 | | - ENV_VAR_FROM_DOTENV_FILE=Content from ${envPath} file |
33 | | - VITE_PORTAL=testing |
34 | | - `, |
35 | | - "app/routes.ts": ` |
36 | | - import { type RouteConfig, route } from "@react-router/dev/routes"; |
37 | | - import { flatRoutes } from "@react-router/fs-routes"; |
38 | | - const routes = []; |
39 | | - if (import.meta.env.VITE_PORTAL === "testing") { |
40 | | - routes.push(route("testing", "testing.tsx")); |
41 | | - } |
42 | | - export default [ |
43 | | - ...await flatRoutes(), |
44 | | - ...routes, |
45 | | - ] satisfies RouteConfig; |
46 | | - `, |
47 | | - "app/testing.tsx": String.raw` |
48 | | - export default function TestingRoute() { |
49 | | - return <div data-testing-route>Testing Route</div> |
50 | | - } |
51 | | - `, |
52 | | - "app/routes/dotenv.tsx": String.raw` |
| 5 | +import * as Express from "./helpers/express"; |
| 6 | +import { test } from "./helpers/fixtures"; |
| 7 | +import * as Stream from "./helpers/stream"; |
| 8 | +import { viteMajorTemplates, getTemplates } from "./helpers/templates"; |
| 9 | + |
| 10 | +const templates = [ |
| 11 | + ...viteMajorTemplates, |
| 12 | + ...getTemplates(["rsc-vite-framework"]), |
| 13 | +]; |
| 14 | + |
| 15 | +test.use({ |
| 16 | + files: { |
| 17 | + "app/routes/dotenv.tsx": tsx` |
53 | 18 | import { useState, useEffect } from "react"; |
54 | 19 | import { useLoaderData } from "react-router"; |
55 | 20 |
|
@@ -77,71 +42,74 @@ let getFiles = async ({ |
77 | 42 | </> |
78 | 43 | } |
79 | 44 | `, |
80 | | - }; |
81 | | -}; |
82 | | - |
83 | | -for (const envDir of [undefined, "custom-env-dir"]) { |
84 | | - let envPath = `${envDir ? `${envDir}/` : ""}.env`; |
85 | | - test.describe(`Vite ${envPath}`, () => { |
86 | | - for (const templateName of templateNames) { |
87 | | - test.describe(`template: ${templateName}`, () => { |
88 | | - test.describe("defaults", async () => { |
89 | | - let port: number; |
90 | | - let cwd: string; |
91 | | - let stop: () => void; |
92 | | - |
93 | | - test.beforeAll(async () => { |
94 | | - port = await getPort(); |
95 | | - cwd = await createProject( |
96 | | - await getFiles({ envDir, port, templateName }), |
97 | | - templateName, |
98 | | - ); |
99 | | - stop = await customDev({ cwd, port }); |
100 | | - }); |
101 | | - test.afterAll(() => stop()); |
102 | | - |
103 | | - test("express", async ({ page }) => { |
104 | | - let pageErrors: unknown[] = []; |
105 | | - page.on("pageerror", (error) => pageErrors.push(error)); |
106 | | - |
107 | | - await page.goto(`http://localhost:${port}/dotenv`, { |
108 | | - waitUntil: "networkidle", |
109 | | - }); |
110 | | - expect(pageErrors).toEqual([]); |
111 | | - |
112 | | - let loaderContent = page.locator( |
113 | | - "[data-dotenv-route-loader-content]", |
114 | | - ); |
115 | | - await expect(loaderContent).toHaveText( |
116 | | - `Content from ${envPath} file`, |
117 | | - ); |
118 | | - |
119 | | - let clientContent = page.locator( |
120 | | - "[data-dotenv-route-client-content]", |
121 | | - ); |
122 | | - await expect(clientContent).toHaveText( |
123 | | - "process.env.ENV_VAR_FROM_DOTENV_FILE not available on the client, which is a good thing", |
124 | | - ); |
125 | | - |
126 | | - expect(pageErrors).toEqual([]); |
| 45 | + }, |
| 46 | +}); |
| 47 | + |
| 48 | +const envs = [ |
| 49 | + { name: "default", path: ".env" }, |
| 50 | + { name: "custom env dir", path: "custom-env-dir/.env" }, |
| 51 | +]; |
| 52 | + |
| 53 | +test.describe("Vite .env", () => { |
| 54 | + templates.forEach((template) => { |
| 55 | + test.describe(`template: ${template.displayName}`, () => { |
| 56 | + const isRsc = template.name.startsWith("rsc-"); |
| 57 | + test.use({ template: template.name }); |
| 58 | + envs.forEach((env) => { |
| 59 | + test(env.name, async ({ edit, $, page }) => { |
| 60 | + await edit({ |
| 61 | + "server.mjs": isRsc ? Express.rsc() : Express.server(), |
| 62 | + ".env": ` |
| 63 | + VITE_ENV_ROUTE=dotenv |
| 64 | + ENV_VAR_FROM_DOTENV_FILE=Content from ${env.path} file |
| 65 | + `, |
| 66 | + "app/routes.ts": (contents) => { |
| 67 | + if (template.name === "vite-5-template") return contents; |
| 68 | + return tsx` |
| 69 | + import { type RouteConfig, route } from "@react-router/dev/routes"; |
| 70 | +
|
| 71 | + const routes: RouteConfig = []; |
| 72 | + if (import.meta.env.VITE_ENV_ROUTE === "dotenv") { |
| 73 | + routes.push(route("dotenv", "routes/dotenv.tsx")); |
| 74 | + } |
| 75 | +
|
| 76 | + export default routes |
| 77 | + `; |
| 78 | + }, |
127 | 79 | }); |
| 80 | + await $("pnpm build"); |
128 | 81 |
|
129 | | - test("routes.ts has VITE_* env var", async ({ page }) => { |
130 | | - let pageErrors: unknown[] = []; |
131 | | - page.on("pageerror", (error) => pageErrors.push(error)); |
132 | | - |
133 | | - await page.goto(`http://localhost:${port}/testing`, { |
134 | | - waitUntil: "networkidle", |
135 | | - }); |
136 | | - expect(pageErrors).toEqual([]); |
137 | | - |
138 | | - let testingDiv = page.locator("[data-testing-route]"); |
139 | | - await expect(testingDiv).toHaveText("Testing Route"); |
| 82 | + const port = await getPort(); |
| 83 | + const url = `http://localhost:${port}`; |
140 | 84 |
|
141 | | - expect(pageErrors).toEqual([]); |
| 85 | + const server = $("node server.mjs", { |
| 86 | + env: { |
| 87 | + PORT: String(port), |
| 88 | + HMR_PORT: String(await getPort()), |
| 89 | + }, |
142 | 90 | }); |
| 91 | + await Stream.match(server.stdout, url); |
| 92 | + |
| 93 | + await page.goto(`${url}/dotenv`, { waitUntil: "networkidle" }); |
| 94 | + expect(page.errors).toEqual([]); |
| 95 | + |
| 96 | + let loaderContent = page.locator( |
| 97 | + "[data-dotenv-route-loader-content]", |
| 98 | + ); |
| 99 | + await expect(loaderContent).toHaveText( |
| 100 | + `Content from ${env.path} file`, |
| 101 | + ); |
| 102 | + |
| 103 | + let clientContent = page.locator( |
| 104 | + "[data-dotenv-route-client-content]", |
| 105 | + ); |
| 106 | + await expect(clientContent).toHaveText( |
| 107 | + "process.env.ENV_VAR_FROM_DOTENV_FILE not available on the client, which is a good thing", |
| 108 | + ); |
| 109 | + |
| 110 | + expect(page.errors).toEqual([]); |
143 | 111 | }); |
144 | 112 | }); |
145 | | - } |
| 113 | + }); |
146 | 114 | }); |
147 | | -} |
| 115 | +}); |
0 commit comments