diff --git a/Taskfile b/Taskfile index 9eeaa50..9fa64cf 100755 --- a/Taskfile +++ b/Taskfile @@ -1,11 +1,11 @@ #!/usr/bin/env bash playwright:local() { - bash e2e/Taskfile playwright:local + bash e2e/Taskfile playwright:local "$@" } playwright:ui() { - bash e2e/Taskfile playwright:ui + bash e2e/Taskfile playwright:ui "$@" } refresh_sqlx_db() { diff --git a/e2e/Taskfile b/e2e/Taskfile index 8cb16ea..ee88f38 100755 --- a/e2e/Taskfile +++ b/e2e/Taskfile @@ -10,20 +10,12 @@ playwright:local() { exec docker run \ --interactive --tty --rm --ipc=host --net=host \ --volume "$SCRIPT_DIR":/e2e:rw --env BASE_URL="$BASE_URL" \ - --env ASTRO_TELEMETRY_DISABLED=1 \ "mcr.microsoft.com/playwright:$(_playwright_version)" \ bash -c "cd /e2e && env PROJECT_FILTER=firefox ./Taskfile _test $*" } playwright:ui() { - xhost +local:docker - exec docker run \ - --interactive --tty --rm --ipc=host --net=host\ - --env DISPLAY="$DISPLAY" \ - --volume /tmp/.X11-unix:/tmp/.X11-unix \ - --volume "$SCRIPT_DIR":/e2e:rw --env BASE_URL="$BASE_URL" \ - "mcr.microsoft.com/playwright:$(_playwright_version)" \ - /bin/bash -c "cd /e2e && ./Taskfile _test --ui $*" + playwright:local --ui-host=0.0.0.0 } playwright:ci() { diff --git a/e2e/pages/contact.spec.ts b/e2e/pages/contact.spec.ts index a1e411d..8b4318d 100644 --- a/e2e/pages/contact.spec.ts +++ b/e2e/pages/contact.spec.ts @@ -41,23 +41,52 @@ test('allow marking as inactive', async ({ page }) => { await page.getByRole('link', { name: /edit/i }).click(); await expect(page.locator('#alpine-loaded')).not.toHaveAttribute('x-cloak'); - // TODO: this only works if there's no other comboboxes on the page :/ - await page.getByRole('combobox').selectOption('Inactive') + await page.getByLabel('status').selectOption('Inactive'); await page.getByRole('button', { name: /save/i }).click(); - await expect(page.locator('#alpine-loaded')).not.toHaveAttribute('x-cloak'); await expect(page.locator('#contacts-sidebar').getByText("Test Testerson")).not.toBeVisible(); }); test('allow exempting from stale', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('#freshness')).toContainText('Test Testersonnever'); + await page.locator('#freshness').getByRole('link', { name: /testerson/i }).click(); + await page.getByRole('link', { name: /edit/i }).click(); + await page.getByLabel('status').selectOption('Cannot go stale'); + await page.getByRole('button', { name: /save/i }).click(); + await page.goto('/'); + await expect(page.locator('#freshness')).not.toContainText('Test Testersonnever'); }); test('stale list considers periodicity', async ({ page }) => { + await page.getByRole('link', { name: /edit/i }).click(); + const last_week = (() => { + let last_week = new Date(); + last_week.setDate(last_week.getDate() - 7); + return last_week.toISOString().split("T")[0]; + })(); + await page.getByLabel('freshened').fill(last_week); + await page.getByRole('button', { name: /save/i }).click(); + await expect(page.locator('#journal')).toBeVisible(); + await expect(page.locator('#fields')).toContainText(`freshened${last_week}`); + await page.goto('/'); + await expect(page.locator('#freshness')).toContainText(`Test Testerson${last_week}7d`); + await page.locator('#freshness').getByRole('link', { name: /testerson/i }).click(); + await page.getByRole('link', { name: /edit/i }).click(); + + await page.getByLabel('minimum stale time').fill('2 weeks'); + await page.getByRole('button', { name: /save/i }).click(); + await expect(page.locator('#journal')).toBeVisible(); + + await page.goto('/'); + await expect(page.locator('#freshness')).not.toContainText(`Test Testerson`); }); test('page title has contact primary name', async ({ page }) => { + // wait for page load to finish + await expect(page.locator('#journal')).toBeVisible(); expect(await page.title()).toContain("Test Testerson"); }); diff --git a/src/web/contact/mod.rs b/src/web/contact/mod.rs index 9f4bf8f..7dc487b 100644 --- a/src/web/contact/mod.rs +++ b/src/web/contact/mod.rs @@ -220,12 +220,16 @@ mod get { .await?; let cid_url = format!("/contact/{}", contact.id); - let mfresh_str = contact + let mfresh_on_str = contact .manually_freshened_at .clone() .map_or("".to_string(), |m| { m.to_zoned(TimeZone::UTC).date().to_string() }); + let mfresh_at_str = contact + .manually_freshened_at + .clone() + .map_or("".to_string(), |m| m.to_zoned(TimeZone::UTC).to_string()); let text_body: String = sqlx::query!("select text_body from contacts where id = $1", contact_id) @@ -261,17 +265,17 @@ mod get { input type="button" value="Add" x-on:click="names.push(new_name); new_name = ''"; } } - label { "status" } + label for="status" { "status" } div { - select name="status" x-model=("status") { + select #status name="status" x-model=("status") { option value="normal" { "Normal" } option value="permanent" { "Cannot go stale" } option value="inactive" { "Inactive" } } } - label x-show="status === 'normal'" { "minimum stale time" } + label x-show="status === 'normal'" for="periodicity" { "minimum stale time" } div x-show="status === 'normal'"{ - input name="periodicity" value=(format!("{:#}", contact.periodicity)); + input name="periodicity" id="periodicity" value=(format!("{:#}", contact.periodicity)); span .hint { code { "[0-9]+ (yr|mo|wk|day|h|m|s)" } "(" a href="https://docs.rs/jiff/latest/jiff/struct.Span.html#parsing-and-printing" { "details" } ")" } } label { "birthday" } @@ -279,8 +283,8 @@ mod get { input name="birthday" value=(contact.birthday.clone().map_or("".to_string(), |b| b.serialize())); span .hint { code { "(yyyy|--)mmdd" } " or free text" } } - label { "freshened" } - div x-data=(json!({ "date": mfresh_str, "stamp": "" })) x-init="today = () => (new Date().toISOString().split('T')[0])" { + label for="manually_freshened_on" { "freshened" } + div x-data=(json!({ "date": mfresh_on_str, "stamp": mfresh_at_str })) x-init="today = () => (new Date().toISOString().split('T')[0])" { input type="hidden" name="manually_freshened_at" @@ -288,6 +292,7 @@ mod get { input type="date" name="manually_freshened_on" + id="manually_freshened_on" x-model="date" x-bind:max="today()" x-on:input="stamp = new Date(date).toISOString()";