From c9ba6db2f170febcd72d39d1c5beb75d2130e6cc Mon Sep 17 00:00:00 2001 From: damingishere-coder Date: Tue, 15 Sep 2026 09:51:00 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E4=BF=9D?= =?UTF-8?q?=E7=95=99=20BOSS=20=E5=88=97=E8=A1=A8=E5=92=8C=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E8=84=B1=E6=95=8F=E7=BC=BA=E5=A4=B1=E6=A0=B7=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chrome-extension/tests/fixtures/README.md | 2 + .../redacted-split-partial-20260915.html | 123 +++++++ .../boss/search/redacted-split-20260915.html | 299 ++++++++++++++++++ chrome-extension/tests/fixtures/catalog.json | 65 +++- front/lib/recruitment-fixtures.test.ts | 7 +- 5 files changed, 494 insertions(+), 2 deletions(-) create mode 100644 chrome-extension/tests/fixtures/boss/detail/redacted-split-partial-20260915.html create mode 100644 chrome-extension/tests/fixtures/boss/search/redacted-split-20260915.html diff --git a/chrome-extension/tests/fixtures/README.md b/chrome-extension/tests/fixtures/README.md index 8adcf39..1e8b5af 100644 --- a/chrome-extension/tests/fixtures/README.md +++ b/chrome-extension/tests/fixtures/README.md @@ -3,6 +3,8 @@ `catalog.json` 是样本索引,每条包含平台、页面类型、来源、HTML 路径及期望结果。保留 23 份根据已有测试和采集器编写的 **synthetic** 样本(`capturedAt` 为 null),另有用户主动导出的 **structural-redacted** 样本;二者不能互相冒充,也不等于真实投递验收。 - `boss/detail/redacted-header-only-20260915`:用户使用 1.8.12 导出的真实结构,正文和身份已替换。只含标题区域与地址,缺 JD、公司和岗位身份,是导出不完整的故障证据。禁止用标题/地址的文本回退结果证明完整 JD 已采集。原始截图未提交。 +- `boss/search/redacted-split-20260915`:1.8.13 导出 15 张卡片及 15 个链接;保留薪资被错误替换为标题别名的原始故障,缺公司结构标记。 +- `boss/detail/redacted-split-partial-20260915`:同次用户提交的详情有一个链接,缺公司/JD 结构标记。跨文件别名不证明真实岗位关联;两份样本均不能作为完整采集或投递验收通过。 - BOSS 列表覆盖去重、外部链接、导航伪链接、空列表及替换后的卡片;详情覆盖岗位与公司信息。 - 智联复用现代采集器,覆盖无岗位链接的列表卡片、独立详情身份、过期详情和空列表。 diff --git a/chrome-extension/tests/fixtures/boss/detail/redacted-split-partial-20260915.html b/chrome-extension/tests/fixtures/boss/detail/redacted-split-partial-20260915.html new file mode 100644 index 0000000..dc91aff --- /dev/null +++ b/chrome-extension/tests/fixtures/boss/detail/redacted-split-partial-20260915.html @@ -0,0 +1,123 @@ +
+
+
+
+
+示例产品运营001 +15-25K +
+ +
+
+脱敏文本 +立即沟通 +
+
+
+
+脱敏文本 + +
+

脱敏文本

+
    +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
+

脱敏文本脱敏文本脱敏文本脱敏文本脱敏文本脱敏文本脱敏文本脱敏文本脱敏文本脱敏文本脱敏文本

+
+
+
+
+

脱敏文本 +

+
脱敏文本
+
+
脱敏文本
脱敏文本
+
+
+脱敏文本
脱敏文本
+
+
+
+查看更多信息 +
+
+
+
脱敏文本
+
+
+ + +
+
+
脱敏文本
+
脱敏文本
脱敏文本
+
+脱敏文本 +
+
+
+
+
+
    +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
  • 脱敏文本
  • +
