Files
windmill/cli/test/raw_app_missing_css_unit.test.ts
Guilhem 8a96e3a4ec fix: raw apps with no stylesheet were permanently un-deployable (#10364)
* fix: raw apps with no stylesheet were permanently un-deployable

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: keep js strict when defaulting the raw app bundle css

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test: drop ephemeral narration from raw app bundle regression test

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test: pin the extension each raw app bundle half is fetched under

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 22:32:57 +02:00

67 lines
2.2 KiB
TypeScript

/** Only a `.css` 404 may be forgiven — see `getRawAppBundlePart`. */
import { expect, test, describe } from "bun:test";
import { getRawAppBundlePart } from "../windmill-utils-internal/src/deploy.ts";
function providerThatFailsWith(err: unknown) {
return {
getRawAppData: () => Promise.reject(err),
} as any;
}
function httpError(status: number) {
return Object.assign(new Error(`HTTP ${status}`), { status });
}
describe("getRawAppBundlePart", () => {
test("requests each half under its own extension", async () => {
const asked: Array<{ secretWithExtension: string; workspace: string }> = [];
const provider = {
getRawAppData: (p: { secretWithExtension: string; workspace: string }) => {
asked.push(p);
return Promise.resolve(`body-of-${p.secretWithExtension}`);
},
} as any;
expect(await getRawAppBundlePart(provider, "sec", "js", "ws")).toBe(
"body-of-sec.js"
);
expect(await getRawAppBundlePart(provider, "sec", "css", "ws")).toBe(
"body-of-sec.css"
);
// Swapping the two extensions would deploy the stylesheet as the bundle.
expect(asked).toEqual([
{ secretWithExtension: "sec.js", workspace: "ws" },
{ secretWithExtension: "sec.css", workspace: "ws" },
]);
});
test("treats a missing .css as empty rather than fatal", async () => {
const provider = providerThatFailsWith(httpError(404));
expect(await getRawAppBundlePart(provider, "sec", "css", "ws")).toBe("");
});
test("still fails loudly on a missing .js", async () => {
const provider = providerThatFailsWith(httpError(404));
await expect(
getRawAppBundlePart(provider, "sec", "js", "ws")
).rejects.toThrow();
});
test("does not swallow non-404 failures on .css", async () => {
for (const status of [401, 403, 500]) {
const provider = providerThatFailsWith(httpError(status));
await expect(
getRawAppBundlePart(provider, "sec", "css", "ws")
).rejects.toThrow();
}
});
test("does not swallow a .css failure that carries no status", async () => {
const provider = providerThatFailsWith(new Error("network down"));
await expect(
getRawAppBundlePart(provider, "sec", "css", "ws")
).rejects.toThrow("network down");
});
});