070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
172 lines
6.8 KiB
TypeScript
172 lines
6.8 KiB
TypeScript
import { chmod, mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
import { EventEmitter } from "node:events";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import type { ChildProcess } from "node:child_process";
|
|
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import type { ToolPackConfig } from "../src/config.js";
|
|
import { resolveMacPaths } from "../src/mac/paths.js";
|
|
|
|
const requestJsonIpc = vi.fn(async () => ({ state: "running" }));
|
|
const resolveAppIpcPath = vi.fn(() => "/tmp/open-design/ipc/test/desktop.sock");
|
|
const createSidecarLaunchEnv = vi.fn(({ extraEnv }: { extraEnv: NodeJS.ProcessEnv }) => extraEnv);
|
|
const spawnLoggedProcess = vi.fn(async ({ env }: { env: NodeJS.ProcessEnv }) => {
|
|
return Object.assign(new EventEmitter(), {
|
|
env,
|
|
pid: 1234,
|
|
unref: vi.fn(),
|
|
}) as unknown as ChildProcess & { env: NodeJS.ProcessEnv };
|
|
});
|
|
|
|
vi.mock("@open-design/sidecar", () => ({
|
|
createSidecarLaunchEnv,
|
|
requestJsonIpc,
|
|
resolveAppIpcPath,
|
|
}));
|
|
|
|
vi.mock("@open-design/platform", () => ({
|
|
collectProcessTreePids: vi.fn(),
|
|
createProcessStampArgs: vi.fn(() => []),
|
|
isProcessAlive: vi.fn(() => true),
|
|
listProcessSnapshots: vi.fn(async () => []),
|
|
matchesStampedProcess: vi.fn(() => false),
|
|
readLogTail: vi.fn(async () => []),
|
|
spawnLoggedProcess,
|
|
stopProcesses: vi.fn(async () => []),
|
|
}));
|
|
|
|
const { startPackedMacApp } = await import("../src/mac/lifecycle.js");
|
|
|
|
function makeConfig(root: string, overrides: Partial<ToolPackConfig> = {}): ToolPackConfig {
|
|
return {
|
|
containerized: false,
|
|
electronBuilderCliPath: "/x/electron-builder/cli.js",
|
|
electronDistPath: "/x/electron/dist",
|
|
electronVersion: "41.3.0",
|
|
macCompression: "normal",
|
|
namespace: "local-test",
|
|
platform: "mac",
|
|
portable: true,
|
|
removeData: false,
|
|
removeLogs: false,
|
|
removeProductUserData: false,
|
|
removeSidecars: false,
|
|
requireVelaCli: false,
|
|
roots: {
|
|
output: {
|
|
appBuilderRoot: join(root, ".tmp", "tools-pack", "out", "mac", "namespaces", "local-test", "builder"),
|
|
namespaceRoot: join(root, ".tmp", "tools-pack", "out", "mac", "namespaces", "local-test"),
|
|
platformRoot: join(root, ".tmp", "tools-pack", "out", "mac"),
|
|
root: join(root, ".tmp", "tools-pack", "out"),
|
|
},
|
|
runtime: {
|
|
namespaceBaseRoot: join(root, ".tmp", "tools-pack", "runtime", "mac", "namespaces"),
|
|
namespaceRoot: join(root, ".tmp", "tools-pack", "runtime", "mac", "namespaces", "local-test"),
|
|
},
|
|
cacheRoot: join(root, ".tmp", "tools-pack", "cache"),
|
|
toolPackRoot: join(root, ".tmp", "tools-pack"),
|
|
},
|
|
silent: true,
|
|
signed: false,
|
|
to: "app",
|
|
webOutputMode: "standalone",
|
|
workspaceRoot: root,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
requestJsonIpc.mockResolvedValue({ state: "running" });
|
|
});
|
|
|
|
describe("startPackedMacApp", () => {
|
|
it("writes a launch override when the bundled config is missing", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-mac-lifecycle-"));
|
|
try {
|
|
const config = makeConfig(root);
|
|
const paths = resolveMacPaths(config);
|
|
const executablePath = join(paths.installedAppPath, "Contents", "MacOS", "Open Design");
|
|
|
|
await mkdir(join(paths.installedAppPath, "Contents", "MacOS"), { recursive: true });
|
|
await writeFile(executablePath, "#!/bin/sh\nexit 0\n", "utf8");
|
|
await chmod(executablePath, 0o755);
|
|
|
|
const result = await startPackedMacApp(config);
|
|
const launchConfigPath = join(config.roots.runtime.namespaceRoot, "runtime", "open-design-config.json");
|
|
const launchEnv = spawnLoggedProcess.mock.calls[0]?.[0]?.env as NodeJS.ProcessEnv | undefined;
|
|
|
|
expect(result.source).toBe("installed");
|
|
expect(result.status?.state).toBe("running");
|
|
expect(launchEnv?.OD_PACKAGED_CONFIG_PATH).toBe(launchConfigPath);
|
|
await expect(readFile(launchConfigPath, "utf8")).resolves.toContain(
|
|
`"namespaceBaseRoot": ${JSON.stringify(config.roots.runtime.namespaceBaseRoot)}`,
|
|
);
|
|
} finally {
|
|
await rm(root, { force: true, recursive: true });
|
|
}
|
|
});
|
|
|
|
it("passes a launch override config path for portable mac starts", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-mac-lifecycle-"));
|
|
try {
|
|
const config = makeConfig(root);
|
|
const paths = resolveMacPaths(config);
|
|
const executablePath = join(paths.installedAppPath, "Contents", "MacOS", "Open Design");
|
|
const bundledConfigPath = join(paths.installedAppPath, "Contents", "Resources", "open-design-config.json");
|
|
|
|
await mkdir(join(paths.installedAppPath, "Contents", "MacOS"), { recursive: true });
|
|
await mkdir(join(paths.installedAppPath, "Contents", "Resources"), { recursive: true });
|
|
await writeFile(executablePath, "#!/bin/sh\nexit 0\n", "utf8");
|
|
await chmod(executablePath, 0o755);
|
|
await writeFile(
|
|
bundledConfigPath,
|
|
`${JSON.stringify({
|
|
appVersion: "1.2.3",
|
|
daemonCliEntryRelative: "open-design/bin/od",
|
|
namespace: config.namespace,
|
|
nodeCommandRelative: "open-design/bin/node",
|
|
}, null, 2)}\n`,
|
|
"utf8",
|
|
);
|
|
|
|
const result = await startPackedMacApp(config);
|
|
const launchConfigPath = join(config.roots.runtime.namespaceRoot, "runtime", "open-design-config.json");
|
|
const launchEnv = spawnLoggedProcess.mock.calls[0]?.[0]?.env as NodeJS.ProcessEnv | undefined;
|
|
|
|
expect(result.source).toBe("installed");
|
|
expect(result.status?.state).toBe("running");
|
|
expect(launchEnv?.OD_PACKAGED_CONFIG_PATH).toBe(launchConfigPath);
|
|
await expect(readFile(launchConfigPath, "utf8")).resolves.toContain(
|
|
`"namespaceBaseRoot": ${JSON.stringify(config.roots.runtime.namespaceBaseRoot)}`,
|
|
);
|
|
await expect(readFile(launchConfigPath, "utf8")).resolves.toContain('"appVersion": "1.2.3"');
|
|
} finally {
|
|
await rm(root, { force: true, recursive: true });
|
|
}
|
|
});
|
|
|
|
it("uses the preview executable name for preview release namespaces", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "open-design-tools-pack-mac-lifecycle-"));
|
|
try {
|
|
const config = makeConfig(root, { namespace: "release-preview" });
|
|
const paths = resolveMacPaths(config);
|
|
const executablePath = join(paths.installedAppPath, "Contents", "MacOS", "Open Design Preview");
|
|
|
|
await mkdir(join(paths.installedAppPath, "Contents", "MacOS"), { recursive: true });
|
|
await writeFile(executablePath, "#!/bin/sh\nexit 0\n", "utf8");
|
|
await chmod(executablePath, 0o755);
|
|
|
|
const result = await startPackedMacApp(config);
|
|
|
|
expect(result.source).toBe("installed");
|
|
expect(result.executablePath).toBe(executablePath);
|
|
expect(result.status?.state).toBe("running");
|
|
} finally {
|
|
await rm(root, { force: true, recursive: true });
|
|
}
|
|
});
|
|
});
|