diff options
| author | amankumarsingh77 <amankumarsingh7702@gmail.com> | 2026-07-27 00:27:08 +0530 |
|---|---|---|
| committer | Aman Kumar <145339995+amankumarsingh77@users.noreply.github.com> | 2026-08-02 19:12:46 +0530 |
| commit | 15a537a99efba614e6e108722462bcb78ec6c3c4 (patch) | |
| tree | 2ff20907fee8ace7a071470d491fe7808dce6a63 /test/deep-research | |
| parent | ce5d808cb4cc3581d85b829656d1d478dc43e3a6 (diff) | |
test: port remaining suites to node:test
Mechanical port of the hand-rolled check() harness. Import-after-env
ordering preserved so suites still read their sandbox dirs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'test/deep-research')
| -rw-r--r-- | test/deep-research/agent-config-test.ts | 72 | ||||
| -rw-r--r-- | test/deep-research/readability-test.ts | 91 | ||||
| -rw-r--r-- | test/deep-research/serp-parser-test.ts | 97 |
3 files changed, 150 insertions, 110 deletions
diff --git a/test/deep-research/agent-config-test.ts b/test/deep-research/agent-config-test.ts index 0e9dfe4..5859060 100644 --- a/test/deep-research/agent-config-test.ts +++ b/test/deep-research/agent-config-test.ts @@ -5,38 +5,48 @@ * non-existent web_search / web_fetch tools. Pure string checks over the * markdown file — no browser, no subagent runtime. * - * Run: npx tsx test/deep-research/agent-config-test.ts + * Run: npm test */ +import { test, before, describe } from "node:test"; +import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -let passed = 0; -let failed = 0; -const check = (cond: boolean, label: string): void => { - if (cond) { - passed++; - console.log(` ✓ ${label}`); - } else { - failed++; - console.error(` ✗ ${label}`); - } -}; - -const agentPath = join(import.meta.dirname, "..", "..", ".pi", "agents", "web-search-researcher.md"); -const raw = readFileSync(agentPath, "utf8"); - -const fmMatch = raw.match(/^---\n([\s\S]*?)\n---/); -const frontmatter = fmMatch ? (fmMatch[1] ?? "") : ""; -const body = fmMatch ? raw.slice(fmMatch[0].length) : raw; -const toolsLine = frontmatter.split("\n").find((l) => l.startsWith("tools:")) ?? ""; - -// S20 -check(toolsLine.includes("browser_web_search"), "S20: tools includes browser_web_search"); -check(toolsLine.includes("browser_read_page"), "S20: tools includes browser_read_page"); -check(!/\bweb_search\b/.test(toolsLine), "S20: tools does NOT include web_search"); -check(!/\bweb_fetch\b/.test(toolsLine), "S20: tools does NOT include web_fetch"); -check(/^\s*isolated:\s*true\s*$/m.test(frontmatter), "S20: isolated: true is present"); -check(!/WebSearch|WebFetch/.test(body), "S20: body has no WebSearch/WebFetch references"); - -console.log(`\n${passed} passed, ${failed} failed`); -if (failed > 0) process.exit(1); +describe("web-search-researcher subagent config references only real tools", () => { + let frontmatter: string; + let body: string; + let toolsLine: string; + + before(() => { + const agentPath = join(import.meta.dirname, "..", "..", ".pi", "agents", "web-search-researcher.md"); + const raw = readFileSync(agentPath, "utf8"); + const fmMatch = raw.match(/^---\n([\s\S]*?)\n---/); + frontmatter = fmMatch ? (fmMatch[1] ?? "") : ""; + body = fmMatch ? raw.slice(fmMatch[0].length) : raw; + toolsLine = frontmatter.split("\n").find((l) => l.startsWith("tools:")) ?? ""; + }); + + test("S20: tools includes browser_web_search", () => { + assert.ok(toolsLine.includes("browser_web_search")); + }); + + test("S20: tools includes browser_read_page", () => { + assert.ok(toolsLine.includes("browser_read_page")); + }); + + test("S20: tools does NOT include web_search", () => { + assert.ok(!/\bweb_search\b/.test(toolsLine)); + }); + + test("S20: tools does NOT include web_fetch", () => { + assert.ok(!/\bweb_fetch\b/.test(toolsLine)); + }); + + test("S20: isolated: true is present", () => { + assert.ok(/^\s*isolated:\s*true\s*$/m.test(frontmatter)); + }); + + test("S20: body has no WebSearch/WebFetch references", () => { + assert.ok(!/WebSearch|WebFetch/.test(body)); + }); +}); diff --git a/test/deep-research/readability-test.ts b/test/deep-research/readability-test.ts index 10f9a8b..ba0e0e0 100644 --- a/test/deep-research/readability-test.ts +++ b/test/deep-research/readability-test.ts @@ -1,46 +1,67 @@ /** * Unit tests for the pure readability extractor — no browser required. * - * Run: npx tsx test/deep-research/readability-test.ts + * Run: npm test */ +import { test, describe } from "node:test"; +import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import { extractReadable, type PageCapture } from "../../src/domains/readpage/readability"; -let passed = 0; -let failed = 0; -const check = (cond: boolean, label: string): void => { - if (cond) { - passed++; - console.log(` ✓ ${label}`); - } else { - failed++; - console.error(` ✗ ${label}`); - } -}; - const fixture = (name: string): PageCapture => JSON.parse(readFileSync(join(import.meta.dirname, "fixtures", name), "utf8")) as PageCapture; -// S10: boilerplate stripped, article content preserved -{ - const page = extractReadable(fixture("article-capture.json")); - check(page.text.includes("Chrome DevTools Protocol lets tools instrument"), "S10: article body text is present"); - check(page.text.includes("Sessions and Targets"), "S10: article headings are preserved"); - check(!page.text.includes("Home Products Blog"), "S10: nav boilerplate is dropped"); - check(!page.text.includes("Copyright 2026"), "S10: footer boilerplate is dropped"); - check(!page.text.includes("Subscribe here for our newsletter"), "S10: high-link-density promo block is dropped"); - check(page.text.includes("## Sessions and Targets"), "S10: paragraph/heading structure preserved as markdown"); - check(page.title === "How the Chrome DevTools Protocol Works" && page.url.startsWith("https://"), "S10: title and url passed through"); - check(page.wordCount > 40, "S10: word count reflects the article body"); -} - -// S11: no clear article node falls back to bounded body text -{ - const page = extractReadable(fixture("no-article-capture.json")); - check(page.text.length > 0, "S11: structure-less page falls back to non-empty body text"); - check(page.text.includes("Your account is active"), "S11: fallback body text carries the real content"); -} - -console.log(`\n${passed} passed, ${failed} failed`); -if (failed > 0) process.exit(1); +describe("pure readability extractor", () => { + // S10: boilerplate stripped, article content preserved + test("S10: article body text is present", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(page.text.includes("Chrome DevTools Protocol lets tools instrument")); + }); + + test("S10: article headings are preserved", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(page.text.includes("Sessions and Targets")); + }); + + test("S10: nav boilerplate is dropped", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(!page.text.includes("Home Products Blog")); + }); + + test("S10: footer boilerplate is dropped", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(!page.text.includes("Copyright 2026")); + }); + + test("S10: high-link-density promo block is dropped", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(!page.text.includes("Subscribe here for our newsletter")); + }); + + test("S10: paragraph/heading structure preserved as markdown", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(page.text.includes("## Sessions and Targets")); + }); + + test("S10: title and url passed through", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(page.title === "How the Chrome DevTools Protocol Works" && page.url.startsWith("https://")); + }); + + test("S10: word count reflects the article body", () => { + const page = extractReadable(fixture("article-capture.json")); + assert.ok(page.wordCount > 40); + }); + + // S11: no clear article node falls back to bounded body text + test("S11: structure-less page falls back to non-empty body text", () => { + const page = extractReadable(fixture("no-article-capture.json")); + assert.ok(page.text.length > 0); + }); + + test("S11: fallback body text carries the real content", () => { + const page = extractReadable(fixture("no-article-capture.json")); + assert.ok(page.text.includes("Your account is active")); + }); +}); diff --git a/test/deep-research/serp-parser-test.ts b/test/deep-research/serp-parser-test.ts index dabd72b..af5ac54 100644 --- a/test/deep-research/serp-parser-test.ts +++ b/test/deep-research/serp-parser-test.ts @@ -1,24 +1,14 @@ /** * Unit tests for the pure Google SERP parser — no browser required. * - * Run: npx tsx test/deep-research/serp-parser-test.ts + * Run: npm test */ +import { test, describe } from "node:test"; +import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import { classifySerp, parseGoogleSerp, type SerpExtraction } from "../../src/domains/search/google-serp"; -let passed = 0; -let failed = 0; -const check = (cond: boolean, label: string): void => { - if (cond) { - passed++; - console.log(` ✓ ${label}`); - } else { - failed++; - console.error(` ✗ ${label}`); - } -}; - const fixture = (name: string): SerpExtraction => JSON.parse(readFileSync(join(import.meta.dirname, "fixtures", name), "utf8")) as SerpExtraction; @@ -26,34 +16,53 @@ const ok = fixture("google-serp-ok.json"); const captcha = fixture("google-serp-captcha.json"); const empty = fixture("google-serp-empty.json"); -// S1: redirect unwrapping + internal/javascript anchors dropped -{ - const results = parseGoogleSerp(ok.anchors, 10); - const urls = results.map((r) => r.url); - check(urls.includes("https://real.example/x"), "S1: /url?q= redirect is unwrapped to the real target"); - check(!urls.some((u) => u.includes("google.com")), "S1: google-internal anchors are dropped"); - check(!urls.some((u) => u.startsWith("javascript:")), "S1: javascript: anchors are dropped"); -} - -// S2: dedupe + rank + limit -{ - const results = parseGoogleSerp(ok.anchors, 10); - const realExampleCount = results.filter((r) => r.url.startsWith("https://real.example/x")).length; - check(realExampleCount === 1, "S2: trailing-slash duplicate collapses to one result"); - check( - results.every((r, i) => r.rank === i + 1), - "S2: rank runs 1..n in input order", - ); - const capped = parseGoogleSerp(ok.anchors, 2); - check(capped.length === 2 && capped[capped.length - 1]?.rank === 2, "S2: limit truncates and ranks stay 1..limit"); -} - -// S3: CAPTCHA / no-results classification -{ - check(classifySerp(ok.pageText, parseGoogleSerp(ok.anchors, 10).length) === "ok", "S3: populated SERP classifies as ok"); - check(classifySerp(captcha.pageText, 0) === "captcha", "S3: captcha page classifies as captcha"); - check(classifySerp(empty.pageText, 0) === "no_results", "S3: empty results classify as no_results"); -} - -console.log(`\n${passed} passed, ${failed} failed`); -if (failed > 0) process.exit(1); +describe("pure Google SERP parser", () => { + // S1: redirect unwrapping + internal/javascript anchors dropped + test("S1: /url?q= redirect is unwrapped to the real target", () => { + const results = parseGoogleSerp(ok.anchors, 10); + const urls = results.map((r) => r.url); + assert.ok(urls.includes("https://real.example/x")); + }); + + test("S1: google-internal anchors are dropped", () => { + const results = parseGoogleSerp(ok.anchors, 10); + const urls = results.map((r) => r.url); + assert.ok(!urls.some((u) => u.includes("google.com"))); + }); + + test("S1: javascript: anchors are dropped", () => { + const results = parseGoogleSerp(ok.anchors, 10); + const urls = results.map((r) => r.url); + assert.ok(!urls.some((u) => u.startsWith("javascript:"))); + }); + + // S2: dedupe + rank + limit + test("S2: trailing-slash duplicate collapses to one result", () => { + const results = parseGoogleSerp(ok.anchors, 10); + const realExampleCount = results.filter((r) => r.url.startsWith("https://real.example/x")).length; + assert.equal(realExampleCount, 1); + }); + + test("S2: rank runs 1..n in input order", () => { + const results = parseGoogleSerp(ok.anchors, 10); + assert.ok(results.every((r, i) => r.rank === i + 1)); + }); + + test("S2: limit truncates and ranks stay 1..limit", () => { + const capped = parseGoogleSerp(ok.anchors, 2); + assert.ok(capped.length === 2 && capped[capped.length - 1]?.rank === 2); + }); + + // S3: CAPTCHA / no-results classification + test("S3: populated SERP classifies as ok", () => { + assert.equal(classifySerp(ok.pageText, parseGoogleSerp(ok.anchors, 10).length), "ok"); + }); + + test("S3: captcha page classifies as captcha", () => { + assert.equal(classifySerp(captcha.pageText, 0), "captcha"); + }); + + test("S3: empty results classify as no_results", () => { + assert.equal(classifySerp(empty.pageText, 0), "no_results"); + }); +}); |
