smithery/the-answerai

playwright-assertions

Playwright assertion patterns and matchers

Installation

$ npx skills add smithery/the-answerai --skill playwright-assertions

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/the-answerai · top by installs.

npx skills add smithery/the-answerai

Browse all from smithery/the-answerai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,563 B
  • docs SUMMARY.md 71 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Playwright Assertions Skill

Patterns for assertions in Playwright tests.

Auto-Retrying Assertions

Element Visibility

// Visible (default)
await expect(page.getByRole('button')).toBeVisible()
await expect(page.getByRole('button')).not.toBeVisible()

// Hidden
await expect(page.getByRole('dialog')).toBeHidden()

// Attached to DOM (even if not visible)
await expect(page.locator('#loading')).toBeAttached()
await expect(page.locator('#loading')).not.toBeAttached()

Element State

// Enabled/Disabled
await expect(page.getByRole('button')).toBeEnabled()
await expect(page.getByRole('button')).toBeDisabled()

// Editable
await expect(page.getByRole('textbox')).toBeEditable()
await expect(page.getByRole('textbox')).not.toBeEditable()

// Focused
await expect(page.getByRole('textbox')).toBeFocused()

// Checked (checkboxes/radio)
await expect(page.getByRole('checkbox')).toBeChecked()
await expect(page.getByRole('checkbox')).not.toBeChecked()

Element Content

// Text content
await expect(page.locator('.message')).toHaveText('Hello World')
await expect(page.locator('.message')).toHaveText(/hello/i)
await expect(page.locator('.message')).toContainText('Hello')

// Multiple elements
await expect(page.locator('.item')).toHaveText([
  'First',
  'Second',
  'Third',
])

// Input value
await expect(page.getByRole('textbox')).toHaveValue('[email protected]')
await expect(page.getByRole('textbox')).toHaveValue(/test/)
await expect(page.getByRole('textbox')).not.toBeEmpty()

// Select value
await expect(page.getByRole('combobox')).toHaveValue('option1')
await expect(page.getByRole('combobox')).toHaveValues(['opt1', 'opt2'])

Element Attributes

// Attribute presence
await expect(page.locator('input')).toHaveAttribute('required')

// Attribute value
await expect(page.locator('a')).toHaveAttribute('href', '/home')
await expect(page.locator('a')).toHaveAttribute('href', /\/home/)

// ID
await expect(page.locator('button')).toHaveId('submit-btn')

// Class
await expect(page.locator('div')).toHaveClass('card active')
await expect(page.locator('div')).toHaveClass(/active/)

// CSS property
await expect(page.locator('.box')).toHaveCSS('background-color', 'rgb(255, 0, 0)')
await expect(page.locator('.box')).toHaveCSS('display', 'flex')

Element Count

// Exact count
await expect(page.locator('.item')).toHaveCount(5)
await expect(page.locator('.item')).toHaveCount(0)

// Empty
await expect(page.locator('.list .item')).not.toHaveCount(0)

Page Assertions

URL

// Exact URL
await expect(page).toHaveURL('https://example.com/dashboard')

// URL pattern
await expect(page).toHaveURL(/dashboard/)
await expect(page).toHaveURL(/\/users\/\d+/)

// URL with query params
await expect(page).toHaveURL('https://example.com?page=2')

Title

// Exact title
await expect(page).toHaveTitle('Dashboard - MyApp')

// Pattern
await expect(page).toHaveTitle(/Dashboard/)

Response Assertions

// Wait for response
const response = await page.waitForResponse('**/api/users')

// Status code
expect(response.status()).toBe(200)

// Response body
const body = await response.json()
expect(body.users).toHaveLength(10)

Soft Assertions

// Continue after failure (collect multiple failures)
await expect.soft(page.getByRole('heading')).toHaveText('Title')
await expect.soft(page.getByRole('button')).toBeVisible()
await expect.soft(page.locator('.count')).toHaveText('5')

// Check for any soft assertion failures
expect(test.info().errors).toHaveLength(0)

Custom Timeouts

// Per assertion timeout
await expect(page.locator('.loading')).toBeHidden({ timeout: 10000 })
await expect(page.locator('.data')).toHaveText('Loaded', { timeout: 5000 })

// Global timeout in config
// playwright.config.ts
export default defineConfig({
  expect: {
    timeout: 10000,
  },
})

Negation

// Not assertions
await expect(page.locator('.error')).not.toBeVisible()
await expect(page.locator('input')).not.toBeDisabled()
await expect(page.locator('.items')).not.toHaveCount(0)
await expect(page.locator('.status')).not.toHaveText('Error')

Polling Assertions

// Custom polling condition
await expect.poll(async () => {
  const response = await page.request.get('/api/status')
  return response.json()
}).toEqual({ status: 'ready' })

// With options
await expect.poll(async () => {
  return await page.locator('.count').textContent()
}, {
  timeout: 30000,
  intervals: [100, 250, 500, 1000],
}).toBe('10')

Snapshot Assertions

// Text snapshot
await expect(page.locator('.data')).toHaveText(
  await page.locator('.data').textContent()
)

// Screenshot comparison
await expect(page).toHaveScreenshot('homepage.png')
await expect(page.locator('.card')).toHaveScreenshot('card.png')

// With options
await expect(page).toHaveScreenshot('homepage.png', {
  maxDiffPixels: 100,
  threshold: 0.2,
})

Accessibility Assertions

// Check ARIA attributes
await expect(page.getByRole('button')).toHaveAccessibleName('Submit form')
await expect(page.getByRole('textbox')).toHaveAccessibleDescription('Enter email')

// Combined with role
await expect(page.getByRole('button', { name: 'Submit' })).toBeEnabled()

Multiple Assertions Pattern

// Group related assertions
test('user profile displays correctly', async ({ page }) => {
  await page.goto('/profile')

  const profileCard = page.locator('.profile-card')

  // Assert multiple aspects
  await expect(profileCard).toBeVisible()
  await expect(profileCard.locator('.name')).toHaveText('John Doe')
  await expect(profileCard.locator('.email')).toHaveText('[email protected]')
  await expect(profileCard.locator('.avatar')).toHaveAttribute('src', /avatar/)
  await expect(profileCard.getByRole('button', { name: 'Edit' })).toBeEnabled()
})

Async Assertion Patterns

// Wait for condition then assert
await page.getByRole('button', { name: 'Load' }).click()
await expect(page.locator('.data')).toHaveText('Loaded')

// Assert API response triggered by action
await Promise.all([
  page.waitForResponse('**/api/data'),
  page.getByRole('button', { name: 'Fetch' }).click(),
])

// Assert navigation
await page.getByRole('link', { name: 'Dashboard' }).click()
await expect(page).toHaveURL('/dashboard')

Best Practices

Use Auto-Retrying

// GOOD: Auto-retrying (waits up to timeout)
await expect(page.locator('.result')).toHaveText('Success')

// BAD: Non-retrying (snapshot in time)
const text = await page.locator('.result').textContent()
expect(text).toBe('Success')  // May fail during loading

Assert User-Visible State

// GOOD: Assert what user sees
await expect(page.getByRole('alert')).toHaveText('Saved successfully')
await expect(page.getByRole('button', { name: 'Submit' })).toBeDisabled()

// BAD: Assert implementation details
await expect(page.locator('[data-loading="false"]')).toBeVisible()

Specific Assertions

// GOOD: Specific assertion
await expect(page.getByRole('heading')).toHaveText('Welcome, John')

// BAD: Overly broad assertion
await expect(page.getByRole('heading')).toBeVisible()

Integration

Used by:

  • frontend-developer agent
  • fullstack-developer agent