tldraw/apps/examples/e2e/tests/test-focus.spec.ts
Mime Čuvalo 749b7d4d6d
tests: fix edit→edit flakiness (#3850)
Similar to https://github.com/tldraw/tldraw/pull/3829

Trying to see if adding a small timeout helps fix this flaky test.

### Change Type

<!--  Please select a 'Scope' label ️ -->

- [ ] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [x] `internal` — Does not affect user-facing stuff

<!--  Please select a 'Type' label ️ -->

- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [x] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
2024-05-30 13:06:40 +00:00

227 lines
6.5 KiB
TypeScript

import test, { expect } from '@playwright/test'
import { Editor } from 'tldraw'
declare const EDITOR_A: Editor
declare const EDITOR_B: Editor
declare const EDITOR_C: Editor
// We're just testing the events, not the actual results.
test.describe('Focus', () => {
test('focus events', async ({ page }) => {
await page.goto('http://localhost:5420/multiple/full')
await page.waitForSelector('.tl-canvas')
const EditorA = (await page.$(`.A`))!
const EditorB = (await page.$(`.B`))!
const EditorC = (await page.$(`.C`))!
expect(EditorA).toBeTruthy()
expect(EditorB).toBeTruthy()
expect(EditorC).toBeTruthy()
async function isOnlyFocused(id: 'A' | 'B' | 'C' | null) {
let activeElement: string | null = null
const isA = await EditorA.evaluate(
(node) => document.activeElement === node || node.contains(document.activeElement)
)
const isB = await EditorB.evaluate(
(node) => document.activeElement === node || node.contains(document.activeElement)
)
const isC = await EditorC.evaluate(
(node) => document.activeElement === node || node.contains(document.activeElement)
)
activeElement = isA ? 'A' : isB ? 'B' : isC ? 'C' : null
expect(
activeElement,
`Active element should have been ${id}, but was ${activeElement ?? 'null'} instead`
).toBe(id)
await page.evaluate(
({ id }) => {
if (
!(
EDITOR_A.getInstanceState().isFocused === (id === 'A') &&
EDITOR_B.getInstanceState().isFocused === (id === 'B') &&
EDITOR_C.getInstanceState().isFocused === (id === 'C')
)
) {
throw Error('isFocused is not correct')
}
},
{ id }
)
}
// Component A has autofocus
// Component B does not
// Component C does not
// Component B and C share persistence id
await (await page.$('body'))?.click()
await isOnlyFocused('A')
await EditorA.click()
await isOnlyFocused('A')
await EditorA.click()
await isOnlyFocused('A')
await EditorB.click()
await isOnlyFocused('B')
// Escape does not break focus
await page.keyboard.press('Escape')
await isOnlyFocused('B')
})
test('kbds when not focused', async ({ page }) => {
await page.goto('http://localhost:5420/multiple/full')
await page.waitForSelector('.tl-canvas')
// Should not have any shapes on the page
expect(await page.evaluate(() => EDITOR_A.getCurrentPageShapes().length)).toBe(0)
const EditorA = (await page.$(`.A`))!
await page.keyboard.press('r')
await EditorA.click({ position: { x: 100, y: 100 } })
// Should not have created a shape
expect(await page.evaluate(() => EDITOR_A.getCurrentPageShapes().length)).toBe(1)
const TextArea = page.getByTestId(`textarea`)
await TextArea.focus()
await page.keyboard.type('hello world')
await page.keyboard.press('Control+A')
await page.keyboard.press('Delete')
// Should not have deleted the page
expect(await page.evaluate(() => EDITOR_A.getCurrentPageShapes().length)).toBe(1)
})
test('kbds when focused', async ({ page }) => {
await page.goto('http://localhost:5420/multiple/full')
await page.waitForSelector('.tl-canvas')
const EditorA = (await page.$(`.A`))!
const EditorB = (await page.$(`.B`))!
const EditorC = (await page.$(`.C`))!
expect(EditorA).toBeTruthy()
expect(EditorB).toBeTruthy()
expect(EditorC).toBeTruthy()
await (await page.$('body'))?.click()
expect(await EditorA.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).toBe(
null
)
expect(await EditorB.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).toBe(
null
)
await page.keyboard.press('d')
expect(await EditorA.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).not.toBe(
null
)
expect(await EditorB.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).toBe(
null
)
await EditorB.click()
await page.waitForTimeout(100) // takes 30ms or so to focus
await page.keyboard.press('d')
expect(await EditorA.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).not.toBe(
null
)
expect(await EditorB.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).not.toBe(
null
)
})
test('kbds after clicking on ui elements', async ({ page }) => {
await page.goto('http://localhost:5420/end-to-end')
await page.waitForSelector('.tl-canvas')
const EditorA = (await page.$(`.tl-container`))!
expect(EditorA).toBeTruthy()
const drawButton = await EditorA.$('.tlui-button[data-testid="tools.draw"]')
// select button should be selected, not the draw button
expect(await EditorA.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).toBe(
null
)
await drawButton?.click()
// draw button should be selected now
expect(await EditorA.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).not.toBe(
null
)
await page.keyboard.press('v')
// select button should be selected again
expect(await EditorA.$('.tlui-button[data-testid="tools.draw"][aria-checked="true"]')).toBe(
null
)
})
test('still focuses text after clicking on style button', async ({ page }) => {
await page.goto('http://localhost:5420/end-to-end')
await page.waitForSelector('.tl-canvas')
const EditorA = (await page.$(`.tl-container`))!
expect(EditorA).toBeTruthy()
// Create a new note, text should be focused
await page.keyboard.press('n')
await (await page.$('body'))?.click()
await page.waitForSelector('.tl-shape')
const blueButton = await page.$('.tlui-button[data-testid="style.color.blue"]')
await blueButton?.dispatchEvent('pointerdown')
await blueButton?.click()
await blueButton?.dispatchEvent('pointerup')
// Text should still be focused.
expect(await page.evaluate(() => document.activeElement?.nodeName === 'TEXTAREA')).toBe(true)
})
test('edit->edit, focus stays in the text areas when going from shape-to-shape', async ({
page,
}) => {
await page.goto('http://localhost:5420/end-to-end')
await page.waitForSelector('.tl-canvas')
const EditorA = (await page.$(`.tl-container`))!
expect(EditorA).toBeTruthy()
// Create a new note, text should be focused
await page.keyboard.press('n')
await (await page.$('body'))?.click()
await page.waitForSelector('.tl-shape')
await page.keyboard.type('test')
// create new note next to it
await page.keyboard.press('Tab')
await (await page.$('body'))?.click()
await page.waitForTimeout(1000)
// First note's textarea should be focused.
expect(await EditorA.evaluate(() => !!document.querySelector('.tl-shape textarea:focus'))).toBe(
true
)
})
})