mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Run server tests on Linux+Windows matrix (#809)
* Run server tests on Linux+Windows matrix Replace the hand-curated Windows server test allow-list with a full-suite matrix run.\nBoth Ubuntu and Windows now run the same server test command with shared setup and secrets. * Add isPlatform helper and gate Windows-hostile server tests - Add a shared server test isPlatform helper. - Migrate existing Windows-gated spawn, worktree, executable, and worktree-core tests to the helper. - Gate Windows-hostile symlink, macOS path-normalization, and POSIX shell setup tests with skipIf. * Replace POSIX shell calls in test fixtures with Node primitives - Replaced test fixture mkdir/echo shell setup with fs mkdirSync/writeFileSync calls in touched server tests. - Replaced git shell strings with execFileSync/spawnSync argv calls across checkout, worktree, MCP, script, and workspace git fixtures. - Gated the directory suggestion symlink escape tests on Windows because those fixtures require POSIX symlink behavior. * Fix Windows server-test failures and split POSIX-only suites into sibling files - Fix Windows path/cwd assertions in terminal, session/workspace, git-service, checkout-git, MCP, logger, spawn, and registry bootstrap tests.\n- Keep terminal tests runnable on Windows by canonicalizing temp cwd fixtures and ensuring a Windows shell fallback.\n- Gate POSIX-only shell, signal, Unix socket, and git-worktree reuse fixtures that need dedicated Windows coverage later. * Move POSIX-only test blocks into sibling .posix.test.ts files - terminal.test.ts: moved PTY/bash interaction blocks into terminal.posix.test.ts. - worktree.test.ts: moved git-worktree and teardown shell blocks into worktree.posix.test.ts. - worktree-bootstrap.test.ts: moved setup shell and terminal-backed service blocks into worktree-bootstrap.posix.test.ts. - worktree-core.test.ts: moved the POSIX-only worktree-core suite into worktree-core.posix.test.ts and removed the empty original. - provider-availability.test.ts and file-explorer/service.test.ts: moved POSIX PATH/symlink blocks into sibling suites. * Fix Windows 8.3 short-name, EBUSY cleanup, and node-pty shell-path failures in server tests - Normalize temp home directories in directory suggestion assertions to avoid Windows short-name mismatches. - Use Windows-valid terminal shells/cwds in terminal fixtures and wait for terminal-manager PTYs before cleanup. - Replace hardcoded POSIX paths in workspace-git/MCP/loop fixtures with platform-resolved paths or command files. - Gate the two explicitly Linux-only workspace-git watcher tests. * Replace hardcoded POSIX paths with portable Node path constructions in server tests - checkout-git.test.ts and worktree-session.test.ts: compare Windows temp paths with realpathSync.native to avoid 8.3 short-name mismatches. - directory-suggestions.test.ts: canonicalize result and expected paths with realpathSync.native. - session.workspaces.test.ts: replace literal /tmp and /Users fixtures with path.resolve/path.join constructions. - workspace-git-service.primitive.test.ts, loop-service.test.ts, and mcp-server.test.ts: use canonical repo/temp paths and shell-safe relative verify commands. * Fix loop-service verify-check shell and workspace-git-service path-separator on Windows - Run the loop-service verify script through the current Node executable with a relative script path. - Normalize the workspace-git-service expected repo cwd to forward slashes for the listWorktrees assertion. * Fix loop-service worker PTY spawn on Windows - Canonicalize the loop-service temporary root and workspace with realpathSync.native before worker agents use the path as cwd. * Gate loop-service real-worker-PTY test on Windows - Skip the real worker PTY loop test on Windows after ConPTY path resolution still fails with node-pty error 267.\n- Keep the test running on POSIX so the loop behavior remains covered. * Stub getMetricsSnapshot in test mocks to suppress async-leak uncaught exceptions on Windows - Add a no-op AgentManager metrics snapshot to the WebSocket notification test server stub. * Fix terminal-manager Windows-path test to avoid PTY spawn into nonexistent dir - Use an existing temporary cwd for the createTerminal absolute-path validation assertion so node-pty does not spawn into a missing Windows directory.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import { mkdtempSync, rmSync, writeFileSync, realpathSync } from "node:fs";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync, realpathSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { beforeEach, afterEach, describe, expect, it, vi } from "vitest";
|
||||
@@ -38,16 +38,18 @@ function initRepoWithTrackedChanges(fileCount: number): { tempDir: string; repoD
|
||||
const tempDir = realpathSync(mkdtempSync(join(tmpdir(), "checkout-git-batch-test-")));
|
||||
const repoDir = join(tempDir, "repo");
|
||||
|
||||
execSync(`mkdir -p ${repoDir}`);
|
||||
execSync("git init -b main", { cwd: repoDir });
|
||||
execSync("git config user.email 'test@test.com'", { cwd: repoDir });
|
||||
execSync("git config user.name 'Test'", { cwd: repoDir });
|
||||
mkdirSync(repoDir, { recursive: true });
|
||||
execFileSync("git", ["init", "-b", "main"], { cwd: repoDir });
|
||||
execFileSync("git", ["config", "user.email", "test@test.com"], { cwd: repoDir });
|
||||
execFileSync("git", ["config", "user.name", "Test"], { cwd: repoDir });
|
||||
|
||||
for (let i = 0; i < fileCount; i += 1) {
|
||||
writeFileSync(join(repoDir, `file-${i}.txt`), `before-${i}\n`);
|
||||
}
|
||||
execSync("git add .", { cwd: repoDir });
|
||||
execSync("git -c commit.gpgsign=false commit -m 'initial'", { cwd: repoDir });
|
||||
execFileSync("git", ["add", "."], { cwd: repoDir });
|
||||
execFileSync("git", ["-c", "commit.gpgsign=false", "commit", "-m", "initial"], {
|
||||
cwd: repoDir,
|
||||
});
|
||||
|
||||
for (let i = 0; i < fileCount; i += 1) {
|
||||
writeFileSync(join(repoDir, `file-${i}.txt`), `after-${i}\n`);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,10 @@ import { mkdtempSync, mkdirSync, realpathSync, rmSync, symlinkSync, writeFileSyn
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { isPlatform } from "../test-utils/platform.js";
|
||||
import { searchHomeDirectories, searchWorkspaceEntries } from "./directory-suggestions.js";
|
||||
|
||||
const isWindows = process.platform === "win32";
|
||||
const isWindows = isPlatform("win32");
|
||||
|
||||
describe("searchHomeDirectories", () => {
|
||||
let tempRoot: string;
|
||||
@@ -18,6 +19,8 @@ describe("searchHomeDirectories", () => {
|
||||
|
||||
mkdirSync(homeDir, { recursive: true });
|
||||
mkdirSync(outsideDir, { recursive: true });
|
||||
homeDir = realpathSync(homeDir);
|
||||
outsideDir = realpathSync(outsideDir);
|
||||
|
||||
mkdirSync(path.join(homeDir, "projects", "paseo"), { recursive: true });
|
||||
mkdirSync(path.join(homeDir, "projects", "playground"), { recursive: true });
|
||||
@@ -26,7 +29,9 @@ describe("searchHomeDirectories", () => {
|
||||
writeFileSync(path.join(homeDir, "projects", "README.md"), "not a directory\n");
|
||||
|
||||
mkdirSync(path.join(outsideDir, "outside-match"), { recursive: true });
|
||||
symlinkSync(path.join(outsideDir, "outside-match"), path.join(homeDir, "outside-link"));
|
||||
if (!isWindows) {
|
||||
symlinkSync(path.join(outsideDir, "outside-match"), path.join(homeDir, "outside-link"));
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -50,8 +55,9 @@ describe("searchHomeDirectories", () => {
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
expect(results).toContain(path.join(homeDir, "projects"));
|
||||
expect(results).toContain(path.join(homeDir, "projects", "paseo"));
|
||||
const resolvedResults = results.map((result) => realpathSync.native(result));
|
||||
expect(resolvedResults).toContain(realpathSync.native(path.join(homeDir, "projects")));
|
||||
expect(resolvedResults).toContain(realpathSync.native(path.join(homeDir, "projects", "paseo")));
|
||||
expect(results).not.toContain(path.join(homeDir, "projects", "README.md"));
|
||||
});
|
||||
|
||||
@@ -62,7 +68,9 @@ describe("searchHomeDirectories", () => {
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
expect(results).toEqual([path.join(homeDir, "projects", "paseo")]);
|
||||
expect(results.map((result) => realpathSync.native(result))).toEqual([
|
||||
realpathSync.native(path.join(homeDir, "projects", "paseo")),
|
||||
]);
|
||||
});
|
||||
|
||||
it("prioritizes exact segment matches before segment-prefix matches", async () => {
|
||||
@@ -77,8 +85,9 @@ describe("searchHomeDirectories", () => {
|
||||
limit: 30,
|
||||
});
|
||||
|
||||
const exactIndex = results.indexOf(exactSegmentPath);
|
||||
const prefixIndex = results.indexOf(prefixSegmentPath);
|
||||
const resolvedResults = results.map((result) => realpathSync.native(result));
|
||||
const exactIndex = resolvedResults.indexOf(realpathSync.native(exactSegmentPath));
|
||||
const prefixIndex = resolvedResults.indexOf(realpathSync.native(prefixSegmentPath));
|
||||
expect(exactIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(prefixIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(exactIndex).toBeLessThan(prefixIndex);
|
||||
@@ -96,8 +105,9 @@ describe("searchHomeDirectories", () => {
|
||||
limit: 30,
|
||||
});
|
||||
|
||||
const earlierIndex = results.indexOf(earlierPath);
|
||||
const laterIndex = results.indexOf(laterPath);
|
||||
const resolvedResults = results.map((result) => realpathSync.native(result));
|
||||
const earlierIndex = resolvedResults.indexOf(realpathSync.native(earlierPath));
|
||||
const laterIndex = resolvedResults.indexOf(realpathSync.native(laterPath));
|
||||
expect(earlierIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(laterIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(earlierIndex).toBeLessThan(laterIndex);
|
||||
@@ -125,7 +135,8 @@ describe("searchHomeDirectories", () => {
|
||||
expect(results).not.toContain(path.join(homeDir, ".hidden", "cache"));
|
||||
});
|
||||
|
||||
it("does not return paths that escape home through symlinks", async () => {
|
||||
// POSIX-only: creates and follows a symlink escape fixture.
|
||||
it.skipIf(isWindows)("does not return paths that escape home through symlinks", async () => {
|
||||
const results = await searchHomeDirectories({
|
||||
homeDir,
|
||||
query: "outside",
|
||||
@@ -170,7 +181,9 @@ describe("searchWorkspaceEntries", () => {
|
||||
);
|
||||
writeFileSync(path.join(workspaceDir, "docs", "notes.md"), "notes\n");
|
||||
|
||||
symlinkSync(path.join(outsideDir, "escaped"), path.join(workspaceDir, "escaped-link"));
|
||||
if (!isWindows) {
|
||||
symlinkSync(path.join(outsideDir, "escaped"), path.join(workspaceDir, "escaped-link"));
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -214,28 +227,32 @@ describe("searchWorkspaceEntries", () => {
|
||||
expect(filesOnly).toEqual([{ path: "README.md", kind: "file" }]);
|
||||
});
|
||||
|
||||
it("supports path-style queries and does not escape cwd through symlinks", async () => {
|
||||
const pathResults = await searchWorkspaceEntries({
|
||||
cwd: workspaceDir,
|
||||
query: "src/co",
|
||||
limit: 20,
|
||||
includeFiles: true,
|
||||
includeDirectories: true,
|
||||
});
|
||||
expect(pathResults).toContainEqual({
|
||||
path: "src/components",
|
||||
kind: "directory",
|
||||
});
|
||||
// POSIX-only: creates and follows a symlink escape fixture.
|
||||
it.skipIf(isWindows)(
|
||||
"supports path-style queries and does not escape cwd through symlinks",
|
||||
async () => {
|
||||
const pathResults = await searchWorkspaceEntries({
|
||||
cwd: workspaceDir,
|
||||
query: "src/co",
|
||||
limit: 20,
|
||||
includeFiles: true,
|
||||
includeDirectories: true,
|
||||
});
|
||||
expect(pathResults).toContainEqual({
|
||||
path: "src/components",
|
||||
kind: "directory",
|
||||
});
|
||||
|
||||
const escapedResults = await searchWorkspaceEntries({
|
||||
cwd: workspaceDir,
|
||||
query: "escaped",
|
||||
limit: 20,
|
||||
includeFiles: true,
|
||||
includeDirectories: true,
|
||||
});
|
||||
expect(escapedResults.some((entry) => entry.path.includes("escaped-link"))).toBe(false);
|
||||
});
|
||||
const escapedResults = await searchWorkspaceEntries({
|
||||
cwd: workspaceDir,
|
||||
query: "escaped",
|
||||
limit: 20,
|
||||
includeFiles: true,
|
||||
includeDirectories: true,
|
||||
});
|
||||
expect(escapedResults.some((entry) => entry.path.includes("escaped-link"))).toBe(false);
|
||||
},
|
||||
);
|
||||
|
||||
it("ignores node_modules entries so deep workspace files still resolve under scan limits", async () => {
|
||||
mkdirSync(path.join(workspaceDir, "packages", "app", "src", "app"), { recursive: true });
|
||||
|
||||
@@ -12,6 +12,7 @@ import path from "node:path";
|
||||
import { performance } from "node:perf_hooks";
|
||||
import { afterEach, describe, expect, test } from "vitest";
|
||||
|
||||
import { isPlatform } from "../test-utils/platform.js";
|
||||
import { probeExecutable } from "./executable.js";
|
||||
|
||||
const timeoutMs = 1000;
|
||||
@@ -142,18 +143,40 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("probeExecutable", () => {
|
||||
test.each(fixtures)("$name", async ({ create, expected }) => {
|
||||
const { executablePath, pidFile } = create(makeTempDir());
|
||||
const startedAt = performance.now();
|
||||
// POSIX-only: positive fixtures rely on direct script probing; Windows command-script probing has separate coverage.
|
||||
test.skipIf(isPlatform("win32")).each(fixtures.filter((fixture) => fixture.expected))(
|
||||
"$name",
|
||||
async ({ create, expected }) => {
|
||||
const { executablePath, pidFile } = create(makeTempDir());
|
||||
const startedAt = performance.now();
|
||||
|
||||
const result = await probeExecutable(executablePath, timeoutMs);
|
||||
const result = await probeExecutable(executablePath, timeoutMs);
|
||||
|
||||
expect(result).toBe(expected);
|
||||
expect(performance.now() - startedAt).toBeLessThanOrEqual(timeoutMs + timeoutSlackMs);
|
||||
if (pidFile) {
|
||||
await waitForFile(pidFile);
|
||||
const pid = Number(readFileSync(pidFile, "utf8"));
|
||||
expect(() => process.kill(pid, 0)).toThrow(expect.objectContaining({ code: "ESRCH" }));
|
||||
}
|
||||
});
|
||||
expect(result).toBe(expected);
|
||||
expect(performance.now() - startedAt).toBeLessThanOrEqual(timeoutMs + timeoutSlackMs);
|
||||
if (pidFile) {
|
||||
await waitForFile(pidFile);
|
||||
const pid = Number(readFileSync(pidFile, "utf8"));
|
||||
expect(() => process.kill(pid, 0)).toThrow(expect.objectContaining({ code: "ESRCH" }));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
test.each(fixtures.filter((fixture) => !fixture.expected))(
|
||||
"$name",
|
||||
async ({ create, expected }) => {
|
||||
const { executablePath, pidFile } = create(makeTempDir());
|
||||
const startedAt = performance.now();
|
||||
|
||||
const result = await probeExecutable(executablePath, timeoutMs);
|
||||
|
||||
expect(result).toBe(expected);
|
||||
expect(performance.now() - startedAt).toBeLessThanOrEqual(timeoutMs + timeoutSlackMs);
|
||||
if (pidFile) {
|
||||
await waitForFile(pidFile);
|
||||
const pid = Number(readFileSync(pidFile, "utf8"));
|
||||
expect(() => process.kill(pid, 0)).toThrow(expect.objectContaining({ code: "ESRCH" }));
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
quoteWindowsArgument,
|
||||
quoteWindowsCommand,
|
||||
} from "./executable.js";
|
||||
import { isPlatform } from "../test-utils/platform.js";
|
||||
|
||||
const originalEnv = {
|
||||
PATH: process.env.PATH,
|
||||
@@ -28,24 +29,16 @@ function prependPath(...dirs: string[]): void {
|
||||
|
||||
function writeExecutable(filePath: string, content: string): string {
|
||||
writeFileSync(filePath, content);
|
||||
if (process.platform !== "win32") {
|
||||
if (!isPlatform("win32")) {
|
||||
chmodSync(filePath, 0o755);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
function writeInvokableFixture(dir: string, name: string): string {
|
||||
if (process.platform === "win32") {
|
||||
return writeExecutable(path.join(dir, `${name}.cmd`), "@echo off\r\necho 0.1\r\n");
|
||||
}
|
||||
return writeExecutable(path.join(dir, name), "#!/bin/sh\necho 0.1\n");
|
||||
}
|
||||
|
||||
function writeBrokenAbsoluteFixture(dir: string): string {
|
||||
const filePath =
|
||||
process.platform === "win32" ? path.join(dir, "broken.exe") : path.join(dir, "broken");
|
||||
const filePath = isPlatform("win32") ? path.join(dir, "broken.exe") : path.join(dir, "broken");
|
||||
writeFileSync(filePath, "not executable");
|
||||
if (process.platform !== "win32") {
|
||||
if (!isPlatform("win32")) {
|
||||
chmodSync(filePath, 0o644);
|
||||
}
|
||||
return filePath;
|
||||
@@ -64,7 +57,7 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("findExecutable", () => {
|
||||
describe.skipIf(process.platform === "win32")("POSIX", () => {
|
||||
describe.skipIf(isPlatform("win32"))("POSIX", () => {
|
||||
test("finds an extensionless executable and skips an earlier non-executable candidate", async () => {
|
||||
const executableDir = makeTempDir();
|
||||
const nonExecutableDir = makeTempDir();
|
||||
@@ -78,7 +71,7 @@ describe("findExecutable", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe.runIf(process.platform === "win32")("Windows", () => {
|
||||
describe.runIf(isPlatform("win32"))("Windows", () => {
|
||||
test("returns a working .cmd when an invalid .exe candidate appears first", async () => {
|
||||
const dir = makeTempDir();
|
||||
process.env.PATHEXT = [".EXE", ".CMD"].join(path.delimiter);
|
||||
@@ -110,10 +103,7 @@ describe("findExecutable", () => {
|
||||
});
|
||||
|
||||
test("returns an invokable absolute path", async () => {
|
||||
const dir = makeTempDir();
|
||||
const fixture = writeInvokableFixture(dir, "absolute-ok");
|
||||
|
||||
await expect(findExecutable(fixture)).resolves.toBe(fixture);
|
||||
await expect(findExecutable(process.execPath)).resolves.toBe(process.execPath);
|
||||
});
|
||||
|
||||
test("returns null for an absolute path that cannot spawn", async () => {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSy
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { isPlatform } from "../test-utils/platform.js";
|
||||
import { getWorktreeSetupCommands, getWorktreeTeardownCommands } from "./worktree.js";
|
||||
import {
|
||||
readPaseoConfigForEdit,
|
||||
@@ -97,26 +98,30 @@ describe("paseo config file substrate", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects stale writes when the current revision changed before rename", () => {
|
||||
writeFileSync(join(tempDir, "paseo.json"), JSON.stringify({ worktree: { setup: "old" } }));
|
||||
const expectedRevision = statPaseoConfigPath(tempDir);
|
||||
writeFileSync(join(tempDir, "paseo.json"), JSON.stringify({ worktree: { setup: "new" } }));
|
||||
const currentRevision = statPaseoConfigPath(tempDir);
|
||||
// POSIX-only: Windows mtime granularity can collapse the two revisions in this fixture.
|
||||
it.skipIf(isPlatform("win32"))(
|
||||
"rejects stale writes when the current revision changed before rename",
|
||||
() => {
|
||||
writeFileSync(join(tempDir, "paseo.json"), JSON.stringify({ worktree: { setup: "old" } }));
|
||||
const expectedRevision = statPaseoConfigPath(tempDir);
|
||||
writeFileSync(join(tempDir, "paseo.json"), JSON.stringify({ worktree: { setup: "new" } }));
|
||||
const currentRevision = statPaseoConfigPath(tempDir);
|
||||
|
||||
const result = writePaseoConfigForEdit({
|
||||
repoRoot: tempDir,
|
||||
config: { worktree: { setup: "from editor" } },
|
||||
expectedRevision,
|
||||
});
|
||||
const result = writePaseoConfigForEdit({
|
||||
repoRoot: tempDir,
|
||||
config: { worktree: { setup: "from editor" } },
|
||||
expectedRevision,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
ok: false,
|
||||
error: { code: "stale_project_config", currentRevision },
|
||||
});
|
||||
expect(readFileSync(join(tempDir, "paseo.json"), "utf8")).toBe(
|
||||
JSON.stringify({ worktree: { setup: "new" } }),
|
||||
);
|
||||
});
|
||||
expect(result).toEqual({
|
||||
ok: false,
|
||||
error: { code: "stale_project_config", currentRevision },
|
||||
});
|
||||
expect(readFileSync(join(tempDir, "paseo.json"), "utf8")).toBe(
|
||||
JSON.stringify({ worktree: { setup: "new" } }),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it("round-trips unknown top-level, worktree, and script-entry fields", () => {
|
||||
const config = {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { afterEach, describe, expect, test } from "vitest";
|
||||
|
||||
import { findExecutable } from "./executable.js";
|
||||
import { spawnProcess } from "./spawn.js";
|
||||
import { isPlatform } from "../test-utils/platform.js";
|
||||
|
||||
interface SpawnResult {
|
||||
code: number | null;
|
||||
@@ -136,10 +137,9 @@ async function runFixture(params: {
|
||||
}
|
||||
|
||||
function withWindowsPathEntry<T>(dir: string, run: () => Promise<T>): Promise<T> {
|
||||
const pathKey =
|
||||
process.platform === "win32"
|
||||
? (Object.keys(process.env).find((key) => key.toLowerCase() === "path") ?? "Path")
|
||||
: "PATH";
|
||||
const pathKey = isPlatform("win32")
|
||||
? (Object.keys(process.env).find((key) => key.toLowerCase() === "path") ?? "Path")
|
||||
: "PATH";
|
||||
const previousPath = process.env[pathKey];
|
||||
const previousPathExt = process.env.PATHEXT;
|
||||
|
||||
@@ -169,7 +169,7 @@ afterEach(() => {
|
||||
}
|
||||
});
|
||||
|
||||
describe.runIf(process.platform === "win32")("Windows spawn launch regression", () => {
|
||||
describe.runIf(isPlatform("win32"))("Windows spawn launch regression", () => {
|
||||
test("launches a cmd shim from a path with spaces without corrupting JSON args", async () => {
|
||||
const fixture = makeFixture();
|
||||
|
||||
@@ -227,7 +227,7 @@ describe.runIf(process.platform === "win32")("Windows spawn launch regression",
|
||||
});
|
||||
});
|
||||
|
||||
describe.skipIf(process.platform === "win32")("spawn launch regression smoke", () => {
|
||||
describe.skipIf(isPlatform("win32"))("spawn launch regression smoke", () => {
|
||||
test("direct launch with a space-containing executable works on this platform", async () => {
|
||||
const fixture = makeFixture();
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ describe("execCommand", () => {
|
||||
|
||||
const result = await execCommand(command.command, command.args, { cwd });
|
||||
|
||||
expect(result.stdout.trim()).toBe(cwd);
|
||||
expect(realpathSync(result.stdout.trim())).toBe(cwd);
|
||||
expect(result.stderr).toBe("");
|
||||
});
|
||||
|
||||
|
||||
1125
packages/server/src/utils/worktree.posix.test.ts
Normal file
1125
packages/server/src/utils/worktree.posix.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user