Spaces:
Runtime error
Runtime error
Download scribe/frontend/scripts/validate-deploy-env.test.mjs from tranth3truong/carepath-api: direct link, hf CLI and curl.
- Browser
- Download file 5.01 kB
-
https://huggingface.co/spaces/tranth3truong/carepath-api/resolve/main/scribe/frontend/scripts/validate-deploy-env.test.mjs
- Command line
-
hf download hf://spaces/tranth3truong/carepath-api/scribe/frontend/scripts/validate-deploy-env.test.mjs
-
curl -L -o validate-deploy-env.test.mjs https://huggingface.co/spaces/tranth3truong/carepath-api/resolve/main/scribe/frontend/scripts/validate-deploy-env.test.mjs
5.01 kB
| import assert from "node:assert/strict"; | |
| import { readFile } from "node:fs/promises"; | |
| import test from "node:test"; | |
| import { validateDeployEnv } from "./validate-deploy-env.mjs"; | |
| const validEnv = { | |
| VITE_API_BASE: "https://carepath.hf.space", | |
| }; | |
| test("accepts one HTTPS Space origin", () => { | |
| assert.doesNotThrow(() => validateDeployEnv(validEnv)); | |
| }); | |
| test("accepts an empty API base when the websocket names its own host", () => { | |
| // The production shape after DEC-0021: /api/* is rewritten same-origin by | |
| // Vercel, so no CORS allow-list can take the site down again. | |
| assert.doesNotThrow(() => | |
| validateDeployEnv({ VITE_API_BASE: "", VITE_WS_BASE: "https://carepath.hf.space" }), | |
| ); | |
| }); | |
| test("rejects an empty API base with no websocket host to fall back on", () => { | |
| // Both empty means the socket would target the Vercel origin, which cannot | |
| // proxy the upgrade — the visit screen would connect to nothing. | |
| assert.throws(() => validateDeployEnv({}), /VITE_WS_BASE is required/); | |
| }); | |
| test("rejects a websocket base with a path", () => { | |
| assert.throws( | |
| () => validateDeployEnv({ VITE_WS_BASE: "https://carepath.hf.space/ws" }), | |
| /VITE_WS_BASE pathname must be \//, | |
| ); | |
| }); | |
| test("rejects HTTP", () => { | |
| assert.throws( | |
| () => validateDeployEnv({ VITE_API_BASE: "http://api.example.test" }), | |
| /must use HTTPS/, | |
| ); | |
| }); | |
| test("rejects paths, queries, and fragments that would corrupt runtime URLs", () => { | |
| assert.throws( | |
| () => validateDeployEnv({ VITE_API_BASE: "https://carepath.hf.space/wrong?token=secret" }), | |
| /must not include a query or fragment[\s\S]*pathname must be \//, | |
| ); | |
| }); | |
| test("Vercel runs validation before the production build", async () => { | |
| const config = JSON.parse( | |
| await readFile(new URL("../vercel.json", import.meta.url), "utf8"), | |
| ); | |
| assert.equal(config.buildCommand, "npm run validate:deploy && npm run build"); | |
| const spa = config.rewrites.filter((rule) => rule.destination === "/index.html"); | |
| assert.deepEqual(spa, [ | |
| { source: "/thu-nghiem", destination: "/index.html" }, | |
| { source: "/thu-nghiem/", destination: "/index.html" }, | |
| { source: "/thu-nghiem/:path*", destination: "/index.html" }, | |
| { source: "/ghi-chep-lam-sang", destination: "/index.html" }, | |
| { source: "/ghi-chep-lam-sang/", destination: "/index.html" }, | |
| { source: "/ghi-chep-lam-sang/:path*", destination: "/index.html" }, | |
| { source: "/kham-song-ngu", destination: "/index.html" }, | |
| { source: "/kham-song-ngu/", destination: "/index.html" }, | |
| { source: "/kham-song-ngu/:path*", destination: "/index.html" }, | |
| ]); | |
| }); | |
| test("the API proxy does not swallow the demo functions", async () => { | |
| // /api/demo/* are serverless functions in this project. If the catch-all | |
| // proxied them to the Space they would 404 there, and the quota that keeps | |
| // anonymous traffic off the paid provider would never run. | |
| const config = JSON.parse( | |
| await readFile(new URL("../vercel.json", import.meta.url), "utf8"), | |
| ); | |
| const api = config.rewrites.find((rule) => rule.source.startsWith("/api/")); | |
| const pattern = new RegExp(`^${api.source}$`); | |
| assert.ok(pattern.test("/api/v1/health"), "product API must still be proxied"); | |
| assert.ok(pattern.test("/api/sessions"), "product API must still be proxied"); | |
| assert.equal(pattern.test("/api/demo/document"), false); | |
| assert.equal(pattern.test("/api/demo/session"), false); | |
| }); | |
| test("the API is proxied same-origin so no CORS allow-list can break it", async () => { | |
| // Regression guard for the outage this fixed: moving the site to | |
| // carepath-medicaltranslation.vercel.app while the Space still allowed only | |
| // carepath-omega.vercel.app returned 400 Disallowed CORS origin on every | |
| // call, and both tool routes rendered "Mất kết nối máy chủ". | |
| const config = JSON.parse( | |
| await readFile(new URL("../vercel.json", import.meta.url), "utf8"), | |
| ); | |
| const api = config.rewrites.find((rule) => rule.source.startsWith("/api/")); | |
| assert.ok(api, "vercel.json must rewrite /api/* to the API host"); | |
| assert.match(api.destination, /^https:\/\/[^/]+\/api\//); | |
| // It has to win before any SPA catch-all could swallow it. | |
| assert.equal(config.rewrites.indexOf(api), 0); | |
| }); | |
| test("every SPA route the app serves has a Vercel rewrite", async () => { | |
| // A missing rewrite is a hard 404 on a direct visit, and /kham-song-ngu/ is | |
| // the demo URL. Keep this derived from the app's own route table. | |
| const app = await readFile(new URL("../src/App.tsx", import.meta.url), "utf8"); | |
| const routes = [...app.matchAll(/^const \w*_?PATH = "(\/[^"]+)";$/gm)].map((m) => m[1]); | |
| assert.ok(routes.length >= 2, `expected app routes, found ${routes.join(", ")}`); | |
| const config = JSON.parse( | |
| await readFile(new URL("../vercel.json", import.meta.url), "utf8"), | |
| ); | |
| const sources = new Set(config.rewrites.map((rule) => rule.source)); | |
| for (const route of routes) { | |
| assert.ok(sources.has(route), `vercel.json has no rewrite for ${route}`); | |
| } | |
| }); | |