11.3 인증, File, Popup Journey
이 시나리오는 setup project, storage state, file event, popup을 하나의 사용자 흐름으로 결합합니다.
인증 상태 준비
auth.setup.ts가 login UI를 통과하고 storage state를 저장합니다. Main project는 이를 dependency로 사용합니다.
setup('student login', async ({ page }) => {
await page.goto('/login.html');
await page.getByLabel('이메일').fill('student@example.com');
await page.getByRole('button', { name: '로그인' }).click();
await expect(page).toHaveURL(/dashboard\.html/);
await page.context().storageState({ path: authFile });
});
Password가 필요한 실제 환경에서는 source나 storage file에 넣지 않고 CI secret을 주입합니다. Storage state는 session을 탈취할 수 있으므로 version control에서 제외합니다.
File과 popup 결합
test('evidence를 첨부하고 도움말을 확인한다', async ({ page }) => {
await page.goto('/');
await page.getByLabel('증거 파일').setInputFiles({
name: 'incident.txt',
mimeType: 'text/plain',
buffer: Buffer.from('incident=INC-42'),
});
await expect(page.getByTestId('selected-file')).toHaveText('incident.txt');
const popupPromise = page.waitForEvent('popup');
await page.getByRole('link', { name: '도움말 새 창' }).click();
const popup = await popupPromise;
await expect(popup.getByRole('heading')).toHaveText('Playwright Lab Help');
});
Download evidence 보존
const downloadPromise = page.waitForEvent('download');
await page.getByRole('link', { name: 'CSV 내려받기' }).click();
const download = await downloadPromise;
const output = testInfo.outputPath(download.suggestedFilename());
await download.saveAs(output);
await testInfo.attach('export', { path: output, contentType: 'text/csv' });
실패 injection
- Storage state file이 만료됨
- Login redirect는 성공했지만 user menu가 로드되지 않음
- Upload filename에 Unicode 포함
- Download가 500 response를 반환
- Popup이 opener policy로 막힘
각 실패는 product가 사용자에게 보여줄 recovery action을 assertion합니다.
완료 조건
- Auth setup failure가 main test failure와 구분된다.
- Storage state가 commit되지 않는다.
- File event가 trigger 전에 등록된다.
- Download payload와 UI success message가 일치한다.
- Popup을 닫아 resource를 정리한다.
실행 파일: auth.setup.ts, interactions.spec.ts