Files
windmill/cli/test/raw_app_shared_ui_unit.test.ts
T
hugocasaandClaude Opus 5.5 3ee745192c fix(cli): resolve /ui/ in app dev and lint, bare ui/ imports from the app (#12050)
* fix(cli): resolve /ui/ in app dev and lint, and its bare imports from the app

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(cli): match shared ui/ files by real path so a symlinked ui/ still redirects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(cli): keep relative css @import in shared ui/ resolving next to the file

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(cli): let esbuild resolve relative css @import in ui/ so suffixes keep working

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:08:28 +01:00

59 lines
2.3 KiB
TypeScript

/**
* `/ui/...` imports, driven through `createBundle` the way `app dev` and
* `app lint` find the shared folder: from the app up to its wmill.yaml.
*/
import { afterAll, beforeAll, expect, test } from "bun:test";
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { createBundle, findSharedUiDir } from "../src/commands/app/bundle.ts";
let root: string;
let originalCwd: string;
function write(rel: string, content: string) {
const full = path.join(root, rel);
fs.mkdirSync(path.dirname(full), { recursive: true });
fs.writeFileSync(full, content, "utf-8");
}
beforeAll(() => {
originalCwd = process.cwd();
root = fs.mkdtempSync(path.join(os.tmpdir(), "raw-app-shared-ui-"));
write("wmill.yaml", "defaultTs: bun\n");
// ui/ as a symlink, with the bare import one relative hop away: esbuild reaches
// inner.ts by its real path, not through the link.
write("shared/button.ts", `export { label } from "./inner";\n`);
write("shared/inner.ts", `import { who } from "pkg";\nimport "./styles.css";\nexport const label = who;\n`);
write("shared/styles.css", `@import "base.css?theme";\n`);
write("shared/base.css", `.from-ui-css { color: red; }\n`);
fs.symlinkSync(path.join(root, "shared"), path.join(root, "ui"));
write("f/demo.raw_app/package.json", `{"name":"demo"}`);
write("f/demo.raw_app/index.tsx", `import { label } from "/ui/button";\nconsole.log(label);\n`);
write("f/demo.raw_app/node_modules/pkg/index.js", `export const who = "from-app";\n`);
// A copy above ui/ must not win: it would be a second instance of the package.
write("node_modules/pkg/index.js", `export const who = "from-root";\n`);
process.chdir(path.join(root, "f/demo.raw_app"));
});
afterAll(() => {
process.chdir(originalCwd);
fs.rmSync(root, { recursive: true, force: true });
});
test("bare imports in ui/ resolve from the app's node_modules", async () => {
const appDir = path.join(root, "f/demo.raw_app");
const sharedUiDir = findSharedUiDir(appDir);
expect(sharedUiDir).toBe(path.join(root, "ui"));
const { js, css } = await createBundle({
entryPoint: path.join(appDir, "index.tsx"),
minify: false,
sharedUiDir,
});
expect(js).toContain("from-app");
expect(js).not.toContain("from-root");
expect(css).toContain("from-ui-css");
});