Skip to content

Commit

Permalink
Use Playwright assertions for autofocus (#1219)
Browse files Browse the repository at this point in the history
Closes [#1154][]

Replace bespoke CSS selector-based assertions with Playwright's built-in
[toBeFocused](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-be-focused)
assertion.

Like other assertions, `toBeFocused` will wait and retry for a period of
time, which makes `nextBeat` calls unnecessary.

[#1154]: #1154
  • Loading branch information
seanpdoyle committed Mar 5, 2024
1 parent f0beef3 commit 8c66861
Showing 1 changed file with 12 additions and 102 deletions.
114 changes: 12 additions & 102 deletions src/tests/functional/autofocus_tests.js
Original file line number Diff line number Diff line change
@@ -1,150 +1,65 @@
import { test } from "@playwright/test"
import { assert } from "chai"
import { hasSelector, nextBeat } from "../helpers/page"
import { expect, test } from "@playwright/test"

test.beforeEach(async ({ page }) => {
await page.goto("/src/tests/fixtures/autofocus.html")
})

test("autofocus first autofocus element on load", async ({ page }) => {
await nextBeat()
assert.ok(
await hasSelector(page, "#first-autofocus-element:focus"),
"focuses the first [autofocus] element on the page"
)
assert.notOk(
await hasSelector(page, "#second-autofocus-element:focus"),
"focuses the first [autofocus] element on the page"
)
await expect(page.locator("#first-autofocus-element")).toBeFocused()
})

test("autofocus first [autofocus] element on visit", async ({ page }) => {
await page.goto("/src/tests/fixtures/navigation.html")
await page.click("#autofocus-link")
await nextBeat()

assert.ok(
await hasSelector(page, "#first-autofocus-element:focus"),
"focuses the first [autofocus] element on the page"
)
assert.notOk(
await hasSelector(page, "#second-autofocus-element:focus"),
"focuses the first [autofocus] element on the page"
)
await expect(page.locator("#first-autofocus-element")).toBeFocused()
})

test("navigating a frame with a descendant link autofocuses [autofocus]:first-of-type", async ({ page }) => {
await page.click("#frame-inner-link")
await nextBeat()

assert.ok(
await hasSelector(page, "#frames-form-first-autofocus-element:focus"),
"focuses the first [autofocus] element in frame"
)
assert.notOk(
await hasSelector(page, "#frames-form-second-autofocus-element:focus"),
"focuses the first [autofocus] element in frame"
)
await expect(page.locator("#frames-form-first-autofocus-element")).toBeFocused()
})

test("autofocus visible [autofocus] element on visit with inert elements", async ({ page }) => {
await page.click("#autofocus-inert-link")
await nextBeat()

assert.notOk(
await hasSelector(page, "#dialog-autofocus-element:focus"),
"autofocus element is ignored in a closed dialog"
)
assert.notOk(
await hasSelector(page, "#details-autofocus-element:focus"),
"autofocus element is ignored in a closed details"
)
assert.notOk(
await hasSelector(page, "#hidden-autofocus-element:focus"),
"autofocus element is ignored in a hidden div"
)
assert.notOk(
await hasSelector(page, "#inert-autofocus-element:focus"),
"autofocus element is ignored in an inert div"
)
assert.notOk(
await hasSelector(page, "#disabled-autofocus-element:focus"),
"autofocus element is ignored when disabled"
)
assert.ok(
await hasSelector(page, "#visible-autofocus-element:focus"),
"focuses the visible [autofocus] element on the page"
)
await expect(page.locator("#visible-autofocus-element")).toBeFocused()
})

test("navigating a frame with a link targeting the frame autofocuses [autofocus]:first-of-type", async ({
page
}) => {
await page.click("#frame-outer-link")
await nextBeat()

assert.ok(
await hasSelector(page, "#frames-form-first-autofocus-element:focus"),
"focuses the first [autofocus] element in frame"
)
assert.notOk(
await hasSelector(page, "#frames-form-second-autofocus-element:focus"),
"focuses the first [autofocus] element in frame"
)
await expect(page.locator("#frames-form-first-autofocus-element")).toBeFocused()
})

test("navigating a frame with a turbo-frame targeting the frame autofocuses [autofocus]:first-of-type", async ({
page
}) => {
await page.click("#drives-frame-target-link")
await nextBeat()

assert.ok(
await hasSelector(page, "#frames-form-first-autofocus-element:focus"),
"focuses the first [autofocus] element in frame"
)
assert.notOk(
await hasSelector(page, "#frames-form-second-autofocus-element:focus"),
"focuses the first [autofocus] element in frame"
)
await expect(page.locator("#frames-form-first-autofocus-element")).toBeFocused()
})

test("receiving a Turbo Stream message with an [autofocus] element when the activeElement is the document", async ({ page }) => {
await page.evaluate(() => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur()
}
document.activeElement.blur()
window.Turbo.renderStreamMessage(`
<turbo-stream action="append" targets="body">
<template><input id="autofocus-from-stream" autofocus></template>
</turbo-stream>
`)
})
await nextBeat()

assert.ok(
await hasSelector(page, "#autofocus-from-stream:focus"),
"focuses the [autofocus] element in from the turbo-stream"
)
await expect(page.locator("#autofocus-from-stream")).toBeFocused()
})

test("autofocus from a Turbo Stream message does not leak a placeholder [id]", async ({ page }) => {
await page.evaluate(() => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur()
}
document.activeElement.blur()
window.Turbo.renderStreamMessage(`
<turbo-stream action="append" targets="body">
<template><div id="container-from-stream"><input autofocus></div></template>
</turbo-stream>
`)
})
await nextBeat()

assert.ok(
await hasSelector(page, "#container-from-stream input:focus"),
"focuses the [autofocus] element in from the turbo-stream"
)
await expect(page.locator("#container-from-stream input")).toBeFocused()
})

test("receiving a Turbo Stream message with an [autofocus] element when an element within the document has focus", async ({ page }) => {
Expand All @@ -155,10 +70,5 @@ test("receiving a Turbo Stream message with an [autofocus] element when an eleme
</turbo-stream>
`)
})
await nextBeat()

assert.ok(
await hasSelector(page, "#first-autofocus-element:focus"),
"focuses the first [autofocus] element on the page"
)
await expect(page.locator("#first-autofocus-element")).toBeFocused()
})

0 comments on commit 8c66861

Please sign in to comment.