IKivan-kozenko -aqa
Try yourself as a QA tester
All topics·Beginner·6 / 16

Actions

fill, click, check, selectOption — these are the actions you use in 90% of tests. Each one waits for the element to be ready before acting.

Text input — fill vs type

fill is what you want 95% of the time — it focuses the field, clears it, sets the value, and fires the input event. Fast and reliable. Use it for login forms, order creation, search fields.

pressSequentially types character by character — useful for testing autocomplete or fields that react to each keystroke. It's slower than fill on purpose.

ts
test('fill login form', async ({ page }) => {
  await page.goto('/login')

  // fill — найшвидший і найнадійніший спосіб
  await page.getByLabel('Email').fill('admin@example.com')
  await page.getByLabel('Password').fill(process.env.TEST_PASSWORD!)

  // Дата, час — теж через fill
  await page.getByLabel('Order date').fill('2026-05-14')
  await page.getByLabel('Delivery time').fill('14:30')

  await page.getByRole('button', { name: 'Sign in' }).click()
})

test('autocomplete reacts to typing', async ({ page }) => {
  await page.goto('/orders/new')

  // pressSequentially — символ за символом, для autocomplete
  await page.getByLabel('Customer name').pressSequentially('Iva', { delay: 50 })

  // Autocomplete список з'явився
  await expect(page.getByRole('listbox')).toBeVisible()
  await page.getByRole('option', { name: 'Ivan Kozenko' }).click()
})

Checkboxes and radio buttons

check() and uncheck() are semantic — they verify the current state first. check() on an already-checked box does nothing. setChecked(true/false) explicitly sets the state regardless. I use check() for clarity and setChecked when I need to be explicit about the end state.

ts
test('accept terms and subscribe', async ({ page }) => {
  await page.goto('/register')

  await page.getByLabel('I agree to the terms').check()
  await expect(page.getByLabel('I agree to the terms')).toBeChecked()

  // Відмінити
  await page.getByLabel('Subscribe to newsletter').uncheck()
  await expect(page.getByLabel('Subscribe to newsletter')).not.toBeChecked()

  // setChecked — явна установка
  await page.getByLabel('Send notifications').setChecked(true)
})

test('select delivery method', async ({ page }) => {
  await page.goto('/checkout')

  // Радіокнопка — те саме API
  await page.getByLabel('Express delivery').check()
  await expect(page.getByLabel('Express delivery')).toBeChecked()
  await expect(page.getByLabel('Standard delivery')).not.toBeChecked()
})

Select dropdowns

selectOption works on native <select> elements. You can select by value (what's in the value attribute), by label (what the user sees), or by index. For multiple-select, pass an array.

ts
test('filter orders by status', async ({ page }) => {
  await page.goto('/orders')

  // За value — те що в HTML <option value="pending">
  await page.getByRole('combobox', { name: 'Status' }).selectOption('pending')

  // За label — те що бачить користувач
  await page.getByRole('combobox', { name: 'Status' }).selectOption({ label: 'Pending' })

  // За індексом (з 0)
  await page.getByRole('combobox', { name: 'Items per page' }).selectOption({ index: 2 })

  // Multi-select
  await page.getByLabel('Tags').selectOption(['urgent', 'vip', 'export'])
})

Clicks and mouse actions

click() is the most-used action — it waits for the element to be visible, stable (animations done), and not obscured. It also scrolls the element into view first. Variants: dblclick(), right-click with { button: 'right' }, shift+click with { modifiers: ['Shift'] }.

ts
test('order table interactions', async ({ page }) => {
  await page.goto('/orders')

  // Звичайний клік
  await page.getByRole('button', { name: 'Create order' }).click()

  // Подвійний клік (відкрити для редагування)
  await page.getByRole('row').filter({ hasText: 'ORDER-042' }).dblclick()

  // Правий клік (контекстне меню)
  await page.getByRole('row').filter({ hasText: 'ORDER-007' })
    .click({ button: 'right' })
  await page.getByRole('menuitem', { name: 'Archive' }).click()

  // Ctrl+клік (мульти-вибір)
  await page.getByRole('row').nth(1).click()
  await page.getByRole('row').nth(3).click({ modifiers: ['ControlOrMeta'] })
  await page.getByRole('row').nth(5).click({ modifiers: ['ControlOrMeta'] })

  // Hover (показати тултіп)
  await page.getByTestId('info-icon').hover()
  await expect(page.getByRole('tooltip')).toBeVisible()
})

Keyboard shortcuts and key presses

press() sends a keyboard event to the focused element. Common use cases: submitting forms with Enter, clearing fields with Control+A then Backspace, navigating with ArrowDown/Tab. For combinations, use + separator.

ts
test('keyboard navigation in order form', async ({ page }) => {
  await page.goto('/orders/new')

  const nameField = page.getByLabel('Customer name')
  await nameField.fill('Test')

  // Очистити і ввести нове значення
  await nameField.press('Control+a')
  await nameField.press('Backspace')
  await nameField.fill('Ivan Kozenko')

  // Enter для відправки форми
  await page.getByLabel('Search').press('Enter')

  // Tab між полями
  await page.getByLabel('First name').press('Tab') // переходить на Last name

  // Escape для закриття модального
  await page.keyboard.press('Escape')
  await expect(page.getByRole('dialog')).not.toBeVisible()

  // Arrow down в dropdown
  await page.getByRole('combobox', { name: 'Status' }).press('ArrowDown')
})

File upload

setInputFiles sets files on an <input type="file"> element without opening the OS file picker. Pass a file path or multiple paths for multi-file inputs. For drag-and-drop upload zones, use page.dragAndDrop() or dispatchEvent.

ts
test('upload order document', async ({ page }) => {
  await page.goto('/orders/42/documents')

  // Один файл
  await page.getByLabel('Upload document').setInputFiles('tests/fixtures/invoice.pdf')

  // Кілька файлів
  await page.getByLabel('Upload documents').setInputFiles([
    'tests/fixtures/invoice.pdf',
    'tests/fixtures/contract.pdf',
  ])

  // Очистити вибір файлів
  await page.getByLabel('Upload document').setInputFiles([])

  await page.getByRole('button', { name: 'Submit' }).click()
  await expect(page.getByText('2 documents uploaded')).toBeVisible()
})

Drag and drop

For HTML5 drag-and-drop (elements with draggable attribute), page.dragAndDrop() handles the whole sequence. For custom drag implementations that listen to mouse events directly, use the lower-level mouse.down(), mouse.move(), mouse.up() sequence.

ts
test('reorder items in kanban', async ({ page }) => {
  await page.goto('/orders/kanban')

  // HTML5 dragAndDrop: з "Pending" колонки до "In Progress"
  await page.dragAndDrop(
    '[data-testid="card-ORDER-042"]',
    '[data-testid="column-in-progress"]'
  )

  await expect(
    page.getByTestId('column-in-progress').getByText('ORDER-042')
  ).toBeVisible()
})