

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
123456# Frontend Testing Rules78Use this rule when creating or updating frontend Vitest tests. For canonical lint and format commands, use `linting_formating.mdc`.910## Test Commands1112From the repo root:1314```bash15CURSOR_DEV=true nix develop -c pnpm frontend:test16```1718Run tests with browser rendering UI:1920```bash21CURSOR_DEV=true nix develop -c pnpm frontend:test:ui22```2324Run tests in browser-rendered watch mode:2526```bash27CURSOR_DEV=true nix develop -c pnpm frontend:test:watch28```2930Run a single test file from the repo root:3132```bash33CURSOR_DEV=true nix develop -c pnpm frontend:test tests/path/to/TestFile.spec.ts34```3536Or only the frontend package:3738```bash39CURSOR_DEV=true nix develop -c pnpm -C frontend test tests/path/to/TestFile.spec.ts40```4142Run a specific test case:4344```bash45CURSOR_DEV=true nix develop -c pnpm -C frontend test -t "test name pattern"46```4748The test file path is relative to `frontend/`. Do not use `pnpm ... test -- tests/...`; the `--` is forwarded to Vitest and file filtering is skipped.4950In most situations, run all unit tests instead of a selected file only. Use a single test file when actively debugging or iterating on a specific component.5152## Component Behavior5354- Test through user interactions.55- Avoid testing implementation details.56- For cross-cutting guidance about observable outcomes, high-level entry points, and avoiding 1:1 test/file mapping, use the `phased-planning` skill's Observable behavior first section.57- Use `data-testid` for test selectors.58- Use Vitest browser mode and prefer real browser rendering over mocking; stop using jsdom.5960## Avoid Role Queries6162- Do not use `getByRole`, `findByRole`, `queryByRole`, `getAllByRole`, and similar queries; they are slow due to expensive visibility checks.63- Testing Library recommends role queries for accessibility, but this project prioritizes test performance.64- Use faster alternatives: `getByText`, `getByLabelText`, `getByTitle`, or `querySelector` / `querySelectorAll`.6566## Mock SDK Services6768- Use `mockSdkService` from `@tests/helpers` for type-safe mocking: pass the generated **controller class** and the **method name** (same static methods as `@generated/doughnut-backend-api/sdk.gen`).69- It automatically wraps responses in the standard format `{ data, error, request, response }`.70- It returns a spy that can be reconfigured in tests.71- Use `wrapSdkResponse` when updating mock return values.72- Use `mockSdkServiceWithImplementation` only for custom async logic based on options.7374```typescript75import { NoteController } from "@generated/doughnut-backend-api/sdk.gen"76import { mockSdkService } from "@tests/helpers"7778beforeEach(() => {79 mockSdkService(NoteController, "getRecentNotes", [])80 mockSdkService(NoteController, "showNote", makeMe.aNoteRealm.please())81})82```8384```typescript85import { NoteController } from "@generated/doughnut-backend-api/sdk.gen"86import { mockSdkService, wrapSdkResponse } from "@tests/helpers"8788const spy = mockSdkService(NoteController, "showNote", makeMe.aNoteRealm.please())89spy.mockResolvedValue(wrapSdkResponse(differentNote))90```9192```typescript93import { TextContentController } from "@generated/doughnut-backend-api/sdk.gen"94import { mockSdkServiceWithImplementation } from "@tests/helpers"9596mockSdkServiceWithImplementation(TextContentController, "updateNoteContent", async (options) => {97 return await someAsyncOperation(options)98})99```100101## Component Props102103- Use `helper.component(ComponentName).withStorageProps` if the component requires a `storageAccessor` prop.104- Use `withProps` instead of `withStorageProps` if the component does not require `storageAccessor`.105- Test prop changes and their effects.106107```typescript108const wrapper = helper109 .component(Component)110 .withStorageProps({ value: initialValue })111 .mount()112113await wrapper.setProps({ value: newValue })114```115116## Data Builders117118- Use `makeMe` for API-shaped test data; implementation lives in `packages/doughnut-test-fixtures`.119- Import `doughnut-test-fixtures/makeMe` only. Do not import the bare package name or deep paths into `src/`.120- Builders handle complex object creation.121122```typescript123const note = makeMe.aNoteRealm124 .topicConstructor("Dummy Title")125 .content("Description")126 .please()127```128129## Browser Mode Mounting130131- Use `render()` from `@testing-library/vue` for most tests.132- `render()` encourages user-perspective tests and returns fast queries such as `getByText`, `getByLabelText`, and `data-testid`.133- Use `mount()` from `@vue/test-utils` only when you need direct access to Vue internals, emitted events, slots, or provide/inject edge cases.134- Query the DOM, not Vue components.135136Prefer:137138```typescript139page.getByText(/submit/i)140screen.getByText("Loading...")141```142143Avoid:144145```typescript146wrapper.findComponent(MyButton)147wrapper.find("[data-testid='my-component']")148```149150## Deterministic Tests151152- Tests must always execute the same way.153- Use assertions instead of if-conditions so failures are clear.154- Use sequential async operations instead of loops where possible.155156Avoid:157158```typescript159if (vm.searchResults) {160 const selected = vm.searchResults.find((result) => result.id === wikidataId)161 if (selected) {162 // do something163 }164}165```166167Prefer:168169```typescript170expect(vm.searchResults).toBeDefined()171expect(vm.searchResults.length).toBeGreaterThan(0)172const selected = vm.searchResults.find((result) => result.id === wikidataId)173expect(selected).toBeDefined()174```175
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| nerds-odd-e/doughnut.cursor/rules/general.mdc · 49 | Cursor rules | styledo-not | 49/100 | 14 days ago | |
| nerds-odd-e/doughnut.clinerules/daisyui.md · 49 | Cline rules | setuplint-formatstyleui+1 | 57/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/architecture-decisions.mdc · 49 | Cursor rules | no sections | 16/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/backend-code.mdc · 49 | Cursor rules | styletypesdatabasedo-not | 61/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/backend-testing.mdc · 49 | Cursor rules | buildteststyletesting-strategy+2 | 73/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/cli.mdc · 49 | Cursor rules | setupbuildteststyle+4 | 96/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/db-migration.mdc · 49 | Cursor rules | stylearchdatabasedeployment | 64/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/e2e-authoring.mdc · 49 | Cursor rules | setupteststylearch+3 | 80/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/e2e-ocr.mdc · 49 | Cursor rules | setuptesting-strategydo-not | 46/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/frontend-api.mdc · 49 | Cursor rules | styletesting-strategyapido-not | 57/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/frontend-component.mdc · 49 | Cursor rules | testlint-formatstylearch+2 | 76/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/frontend-storybook.mdc · 49 | Cursor rules | buildteststyletesting-strategy+1 | 69/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/gsd-coexistence.mdc · 49 | Cursor rules | style | 60/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/linting_formating.mdc · 49 | Cursor rules | testlint-formatstylearch+6 | 88/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/mcp-server.mdc · 49 | Cursor rules | buildtestlint-formatarch+2 | 85/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/planning.mdc · 49 | Cursor rules | teststylearchdo-not+1 | 75/100 | 14 days ago | |
| nerds-odd-e/doughnut.cursor/rules/script.mdc · 49 | Cursor rules | testarch | 58/100 | 14 days ago | |
| nerds-odd-e/doughnutAGENTS.md · 49 | AGENTS.md | no sections | 47/100 | 14 days ago | |
| nerds-odd-e/doughnutCLAUDE.md · 49 | CLAUDE.md | agent-behaviour | 47/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 46 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/nerds-odd-e-doughnut-cursor-rules-frontend-testing)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.