From 97485aa4e9e2f2acbd775228adc24ffec1713894 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 16 Jun 2026 13:50:48 +0800 Subject: [PATCH] test: add optimizer mvp samples and smoke test --- package-lock.json | 21 +++++++++++++-- package.json | 1 + playwright.config.ts | 21 +++++++++++++++ samples/articles/company-name.json | 12 +++++++++ samples/articles/experience-conflict.json | 12 +++++++++ samples/articles/image-text-mismatch.json | 12 +++++++++ samples/articles/industry-drift.json | 12 +++++++++ samples/articles/title-quality.json | 12 +++++++++ tests/e2e/mvp.spec.ts | 33 +++++++++++++++++++++++ vitest.config.ts | 1 + 10 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 playwright.config.ts create mode 100644 samples/articles/company-name.json create mode 100644 samples/articles/experience-conflict.json create mode 100644 samples/articles/image-text-mismatch.json create mode 100644 samples/articles/industry-drift.json create mode 100644 samples/articles/title-quality.json create mode 100644 tests/e2e/mvp.spec.ts diff --git a/package-lock.json b/package-lock.json index 5d8ebc9..9a6171f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "zod": "^4.4.3" }, "devDependencies": { + "@playwright/test": "^1.61.0", "@types/better-sqlite3": "^7.6.13", "@types/node": "^25.9.3", "@types/react": "^19.2.17", @@ -1534,6 +1535,22 @@ "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@playwright/test": { + "version": "1.61.0", + "resolved": "https://registry.npmmirror.com/@playwright/test/-/test-1.61.0.tgz", + "integrity": "sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.61.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", @@ -6620,7 +6637,7 @@ "version": "1.61.0", "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.61.0.tgz", "integrity": "sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "dependencies": { "playwright-core": "1.61.0" @@ -6639,7 +6656,7 @@ "version": "1.61.0", "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.61.0.tgz", "integrity": "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" diff --git a/package.json b/package.json index cbb03f5..ebe8ca9 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "zod": "^4.4.3" }, "devDependencies": { + "@playwright/test": "^1.61.0", "@types/better-sqlite3": "^7.6.13", "@types/node": "^25.9.3", "@types/react": "^19.2.17", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..73f92d4 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,21 @@ +import { defineConfig, devices } from "@playwright/test"; + +export default defineConfig({ + testDir: "./tests/e2e", + webServer: { + command: "npm run dev", + url: "http://localhost:3000", + reuseExistingServer: true, + timeout: 120_000, + }, + use: { + baseURL: "http://localhost:3000", + trace: "on-first-retry", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], +}); diff --git a/samples/articles/company-name.json b/samples/articles/company-name.json new file mode 100644 index 0000000..49e81af --- /dev/null +++ b/samples/articles/company-name.json @@ -0,0 +1,12 @@ +{ + "name": "Incomplete company name sample", + "input": { + "title": "Example GEO Guide", + "body": "Example has 8 years of GEO optimization experience and helps marketing teams improve content structure.", + "image_lines": "Product dashboard", + "platform": "official_site", + "user_instructions": "Use the confirmed company full name." + }, + "expectedHardFailures": ["company_name_integrity"], + "expectedWarnings": [] +} diff --git a/samples/articles/experience-conflict.json b/samples/articles/experience-conflict.json new file mode 100644 index 0000000..2161eb1 --- /dev/null +++ b/samples/articles/experience-conflict.json @@ -0,0 +1,12 @@ +{ + "name": "Experience conflict sample", + "input": { + "title": "Example Technology Co., Ltd. GEO experience", + "body": "Example Technology Co., Ltd. has 8 years of GEO optimization experience. Another paragraph says it has 12 years of service.", + "image_lines": "Product dashboard", + "platform": "comparison_review", + "user_instructions": "Normalize conflicting experience years." + }, + "expectedHardFailures": ["claim_consistency"], + "expectedWarnings": [] +} diff --git a/samples/articles/image-text-mismatch.json b/samples/articles/image-text-mismatch.json new file mode 100644 index 0000000..71df839 --- /dev/null +++ b/samples/articles/image-text-mismatch.json @@ -0,0 +1,12 @@ +{ + "name": "Image text mismatch sample", + "input": { + "title": "Example Technology Co., Ltd. GEO guide", + "body": "Example Technology Co., Ltd. has 8 years of GEO optimization experience for marketing teams.", + "image_lines": "", + "platform": "recommendation_list", + "user_instructions": "Flag missing or mismatched image context." + }, + "expectedHardFailures": [], + "expectedWarnings": ["image_text_match"] +} diff --git a/samples/articles/industry-drift.json b/samples/articles/industry-drift.json new file mode 100644 index 0000000..0bb2bc6 --- /dev/null +++ b/samples/articles/industry-drift.json @@ -0,0 +1,12 @@ +{ + "name": "Industry drift sample", + "input": { + "title": "Example Technology Co., Ltd. Finance Automation Launch", + "body": "Example Technology Co., Ltd. has 8 years of GEO optimization experience, but this draft shifts into banking automation and unrelated finance workflow claims.", + "image_lines": "Product dashboard", + "platform": "official_site", + "user_instructions": "Keep the article factual." + }, + "expectedHardFailures": ["industry_alignment"], + "expectedWarnings": [] +} diff --git a/samples/articles/title-quality.json b/samples/articles/title-quality.json new file mode 100644 index 0000000..ab50348 --- /dev/null +++ b/samples/articles/title-quality.json @@ -0,0 +1,12 @@ +{ + "name": "Title quality sample", + "input": { + "title": "GEO GEO GEO!!!", + "body": "Example Technology Co., Ltd. has 8 years of GEO optimization experience.", + "image_lines": "Product dashboard", + "platform": "media_article", + "user_instructions": "Fix the title grammar." + }, + "expectedHardFailures": ["title_quality"], + "expectedWarnings": [] +} diff --git a/tests/e2e/mvp.spec.ts b/tests/e2e/mvp.spec.ts new file mode 100644 index 0000000..e8e5af4 --- /dev/null +++ b/tests/e2e/mvp.spec.ts @@ -0,0 +1,33 @@ +import { expect, test } from "@playwright/test"; + +test("happy path creates optimized article and export links", async ({ page }) => { + await page.goto("/"); + + await page.getByLabel("Title").fill("Example Technology Co., Ltd. GEO guide"); + await page + .getByLabel("Body") + .fill( + "Example Technology Co., Ltd. has 8 years of GEO optimization experience. Example GEO helps marketing teams improve content structure.", + ); + await page.getByLabel("Images").fill("Product dashboard"); + await page.getByLabel("User instructions").fill("Keep factual"); + + await page.getByRole("button", { name: "Analyze" }).click(); + await expect(page.getByText("Candidate fact card created.")).toBeVisible(); + + await page + .locator("label") + .filter({ hasText: "uncertain items" }) + .locator("textarea") + .fill(""); + await page.getByRole("button", { name: "Confirm" }).click(); + await expect(page.getByText("Fact card confirmed.")).toBeVisible(); + + await page.getByRole("button", { name: "Optimize" }).click(); + await expect(page.getByText("Optimization complete.")).toBeVisible(); + await expect(page.getByText("Quality Report")).toBeVisible(); + + await expect(page.getByRole("link", { name: "optimized.md" })).toBeVisible(); + await expect(page.getByRole("link", { name: "optimized.docx" })).toBeVisible(); + await expect(page.getByRole("link", { name: "qa_report.json" })).toBeVisible(); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 835a0e0..26e69ed 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { environment: "jsdom", + exclude: ["**/node_modules/**", "**/.git/**", "tests/e2e/**"], passWithNoTests: true, }, });