Refine PitchFast campaign visual identity
This commit is contained in:
@@ -9,8 +9,9 @@ const campaignsBoardPath = join(
|
||||
"campaigns",
|
||||
"campaigns-board.tsx",
|
||||
);
|
||||
const globalsPath = join(process.cwd(), "app", "globals.css");
|
||||
|
||||
test("campaign board renders campaigns as responsive cards", async () => {
|
||||
test("campaign board renders campaigns as a desktop ledger with mobile records", async () => {
|
||||
const source = await readFile(campaignsBoardPath, "utf8");
|
||||
|
||||
assert.doesNotMatch(source, /<table\b/i);
|
||||
@@ -20,16 +21,25 @@ test("campaign board renders campaigns as responsive cards", async () => {
|
||||
assert.doesNotMatch(source, /<td\b/i);
|
||||
assert.doesNotMatch(source, /<th\b/i);
|
||||
|
||||
assert.doesNotMatch(source, /md:hidden/i);
|
||||
assert.doesNotMatch(source, /md:block/i);
|
||||
assert.doesNotMatch(source, /className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3"/);
|
||||
assert.match(source, /2xl:grid-cols-\[minmax\(0,1fr\)_21rem\]/);
|
||||
assert.match(source, /campaign-ledger hidden 2xl:block/);
|
||||
assert.match(source, /campaign-mobile-records grid gap-3 2xl:hidden/);
|
||||
assert.match(source, /role="table"/);
|
||||
assert.match(source, /role="rowgroup"/);
|
||||
assert.match(source, /role="row"/);
|
||||
assert.match(source, /role="cell"/);
|
||||
|
||||
assert.match(source, /className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3"/);
|
||||
assert.match(source, /<Card[^>]+aria-labelledby=\{campaignTitleId\}/);
|
||||
assert.match(source, /<Switch/);
|
||||
assert.match(source, /id=\{campaignTitleId\}/);
|
||||
assert.match(source, /openEditDialog\(campaign\)/);
|
||||
assert.match(source, /toggleCampaign\(campaign\)/);
|
||||
assert.match(source, /runCampaign\(campaign\)/);
|
||||
assert.match(source, /Lead-Limit:\s*\{campaign\.maxNewLeadsPerRun\}/);
|
||||
assert.match(source, /Suchlauf starten/);
|
||||
assert.match(source, /Lead-Limit/);
|
||||
assert.match(source, /Audit-Limit/);
|
||||
assert.match(source, /Letzter Lauf/);
|
||||
assert.match(source, /Nächster Lauf/);
|
||||
assert.doesNotMatch(source, /Limits:\s*L/);
|
||||
});
|
||||
|
||||
@@ -39,6 +49,18 @@ test("campaign board surfaces recent run logs", async () => {
|
||||
assert.match(source, /api\.runs\.list/);
|
||||
assert.match(source, /type:\s*"campaign"/);
|
||||
assert.match(source, /Aktuelle Run-Logs/);
|
||||
assert.match(source, /campaign-status-rail/);
|
||||
assert.match(source, /Versand nur nach Freigabe/);
|
||||
assert.match(source, /getRunStatusClassName/);
|
||||
assert.match(source, /getRunStepClassName/);
|
||||
assert.match(source, /run\.errorSummary/);
|
||||
assert.match(source, /campaign_cron_skipped/);
|
||||
});
|
||||
|
||||
test("campaign ledger avoids clipping actions at desktop breakpoints", async () => {
|
||||
const styles = await readFile(globalsPath, "utf8");
|
||||
|
||||
assert.match(styles, /\.campaign-ledger\s*{[\s\S]*overflow-x:\s*auto;/);
|
||||
assert.doesNotMatch(styles, /\.campaign-ledger\s*{[\s\S]*overflow:\s*hidden;/);
|
||||
assert.match(styles, /\.campaign-ledger-row\s*{[\s\S]*min-width:\s*58rem;/);
|
||||
});
|
||||
|
||||
42
tests/dashboard-sidebar-branding.test.ts
Normal file
42
tests/dashboard-sidebar-branding.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
const sidebarPath = join(
|
||||
process.cwd(),
|
||||
"components",
|
||||
"dashboard-sidebar.tsx",
|
||||
);
|
||||
const authEntryPath = join(process.cwd(), "components", "auth-entry.tsx");
|
||||
const layoutPath = join(process.cwd(), "app", "layout.tsx");
|
||||
const globalsPath = join(process.cwd(), "app", "globals.css");
|
||||
|
||||
test("dashboard sidebar uses PitchFast SaaS branding", async () => {
|
||||
const source = await readFile(sidebarPath, "utf8");
|
||||
|
||||
assert.match(source, />\s*PF\s*</);
|
||||
assert.match(source, />\s*PitchFast\s*</);
|
||||
assert.match(source, />\s*Agency Evidence Desk\s*</);
|
||||
assert.doesNotMatch(source, />\s*WebDev Pipeline\s*</);
|
||||
});
|
||||
|
||||
test("light theme sidebar remains a light operational rail", async () => {
|
||||
const styles = await readFile(globalsPath, "utf8");
|
||||
const rootBlock = styles.match(/:root\s*{([\s\S]*?)\n}/)?.[1] ?? "";
|
||||
const darkBlock = styles.match(/\.dark\s*{([\s\S]*?)\n}/)?.[1] ?? "";
|
||||
|
||||
assert.match(rootBlock, /--sidebar:\s*oklch\(0\.94/);
|
||||
assert.match(rootBlock, /--sidebar-foreground:\s*oklch\(0\.19/);
|
||||
assert.match(darkBlock, /--sidebar:\s*oklch\(0\.13/);
|
||||
});
|
||||
|
||||
test("public entry branding also uses PitchFast", async () => {
|
||||
const authEntry = await readFile(authEntryPath, "utf8");
|
||||
const layout = await readFile(layoutPath, "utf8");
|
||||
|
||||
assert.match(authEntry, />\s*PF\s*</);
|
||||
assert.match(authEntry, />\s*PitchFast\s*</);
|
||||
assert.doesNotMatch(authEntry, />\s*WebDev Pipeline\s*</);
|
||||
assert.match(layout, /title:\s*"PitchFast"/);
|
||||
});
|
||||
Reference in New Issue
Block a user