test(e2e): take the mood empty state's add control in the managed-profile journey

Since an empty mood list carries the one add control and the header drops
its own, the journey clicked a header button that unmounted as the list
resolved. Start the profile without entries, assert the empty-state add,
then the header add once an entry exists. Both carry a data-slot.
This commit is contained in:
Marc-André Bombeck committed 2026-10-09 00:41:54 +02:00
1 parent 10f17e71e3
commit 4a02b78f5a
2 files changed
+34 -4

No files matched your search

+29 -3
View File
@@ -26,6 +26,7 @@
* the same ones, for the same reasons written there.
*/
import type { Page } from "@playwright/test";
import pg from "pg";
import { expect, test } from "./setup/test";
import {
@@ -111,15 +112,38 @@ test.describe.serial("a guardian's controls inside a managed profile", () => {
if (!managed) throw new Error("managed record fixture is missing");
test("offers the mood add control and lands the entry", async ({ page }) => {
// The profile starts every run without mood entries. The form stamps an
// entry to the minute and `(user, date, moodLoggedAt)` is unique, so a
// second run inside the same minute (a retry, a repeat) met a 409 for the
// entry the first one wrote. An empty record also fixes which control the
// page offers: the empty state's add, not the header's.
const dbUrl = process.env.DATABASE_URL;
test.skip(!dbUrl, "DATABASE_URL is required to reset the profile's mood");
const pool = new pg.Pool({ connectionString: dbUrl });
try {
await pool.query(
`DELETE FROM mood_entries
WHERE user_id = (SELECT id FROM users WHERE username = $1)`,
[managed.username],
);
} finally {
await pool.end();
}
await openRecord(page, managed.username);
const banner = page.locator('[data-slot="shared-record-banner"]');
await expect(banner).toHaveAttribute("data-record-kind", "managed");
await expect(banner).toHaveAttribute("data-access-level", "manage");
await page.goto("/mood");
const add = page.locator('[data-slot="mood-add-entry"]');
await expect(add).toBeVisible({ timeout: 30_000 });
await add.click();
// Since v1.42 an empty list carries the one add control in its empty
// state and the header drops its own; the header's returns once there is
// an entry to list. Both are asserted on their data-slots.
const addFirst = page.locator('[data-slot="mood-add-first"]');
const addHeader = page.locator('[data-slot="mood-add-entry"]');
await expect(addFirst).toBeVisible({ timeout: 30_000 });
await expect(addHeader).toHaveCount(0);
await addFirst.click();
const face = page.locator('[data-slot="mood-face"][data-mood="GUT"]');
await expect(face).toBeVisible();
@@ -139,6 +163,8 @@ test.describe.serial("a guardian's controls inside a managed profile", () => {
await expect(page.locator('[data-slot="mood-rows"]').first()).toBeVisible({
timeout: 30_000,
});
await expect(addHeader).toBeVisible();
await expect(addFirst).toHaveCount(0);
await leaveRecord(page);
});
+5 -1
View File
@@ -742,7 +742,11 @@ export function MoodList({ onAddFirst, onEmptyChange }: MoodListProps = {}) {
{t("mood.emptyResetFilter")}
</Button>
) : onAddFirst && canManageMind ? (
<Button size="sm" onClick={onAddFirst}>
<Button
size="sm"
onClick={onAddFirst}
data-slot="mood-add-first"
>
<Plus className="h-4 w-4" />
{t("mood.emptyAddFirst")}
</Button>