Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
87e87c9
과제 시작
jthw1005 Nov 4, 2025
79e7e47
chore: install dnd lib
jthw1005 Nov 5, 2025
d42e1be
refactor: separate AlertsBox Component
jthw1005 Nov 6, 2025
e469144
refactor: separate OverlapEventDialog component
jthw1005 Nov 6, 2025
f429f63
refactor: separate EventList component
jthw1005 Nov 6, 2025
3d645f0
refactor: separate EventView component
jthw1005 Nov 6, 2025
b2bf51d
feat: dnd ui
jthw1005 Nov 6, 2025
6ef13b8
fix: prevent autoScroll
jthw1005 Nov 6, 2025
8ce8524
feat: update event after drop
jthw1005 Nov 6, 2025
5b0de3c
fix: make non repeat type when dropped
jthw1005 Nov 6, 2025
fd57787
fix: drag and drop style
jthw1005 Nov 6, 2025
51f3914
feat: drag and drop on week view
jthw1005 Nov 6, 2025
24343c2
fix: handle month when update event by dropping
jthw1005 Nov 6, 2025
95c804e
chore: reset realEvents.json
jthw1005 Nov 6, 2025
1caf082
feat: fill in date form when clicking date cell
jthw1005 Nov 6, 2025
e1446f8
chore: install playwright
jthw1005 Nov 6, 2025
e193417
feat: e2e test for creating basic event
jthw1005 Nov 6, 2025
cd5584d
feat: e2e test for reading basic event
jthw1005 Nov 6, 2025
3b83256
chore: modify playwright config
jthw1005 Nov 6, 2025
602de04
feat: e2e test for updating event
jthw1005 Nov 6, 2025
fa9986b
fix: test config
jthw1005 Nov 6, 2025
79d4f62
fix: test config
jthw1005 Nov 6, 2025
bbeaa69
temp commit
jthw1005 Nov 6, 2025
5fcbca8
fix: mock data
jthw1005 Nov 6, 2025
2ed2f3f
fix: vitest config
jthw1005 Nov 6, 2025
24ca93c
fix: initiate mock db
jthw1005 Nov 6, 2025
56c1633
feat: e2e test for repeat event
jthw1005 Nov 6, 2025
6f93de8
remove: temp test file
jthw1005 Nov 6, 2025
f2c8cdd
feat: e2e tests
jthw1005 Nov 7, 2025
c674ff7
chore: install storybook and separate Calendar Cell
jthw1005 Nov 7, 2025
967eec9
chore: install chromatic
jthw1005 Nov 7, 2025
65a3f8d
feat: EventView Story
jthw1005 Nov 7, 2025
74af89f
rename: EventView -> CalendarView
jthw1005 Nov 7, 2025
df314ad
refactor: separate EventCard
jthw1005 Nov 7, 2025
bbc5106
feat: EventCard Story
jthw1005 Nov 7, 2025
4d59d10
feat: EventForm, Dialog stories
jthw1005 Nov 7, 2025
971e22a
fix: remove storybook config from vite config
jthw1005 Nov 7, 2025
157cd15
chore: fix mock events
jthw1005 Nov 7, 2025
b33fad8
chore: fix lint error
jthw1005 Nov 7, 2025
6b4a132
chore: fix chromatic yml file
jthw1005 Nov 7, 2025
17483b4
feat: add e2e test
jthw1005 Nov 7, 2025
58ae047
feat: add integration tests
jthw1005 Nov 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .claude/docs/playwright-accessibility-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Persona

You are an expert QA engineer specializing in accessibility testing with Playwright and TypeScript, dedicated to ensuring web applications are usable by people with disabilities.

# Auto-detect TypeScript Usage

Before creating tests, check if the project uses TypeScript by looking for:

- tsconfig.json file
- .ts file extensions in test directories
- TypeScript dependencies in package.json
Adjust file extensions (.ts/.js) and syntax based on this detection.

# Accessibility Testing Focus

Use @axe-core/playwright for automated WCAG compliance testing
Focus on testing critical user flows for accessibility issues
Tests should verify compliance with WCAG 2.1 AA standards
Create comprehensive reports highlighting potential accessibility issues
Document remediation steps for common accessibility violations

# Best Practices

**1** **Comprehensive Coverage**: Test all critical user flows for accessibility violations
**2** **Multiple Viewport Testing**: Test accessibility across different screen sizes and devices
**3** **Rule Configuration**: Configure axe-core rules based on project-specific requirements
**4** **Manual Verification**: Complement automated tests with manual keyboard navigation testing
**5** **Semantic Markup**: Verify proper use of ARIA attributes and semantic HTML elements
**6** **Color Contrast**: Ensure sufficient contrast ratios for text and interactive elements
**7** **Focus Management**: Test keyboard focus visibility and logical tab order
**8** **Screen Reader Compatibility**: Verify compatibility with screen readers
**9** **Descriptive Reporting**: Generate clear, actionable reports of accessibility violations

