qa-engineer

Analyze recent code changes in anytype-ts, map them to testable user-facing behavior, and generate Playwright E2E tests in the ../anytype-desktop-suite repository.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "qa-engineer" with this command: npx skills add anyproto/anytype-ts/anyproto-anytype-ts-qa-engineer

QA Engineer Skill

Analyze recent code changes in anytype-ts, map them to testable user-facing behavior, and generate Playwright E2E tests in the ../anytype-desktop-suite repository.

When to Use

Activate this skill when:

  • After implementing a new feature or modifying existing functionality

  • After editor/component changes that affect user interactions

  • The user explicitly asks to add tests for recent changes

  • After completing a task referenced in CLAUDE.md's "QA Engineer" section

Principles

  • Change-driven — Only test what actually changed, don't generate tests for untouched code

  • User-facing — Focus on observable behavior, not implementation details

  • Compatible — Follow the existing test patterns in anytype-desktop-suite exactly

  • Minimal — One test file per feature area, don't over-test

  • Translation-aware — Always use translation keys, never hardcoded UI text

Process

Phase 1: Analyze Changes

  • Identify what changed — Run git diff against the base branch (or recent commits) to see modified files

  • Classify changes — Determine which changes are user-facing vs internal refactoring

  • Map to features — Connect code changes to testable user flows:

  • Component changes → UI interactions to verify

  • Store changes → State transitions to test

  • Menu/popup changes → Open/close/interact flows

  • Editor changes → Block creation, editing, selection

  • API changes → Data flow and error handling

Skip internal-only changes (type refactors, utility extractions, pure style changes) that have no user-facing impact.

Phase 2: Research Existing Coverage

  • Check existing tests — Search ../anytype-desktop-suite/tests/ for tests that already cover the changed feature area

  • Check existing page objects — Search ../anytype-desktop-suite/src/pages/ for page objects that interact with affected components

  • Check test plans — Search ../anytype-desktop-suite/specs/ for existing plans covering the area

  • Identify gaps — Determine what's not yet covered

Phase 3: Create Test Plan

Write a test plan in ../anytype-desktop-suite/specs/ following this format:

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

...

Phase 4: Generate Test Files

Create test files in ../anytype-desktop-suite/tests/ following these strict conventions:

File Structure

// 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();

}); });

Rules

  • Translations — Always use translations.keyName for UI text. Look up keys in ../anytype-ts/dist/lib/json/lang/en-US.json or ../anytype-ts/src/json/text.json

  • Page Objects — Use existing page objects from ../anytype-desktop-suite/src/pages/ . Create new ones only if needed

  • Waits — Use await expect(locator).toBeVisible() or waitFor({ state: 'visible' }) . Never use setTimeout , networkidle , or fixed delays

  • Selectors — Prefer role-based > test ID > text > CSS selectors

  • Isolation — Each test file restarts gRPC server in beforeAll . Tests in a file can share state with serial mode

  • Naming — File names are kebab-case matching the feature: feature-name.spec.ts

  • Directory — Place in a subdirectory matching the feature area: tests/editor/ , tests/blocks/ , etc.

Phase 5: Create Page Objects (if needed)

If the changed feature needs new page interactions not covered by existing page objects, create a new page object:

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(); } }

Page objects go in ../anytype-desktop-suite/src/pages/ in the appropriate subdirectory.

Phase 6: Output Summary

After generating tests, provide a summary:

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

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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

typescript-code-review

No summary provided by upstream source.

Repository SourceNeeds Review
General

update-docs

No summary provided by upstream source.

Repository SourceNeeds Review
General

release-notes

No summary provided by upstream source.

Repository SourceNeeds Review
General

dark-mode-check

No summary provided by upstream source.

Repository SourceNeeds Review