+
+脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +脱敏文本 +
+
+
+ +
+
+
+
+
+
+
+
diff --git a/chrome-extension/tests/fixtures/boss/search/redacted-split-20260915.html b/chrome-extension/tests/fixtures/boss/search/redacted-split-20260915.html new file mode 100644 index 0000000..28c353c --- /dev/null +++ b/chrome-extension/tests/fixtures/boss/search/redacted-split-20260915.html @@ -0,0 +1,299 @@ +
+ +
+
+
+
+
+
+
+
+
+
+
diff --git a/chrome-extension/tests/fixtures/catalog.json b/chrome-extension/tests/fixtures/catalog.json index 8a4e3df..3d63715 100644 --- a/chrome-extension/tests/fixtures/catalog.json +++ b/chrome-extension/tests/fixtures/catalog.json @@ -409,7 +409,7 @@ "file": "boss/detail/redacted-header-only-20260915.html", "provenance": { "kind": "structural-redacted", - "capturedAt": "2026-09-15T01:19:39.4290000Z", + "capturedAt": "2026-09-15T01:19:39.429Z", "reference": "user-provided boss-job_detail-fixture.json", "redactionVersion": "structural-fixture/1", "limitations": [ @@ -431,5 +431,68 @@ ".company-name" ] } + }, + { + "id": "boss/search/redacted-split-20260915", + "platform": "boss", + "pageType": "SEARCH", + "file": "boss/search/redacted-split-20260915.html", + "provenance": { + "kind": "structural-redacted", + "capturedAt": "2026-09-15T01:44:20.2400000Z", + "reference": "user-provided boss-search-fixture.json", + "redactionVersion": "structural-fixture/2", + "limitations": [ + "公司及 JD 结构标记缺失,不能证明完整解析通过。", + "搜索样本薪资被 1.8.13 错误替换为标题别名;保留原故障,不补造公司或 JD。", + "不同导出文件的 fixture001 等别名不能作为跨文件岗位关联证据。" + ] + }, + "expected": { + "selectorCounts": { + ".job-card-box": 15, + ".job-name": 15, + ".job-salary": 15, + ".company-name": 0 + }, + "firstCard": { + "id": "fixture001", + "title": "示例产品运营001", + "company": "", + "salary": "示例产品运营002" + } + } + }, + { + "id": "boss/detail/redacted-split-partial-20260915", + "platform": "boss", + "pageType": "JOB_DETAIL", + "file": "boss/detail/redacted-split-partial-20260915.html", + "provenance": { + "kind": "structural-redacted", + "capturedAt": "2026-09-15T01:44:26.1010000Z", + "reference": "user-provided boss-job_detail-fixture.json", + "redactionVersion": "structural-fixture/2", + "limitations": [ + "公司及 JD 结构标记缺失,不能证明完整解析通过。", + "搜索样本薪资被 1.8.13 错误替换为标题别名;保留原故障,不补造公司或 JD。", + "不同导出文件的 fixture001 等别名不能作为跨文件岗位关联证据。" + ] + }, + "expected": { + "detail": { + "title": "示例产品运营001", + "salary": "15-25K", + "company": "" + }, + "absentSelectors": [ + ".company-name", + ".job-description", + ".job-sec-text" + ], + "selectorCounts": { + "a[href*=\"/job_detail/\"]": 1 + } + } } ] diff --git a/front/lib/recruitment-fixtures.test.ts b/front/lib/recruitment-fixtures.test.ts index ed16e0a..d78f527 100644 --- a/front/lib/recruitment-fixtures.test.ts +++ b/front/lib/recruitment-fixtures.test.ts @@ -5,7 +5,7 @@ import { describe, expect, it } from 'vitest' const extension = resolve(process.cwd(), '../chrome-extension') const fixtureRoot = resolve(extension, 'tests/fixtures') -type Fixture = { id: string; platform: string; file: string; provenance: { kind: string; reference: string; capturedAt: string | null; redactionVersion?: string; limitations?: string[] }; expected: { jobs?: Record[]; candidateCount?: number; detail?: Record; rejectedExpectedId?: string; cardCount?: number; marker?: string; absentSelectors?: string[] } } +type Fixture = { id: string; platform: string; file: string; provenance: { kind: string; reference: string; capturedAt: string | null; redactionVersion?: string; limitations?: string[] }; expected: { jobs?: Record[]; candidateCount?: number; detail?: Record; rejectedExpectedId?: string; cardCount?: number; marker?: string; absentSelectors?: string[]; selectorCounts?: Record; firstCard?: Record } } const fixtures: Fixture[] = JSON.parse(readFileSync(resolve(fixtureRoot, 'catalog.json'), 'utf8')) function load(fixture: Fixture) { const doc = document.implementation.createHTMLDocument('offline fixture') @@ -51,6 +51,11 @@ describe('versioned recruitment fixture baseline', () => { if (expected.cardCount !== undefined) expect(doc.querySelectorAll('.job-card')).toHaveLength(expected.cardCount) if (expected.marker) expect(doc.body.textContent).toContain(expected.marker) for (const selector of expected.absentSelectors || []) expect(doc.querySelector(selector)).toBeNull() + for (const [selector, count] of Object.entries(expected.selectorCounts || {})) expect(doc.querySelectorAll(selector)).toHaveLength(count) + if (expected.firstCard) { + const result = scope.GetJobsBossSearchCollector.parseCard(doc.querySelector('.job-card-box'), '运营', scope.GetJobsBossSelectors, { origin: 'https://www.zhipin.com', support: scope.GetJobsBossScanSupport }) + expect(result).toMatchObject(expected.firstCard) + } }) it('BOSS explicit parsers do not read the ambient page or mutate the supplied DOM', () => { const fixture = fixtures.find(f => f.id === 'boss/detail/full')! From 98182da385e29757617996ebcbedc2973c2eb906 Mon Sep 17 00:00:00 2001 From: damingishere-coder Date: Tue, 15 Sep 2026 09:51:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E8=84=B1?= =?UTF-8?q?=E6=95=8F=E5=AD=97=E6=AE=B5=E6=8C=89=E6=9C=80=E8=BF=91=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E5=8C=B9=E9=85=8D=E9=81=BF=E5=85=8D=E8=96=AA=E8=B5=84?= =?UTF-8?q?=E8=AF=AF=E5=BD=92=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chrome-extension/fixture-export.js | 9 +++++++-- chrome-extension/manifest.json | 2 +- chrome-extension/tests/boss-hr-assistant.test.cjs | 2 +- chrome-extension/tests/manifest-id.test.cjs | 2 +- .../tests/profile-scoped-scan-contract.test.cjs | 2 +- docs/dom-fixture-regression.md | 10 +++++++--- docs/job-agent-release-acceptance.md | 2 ++ front/lib/fixture-export.test.ts | 9 +++++++++ .../service/BrowserRuntimeRegressionTest.java | 2 +- 9 files changed, 30 insertions(+), 10 deletions(-) diff --git a/chrome-extension/fixture-export.js b/chrome-extension/fixture-export.js index ca47c5d..b467c1e 100644 --- a/chrome-extension/fixture-export.js +++ b/chrome-extension/fixture-export.js @@ -1,6 +1,6 @@ (function (root) { const VERSION = "structural-fixture/1"; - const REDACTION_VERSION = "structural-fixture/2"; + const REDACTION_VERSION = "structural-fixture/3"; const errors = Object.freeze({ UNSUPPORTED_PAGE: "当前页面不是受支持的 BOSS / 智联 HTTPS 招聘页。", CHAT_PAGE: "聊天页面不支持导出,请切换到岗位搜索列表或详情。", @@ -86,7 +86,12 @@ if (!text) return " "; if (fixedText.has(text)) return text; if (/^今日还可沟通\d{1,3}次$/.test(text)) return text === "今日还可沟通0次" ? text : "今日还可沟通3次"; - const field = fields.find(([selector]) => parent?.closest(selector))?.[1]; + // A title/layout wrapper can contain salary or company fields. The nearest + // matching element determines the replacement, not the order of distant ancestors. + let field; + for (let node = parent; node && !field; node = node.parentElement) { + field = fields.find(([selector]) => node.matches(selector))?.[1]; + } if (field === "title") return alias(titles, text, "示例产品运营"); if (field === "company") return alias(companies, text, "示例科技公司"); if (field === "salary") return platform === "boss" ? "15-25K" : "8000-12000元"; diff --git a/chrome-extension/manifest.json b/chrome-extension/manifest.json index 0b06461..cd53c94 100644 --- a/chrome-extension/manifest.json +++ b/chrome-extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "投递牛马 Chrome Bridge", - "version": "1.8.13", + "version": "1.8.14", "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzzdIlNVOv76Y/cSWrjD5Tg2Vlsha8yWHzsn46PBsg724/2dftOUzIIr2n70VRaRgGwEd8FjO/Y768Ori443zF4pQpWvuxXxm05YO25ILQ/+aJLmUycAEdWbkdhcagr4YXnXJdYlSCGSAToSQBjk+owQOdlBLQn5wofPoshrqayoJjRQ5aAUj1SuSlnNv9iimle8GMA1IaA1l5rw6K/chfcgwMTg6HxRAIoludt5JGbIBryi2Lu1hOJRMaDnL7A57ofBnn3qx3H2HIGWGkkTW9EMkls0XMXwx8+mJVIj5HSYl0EeuCvEoTa1W3i1CbOf3kY2yCPKS3Qz3lOvJiwJ4ZQIDAQAB", "description": "Use signed-in Chrome tabs to scan jobs, confirm deliveries, and review BOSS HR reply drafts for 投递牛马.", "icons": { diff --git a/chrome-extension/tests/boss-hr-assistant.test.cjs b/chrome-extension/tests/boss-hr-assistant.test.cjs index 30010d2..30d1828 100644 --- a/chrome-extension/tests/boss-hr-assistant.test.cjs +++ b/chrome-extension/tests/boss-hr-assistant.test.cjs @@ -15,7 +15,7 @@ test("manifest loads the direct HR bridge and one-minute alarm capability", () = const bossScripts = manifest.content_scripts.find((entry) => entry.matches.includes("https://www.zhipin.com/*")).js; assert.deepEqual(bossScripts.slice(-3), ["boss-hr-support.js", "boss-hr-bridge.js", "boss-hr-assistant.js"]); assert.ok(manifest.permissions.includes("alarms")); - assert.equal(manifest.version, "1.8.13"); + assert.equal(manifest.version, "1.8.14"); }); test("assistant exposes policy-gated dedicated watch and preserves explicit manual send", () => { diff --git a/chrome-extension/tests/manifest-id.test.cjs b/chrome-extension/tests/manifest-id.test.cjs index ca2b808..352bb80 100644 --- a/chrome-extension/tests/manifest-id.test.cjs +++ b/chrome-extension/tests/manifest-id.test.cjs @@ -17,7 +17,7 @@ function extensionIdFromKey(key) { test('manifest public key derives the backend allowlisted extension id', () => { const manifestPath = path.join(__dirname, '..', 'manifest.json'); const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')); - assert.equal(manifest.version, '1.8.13'); + assert.equal(manifest.version, '1.8.14'); assert.equal(extensionIdFromKey(manifest.key), EXPECTED_EXTENSION_ID); const publicKey = crypto.createPublicKey({ diff --git a/chrome-extension/tests/profile-scoped-scan-contract.test.cjs b/chrome-extension/tests/profile-scoped-scan-contract.test.cjs index e3965bd..257d6e9 100644 --- a/chrome-extension/tests/profile-scoped-scan-contract.test.cjs +++ b/chrome-extension/tests/profile-scoped-scan-contract.test.cjs @@ -15,7 +15,7 @@ test("extension release and both content scripts use the profile-scoped contract const boss = source("boss-content.js"); const zhilian = source("zhilian-content.js"); - assert.equal(manifest.version, "1.8.13"); + assert.equal(manifest.version, "1.8.14"); assert.match(background, /BACKGROUND_VERSION = "2026-09-14-runtime-adapters"/); assert.match(background, /REQUIRED_BOSS_CONTENT_VERSION = "2026-09-14-boss-adapter"/); assert.match(boss, /EXTENSION_VERSION = "2026-09-14-boss-adapter"/); diff --git a/docs/dom-fixture-regression.md b/docs/dom-fixture-regression.md index ba74957..2902d13 100644 --- a/docs/dom-fixture-regression.md +++ b/docs/dom-fixture-regression.md @@ -1,10 +1,10 @@ # P0.2:DOM Fixture 与纯解析入口 -本轮保护现有采集/投递行为。没有修改 BOSS content、智联执行器、后台派发、AI、后端或数据库;没有新增权限、自动采集或上传通道。导出器兼容修复随扩展 1.8.13 发布。 +本轮保护现有采集/投递行为。没有修改 BOSS content、智联执行器、后台派发、AI、后端或数据库;没有新增权限、自动采集或上传通道。结构范围修复随 1.8.13 发布,嵌套字段识别修复随 1.8.14 发布。 ## 样本与运行 -`chrome-extension/tests/fixtures/catalog.json` 管理平台、页面类型、来源、日期、HTML 路径及期望结果。保留 23 份 **合成样本**;新增一份 2026-09-15 用户主动导出的 **脱敏结构故障样本**,仅有标题和地址,不能当成完整页面或投递验收通过。没有保存账号数据或原始截图。 +`chrome-extension/tests/fixtures/catalog.json` 管理平台、页面类型、来源、日期、HTML 路径及期望结果。保留 23 份 **合成样本**和三份 2026-09-15 用户主动导出的 **脱敏结构故障样本**。首份只有标题和地址,后两份已包含列表卡片及详情链接,但仍有字段缺失,不能当成完整页面或投递验收通过。没有保存账号数据或原始截图。 - BOSS:列表字段、去重、非法/导航 URL、空列表、卡片替换后的结构;详情的标题、公司、薪资、地点、经验、学历、JD、公司介绍。 - 智联:现代分栏详情、稳定岗位身份、旧详情拒绝、空列表;复用现有 `readCard/readDetail`,不重构智联。 @@ -40,7 +40,7 @@ pnpm typecheck ## 用户主动导出 -1. 在 Chrome 扩展管理页重新加载 1.8.13,并刷新招聘标签页。打开自己正在使用的 BOSS / 智联页面,无需启动扫描。 +1. 在 Chrome 扩展管理页重新加载当前版本,并刷新招聘标签页。打开自己正在使用的 BOSS / 智联页面,无需启动扫描。 2. 点击工具栏上的投递牛马扩展图标,选择搜索列表、岗位详情或阻断弹窗。 3. 点击“生成脱敏预览”。只有此动作才读取当前标签页的白名单 DOM;没有白名单结构就失败,不回退整页抓取。 4. 在只读文本框检查 JSON。确认无个人信息、聊天或凭据后勾选确认框,再点击下载。 @@ -50,6 +50,10 @@ pnpm typecheck 本次输入未包含搜索列表 DOM,截图无法确定其精确类名。已验证的是新增结构模式的离线回归;当天真实列表/完整 JD 的兼容性仍需用户重导验证。不要把这次兼容扩展标记为真实 Smoke 已通过。 +后续 1.8.13 重导样本保留了 15 张卡片和 15 个链接,但 `.job-salary` 位于 `.job-title` 内,旧字段替换按照字段列表优先级寻找任意祖先,误将薪资替换成标题别名。1.8.14 改为由当前元素逐层向上匹配,最近字段优先;下载格式仍为 `structural-fixture/1`,脱敏规则版本为 `structural-fixture/3`。原故障样本不重写,测试分别验证历史输入和新规则。 + +同批详情已保留一个岗位链接,原始公司/JD 类名仍在脱敏过程中丢失,不能由当前文件反推 Selector。需要用户提供这两处最小 `class` 信息后再适配;不能把普通“脱敏文本”或标题回退结果算作完整公司/JD。不同文件里的 `fixture001` 独立分配,不证明列表与详情是同一个真实岗位。 + 导出器先构造新的脱敏 DOM,再序列化。原始整页 HTML 不先落盘,也不发送给后台。脚本、图片、表单、可编辑区、聊天和身份子树被排除;任意属性、类名、URL 参数/片段被删除。只保留固定标签、类名、少量 display/visibility/position/opacity 值、已知状态词;自由文本和身份替换为虚构内容。同名标题保持同名,岗位 ID 在一次导出内一致映射。跨导出别名不能当成稳定业务 ID。 这是 **结构脱敏样本**:能复现已知 Selector 与有限布局形状,不能证明真实 JD 或未知状态词解析正确;未允许的类名与文本会损失。遇到新结构应人工编写对应合成变体和期望结果,不能放宽为原文全量导出。超过节点/深度/根数量限制则整次失败,不输出部分成功。 diff --git a/docs/job-agent-release-acceptance.md b/docs/job-agent-release-acceptance.md index 776a6b1..118f02c 100644 --- a/docs/job-agent-release-acceptance.md +++ b/docs/job-agent-release-acceptance.md @@ -33,6 +33,8 @@ 2026-09-15 用户确认加载 1.8.12,并提供 BOSS 详情脱敏 JSON 与导出失败截图:详情只含标题和地址,搜索导出失败。本次记为“导出验收未通过”,已将脱敏详情保留为故障 Fixture;1.8.13 补充结构范围、失败原因和不完整提示后,等待同页面重新导出。没有据此执行真实投递或启用 Runtime。 +同日后续收到规则版本 2 的搜索/详情 JSON:搜索导出通道已通过,保留 15 张卡片及 15 个链接;详情保留一个链接。公司/JD 仍缺失,而且列表薪资被标题祖先错误替换,完整 Fixture 验收仍未通过。1.8.14 修正就近字段匹配;公司/JD 适配等待最小源元素 class 信息,不通过放宽全部类名或保留原文绕过脱敏边界。 + 真实 Smoke 未完成前不启用新 Runtime、不删除 Legacy、不宣称 Phase A 全部验收。实际 Next.js 确认链已由离线浏览器测试覆盖;招聘平台预检和副作用仍是合成场景,不能代替真人网站验收。 ## 回滚与后续使用 diff --git a/front/lib/fixture-export.test.ts b/front/lib/fixture-export.test.ts index b87e4de..35e52a7 100644 --- a/front/lib/fixture-export.test.ts +++ b/front/lib/fixture-export.test.ts @@ -18,6 +18,15 @@ function doc(html: string) { return d } describe('user-triggered structural redaction', () => { + it('uses the nearest field element, so salary inside a title wrapper remains salary', () => { + const input = doc('
  • PRIVATE_CITYPRIVATE_COMPANY
  • ') + const output = doc(exporter().capture(input, 'https://www.zhipin.com/web/geek/jobs', 'SEARCH').html) + expect(output.querySelector('.job-name')?.textContent).toBe('示例产品运营001') + expect(output.querySelector('.job-salary')?.textContent).toBe('15-25K') + expect(output.querySelector('.job-area')?.textContent).toBe('北京') + expect(output.querySelector('.company-name')?.textContent).toContain('示例科技公司001') + expect(output.body.textContent).not.toContain('PRIVATE') + }) it('exports BOSS collector-supported split containers without retaining unknown class names or private text', () => { const input = doc('
    PRIVATE_TITLEPRIVATE_COMPANY30-50K
    PRIVATE_TITLE
    PRIVATE_JD
    PRIVATE_HR
    ') const list = exporter().capture(input, 'https://www.zhipin.com/web/geek/jobs', 'SEARCH') diff --git a/src/test/java/com/getjobs/application/service/BrowserRuntimeRegressionTest.java b/src/test/java/com/getjobs/application/service/BrowserRuntimeRegressionTest.java index c40d6e6..48179d1 100644 --- a/src/test/java/com/getjobs/application/service/BrowserRuntimeRegressionTest.java +++ b/src/test/java/com/getjobs/application/service/BrowserRuntimeRegressionTest.java @@ -97,7 +97,7 @@ Object probe(String body) { worker.getByText("缺少职位描述(JD)", new Page.GetByTextOptions().setExact(false)).waitFor(); var bundle = new com.fasterxml.jackson.databind.ObjectMapper().readTree(worker.locator("#preview").inputValue()); assertThat(bundle.path("coverage").path("descriptions").asInt()).isZero(); - assertThat(bundle.path("provenance").path("redactionVersion").asText()).isEqualTo("structural-fixture/2"); + assertThat(bundle.path("provenance").path("redactionVersion").asText()).isEqualTo("structural-fixture/3"); assertThat(worker.locator("#download").isDisabled()).isTrue(); worker.locator("#reviewed").check(); assertThat(worker.locator("#download").isEnabled()).isTrue();