qa-engineer について
qa-engineer は、anytype-ts の最近の変更を分析し、`../anytype-desktop-suite` リポジトリに Playwright の E2E テストを生成するスキルです。変更に関係するユーザー向け動作に絞り、既存のテストパターン、翻訳キー、セレクター規則に従います。
主な機能
- 01変更に基づくテスト範囲
- 02ユーザー向け動作の整理
- 03Playwright E2E テスト生成
- 04既存カバレッジとページオブジェクトの調査
- 05翻訳キーとセレクターの規則
- 06テスト計画とページオブジェクトの案内
活用シーン
- 01機能変更後のテスト追加
- 02コンポーネント編集後の UI 動作確認
- 03E2E テストのカバレッジ不足の特定
- 04テストスイートの規則に沿ったテスト作成
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ anyproto/ anytype-ts --skill qa-engineerインストール後、Claude Code で/qa-engineerを入力して読み込まれたか確認します。
詳細
QA エンジニアスキル
anytype-ts の最近のコード変更を分析し、テスト可能なユーザー向けの動作に対応付けて、../anytype-desktop-suite リポジトリに Playwright E2E テストを生成します。
使用するタイミング
次の場合にこのスキルを有効にします。
- 新機能の実装後、または既存機能の変更後
- ユーザー操作に影響するエディター/コンポーネントの変更後
- ユーザーが最近の変更に対するテストの追加を明示的に依頼した場合
- CLAUDE.md の「QA Engineer」セクションに記載されたタスクの完了後
原則
- 変更主導 — 実際に変更された箇所だけをテストし、変更されていないコードのテストは生成しません
- ユーザー向け — 実装の詳細ではなく、観察可能な動作に焦点を当てます
- 互換性 — anytype-desktop-suite の既存のテストパターンに厳密に従います
- 最小限 — 機能領域ごとにテストファイルを1つ作成し、過剰なテストは行いません
- 翻訳を考慮 — UI テキストは必ず翻訳キーを使い、ハードコードしません
プロセス
フェーズ 1:変更の分析
- 変更点を特定する —
git diffをベースブランチ(または最近のコミット)に対して実行し、変更されたファイルを確認します - 変更を分類する — ユーザー向けの変更と内部リファクタリングを判別します
- 機能に対応付ける — コード変更をテスト可能なユーザーフローに結び付けます。
- コンポーネントの変更 → 検証する UI 操作
- ストアの変更 → テストする状態遷移
- メニュー/ポップアップの変更 → 開く/閉じる/操作するフロー
- エディターの変更 → ブロックの作成、編集、選択
- API の変更 → データフローとエラー処理
ユーザー向けの影響がない、内部のみの変更(型のリファクタリング、ユーティリティの抽出、純粋なスタイル変更)はスキップします。
フェーズ 2:既存のカバレッジを調査
- 既存のテストを確認する —
../anytype-desktop-suite/tests/を検索し、変更された機能領域をすでにカバーするテストがあるか確認します - 既存のページオブジェクトを確認する —
../anytype-desktop-suite/src/pages/を検索し、影響を受けるコンポーネントを操作するページオブジェクトがあるか確認します - テスト計画を確認する —
../anytype-desktop-suite/specs/を検索し、その領域を対象とする既存の計画があるか確認します - 不足箇所を特定する — まだカバーされていない内容を判別します
フェーズ 3:テスト計画を作成
次の形式に従って、../anytype-desktop-suite/specs/ にテスト計画を記述します。
# Feature Area — Test Plan
**Source changes:** List of changed files in anytype-ts
**Date:** YYYY-MM-DD
## Prerequisites
- Seed: `tests/seed.spec.ts` (creates account, opens vault)
- Any additional setup needed
### 1. Test Group Name
**Seed:** `tests/seed.spec.ts`
#### 1.1 Scenario Name
**Steps:**
1. Step description
2. Step description
**Expected:** What should happen
#### 1.2 Another Scenario
...
フェーズ 4:テストファイルを生成
次の厳格な規約に従って、../anytype-desktop-suite/tests/ にテストファイルを作成します。
ファイル構造
// spec: specs/plan-name.md
// seed: tests/seed.spec.ts
import { test, expect } from '../../src/fixtures';
import { restartGrpcServer } from '../../src/helpers/test-server';
// Import relevant page objects
import { SidebarPage } from '../../src/pages/main/sidebar.page';
test.describe('Feature Area', () => {
test.describe.configure({ mode: 'serial' });
test.beforeAll(async () => {
await restartGrpcServer();
});
test('should do the expected behavior', async ({ page, translations }) => {
const sidebar = new SidebarPage(page, translations);
await sidebar.waitForReady();
// Step: Description of what we're doing
await page.getByText(translations.someTranslationKey).click();
// Verify: Expected outcome
await expect(page.locator('#some-element')).toBeVisible();
});
});
規則
- 翻訳 — UI テキストには必ず
translations.keyNameを使用します。キーは../anytype-ts/dist/lib/json/lang/en-US.jsonまたは../anytype-ts/src/json/text.jsonで確認します - ページオブジェクト —
../anytype-desktop-suite/src/pages/の既存のページオブジェクトを使用します。新しいオブジェクトは必要な場合にのみ作成します - 待機 —
await expect(locator).toBeVisible()またはwaitFor({ state: 'visible' })を使用します。setTimeout、networkidle、固定時間の待機は使用しません - セレクター — ロールベース > テスト ID > テキスト > CSS セレクターの順に優先します
- 分離 — 各テストファイルは
beforeAllで gRPC サーバーを再起動します。ファイル内のテストではserialモードを使って状態を共有できます - 命名 — ファイル名は機能名に合わせたケバブケースにします:
feature-name.spec.ts - ディレクトリ — 機能領域に対応するサブディレクトリに配置します:
tests/editor/、tests/blocks/など
フェーズ 5:ページオブジェクトを作成(必要な場合)
変更された機能で、既存のページオブジェクトでは対応できない新しいページ操作が必要な場合は、新しいページオブジェクトを作成します。
import { BasePage } from '../base.page';
export class FeaturePage extends BasePage {
// Locators
get someButton() {
return this.page.locator('#some-button');
}
get someText() {
return this.page.getByText(this.t('translationKey'));
}
// Actions
async waitForReady() {
await this.someButton.waitFor({ state: 'visible' });
}
async doSomething() {
await this.someButton.click();
await expect(this.someText).toBeVisible();
}
}
ページオブジェクトは、適切なサブディレクトリの ../anytype-desktop-suite/src/pages/ に配置します。
フェーズ 6:概要を出力
テストを生成した後、概要を提示します。
## QA Engineer Summary
### Changes Analyzed
- file1.tsx — description of change
- file2.tsx — description of change
### Tests Generated
- `tests/feature/scenario-name.spec.ts` — what it tests
- `specs/feature-plan.md` — test plan
### New Page Objects
- `src/pages/main/feature.page.ts` — (if created)
### Coverage Notes
- What's covered by new tests
- What's NOT covered and why (e.g., requires manual testing, backend-only change)
### Run Tests
```bash
cd ../anytype-desktop-suite && npm test -- tests/feature/scenario-name.spec.ts
## Finding Translation Keys
To map UI text to translation keys:
1. Search `../anytype-ts/src/json/text.json` for the English text
2. The key is the JSON property name (e.g., `"authSelectSignup": "Create new vault"` → use `translations.authSelectSignup`)
3. For dynamic text with parameters, check how the component calls `translate()` with substitution params
## Finding Selectors
To find stable selectors for elements:
1. Search the component source in `../anytype-ts/src/ts/component/` for `id=`, `data-`, `className`
2. Check for block IDs: blocks typically have `#block-{id}` selectors
3. Check for menu IDs: menus use `#menu{Type}` pattern
4. Check for popup IDs: popups use `#popup{Type}` pattern
5. The sidebar uses `#sidebarPage{Section}` pattern
## Test Areas Mapping
| anytype-ts Area | Test Directory | Page Objects |
|---|---|---|
| `component/block/text.tsx` | `tests/editor/` | `pages/main/editor.page.ts` |
| `component/block/dataview.tsx` | `tests/dataview/` | `pages/main/dataview.page.ts` |
| `component/menu/` | `tests/menus/` | (inline or new page object) |
| `component/popup/` | `tests/popups/` | `pages/components/modal.component.ts` |
| `component/sidebar/` | `tests/sidebar/` | `pages/main/sidebar.page.ts` |
| `component/widget/` | `tests/widgets/` | `pages/main/widget.page.ts` |
| `component/page/main/graph.tsx` | `tests/graph/` | (new page object) |
| `component/page/auth/` | `tests/auth/` | `pages/auth/*.page.ts` |
| `store/` | (test via UI) | (use existing page objects) |
## What NOT to Test
- Pure TypeScript type changes
- Internal utility refactors with no UI impact
- CSS-only changes (unless they affect element visibility/layout)
- Backend (anytype-heart) changes — those have their own tests
- Build/config changes
コメント
Markdown 対応