QA Interaction Agent. 사용자 인터랙션 테스트 계획 및 Playwright E2E 테스트 작성을 담당합니다. UX/UI 명세 기반의 상세한 테스트 시나리오를 설계합니다.
48
48%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Risky
Do not use without reviewing
Fix and improve this skill with Tessl
tessl review fix ./skills/qa-interaction/SKILL.md사용자 인터랙션을 중심으로 테스트를 계획하고, Playwright를 사용하여 E2E 테스트를 작성/실행합니다.
## 테스트 시나리오: [플로우명]
### 전제 조건
- [ ] 사용자 로그인 상태
- [ ] 필요한 데이터 준비
### 테스트 단계
| # | 동작 | 예상 결과 | 검증 방법 |
|---|------|----------|----------|
| 1 | 페이지 접근 | 페이지 로드 완료 | URL, 제목 확인 |
| 2 | 버튼 클릭 | 모달 표시 | 요소 visibility |
| 3 | 폼 입력 | 유효성 통과 | 에러 메시지 없음 |
| 4 | 제출 | 성공 메시지 | 토스트/알림 |
### 엣지 케이스
- [ ] 네트워크 오류 시
- [ ] 타임아웃 발생 시
- [ ] 동시 요청 시import { test, expect } from '@playwright/test';
test.describe('User Profile Page', () => {
test.beforeEach(async ({ page }) => {
// 로그인 및 페이지 접근
await page.goto('/login');
await page.fill('[data-testid="email"]', 'test@example.com');
await page.fill('[data-testid="password"]', 'password123');
await page.click('[data-testid="login-button"]');
await page.waitForURL('/dashboard');
});
test('should display user profile', async ({ page }) => {
await page.goto('/profile');
await expect(page.locator('[data-testid="user-name"]')).toBeVisible();
await expect(page.locator('[data-testid="user-email"]')).toBeVisible();
});
test('should edit profile successfully', async ({ page }) => {
await page.goto('/profile');
// 편집 모드 진입
await page.click('[data-testid="edit-button"]');
// 이름 변경
await page.fill('[data-testid="name-input"]', 'New Name');
// 저장
await page.click('[data-testid="save-button"]');
// 성공 확인
await expect(page.locator('[data-testid="success-toast"]')).toBeVisible();
await expect(page.locator('[data-testid="user-name"]')).toHaveText('New Name');
});
});test.describe('Registration Form', () => {
test('should validate required fields', async ({ page }) => {
await page.goto('/register');
// 빈 폼 제출
await page.click('[data-testid="submit-button"]');
// 에러 메시지 확인
await expect(page.locator('[data-testid="email-error"]')).toHaveText('이메일을 입력하세요');
await expect(page.locator('[data-testid="password-error"]')).toHaveText('비밀번호를 입력하세요');
});
test('should show password strength indicator', async ({ page }) => {
await page.goto('/register');
// 약한 비밀번호
await page.fill('[data-testid="password"]', '123');
await expect(page.locator('[data-testid="strength-weak"]')).toBeVisible();
// 강한 비밀번호
await page.fill('[data-testid="password"]', 'StrongP@ss123!');
await expect(page.locator('[data-testid="strength-strong"]')).toBeVisible();
});
test('should handle form submission', async ({ page }) => {
await page.goto('/register');
await page.fill('[data-testid="email"]', 'new@example.com');
await page.fill('[data-testid="password"]', 'SecureP@ss123');
await page.fill('[data-testid="confirm-password"]', 'SecureP@ss123');
await page.check('[data-testid="terms-checkbox"]');
await page.click('[data-testid="submit-button"]');
// 성공 페이지로 리다이렉트
await page.waitForURL('/register/success');
await expect(page.locator('h1')).toHaveText('가입 완료');
});
});test.describe('Shopping Cart', () => {
test('should update cart count on add', async ({ page }) => {
await page.goto('/products');
// 초기 카트 수량
await expect(page.locator('[data-testid="cart-count"]')).toHaveText('0');
// 상품 추가
await page.click('[data-testid="add-to-cart-1"]');
// 카트 수량 업데이트
await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');
});
test('should show loading state during checkout', async ({ page }) => {
await page.goto('/cart');
await page.click('[data-testid="checkout-button"]');
// 로딩 상태 확인
await expect(page.locator('[data-testid="loading-spinner"]')).toBeVisible();
// 완료 후 리다이렉트
await page.waitForURL('/checkout/success');
});
});test.describe('Accessibility', () => {
test('should be keyboard navigable', async ({ page }) => {
await page.goto('/');
// Tab 키로 네비게이션
await page.keyboard.press('Tab');
await expect(page.locator(':focus')).toHaveAttribute('data-testid', 'nav-home');
await page.keyboard.press('Tab');
await expect(page.locator(':focus')).toHaveAttribute('data-testid', 'nav-products');
// Enter 키로 활성화
await page.keyboard.press('Enter');
await page.waitForURL('/products');
});
test('should have proper ARIA labels', async ({ page }) => {
await page.goto('/');
// 주요 영역 ARIA 확인
await expect(page.locator('nav')).toHaveAttribute('aria-label', 'Main navigation');
await expect(page.locator('main')).toHaveAttribute('role', 'main');
await expect(page.locator('footer')).toHaveAttribute('role', 'contentinfo');
});
});test.describe('Responsive Design', () => {
test('should show mobile menu on small screens', async ({ page }) => {
// 모바일 뷰포트
await page.setViewportSize({ width: 375, height: 667 });
await page.goto('/');
// 햄버거 메뉴 표시
await expect(page.locator('[data-testid="mobile-menu-button"]')).toBeVisible();
await expect(page.locator('[data-testid="desktop-nav"]')).not.toBeVisible();
// 메뉴 열기
await page.click('[data-testid="mobile-menu-button"]');
await expect(page.locator('[data-testid="mobile-nav"]')).toBeVisible();
});
test('should show desktop nav on large screens', async ({ page }) => {
// 데스크톱 뷰포트
await page.setViewportSize({ width: 1280, height: 720 });
await page.goto('/');
await expect(page.locator('[data-testid="desktop-nav"]')).toBeVisible();
await expect(page.locator('[data-testid="mobile-menu-button"]')).not.toBeVisible();
});
});# Playwright 테스트 실행
npx playwright test
# 특정 파일 실행
npx playwright test user-profile.spec.ts
# UI 모드로 실행
npx playwright test --ui
# 디버그 모드
npx playwright test --debug
# 특정 브라우저
npx playwright test --project=chromium
# 리포트 생성
npx playwright show-report# [기능명] 인터랙션 테스트 계획
## 1. 테스트 범위
### 포함
### 제외
## 2. 테스트 환경
- 브라우저: Chrome, Firefox, Safari
- 디바이스: Desktop, Tablet, Mobile
## 3. 사용자 플로우별 테스트
### 플로우 1: [플로우명]
### 플로우 2: [플로우명]
## 4. 엣지 케이스
## 5. 성능 기준
- 페이지 로드: < 3초
- 인터랙션 응답: < 100ms
## 6. 접근성 요구사항
- WCAG 2.1 Level AA
## 7. 테스트 데이터docs/features/<기능명>/test-plans/interaction-tests.mde2e/**/*.spec.tsplaywright-report/test-results/9242c58
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.