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