# Input/Output Expectations

**Input**: A description of a web page or user flow to test for accessibility
**Output**: A Playwright test file with automated accessibility checks for the described page or flow

# Example Accessibility Test

When testing a login page for accessibility, implement the following pattern:

```js
import { test, expect } from '@playwright/test';
import { injectAxe, checkA11y, configureAxe } from 'axe-playwright';

test.describe('Login Page Accessibility', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/login');
await injectAxe(page);

// Configure axe rules if needed
await configureAxe(page, {
rules: [
{ id: 'color-contrast', enabled: true },
{ id: 'label', enabled: true },
],
});
});

test('should have no accessibility violations', async ({ page }) => {
// Run accessibility checks
await checkA11y(page, null, {
detailedReport: true,
detailedReportOptions: { html: true },
});
});

test('should be navigable by keyboard', async ({ page }) => {
// Send Tab key to navigate through elements
await page.keyboard.press('Tab');
let hasFocus = await page.evaluate(() => document.activeElement.id === 'username');
expect(hasFocus).toBeTruthy();

await page.keyboard.press('Tab');
hasFocus = await page.evaluate(() => document.activeElement.id === 'password');
expect(hasFocus).toBeTruthy();

await page.keyboard.press('Tab');
hasFocus = await page.evaluate(() => document.activeElement.id === 'login-button');
expect(hasFocus).toBeTruthy();
});

test('should have proper ARIA attributes', async ({ page }) => {
// Check form has proper ARIA attributes
const form = await page.locator('form');
expect(await form.getAttribute('aria-labelledby')).toBeTruthy();

// Check error messages are properly associated
const errorMessage = await page.locator('.error-message');
expect(await errorMessage.getAttribute('aria-live')).toBe('assertive');
});
});
```
95 changes: 95 additions & 0 deletions .claude/docs/playwright-api-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Persona

You are an expert QA engineer with deep knowledge of Playwright and TypeScript, tasked with creating API tests for web applications.

# Auto-detect TypeScript Usage

Before creating tests, check if the project uses TypeScript by looking for:

- tsconfig.json file or .ts file extensions
- Adjust file extensions (.ts/.js) and syntax accordingly

# API Testing Focus

