feat: convert campaign and lead views to cards
This commit is contained in:
30
tests/campaigns-board-layout.test.ts
Normal file
30
tests/campaigns-board-layout.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
const campaignsBoardPath = join(
|
||||
process.cwd(),
|
||||
"components",
|
||||
"campaigns",
|
||||
"campaigns-board.tsx",
|
||||
);
|
||||
|
||||
test("campaign board renders campaigns as responsive cards", async () => {
|
||||
const source = await readFile(campaignsBoardPath, "utf8");
|
||||
|
||||
assert.doesNotMatch(source, /<table\b/i);
|
||||
assert.doesNotMatch(source, /<thead\b/i);
|
||||
assert.doesNotMatch(source, /<tbody\b/i);
|
||||
assert.doesNotMatch(source, /<tr\b/i);
|
||||
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.match(source, /className="grid gap-3"/);
|
||||
assert.match(source, /openEditDialog\(campaign\)/);
|
||||
assert.match(source, /toggleCampaign\(campaign\)/);
|
||||
assert.match(source, /runCampaign\(campaign\)/);
|
||||
});
|
||||
112
tests/leads-review-table.test.ts
Normal file
112
tests/leads-review-table.test.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
|
||||
const leadsReviewPath = join(
|
||||
process.cwd(),
|
||||
"components",
|
||||
"leads",
|
||||
"leads-review-table.tsx",
|
||||
);
|
||||
|
||||
test("LeadsReviewTable uses compact card summaries with expandable review details", async () => {
|
||||
const source = await readFile(leadsReviewPath, "utf8");
|
||||
|
||||
assert.doesNotMatch(source, /<table\b/i);
|
||||
assert.doesNotMatch(source, /<thead\b/i);
|
||||
assert.doesNotMatch(source, /<tbody\b/i);
|
||||
assert.doesNotMatch(source, /<tr\b/i);
|
||||
assert.doesNotMatch(source, /<td\b/i);
|
||||
assert.doesNotMatch(source, /<th\b/i);
|
||||
assert.doesNotMatch(source, /min-w-\[/i);
|
||||
|
||||
assert.match(source, /Mehr anzeigen/);
|
||||
assert.match(source, /Weniger anzeigen/);
|
||||
assert.match(source, /aria-expanded=\{[^}]+\}/);
|
||||
assert.match(source, /aria-controls=\{[^}]+\}/);
|
||||
assert.match(source, /id=\{[^}]+\}/);
|
||||
assert.match(
|
||||
source,
|
||||
/aria-expanded=\{[^}]+\}[\s\S]{0,160}aria-controls=\{[^}]+\}[\s\S]{0,160}(Mehr anzeigen|Weniger anzeigen)/i,
|
||||
);
|
||||
assert.match(
|
||||
source,
|
||||
/hidden=\{!?isExpanded\}/,
|
||||
);
|
||||
|
||||
const companyNameMatch = source.match(
|
||||
/<p className="([^"]+)">\s*\{lead\.companyName\}\s*<\/p>/,
|
||||
);
|
||||
assert.ok(
|
||||
companyNameMatch !== null &&
|
||||
/(?:^|\s)(truncate|max-w-full|min-w-0|break-words)(?:\s|$)/.test(
|
||||
companyNameMatch[1],
|
||||
),
|
||||
"Company name should use overflow-safe text classes in compact card.",
|
||||
);
|
||||
|
||||
const nicheMatch = source.match(
|
||||
/lead\.niche\s+\?\?\s+"Nische offen"\}\s*<\/span>/,
|
||||
);
|
||||
assert.ok(
|
||||
nicheMatch !== null,
|
||||
"Niche rendering should still be asserted in test fixture.",
|
||||
);
|
||||
const nicheContainerMatch = source.match(
|
||||
/<span className="([^"]+)">\s*\{lead\.niche\s+\?\?\s+"Nische offen"\}\s*<\/span>/,
|
||||
);
|
||||
assert.ok(
|
||||
nicheContainerMatch !== null &&
|
||||
/(?:^|\s)(truncate|max-w-full|break-all|break-words)(?:\s|$)/.test(
|
||||
nicheContainerMatch[1],
|
||||
),
|
||||
"Niche should use overflow-safe text classes in compact card.",
|
||||
);
|
||||
|
||||
const locationMatch = source.match(/\{location\}/);
|
||||
assert.ok(
|
||||
locationMatch !== null,
|
||||
"Location rendering should still be present in compact card.",
|
||||
);
|
||||
const locationContainerMatch = source.match(
|
||||
/<span className="([^"]+)">\s*\{location\}\s*<\/span>/,
|
||||
);
|
||||
assert.ok(
|
||||
locationContainerMatch !== null &&
|
||||
/(?:^|\s)(truncate|max-w-full|break-words)(?:\s|$)/.test(
|
||||
locationContainerMatch[1],
|
||||
),
|
||||
"Location should use overflow-safe text classes in compact card.",
|
||||
);
|
||||
|
||||
const emailSpanMatch = source.match(
|
||||
/<span className="([^"]+)">\s*\{lead\.email \|\| "Keine E-Mail"\}\s*<\/span>/,
|
||||
);
|
||||
assert.ok(
|
||||
emailSpanMatch !== null &&
|
||||
/(?:^|\s)(break-all|max-w-full|min-w-0)(?:\s|$)/.test(
|
||||
emailSpanMatch[1],
|
||||
),
|
||||
"Lead email should use overflow-safe text classes in compact card.",
|
||||
);
|
||||
|
||||
const phoneSpanMatch = source.match(
|
||||
/<span className="([^"]+)">\s*\{lead\.phone\}\s*<\/span>/,
|
||||
);
|
||||
assert.ok(
|
||||
phoneSpanMatch !== null &&
|
||||
/(?:^|\s)(break-all|max-w-full|min-w-0)(?:\s|$)/.test(phoneSpanMatch[1]),
|
||||
"Lead phone should use overflow-safe text classes in compact card.",
|
||||
);
|
||||
|
||||
assert.match(source, /Kontaktstatus/);
|
||||
assert.match(source, /Review-E-Mail/);
|
||||
assert.match(source, /Review-Quelle/);
|
||||
assert.match(source, /Ansprechperson/);
|
||||
assert.match(source, /Genannte E-Mail als Business-Kontakt/);
|
||||
assert.match(source, /Duplikatstatus/);
|
||||
assert.match(source, /Sperrstatus/);
|
||||
assert.match(source, /Sperren/);
|
||||
assert.match(source, /Speichern/);
|
||||
});
|
||||
Reference in New Issue
Block a user