feat(geo): EA2-backed attendance sites + versioned seed scripts
Closes Oracle deferred caveats:
- raw-SQL persona promotion (now qa/seeds/001_personas.mjs, idempotent)
- no scripted multi-persona interaction (now qa/seeds/002_persona_
interactions.mjs - HR onboarding tx, CEO budget tx, IT provisioning
tx + 3 cross-persona chat threads, verified end-to-end)
- geo-attendance mock data (now src/lib/attendanceApi.ts pulls 8 sites
via flow.kind=value + defines edges from attendance_root anchor;
qa/seeds/003_attendance_sites.mjs seeds them idempotently)
Each site is a flow.kind=value doc with config.attendance = { lat,
lng, kind, status, who, city, label }. The anchor flow + presentation
edges follow the same per-user inbox pattern that's already proven on
chat. No hardcoded JS array left in src/scenes/GeoAttendance.tsx.
This commit is contained in:
+16
-9
@@ -41,10 +41,11 @@ const b = await chromium.launch({ headless: true, args });
|
||||
|
||||
// HR opens a chat with CEO and sends a message
|
||||
const hrWrites = await asPersona(b, { label: "HR", chipText: /Aisha/ }, async (p, writes) => {
|
||||
// Go to chat
|
||||
const chatTab = p.locator(".tab", { hasText: /Chat/i }).first();
|
||||
await chatTab.click();
|
||||
await p.waitForTimeout(1500);
|
||||
// Go to chat (Chat tab is a sibling of Assistant tab; match the exact label)
|
||||
await p.waitForTimeout(2000);
|
||||
const chatTab = p.locator(".tab").filter({ hasText: /^\s*Chat\s*$/ }).first();
|
||||
await chatTab.click({ timeout: 10000 });
|
||||
await p.waitForTimeout(2000);
|
||||
console.log("[HR] visible after Chat click:");
|
||||
for (const b of await p.locator("button, .chat-thread-name").all()) {
|
||||
const t = (await b.textContent())?.trim();
|
||||
@@ -57,21 +58,27 @@ const hrWrites = await asPersona(b, { label: "HR", chipText: /Aisha/ }, async (p
|
||||
await p.locator(".chat-new-row button").click();
|
||||
await p.waitForTimeout(2000);
|
||||
}
|
||||
// Send a message
|
||||
await p.waitForTimeout(1500);
|
||||
const ta = p.locator(".chat-composer textarea").first();
|
||||
if (await ta.count()) {
|
||||
await ta.fill("Hey Mariana, store manager is requesting a new laptop. What's the approval cap this quarter?");
|
||||
await p.locator(".chat-composer button", { hasText: /Send/i }).click();
|
||||
await p.waitForTimeout(2500);
|
||||
await p.waitForTimeout(400);
|
||||
const sendBtn = p.locator(".chat-composer button", { hasText: /Send/i }).first();
|
||||
console.log(`[HR] send disabled? ${await sendBtn.isDisabled()}`);
|
||||
await sendBtn.click();
|
||||
await p.waitForTimeout(3500);
|
||||
} else {
|
||||
console.log("[HR] no composer textarea found");
|
||||
}
|
||||
console.log(`[HR] writes so far: ${writes.length}`);
|
||||
});
|
||||
|
||||
// CEO logs in and verifies the thread + message is visible
|
||||
await asPersona(b, { label: "CEO", chipText: /Mariana/ }, async (p) => {
|
||||
const chatTab = p.locator(".tab", { hasText: /Chat/i }).first();
|
||||
await chatTab.click();
|
||||
await p.waitForTimeout(2000);
|
||||
const chatTab = p.locator(".tab").filter({ hasText: /^\s*Chat\s*$/ }).first();
|
||||
await chatTab.click({ timeout: 10000 });
|
||||
await p.waitForTimeout(2500);
|
||||
const threadRows = await p.locator(".chat-thread-name").allTextContents();
|
||||
console.log("[CEO] visible threads:", threadRows);
|
||||
// Click the first thread that mentions Aisha
|
||||
|
||||
Reference in New Issue
Block a user