3db642e76b
getRecentTimeLogs was still receiving the page-level brand constant, so Recent Activity read 'No shifts yet' even when manual entries existed for the worker's actual brand. Mirror the getOpenClockIn / getWorkerPayPeriodHours / submitManualTimeLog pattern: prefer session.brand_id over the page prop so the Hub, manual-entry, and history surfaces all see the same data regardless of which brand slug the URL carries. Adds scripts/cycle12-flow.mjs and scripts/cycle12-submit.mjs as end-to-end coverage for Hub → Manual Entry → Recent Activity → Submit, so the brand_id wiring stays regression-protected.
98 lines
3.3 KiB
JavaScript
98 lines
3.3 KiB
JavaScript
/**
|
|
* Cycle 12 — submit a manual entry and verify the success screen
|
|
* renders. Uses yesterday's date so the server's 30-day window
|
|
* accepts it.
|
|
*/
|
|
import { chromium } from "playwright";
|
|
import { mkdirSync } from "node:fs";
|
|
|
|
const BASE = process.env.PLAYWRIGHT_URL ?? "http://localhost:4000";
|
|
const OUT = "tests/_artifacts/cycle12";
|
|
mkdirSync(OUT, { recursive: true });
|
|
|
|
const COOKIE_VALUE = [
|
|
"5a83c1a3-8eb5-44c4-bb66-323e72d38c91",
|
|
"smoke-" + Math.random().toString(36).slice(2, 10),
|
|
new Date(Date.now() + 12 * 3600 * 1000).toISOString(),
|
|
"Worker 1",
|
|
"time_admin",
|
|
"en",
|
|
"11111111-1111-1111-1111-111111111111",
|
|
].join("|");
|
|
|
|
async function main() {
|
|
const browser = await chromium.launch({ headless: true });
|
|
const ctx = await browser.newContext({
|
|
viewport: { width: 412, height: 900 },
|
|
deviceScaleFactor: 2,
|
|
});
|
|
await ctx.addCookies([
|
|
{
|
|
name: "time_tracking_session",
|
|
value: COOKIE_VALUE,
|
|
url: BASE,
|
|
httpOnly: false,
|
|
secure: false,
|
|
sameSite: "Lax",
|
|
},
|
|
]);
|
|
const page = await ctx.newPage();
|
|
page.on("pageerror", (e) => console.error("PAGE ERROR:", e.message));
|
|
page.on("console", (m) => {
|
|
if (m.type() === "error") console.error("CONSOLE ERR:", m.text());
|
|
});
|
|
|
|
await page.goto(`${BASE}/tuxedo/time-clock`, { waitUntil: "domcontentloaded" });
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Hub → Manual entry
|
|
await page.locator('button:has-text("Manual entry")').first().click();
|
|
await page.waitForTimeout(800);
|
|
|
|
// Fill form. Date defaults to today; use yesterday's date to make
|
|
// sure we're definitely within the 30-day window and not in the
|
|
// future. Use a real-looking shift: 07:00 → 15:30 (8h 30m, minus
|
|
// 30m lunch = 8h).
|
|
const yesterday = new Date(Date.now() - 86_400_000);
|
|
const yyyy = yesterday.getFullYear();
|
|
const mm = String(yesterday.getMonth() + 1).padStart(2, "0");
|
|
const dd = String(yesterday.getDate()).padStart(2, "0");
|
|
const dateStr = `${yyyy}-${mm}-${dd}`;
|
|
|
|
await page.locator('input[type="date"]').first().fill(dateStr);
|
|
await page.locator('input[placeholder*="Harvesting"]').first().fill("Harvesting");
|
|
await page
|
|
.locator('input[placeholder*="Required"]')
|
|
.first()
|
|
.fill("Forgot to clock in this morning");
|
|
await page.screenshot({ path: `${OUT}/05_manual_before_submit.png` });
|
|
|
|
await page.locator('button:has-text("Submit entry")').click();
|
|
// Wait for either success or error
|
|
await page.waitForTimeout(3000);
|
|
await page.screenshot({ path: `${OUT}/06_after_submit.png` });
|
|
const text = await page.locator("body").innerText();
|
|
if (/Entry submitted|Entrada enviada/i.test(text)) {
|
|
console.log("✓ Success screen rendered");
|
|
} else if (/16 hours|30 days|3 characters|cannot be in the future|Must be after|Reason/i.test(text)) {
|
|
console.error("✗ Validation error visible:");
|
|
console.error(text.slice(0, 1500));
|
|
process.exit(1);
|
|
} else {
|
|
console.error("? Unknown state after submit:");
|
|
console.error(text.slice(0, 1500));
|
|
process.exit(1);
|
|
}
|
|
|
|
// Take a clean success shot by scrolling to top
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await page.waitForTimeout(300);
|
|
await page.screenshot({ path: `${OUT}/07_success.png` });
|
|
|
|
await browser.close();
|
|
}
|
|
|
|
main().catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
}); |