Skip to content

Commit bdf74d4

Browse files
committed
test: cover studio local render fallback
1 parent d7ab757 commit bdf74d4

3 files changed

Lines changed: 100 additions & 8 deletions

File tree

packages/studio/vite.config.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { defineConfig, type Plugin, type ViteDevServer } from "vite";
22
import react from "@vitejs/plugin-react";
3-
import { execFileSync } from "node:child_process";
43
import {
54
readFileSync,
65
readdirSync,
@@ -15,6 +14,7 @@ import type {
1514
ResolvedProject,
1615
RenderJobState,
1716
} from "@hyperframes/core/studio-api";
17+
import { ensureProducerDist } from "./vite.producer";
1818

1919
// ── Shared Puppeteer browser ─────────────────────────────────────────────────
2020

@@ -81,16 +81,14 @@ function createViteAdapter(dataDir: string, server: ViteDevServer): StudioApiAda
8181
const getProducerModule = async () => {
8282
if (!_producerModulePromise) {
8383
_producerModulePromise = (async () => {
84-
const producerDistEntry = resolve(__dirname, "../producer/dist/index.js");
85-
if (!existsSync(producerDistEntry)) {
84+
const { built } = ensureProducerDist({
85+
studioDir: __dirname,
86+
env: process.env,
87+
});
88+
if (built) {
8689
console.warn(
8790
"[Studio] @hyperframes/producer dist missing; building producer package for local renders...",
8891
);
89-
execFileSync("bun", ["run", "--filter", "@hyperframes/producer", "build"], {
90-
cwd: resolve(__dirname, "../.."),
91-
stdio: "pipe",
92-
env: process.env,
93-
});
9492
}
9593
const producerPkg = "@hyperframes/producer";
9694
return await import(/* @vite-ignore */ producerPkg);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
import {
3+
ensureProducerDist,
4+
resolveProducerDistEntry,
5+
resolveWorkspaceRoot,
6+
} from "./vite.producer";
7+
8+
describe("ensureProducerDist", () => {
9+
it("does nothing when the producer dist entry already exists", () => {
10+
const exec = vi.fn();
11+
const result = ensureProducerDist({
12+
studioDir: "/repo/packages/studio",
13+
existsSyncImpl: () => true,
14+
execFileSyncImpl: exec as never,
15+
});
16+
17+
expect(result).toEqual({
18+
built: false,
19+
producerDistEntry: "/repo/packages/producer/dist/index.js",
20+
});
21+
expect(exec).not.toHaveBeenCalled();
22+
});
23+
24+
it("builds producer when the dist entry is missing", () => {
25+
const exec = vi.fn();
26+
const env = { TEST: "1" } as NodeJS.ProcessEnv;
27+
28+
const result = ensureProducerDist({
29+
studioDir: "/repo/packages/studio",
30+
existsSyncImpl: () => false,
31+
execFileSyncImpl: exec as never,
32+
env,
33+
});
34+
35+
expect(result).toEqual({
36+
built: true,
37+
producerDistEntry: "/repo/packages/producer/dist/index.js",
38+
});
39+
expect(exec).toHaveBeenCalledWith(
40+
"bun",
41+
["run", "--filter", "@hyperframes/producer", "build"],
42+
{
43+
cwd: "/repo",
44+
stdio: "pipe",
45+
env,
46+
},
47+
);
48+
});
49+
});
50+
51+
describe("producer path helpers", () => {
52+
it("resolves the producer dist entry relative to studio", () => {
53+
expect(resolveProducerDistEntry("/repo/packages/studio")).toBe(
54+
"/repo/packages/producer/dist/index.js",
55+
);
56+
});
57+
58+
it("resolves the workspace root relative to studio", () => {
59+
expect(resolveWorkspaceRoot("/repo/packages/studio")).toBe("/repo");
60+
});
61+
});

packages/studio/vite.producer.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { execFileSync } from "node:child_process";
2+
import { existsSync } from "node:fs";
3+
import { resolve } from "node:path";
4+
5+
export function resolveProducerDistEntry(studioDir: string): string {
6+
return resolve(studioDir, "../producer/dist/index.js");
7+
}
8+
9+
export function resolveWorkspaceRoot(studioDir: string): string {
10+
return resolve(studioDir, "../..");
11+
}
12+
13+
export function ensureProducerDist(opts: {
14+
studioDir: string;
15+
existsSyncImpl?: (path: string) => boolean;
16+
execFileSyncImpl?: typeof execFileSync;
17+
env?: NodeJS.ProcessEnv;
18+
}): { built: boolean; producerDistEntry: string } {
19+
const producerDistEntry = resolveProducerDistEntry(opts.studioDir);
20+
const exists = opts.existsSyncImpl ?? existsSync;
21+
if (exists(producerDistEntry)) {
22+
return { built: false, producerDistEntry };
23+
}
24+
25+
const exec = opts.execFileSyncImpl ?? execFileSync;
26+
exec("bun", ["run", "--filter", "@hyperframes/producer", "build"], {
27+
cwd: resolveWorkspaceRoot(opts.studioDir),
28+
stdio: "pipe",
29+
env: opts.env,
30+
});
31+
32+
return { built: true, producerDistEntry };
33+
}

0 commit comments

Comments
 (0)