惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
V
Visual Studio Blog
罗磊的独立博客
爱范儿
爱范儿
J
Java Code Geeks
博客园 - 司徒正美
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
美团技术团队
小众软件
小众软件
Google DeepMind News
Google DeepMind News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX
博客园 - 聂微东
云风的 BLOG
云风的 BLOG
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Jina AI
Jina AI
Y
Y Combinator Blog
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Martin Fowler
Martin Fowler
Vercel News
Vercel News

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
test: clear fs-safe broad matchers · openclaw/openclaw@cf...
steipete · 2026-05-10 · via Recent Commits to openclaw:main

@@ -24,6 +24,17 @@ afterEach(async () => {

2424

await tempDirs.cleanup();

2525

});

262627+

async function expectRejectCode(promise: Promise<unknown>, expected: string | RegExp) {

28+

const err = await promise.catch((caught: unknown) => caught);

29+

expect(err).toBeDefined();

30+

const code = (err as NodeJS.ErrnoException).code;

31+

if (typeof expected === "string") {

32+

expect(code).toBe(expected);

33+

} else {

34+

expect(code).toMatch(expected);

35+

}

36+

}

37+2738

async function runWriteOpenRace(params: {

2839

slotPath: string;

2940

outsideDir: string;

@@ -38,11 +49,9 @@ async function runWriteOpenRace(params: {

3849

try {

3950

await params.runWrite();

4051

} catch (err) {

41-

expect(err).toMatchObject({

42-

code: expect.stringMatching(

43-

/outside-workspace|path-mismatch|path-alias|invalid-path|not-file/,

44-

),

45-

});

52+

expect((err as NodeJS.ErrnoException).code).toMatch(

53+

/outside-workspace|path-mismatch|path-alias|invalid-path|not-file/,

54+

);

4655

}

4756

},

4857

});

@@ -121,9 +130,7 @@ describe("fs-safe", () => {

121130122131

it("rejects directories", async () => {

123132

const dir = await tempDirs.make("openclaw-fs-safe-");

124-

await expect(readLocalFileSafely({ filePath: dir })).rejects.toMatchObject({

125-

code: "not-file",

126-

});

133+

await expectRejectCode(readLocalFileSafely({ filePath: dir }), "not-file");

127134

const err = await readLocalFileSafely({ filePath: dir }).catch((e: unknown) => e);

128135

expect(err).toBeInstanceOf(FsSafeError);

129136

expect((err as FsSafeError).message).not.toMatch(/EISDIR/i);

@@ -149,9 +156,7 @@ describe("fs-safe", () => {

149156

const file = path.join(dir, "big.bin");

150157

await fs.writeFile(file, Buffer.alloc(8));

151158152-

await expect(readLocalFileSafely({ filePath: file, maxBytes: 4 })).rejects.toMatchObject({

153-

code: "too-large",

154-

});

159+

await expectRejectCode(readLocalFileSafely({ filePath: file, maxBytes: 4 }), "too-large");

155160

});

156161157162

it.runIf(process.platform !== "win32")("rejects symlinks", async () => {

@@ -161,9 +166,7 @@ describe("fs-safe", () => {

161166

await fs.writeFile(target, "target");

162167

await fs.symlink(target, link);

163168164-

await expect(readLocalFileSafely({ filePath: link })).rejects.toMatchObject({

165-

code: "symlink",

166-

});

169+

await expectRejectCode(readLocalFileSafely({ filePath: link }), "symlink");

167170

});

168171169172

it.runIf(process.platform !== "win32")(

@@ -200,17 +203,15 @@ describe("fs-safe", () => {

200203201204

await expect(

202205

(await openRoot(root)).open(path.join("..", path.basename(outside), "outside.txt")),

203-

).rejects.toMatchObject({ code: "outside-workspace" });

206+

).rejects.toSatisfy((err: NodeJS.ErrnoException) => err.code === "outside-workspace");

204207

});

205208206209

it("rejects directory path within root without leaking EISDIR (issue #31186)", async () => {

207210

const root = await tempDirs.make("openclaw-fs-safe-root-");

208211

await fs.mkdir(path.join(root, "memory"), { recursive: true });

209212210213

const rootFs = await openRoot(root);

211-

await expect(rootFs.open("memory")).rejects.toMatchObject({

212-

code: expect.stringMatching(/invalid-path|not-file/),

213-

});

214+

await expectRejectCode(rootFs.open("memory"), /invalid-path|not-file/);

214215215216

const err = await rootFs.open("memory").catch((e: unknown) => e);

216217

expect(err).toBeInstanceOf(FsSafeError);

@@ -246,9 +247,7 @@ describe("fs-safe", () => {

246247

await fs.writeFile(target, "outside");

247248

await fs.symlink(target, link);

248249249-

await expect((await openRoot(root)).open("link.txt")).rejects.toMatchObject({

250-

code: "symlink",

251-

});

250+

await expectRejectCode((await openRoot(root)).open("link.txt"), "symlink");

252251

});

253252254253

it.runIf(process.platform !== "win32")(

@@ -273,7 +272,7 @@ describe("fs-safe", () => {

273272

(await openRoot(root)).read("link.txt", {

274273

symlinks: "follow-within-root",

275274

}),

276-

).rejects.toMatchObject({ code: "path-mismatch" });

275+

).rejects.toSatisfy((err: NodeJS.ErrnoException) => err.code === "path-mismatch");

277276

},

278277

);

279278

@@ -294,9 +293,7 @@ describe("fs-safe", () => {

294293

if (openedHandle === undefined) {

295294

throw new Error("expected opened file handle");

296295

}

297-

await expect(openedHandle.readFile({ encoding: "utf8" })).rejects.toMatchObject({

298-

code: "EBADF",

299-

});

296+

await expectRejectCode(openedHandle.readFile({ encoding: "utf8" }), "EBADF");

300297

});

301298302299

it("rejects setting fs-safe test hooks outside test mode", () => {

@@ -316,9 +313,7 @@ describe("fs-safe", () => {

316313

await withOutsideHardlinkAlias({

317314

aliasPath: hardlinkPath,

318315

run: async () => {

319-

await expect((await openRoot(root)).open("link.txt")).rejects.toMatchObject({

320-

code: "hardlink",

321-

});

316+

await expectRejectCode((await openRoot(root)).open("link.txt"), "hardlink");

322317

},

323318

});

324319

});

@@ -365,7 +360,7 @@ describe("fs-safe", () => {

365360366361

await (await openRoot(root)).remove("nested/out.txt");

367362368-

await expect(fs.stat(targetPath)).rejects.toMatchObject({ code: "ENOENT" });

363+

await expectRejectCode(fs.stat(targetPath), "ENOENT");

369364

});

370365371366

it("creates directories within root safely", async () => {

@@ -405,9 +400,7 @@ describe("fs-safe", () => {

405400406401

await (await openRoot(root)).remove(path.join("alias", "target.txt"));

407402408-

await expect(fs.stat(path.join(realDir, "target.txt"))).rejects.toMatchObject({

409-

code: "ENOENT",

410-

});

403+

await expectRejectCode(fs.stat(path.join(realDir, "target.txt")), "ENOENT");

411404

},

412405

);

413406

@@ -421,10 +414,8 @@ describe("fs-safe", () => {

421414

(await openRoot(root)).copyIn("nested/big.bin", sourcePath, {

422415

maxBytes: 4,

423416

}),

424-

).rejects.toMatchObject({ code: "too-large" });

425-

await expect(fs.stat(path.join(root, "nested", "big.bin"))).rejects.toMatchObject({

426-

code: "ENOENT",

427-

});

417+

).rejects.toSatisfy((err: NodeJS.ErrnoException) => err.code === "too-large");

418+

await expectRejectCode(fs.stat(path.join(root, "nested", "big.bin")), "ENOENT");

428419

});

429420430421

it("writes a file within root from another local source path safely", async () => {

@@ -439,9 +430,7 @@ describe("fs-safe", () => {

439430

});

440431

it("rejects write traversal outside root", async () => {

441432

const root = await tempDirs.make("openclaw-fs-safe-root-");

442-

await expect((await openRoot(root)).write("../escape.txt", "x")).rejects.toMatchObject({

443-

code: "outside-workspace",

444-

});

433+

await expectRejectCode((await openRoot(root)).write("../escape.txt", "x"), "outside-workspace");

445434

});

446435447436

it.runIf(process.platform !== "win32")("rejects writing through hardlink aliases", async () => {

@@ -450,9 +439,7 @@ describe("fs-safe", () => {

450439

await withOutsideHardlinkAlias({

451440

aliasPath: hardlinkPath,

452441

run: async (outsideFile) => {

453-

await expect((await openRoot(root)).write("alias.txt", "pwned")).rejects.toMatchObject({

454-

code: "path-alias",

455-

});

442+

await expectRejectCode((await openRoot(root)).write("alias.txt", "pwned"), "path-alias");

456443

await expect(fs.readFile(outsideFile, "utf8")).resolves.toBe("outside");

457444

},

458445

});

@@ -468,7 +455,7 @@ describe("fs-safe", () => {

468455

(await openRoot(root)).append("alias.txt", "pwned", {

469456

prependNewlineIfNeeded: true,

470457

}),

471-

).rejects.toMatchObject({ code: "path-alias" });

458+

).rejects.toSatisfy((err: NodeJS.ErrnoException) => err.code === "path-alias");

472459

await expect(fs.readFile(outsideFile, "utf8")).resolves.toBe("outside");

473460

},

474461

});

@@ -526,11 +513,10 @@ describe("fs-safe", () => {

526513

symlinkTarget: outside,

527514

timing: "before-realpath",

528515

run: async () => {

529-

await expect(

516+

await expectRejectCode(

530517

(await openRoot(root)).remove(path.join("slot", "target.txt")),

531-

).rejects.toMatchObject({

532-

code: expect.stringMatching(/path-alias|not-found/),

533-

});

518+

/path-alias|not-found/,

519+

);

534520

},

535521

});

536522

@@ -557,15 +543,14 @@ describe("fs-safe", () => {

557543

symlinkTarget: outside,

558544

timing: "before-realpath",

559545

run: async () => {

560-

await expect(

546+

await expectRejectCode(

561547

(await openRoot(root)).mkdir(path.join("slot", "nested", "deep")),

562-

).rejects.toMatchObject({

563-

code: "path-alias",

564-

});

548+

"path-alias",

549+

);

565550

},

566551

});

567552568-

await expect(fs.stat(path.join(outside, "nested"))).rejects.toMatchObject({ code: "ENOENT" });

553+

await expectRejectCode(fs.stat(path.join(outside, "nested")), "ENOENT");

569554

},

570555

);

571556

@@ -594,9 +579,7 @@ describe("fs-safe", () => {

594579

const missing = path.join(dir, "missing.txt");

595580596581

await expect(readLocalFileSafely({ filePath: missing })).rejects.toBeInstanceOf(FsSafeError);

597-

await expect(readLocalFileSafely({ filePath: missing })).rejects.toMatchObject({

598-

code: "not-found",

599-

});

582+

await expectRejectCode(readLocalFileSafely({ filePath: missing }), "not-found");

600583

});

601584

});

602585

@@ -637,8 +620,9 @@ describe("tilde expansion in file tools", () => {

637620

}

638621639622

const outsideRoot = await tempDirs.make("openclaw-tilde-outside-");

640-

await expect((await openRoot(outsideRoot)).open("~/escape.txt")).rejects.toMatchObject({

641-

code: expect.stringMatching(/outside-workspace|not-found|invalid-path/),

642-

});

623+

await expectRejectCode(

624+

(await openRoot(outsideRoot)).open("~/escape.txt"),

625+

/outside-workspace|not-found|invalid-path/,

626+

);

643627

});

644628

});