Skip to content

Improve Cursor Rules #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions src/generate/cursor/tnf.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Usage instructions for the tnf in the React framework.
globs:
---
Please follow the docs in ./.tnf/docs/general.md.
35 changes: 35 additions & 0 deletions src/generate/cursor/vitest.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
description: Generate unit tests based on Vitest
globs:
---
# Unit Test Specification Expert

## Skills
1. Writing unit tests for React components and functions using Vitest.
2. Implementing isolated and stable test environments by mocking external dependencies.
3. Structuring test code following the arrange-act-assert pattern.
4. Ensuring compliance with file placement conventions for test files.
5. Avoiding source code modifications solely for unit testing purposes.

## Background
Unit testing is essential to ensure the reliability and stability of code, especially for React components and functions. Adhering to best practices and ensuring high test coverage is critical to maintaining a robust codebase.

## Goals
1. Write unit tests for components using Vitest and React Testing Library.
2. Implement integration tests for critical user flows.
3. Maintain unit test coverage of at least 80%.
4. Ensure test code is independent and isolated by mocking external dependencies.
5. Follow test file placement conventions to organize code effectively.
6. Avoid modifying source code for testing purposes.

## Rules
1. Use Vitest exclusively for unit testing; avoid Jest.
2. Use snapshot testing judiciously and only where appropriate.
3. Ensure test files are placed in the correct `__tests__` directory structure:
- Example 1: The unit test file for `root/xxx/src/foo/bar/xxx.ts` should be placed in `root/xxx/__tests__/foo/bar/xxx.test.tsx`.
4. Do use `test()` instead of `describe() + it()` for test cases.
5. Follow the arrange-act-assert pattern in test code organization.
6. Avoid testing external factors like APIs, downstream modules, or environments directly; mock these dependencies.
7. Use `expect(ele?.className).toContain('class-name');` for class verification in React component tests instead of `expect(ele).toHaveClass('class-name');`.
8. Maintain English usage throughout - avoid Chinese comments, test case names, etc
9. Make sure the created files are ending with a new line at the end of the file.
21 changes: 12 additions & 9 deletions src/generate/generate_cursor.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import assert from 'assert';
import fs from 'fs';
import fs from 'fs-extra';
import path from 'pathe';
import { fileURLToPath } from 'url';
import type { Context } from '../types/index.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const CURSOR_RULES_FILE = { old: '.cursorrules', new: '.cursor/rules' };
interface GenerateCursorOpts {
context: Context;
force?: boolean;
Expand All @@ -11,11 +15,13 @@ interface GenerateCursorOpts {
export async function generateCursor(opts: GenerateCursorOpts) {
const { context, force } = opts;
const cwd = context.cwd;
const cursorRulesPath = path.join(cwd, '.cursorrules');
const deprecatedPath = path.join(cwd, CURSOR_RULES_FILE.old);
const rulePath = path.join(cwd, CURSOR_RULES_FILE.new);
const isRulesFileExists = fs.existsSync(deprecatedPath);
if (!force) {
assert(
!fs.existsSync(cursorRulesPath),
`Cursor rules file already exists at ${cursorRulesPath}`,
!isRulesFileExists,
`${CURSOR_RULES_FILE.old} is deprecated and will be removed in the future, please use ${CURSOR_RULES_FILE.new} instead`,
);
}
const generalFilePath = path.join(
Expand All @@ -27,9 +33,6 @@ export async function generateCursor(opts: GenerateCursorOpts) {
fs.existsSync(generalFilePath),
`General file not found at ${generalFilePath}, please run \`tnf sync\` first.`,
);
fs.writeFileSync(
cursorRulesPath,
'Please follow the docs in ./.tnf/docs/general.md',
'utf-8',
);

fs.copySync(path.join(__dirname, './cursor'), rulePath);
}
11 changes: 10 additions & 1 deletion src/sync/write_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export async function writeDocs(opts: { context: Context }) {

const generals = [
`- This a react project.`,
`- Use @umijs/tnf/router for routing, which is reexported from @tanstack/react-router.`,
`- Don't be lazy, write all the code to implement features I ask for.`,
`- Keep a log of what, why and how you did what you did in "fyi.md". Keep it updated.`,
`- Use zod to validate api response.`,
Expand Down Expand Up @@ -63,6 +62,16 @@ export async function writeDocs(opts: { context: Context }) {
path.join(docsPath, 'general.md'),
`

## About Controlled Dependencies
Some dependencies are governed by the Rome team via the \`@umijs/tnf\` package.

These dependencies are not allowed to be directly updated or imported by the user. Instead, the user should use the \`@umijs/tnf\` package to import the dependencies.

This includes:

- \`@umijs/tnf/router\`: The router module, reexported from \`@tanstack/react-router\`.
- \`@umijs/tnf/ssr\`: The ssr module, including \`Meta\`, \`Client\` and \`Server\`.

## General

${generals.join('\n')}
Expand Down