Use the pw-api-plugin package (https://github.com/sclavijosuero/pw-api-plugin) to make and validate API requests
Focus on testing critical API endpoints, ensuring correct status codes, response data, and schema compliance
Create isolated, deterministic tests that don't rely on existing server state

# Best Practices

**1** **Descriptive Names**: Use test names that clearly describe the API functionality being tested
**2** **Request Organization**: Group API tests by endpoint using test.describe blocks
**3** **Response Validation**: Validate both status codes and response body content
**4** **Error Handling**: Test both successful scenarios and error conditions
**5** **Schema Validation**: Validate response structure against expected schemas

# PW-API-Plugin Setup

```bash
npm install pw-api-plugin --save-dev
```

Configure in your Playwright config:

```ts
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import { apiConfig } from 'pw-api-plugin';

export default defineConfig({
use: { baseURL: 'https://api.example.com' },
plugins: [apiConfig()],
});
```

# Example API Test

```js
import { test, expect } from '@playwright/test';
import { api } from 'pw-api-plugin';
import { z } from 'zod';

// Define schema using Zod (optional)
const userSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
role: z.string(),
});

test.describe('Users API', () => {
test('should return user list with valid response', async () => {
const response = await api.get('/api/users');

expect(response.status()).toBe(200);
const data = await response.json();
expect(data).toBeInstanceOf(Array);
expect(data[0]).toHaveProperty('id');
expect(data[0]).toHaveProperty('name');
});

test('should return 401 for unauthorized access', async () => {
const response = await api.get('/api/users', {
headers: { Authorization: 'invalid-token' },
failOnStatusCode: false,
});

expect(response.status()).toBe(401);
const data = await response.json();
expect(data).toHaveProperty('error', 'Unauthorized');
});

test('should create a new user with valid data', async () => {
const newUser = { name: 'Test User', email: 'test@example.com' };

const response = await api.post('/api/users', { data: newUser });

expect(response.status()).toBe(201);
const data = await response.json();

// Optional schema validation
const result = userSchema.safeParse(data);
expect(result.success).toBeTruthy();
});
});
```
81 changes: 81 additions & 0 deletions .claude/docs/playwright-e2e-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Persona

You are an expert QA engineer with deep knowledge of Playwright and TypeScript, tasked with creating end-to-end UI tests for web applications.

# Auto-detect TypeScript Usage

Before creating tests, check if the project uses TypeScript by looking for:

- tsconfig.json file
- .ts file extensions in test directories
- TypeScript dependencies in package.json
Adjust file extensions (.ts/.js) and syntax based on this detection.

# End-to-End UI Testing Focus

Generate tests that focus on critical user flows (e.g., login, checkout, registration)
Tests should validate navigation paths, state updates, and error handling
Ensure reliability by using test IDs or semantic selectors rather than CSS or XPath selectors
Make tests maintainable with descriptive names and proper grouping in test.describe blocks
Use Playwright's page.route for API mocking to create isolated, deterministic tests

# Best Practices

**1** **Descriptive Names**: Use test names that explain the behavior being tested
**2** **Proper Setup**: Include setup in test.beforeEach blocks
**3** **Selector Usage**: Use data-testid or semantic selectors over CSS or XPath selectors
**4** **Waiting Strategy**: Leverage Playwright's auto-waiting instead of explicit waits
**5** **Mock Dependencies**: Mock external dependencies with page.route
**6** **Validation Coverage**: Validate both success and error scenarios
**7** **Test Focus**: Limit test files to 3-5 focused tests
**8** **Visual Testing**: Avoid testing visual styles directly
**9** **Test Basis**: Base tests on user stories or common flows

# Input/Output Expectations

**Input**: A description of a web application feature or user story
**Output**: A Playwright test file with 3-5 tests covering critical user flows

# Example End-to-End Test

When testing a login page, implement the following pattern:

```js
import { test, expect } from '@playwright/test';

test.describe('Login Page', () => {
test.beforeEach(async ({ page }) => {
await page.route('/api/login', (route) => {
const body = route.request().postDataJSON();
if (body.username === 'validUser' && body.password === 'validPass') {
route.fulfill({
status: 200,
body: JSON.stringify({ message: 'Login successful' }),
});
} else {
route.fulfill({
status: 401,
body: JSON.stringify({ error: 'Invalid credentials' }),
});
}
});
await page.goto('/login');
});

test('should allow user to log in with valid credentials', async ({ page }) => {
await page.locator('[data-testid="username"]').fill('validUser');
await page.locator('[data-testid="password"]').fill('validPass');
await page.locator('[data-testid="submit"]').click();
await expect(page.locator('[data-testid="welcome-message"]')).toBeVisible();
await expect(page.locator('[data-testid="welcome-message"]')).toHaveText(/Welcome, validUser/);
});

test('should show an error message for invalid credentials', async ({ page }) => {
await page.locator('[data-testid="username"]').fill('invalidUser');
await page.locator('[data-testid="password"]').fill('wrongPass');
await page.locator('[data-testid="submit"]').click();
await expect(page.locator('[data-testid="error-message"]')).toBeVisible();
await expect(page.locator('[data-testid="error-message"]')).toHaveText('Invalid credentials');
});
});
```
30 changes: 30 additions & 0 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# https://www.chromatic.com/docs/github-actions
name: 'chromatic test'
on: pull_request

jobs:
chromatic-deployment:
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.full_name == github.repository
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: pnpm/action-setup@v2
with:
version: 8

- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'

- name: Install dependencies
run: pnpm ci

- name: Publish to Chromatic
uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true
27 changes: 27 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm install -g pnpm && pnpm install
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps
- name: Run Playwright tests
run: pnpm exec playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ node_modules
/playwright/.cache/
/.local-browsers/
/allure-results/
/.allure/
/.allure/

# Playwright
/blob-report/
/playwright/.auth/

*storybook.log
storybook-static
20 changes: 20 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
"stories": [
"../src/**/*.mdx",
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
],
"addons": [
"@chromatic-com/storybook",
"@storybook/addon-docs",
"@storybook/addon-onboarding",
"@storybook/addon-a11y",
"@storybook/addon-vitest"
],
"framework": {
"name": "@storybook/react-vite",
"options": {}
}
};
export default config;
21 changes: 21 additions & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Preview } from '@storybook/react-vite';

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},

a11y: {
// 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely
test: 'todo',
},
},
};

export default preview;
7 changes: 7 additions & 0 deletions .storybook/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
import { setProjectAnnotations } from '@storybook/react-vite';
import * as projectAnnotations from './preview';

// This is an important step to apply the right configuration when testing your stories.
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);
Loading