148 lines
4.7 KiB
TypeScript
148 lines
4.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
articleInputSchema,
|
|
confirmedFactCardSchema,
|
|
candidateFactCardSchema,
|
|
qaReportSchema,
|
|
} from "../validation";
|
|
|
|
describe("domain validation", () => {
|
|
it("accepts article input with title, body, images, platform, and instructions", () => {
|
|
const parsed = articleInputSchema.parse({
|
|
title: "How GEO Optimization Improves Brand Visibility",
|
|
body: "A practical overview of GEO optimization for marketing teams.",
|
|
images: [
|
|
{ type: "description", content: "Dashboard screenshot" },
|
|
{ type: "link", content: "https://example.com/image.png" },
|
|
],
|
|
platform: "official_site",
|
|
user_instructions: "Keep the article factual and concise.",
|
|
});
|
|
|
|
expect(parsed.images).toHaveLength(2);
|
|
expect(parsed.platform).toBe("official_site");
|
|
});
|
|
|
|
it("marks a fact card with unresolved uncertain items as not ready for optimization", () => {
|
|
const parsed = candidateFactCardSchema.parse({
|
|
company_full_name: "Example Technology Co., Ltd.",
|
|
company_short_names: ["Example Tech"],
|
|
brand_names: ["Example"],
|
|
product_names: ["Example GEO"],
|
|
target_industry: "GEO optimization",
|
|
target_audience: "Marketing teams",
|
|
experience_years: 8,
|
|
core_claims: ["Eight years of GEO optimization experience"],
|
|
forbidden_claims: [],
|
|
image_topics: ["Product dashboard"],
|
|
uncertain_items: ["Conflicting product names found"],
|
|
});
|
|
|
|
expect(parsed.is_ready_for_optimization).toBe(false);
|
|
});
|
|
|
|
it("normalizes near-valid LLM fact card field types", () => {
|
|
const emptyExperience = candidateFactCardSchema.parse({
|
|
company_full_name: "Example Technology Co., Ltd.",
|
|
company_short_names: ["Example Tech"],
|
|
brand_names: ["Example"],
|
|
product_names: ["Example GEO"],
|
|
target_industry: "GEO optimization",
|
|
target_audience: ["Marketing teams", "Brand teams"],
|
|
experience_years: "",
|
|
core_claims: ["GEO optimization experience"],
|
|
forbidden_claims: [],
|
|
image_topics: [],
|
|
uncertain_items: [],
|
|
});
|
|
|
|
const numericExperience = candidateFactCardSchema.parse({
|
|
company_full_name: "Example Technology Co., Ltd.",
|
|
company_short_names: ["Example Tech"],
|
|
brand_names: ["Example"],
|
|
product_names: ["Example GEO"],
|
|
target_industry: "GEO optimization",
|
|
target_audience: "Marketing teams",
|
|
experience_years: "8年",
|
|
core_claims: ["GEO optimization experience"],
|
|
forbidden_claims: [],
|
|
image_topics: [],
|
|
uncertain_items: [],
|
|
});
|
|
|
|
expect(emptyExperience.target_audience).toBe("Marketing teams、Brand teams");
|
|
expect(emptyExperience.experience_years).toBeNull();
|
|
expect(numericExperience.experience_years).toBe(8);
|
|
});
|
|
|
|
it("keeps incomplete candidate fact cards editable and ready", () => {
|
|
const parsed = candidateFactCardSchema.parse({
|
|
company_full_name: "",
|
|
company_short_names: [],
|
|
brand_names: [],
|
|
product_names: [],
|
|
target_industry: "",
|
|
target_audience: "",
|
|
experience_years: "",
|
|
core_claims: [],
|
|
forbidden_claims: [],
|
|
image_topics: [],
|
|
uncertain_items: [],
|
|
});
|
|
|
|
expect(parsed.target_industry).toBe("");
|
|
expect(parsed.target_audience).toBe("");
|
|
expect(parsed.experience_years).toBeNull();
|
|
expect(parsed.uncertain_items).toEqual([]);
|
|
expect(parsed.is_ready_for_optimization).toBe(true);
|
|
});
|
|
|
|
it("rejects a confirmed fact card with an empty company full name", () => {
|
|
expect(() =>
|
|
confirmedFactCardSchema.parse({
|
|
company_full_name: "",
|
|
company_short_names: ["Example"],
|
|
brand_names: ["Example"],
|
|
product_names: ["Example GEO"],
|
|
target_industry: "GEO optimization",
|
|
target_audience: "Marketing teams",
|
|
experience_years: 8,
|
|
core_claims: ["Eight years of GEO optimization experience"],
|
|
forbidden_claims: [],
|
|
image_topics: [],
|
|
uncertain_items: [],
|
|
confirmed_by_user: true,
|
|
}),
|
|
).toThrow();
|
|
});
|
|
|
|
it("accepts QA reports only with pass, warn, or fail statuses", () => {
|
|
const valid = qaReportSchema.parse({
|
|
job_id: "job_123",
|
|
revision: 1,
|
|
overall_status: "warn",
|
|
checks: [
|
|
{
|
|
rule_id: "title_quality",
|
|
status: "pass",
|
|
evidence: "Title reads naturally.",
|
|
reason: "No grammar issue detected.",
|
|
suggested_fix: "",
|
|
target_agent: null,
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(valid.checks[0]?.status).toBe("pass");
|
|
expect(() =>
|
|
qaReportSchema.parse({
|
|
job_id: "job_123",
|
|
revision: 1,
|
|
overall_status: "blocked",
|
|
checks: [],
|
|
}),
|
|
).toThrow();
|
|
});
|
|
});
|