Externalize audit pipeline services
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
import {
|
||||
buildAuditEvidenceInput,
|
||||
type SkillRegistryEntryEvidence,
|
||||
} from "../lib/ai/audit-evidence";
|
||||
import { parseSkillsRegistry } from "../lib/skills-registry";
|
||||
|
||||
const SAMPLE_SKILL_REGISTRY: SkillRegistryEntryEvidence[] = [
|
||||
{
|
||||
@@ -335,3 +338,159 @@ test("buildAuditEvidenceInput selects deterministic skills and supports design/u
|
||||
assert.equal(selectedCategories.has(category), true);
|
||||
}
|
||||
});
|
||||
|
||||
test("buildAuditEvidenceInput prioritizes local-audit v3 skills before cap", () => {
|
||||
const source = readFileSync(
|
||||
join(process.cwd(), "v2_elemente", "skills.md"),
|
||||
"utf8",
|
||||
);
|
||||
const skillRegistry = parseSkillsRegistry(source);
|
||||
|
||||
assert.equal(
|
||||
skillRegistry.some((skill) => skill.id === "visual-design" && !skill.category),
|
||||
true,
|
||||
);
|
||||
|
||||
const actual = buildAuditEvidenceInput({
|
||||
lead: {
|
||||
companyName: "Bäckerei Muster",
|
||||
niche: "Bäckerei",
|
||||
city: "Berlin",
|
||||
websiteDomain: "example.com",
|
||||
},
|
||||
crawlPages: [
|
||||
{
|
||||
sourceUrl: "https://example.com",
|
||||
finalUrl: "https://example.com",
|
||||
pageKind: "homepage",
|
||||
title: "Bäckerei Muster Berlin",
|
||||
visibleTextExcerpt:
|
||||
"Frische Backwaren in Berlin. Rufen Sie uns an oder schreiben Sie uns fuer eine Bestellung.",
|
||||
hasContactCtaSignal: true,
|
||||
},
|
||||
{
|
||||
sourceUrl: "https://example.com/kontakt",
|
||||
finalUrl: "https://example.com/kontakt",
|
||||
pageKind: "contact",
|
||||
title: "Kontakt",
|
||||
visibleTextExcerpt:
|
||||
"Telefon 030 123456, E-Mail hallo@example.com, Öffnungszeiten und Kontaktformular.",
|
||||
hasContactFormSignal: true,
|
||||
hasContactCtaSignal: true,
|
||||
},
|
||||
],
|
||||
technicalChecks: [
|
||||
{
|
||||
sourceUrl: "https://example.com",
|
||||
finalUrl: "https://example.com",
|
||||
usesHttps: true,
|
||||
missingMetaDescription: true,
|
||||
hasVisibleContactPath: true,
|
||||
},
|
||||
],
|
||||
screenshots: [
|
||||
{
|
||||
storageId: "desktop-storage",
|
||||
sourceUrl: "https://example.com",
|
||||
viewport: "desktop",
|
||||
width: 1280,
|
||||
height: 900,
|
||||
mimeType: "image/png",
|
||||
capturedAt: 1700000000000,
|
||||
},
|
||||
{
|
||||
storageId: "mobile-storage",
|
||||
sourceUrl: "https://example.com",
|
||||
viewport: "mobile",
|
||||
width: 390,
|
||||
height: 844,
|
||||
mimeType: "image/png",
|
||||
capturedAt: 1700000001000,
|
||||
},
|
||||
],
|
||||
pageSpeedInputs: [
|
||||
{
|
||||
strategy: "mobile",
|
||||
status: "succeeded",
|
||||
sourceUrl: "https://example.com",
|
||||
normalized: {
|
||||
implications: [
|
||||
"Die wichtigsten Inhalte erscheinen auf dem Smartphone spürbar verzögert.",
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
skillRegistry,
|
||||
});
|
||||
|
||||
const selectedIds = new Set(actual.selectedSkills.map((skill) => skill.id));
|
||||
assert.deepEqual(actual.selectedSkills.map((skill) => skill.id), [
|
||||
"visual-design",
|
||||
"contact-conversion",
|
||||
"local-seo-basics",
|
||||
"performance-experience",
|
||||
"mobile-usability",
|
||||
"conversion-copy",
|
||||
]);
|
||||
assert.equal(actual.selectedSkills.length, 6);
|
||||
for (const id of [
|
||||
"visual-design",
|
||||
"contact-conversion",
|
||||
"local-seo-basics",
|
||||
"performance-experience",
|
||||
]) {
|
||||
assert.equal(selectedIds.has(id), true, `${id} should be inside the cap.`);
|
||||
}
|
||||
assert.equal(
|
||||
actual.selectedSkills.every((skill) => skill.category === undefined),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("buildAuditEvidenceInput gates v3 skills when declared inputs are missing", () => {
|
||||
const source = readFileSync(
|
||||
join(process.cwd(), "v2_elemente", "skills.md"),
|
||||
"utf8",
|
||||
);
|
||||
const skillRegistry = parseSkillsRegistry(source);
|
||||
|
||||
const actual = buildAuditEvidenceInput({
|
||||
lead: {
|
||||
companyName: "Bäckerei Muster",
|
||||
websiteDomain: "example.com",
|
||||
},
|
||||
crawlPages: [
|
||||
{
|
||||
sourceUrl: "https://example.com",
|
||||
finalUrl: "https://example.com",
|
||||
pageKind: "homepage",
|
||||
title: "Bäckerei Muster",
|
||||
},
|
||||
],
|
||||
screenshots: [
|
||||
{
|
||||
storageId: "desktop-storage",
|
||||
sourceUrl: "https://example.com",
|
||||
viewport: "desktop",
|
||||
width: 1280,
|
||||
height: 900,
|
||||
mimeType: "image/png",
|
||||
capturedAt: 1700000000000,
|
||||
},
|
||||
],
|
||||
skillRegistry,
|
||||
});
|
||||
|
||||
const selectedIds = new Set(actual.selectedSkills.map((skill) => skill.id));
|
||||
for (const id of [
|
||||
"visual-design",
|
||||
"first-impression-clarity",
|
||||
"contact-conversion",
|
||||
"mobile-usability",
|
||||
"conversion-copy",
|
||||
"performance-experience",
|
||||
]) {
|
||||
assert.equal(selectedIds.has(id), false, `${id} should require missing inputs.`);
|
||||
}
|
||||
assert.equal(selectedIds.has("accessibility-basics"), true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user