본문으로 건너뛰기

3.5 실전 Interaction Lab

이 Lab은 action을 나열하는 test가 아니라 사용자 목표와 observable result를 연결하는 연습입니다.

시나리오 A: Todo 생성

test('할 일을 추가하고 완료한다', async ({ page }) => {
await page.goto('/');
await page.getByLabel('할 일', { exact: true }).fill('Trace 학습');
await page.getByRole('button', { name: '추가' }).click();

const item = page.getByRole('listitem').filter({ hasText: 'Trace 학습' });
await expect(item).toBeVisible();
await item.getByRole('checkbox').check();
await expect(item.getByRole('checkbox')).toBeChecked();
});

확장 과제

  • 같은 title을 두 번 추가하고 locator가 모호해지는지 확인합니다.
  • Product requirement가 중복을 허용하지 않는다면 UI message를 assertion합니다.
  • Test가 DOM child 순서나 class name에 의존하지 않는지 점검합니다.

시나리오 B: Evidence upload

test('evidence를 memory에서 첨부한다', async ({ page }) => {
await page.goto('/');
await page.getByLabel('증거 파일').setInputFiles({
name: 'evidence.txt',
mimeType: 'text/plain',
buffer: Buffer.from('incident=INC-42\nstatus=verified\n'),
});
await expect(page.getByTestId('selected-file')).toHaveText('evidence.txt');
});

시나리오 C: Confirm과 최종 상태

test('위험 작업을 확인한다', async ({ page }) => {
await page.goto('/');
page.once('dialog', async dialog => {
expect(dialog.type()).toBe('confirm');
await dialog.accept();
});
await page.getByRole('button', { name: '위험 작업' }).click();
await expect(page.getByTestId('dialog-result')).toHaveText('승인됨');
});

Dialog message만 확인하고 끝내지 않습니다. 사용자의 accept가 제품 상태를 실제로 바꿨는지 검증합니다.

시나리오 D: Download payload

import { readFile } from 'node:fs/promises';

test('CSV 결과를 내려받는다', async ({ page }) => {
await page.goto('/');
const downloadPromise = page.waitForEvent('download');
await page.getByRole('link', { name: 'CSV 내려받기' }).click();
const download = await downloadPromise;
const file = await download.path();
expect(file).not.toBeNull();
expect(await readFile(file!, 'utf8')).toContain('id,title');
});

시나리오 E: Popup

test('도움말을 새 창으로 연다', async ({ page }) => {
await page.goto('/');
const popupPromise = page.waitForEvent('popup');
await page.getByRole('link', { name: '도움말 새 창' }).click();
const popup = await popupPromise;
await expect(popup.getByRole('heading')).toHaveText('Playwright Lab Help');
});

스스로 리뷰하기

질문통과 기준
Locator가 사용자 언어인가?role, label, accessible name 중심
Event 순서가 안전한가?promise 등록 → trigger → await
Assertion이 최종 상태를 보는가?action 완료가 아니라 제품 결과 검증
Test data가 독립적인가?순서, 이전 test 상태와 무관
실패 증거가 남는가?trace, screenshot, attachment에서 원인 확인 가능

실행 파일: interactions.spec.ts