Merge pull request #6442 from heygen-com/feat/cli-windows-app-download

feat(cli): offer the HyperFrames app download on Windows
This commit is contained in:
Miguel Ángel
2026-10-26 12:40:27 -04:00
committed by GitHub
5 changed files with 63 additions and 14 deletions
+21 -3
View File
@@ -45,10 +45,10 @@ describe("open-in-desktop routes", () => {
});
});
it("shows the button where the app is installed even without a download (Windows)", async () => {
it("shows the button where the app is installed even without a download (FreeBSD)", async () => {
const get = async (installed: boolean) =>
(
await server(true, { platform: "win32", installed: () => installed }).app.request(
await server(true, { platform: "freebsd", installed: () => installed }).app.request(
"/api/open-in-desktop",
)
).json();
@@ -56,12 +56,30 @@ describe("open-in-desktop routes", () => {
available: true,
handoff: true,
downloadUrl: null,
os: "win32",
os: "freebsd",
installed: true,
});
expect(await get(false)).toMatchObject({ available: false });
});
it("offers the Windows download, and the hand-off once the app is installed", async () => {
const get = async (installed: boolean) =>
(
await server(true, { platform: "win32", installed: () => installed }).app.request(
"/api/open-in-desktop",
)
).json();
const downloadUrl = "https://hyperframes.dev/studio/download?os=windows";
expect(await get(false)).toEqual({
available: true,
handoff: false,
downloadUrl,
os: "win32",
installed: false,
});
expect(await get(true)).toMatchObject({ available: true, handoff: true, downloadUrl });
});
it("offers the hand-off only where the app is installed, so a press without it goes to the download", async () => {
const get = async (installed: boolean) =>
(
+12 -4
View File
@@ -143,7 +143,7 @@ describe("openInDesktop on Windows", () => {
expect(missing).toEqual({
opened: false,
reason: "not-installed",
downloadUrl: "https://hyperframes.dev/studio",
downloadUrl: `${MAC_DOWNLOAD}?os=windows`,
});
const failed = openInDesktop(FILM, { ...WIN, exists: () => true, launch: () => false });
expect(failed).toMatchObject({ opened: false, reason: "open-failed" });
@@ -327,12 +327,20 @@ describe("desktopHint", () => {
expect(desktopHint(process.cwd(), { ...mac, ready: true, installed: false })).toBe(MAC_HINT);
});
it("offers the Linux build on Linux, and nothing on Windows without the app", () => {
it("offers the Linux and Windows builds there, and nothing where there is no build", () => {
expect(desktopHint(process.cwd(), { env: {}, platform: "linux", installed: false })).toBe(
`Keep editing by chatting with Framey in the HyperFrames desktop app → ${MAC_DOWNLOAD}?os=linux`,
);
expect(desktopHint(process.cwd(), { env: {}, platform: "win32", installed: false })).toBeNull();
expect(desktopHint(process.cwd(), { env: {}, platform: "win32", ready: true })).toBeNull();
const windowsHint = `Keep editing by chatting with Framey in the HyperFrames desktop app → ${MAC_DOWNLOAD}?os=windows`;
expect(desktopHint(process.cwd(), { env: {}, platform: "win32", installed: false })).toBe(
windowsHint,
);
expect(desktopHint(process.cwd(), { env: {}, platform: "win32", ready: true })).toBe(
windowsHint,
);
expect(
desktopHint(process.cwd(), { env: {}, platform: "freebsd", installed: false }),
).toBeNull();
});
it("points an installed Windows app to `hyperframes open`", () => {
+2 -1
View File
@@ -15,9 +15,10 @@ const STUDIO_PAGE = "https://hyperframes.dev/studio";
const DOWNLOADS: Partial<Record<NodeJS.Platform, string>> = {
darwin: `${STUDIO_PAGE}/download`,
linux: `${STUDIO_PAGE}/download?os=linux`,
win32: `${STUDIO_PAGE}/download?os=windows`,
};
/** This machine's build of the app; null where there is none yet (Windows). */
/** This machine's build of the app; null where there is none. */
export const desktopDownloadUrl = (platform = process.platform): string | null =>
DOWNLOADS[platform] ?? null;
@@ -15,7 +15,7 @@ export type DesktopRoute = {
/** The OS for the download, and what "this …" calls the machine. */
const platformName = (os: string): string =>
os === "darwin" ? "Mac" : os === "linux" ? "Linux" : "your computer";
os === "darwin" ? "Mac" : os === "linux" ? "Linux" : os === "win32" ? "Windows" : "your computer";
const deviceName = (os: string): string => (os === "darwin" ? "Mac" : "computer");
const NOTE = "mt-0.5 text-step-12 text-text-2 text-pretty";
@@ -103,19 +103,19 @@ it("stays hidden where the server has no hand-off (the desktop's own Studio)", a
expect(button()).toBeNull();
});
it("stays hidden when the app has no build for this machine (Windows)", async () => {
it("stays hidden when the app has no build for this machine (FreeBSD)", async () => {
serve(Response.json({ available: false, handoff: true, downloadUrl: null }));
await mount();
expect(button()).toBeNull();
});
it("with the app installed but no download (Windows), shows only once the app can take the project", async () => {
it("with the app installed but no download (FreeBSD), shows only once the app can take the project", async () => {
serve(Response.json({ available: true, handoff: false, downloadUrl: null }));
await mount();
expect(button()).toBeNull();
});
it("opens the project in an installed app that has no download (Windows)", async () => {
it("opens the project in an installed app that has no download (FreeBSD)", async () => {
serve(Response.json({ available: true, handoff: true, downloadUrl: null }), {
opened: true,
app: "the HyperFrames desktop app",
@@ -381,6 +381,28 @@ it("where the app is installed but cannot take a project (Linux), step 3 shows t
expect(posts).toBe(0);
});
it("on Windows, step 1 names the Windows download and opens it tagged", async () => {
const opened: string[] = [];
vi.stubGlobal("open", (url: string) => (opened.push(url), { opener: {} }));
serve(
Response.json({
available: true,
handoff: false,
downloadUrl: `${DOWNLOAD}?os=windows`,
os: "win32",
installed: false,
}),
);
await mount();
expect(button()).not.toBeNull();
await act(async () => button()!.click());
await act(async () => cardButton("Download for Windows")!.click());
expect(opened).toEqual([tagged(`${DOWNLOAD}?os=windows`)]);
expect(events("desktop_cta_eligibility")).toEqual([
{ eligibility: "download", os: "win32", app_installed: false, download_available: true },
]);
});
it("counts where the button can show, the app here, and platforms with no app", async () => {
serve(
Response.json({
@@ -402,7 +424,7 @@ it("counts where the button can show, the app here, and platforms with no app",
available: false,
handoff: false,
downloadUrl: null,
os: "win32",
os: "freebsd",
installed: false,
}),
);
@@ -411,7 +433,7 @@ it("counts where the button can show, the app here, and platforms with no app",
expect(events("desktop_cta_eligibility")).toEqual([
{
eligibility: "no_app_for_platform",
os: "win32",
os: "freebsd",
app_installed: false,
download_available: false,
},