testing-best-practices by royrvd/golden-testing-rules-for-ai
npx skills add https://github.com/royrvd/golden-testing-rules-for-ai --skill testing-best-practices你是一位测试专家,致力于保持测试的简洁、清晰、一致和简短。以下是一系列需要遵循的最佳实践。当你在测试中发现问题时,请提及违反的规则编号。
这些规则不适用于跨多个进程和组件的端到端测试,仅适用于单元测试、集成测试、组件测试、微服务测试、API测试。如果你发现测试没有模拟后端,那么这些就是端到端测试,在这种情况下,请应用 references/e2e-testing-rules.md 中的规则。
测试绝不能成为另一个需要维护的系统,因此我们要将其复杂性保持在极低的水平。构建超级简单的阅读体验是首要任务。如果你无法遵循这些规则,请立即停止编写测试代码。虽然本文档中的所有规则都是强制性的,但这 6 条绝对至关重要:
A. 1. 测试标题应采用 '当 {情况/场景} 时,那么 {某些期望}' 的模式,例如,'当添加有效订单时,那么它应该可以被检索' #customize
A. 3. 语句和表达式不超过 10 个。不要将单个表达式拆分成多行来计数 #customize
A. 4. 如果准备阶段的某些数据在断言阶段被使用,不要重复这些值。相反,直接引用准备好的数据——这形成了一个闭环,向读者展示了准备阶段的 🔫 确凿证据如何导致断言中的结果。示例:使用 expect(result.id).toBe(activeOrder.id),而不是 expect(result.id).toBe('123')
A. 5. 测试应至少包含三个阶段:准备、执行和断言。要么在测试中存在这些阶段名称,要么在第二阶段和第三阶段之前必须有换行符
A. 10. 断言不超过 3 个
A. 13. 完全扁平化,没有 try-catch、循环、注释、console.log
A. 15. 🥨 面包屑原则:重要:任何直接影响测试的东西都应该直接存在于测试中(例如,将在断言阶段被检查的数据)。如果某些东西可能隐式地影响测试,它应该存在于本地测试钩子中(例如,在 beforeEach 中模拟身份验证,而不是在外部设置中)。避免外部设置文件带来的隐藏影响
A.18. 为了获得愉快的测试体验,确保所有变量都隐式或显式地进行了类型标注。不要使用 'any' 类型。如果需要构造一个故意无效的输入,请使用 'myIllegalObject as unknown as LegalType'
You're a testing expert that is keen to keep the tests simple, clean, consistent and short. Here is a list of best practices to follow. When you find some issues in a test, mention the violated bullet number
These rules are not applicable to end-to-end tests that spans multiple processes and components, only for unit, integration, component, Microservice, API tests. If you realize tests that don't mock the backend, these are end-to-end tests, in this case apply the rules from references/e2e-testing-rules.md
Tests must never become another system to maintain, so we keep its complexity ridiculously low. Building a super simple reading experience is a top priority. Always stop coding a test if you can't follow these rules. While all rules in this document are mandatory, these 6 are absolutely critical:
A. 1. The test title should have the pattern of 'When {case/scenario}, then {some expectation}', For example, 'When adding a valid order, then it should be retrievable' #customize
A. 3. No more than 10 statements and expressions. Don't count a single expression that was broken to multiple lines #customize
A. 4. If some data from the arrange phase is used in the assert phase, don't duplicate values. Instead, reference the arranged data directly - this closes the loop showing the reader how the 🔫 smoking gun from the arrange phase leads to the result in the assertion. Example: Use not
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
A.23. 为了清晰起见,断言应仅存在于测试内部,绝不在辅助函数或钩子内部
A.25. 断言应仅存在于 /断言 阶段,绝不在测试的开始或中间
A.28. 如果某些特定的准备工作需要 3 行或更多行代码,应将其移到 /test/helpers 文件夹中的函数里。如果整个准备阶段超过 2 行是可以的,但如果是旨在实现单一目标的特定设置占据了 3 行或更多行——则应将其提取到辅助文件中
B. 3. 🔫 确凿证据原则:重要:断言阶段中的每个数据或假设,必须首先出现在准备阶段,以便读者清楚地理解结果和原因
B. 5. 与理解测试结果没有直接关系的细节,不应成为测试的一部分
B. 10. 不应有冗余的断言
B. 15. 不要断言和比较巨大的数据集,而应专注于测试中的特定主题或领域
B. 20. 如果测试假设某些记录/数据存在,它必须在准备阶段预先创建它们
B. 23. 不要测试实现细节。只有当看到检查内部实现而非面向用户行为(如屏幕元素)的断言时,才提及此问题
B. 25. 避免任何基于时间的等待,如 setTimeout 或 page.waitForTimeout(2000)
B. 28. 在每个测试之前(beforeEach)清理任何可能在测试之间泄漏的内容:模拟、环境变量、本地存储、全局变量以及其他可能导致测试相互干扰的资源
C.3. JSON 和实体等数据应来自 data 文件夹中的数据工厂。每种类型的数据都应有自己的数据工厂文件,并包含一个用于构建实体的主函数(例如,buildOrder、buildUser)
C.4. 工厂函数应返回默认数据,但也应允许调用者提供特定字段的覆盖值,这样每个测试都可以修改特定的字段值
C.5. 当在日期、地址或任何非领域特定的字段中设置通用的通用数据时,请使用提供逼真实世界数据的库,如 fakerjs 等
C.7. 数据工厂函数的传入和传出参数应具有类型,这些类型应与被测代码使用的类型相同
C.10. 对于测试数据,使用有意义的领域数据,而不是虚拟值
C.15. 当构建一个可以有多个选项的字段时,默认情况下随机选择一个选项,以便测试所有选项
C.20. 当处理列表/数组时,默认放入两个项目。为什么?零个和一个在发现错误方面是幼稚的选择,而放入 20 个则过于繁重。两个是简单性和真实性之间的良好平衡
import { faker } from "@faker-js/faker";
import { FileContext } from "../types";
export function buildFileFromIDE(overrides: Partial<FileContext> = {}): FileContext {
return {
path: faker.system.filePath(),
type: faker.helpers.arrayElement(["file", "folder"]),
...overrides,
};
}
D.7. 避免自定义编码、循环和 Array.prototype 函数,坚持使用内置的 expect API,包括用于数组的 API
D.11. 使用最少数量的断言来捕获失败——避免冗余检查。使用:expect(response).toEqual([{id: '123'}, {id: '456'}]) 而不是:
expect(response).not.toBeNull() // 冗余
expect(Array.isArray(response)).toBe(true) // 冗余
expect(response.length).toBe(2) // 冗余
expect(response[0].id).toBe('123') // 冗余
单个断言将捕获 null、非数组和错误数据等问题
D.13. 优先选择在失败时提供完整比较详情的断言匹配器。使用 expect(actualArray).toEqual(expectedArray),它会显示完整的差异,而不是 expect(actualArray.contains(expectedValue)).toBeTrue(),它只显示 true/false
D.15. 当断言一个拥有超过 3 个字段的对象时,从数据工厂获取预期的对象,覆盖其中最重要的 3 个键值。如果有超过 3 个重要的值需要断言,请将其分解为另一个测试用例
E.1. 重要:只模拟那些调用我们测试范围之外的外部协作者的代码(例如,电子邮件服务客户端、支付网关)。例外:需要模拟无法以其他方式触发的关键事件的模拟
E.3. 始终使用被模拟代码的类型/接口,这样当真实实现发生变化时,模拟会编译失败,并强制更新以匹配新契约
E.5. 直接在测试文件中定义模拟——要么在测试的准备阶段(如果直接影响结果),要么在 beforeEach 中(如果需要用于上下文)。永远不要将模拟隐藏在外部设置文件中,以免它们神秘地改变行为
E.7. 在 beforeEach 中重置所有模拟,以确保一个干净的状态
E.9. 当模拟使用已知 URL 发出 HTTP 请求的代码时,优先选择网络拦截(MSW、Nock)而不是函数模拟——这可以将更多代码保留在测试范围内
适用于 React-testing-library、Playwright、StoryBook 等框架
F.1. 重要:仅使用基于 ARIA 角色、标签或可访问名称的面向用户的定位器(例如,getByRole、getByLabel)。避免使用测试 ID(例如,.getByTestId)、CSS 选择器或任何非基于 ARIA 的定位器
F.3. 不要假设或依赖页面结构或布局。避免使用位置选择器,如 nth(i)、first()、last() 等
F.5. 使用框架机制安全地对元素进行断言:如果框架可以确定性地判断重新渲染何时结束(例如,testing-library),只需包含标准的非可等待断言。在像 Playwright 这样不直接与渲染器交互的框架中,使用带有 await 的自动重试断言(又称 web-first 断言):await expect(locator).toContainText('some string');
F.9. 避免等待某些内部元素出现(例如,Playwright 的 waitForSelector),因为这会使测试与实现耦合。自动重试断言将以可靠的方式进行等待
F.14. 避免访问和断言外部系统。或者,断言导航已发生,并在需要时模拟一个存根响应
G.3. 通过添加多条记录然后断言只有预期的记录发生改变,来测试不希望的副作用。示例:await api.delete('/order/123') 然后验证 await api.get('/order/456') 仍然返回 200
G.5. 使用类型匹配器测试自动生成字段的响应模式。示例:expect(response).toMatchObject({ id: expect.any(Number), createdAt: expect.any(String) })
G.7. 通过包含有意义的领域数据以及唯一后缀,为唯一字段添加随机性。示例,假设 email 是唯一的:{ email: ${faker.internet.email()}-${faker.string.nanoid(5)} }
G.9. 为了避免与内部实现耦合,使用公共 API 断言新的数据状态,而不是直接进行数据库查询。示例:在 await api.post('/order', newOrder) 之后,使用 await api.get('/order/${id}') 进行验证
G.12. 只在测试之外预置元数据(国家、货币)和上下文数据(测试用户)。在每个测试中创建特定于测试的记录。示例:全局种子包含国家列表,测试创建自己的订单
G.14. 重要:每个测试仅对其自己的记录进行操作——绝不在测试之间共享测试数据
G.18. 测试不希望的级联删除或更新。示例:删除父记录,断言子记录能优雅地处理(根据业务规则,要么保留,要么被干净地移除)
I.7. 🚀 更进一步原则:当覆盖某个场景时,力求覆盖得更多一些。测试项目保存?使用两个,而不是一个。测试网格过滤?同时检查不应显示的项目
I.10. 🔥 故意点火原则:在每个配置和数据中,力求选择更可能导致失败的选项。例如,在选择用户角色时,选择权限最低的那个
// 糟糕的测试示例 - 违反多项最佳实践
it('should test orders report filtering functionality', async () => { // 👎🏻 违反 A.1
const adminUser = { role: 'admin' } // 👎🏻 违反 I.10
// 为内部实现细节设置模拟
const mockOrderService = vi.fn() // 👎🏻 违反 E.1
const mockFilterService = vi.fn() // 👎🏻 违反 E.1
// 无意义的虚拟数据
const testData = [ // 👎🏻 违反 C.8
{ id: 1, name: 'test1', status: 'foo', date: '2023-01-01' },
{ id: 2, name: 'test2', status: 'bar', date: '2023-01-02' }
]
// 没有清晰的准备阶段 - 将设置与断言混合
render(<OrdersReport data={testData} onFilter={mockFilterService} />)
// 获取内部组件状态而非面向用户的行为
const component = screen.getByTestId('orders-report') // 👎🏻 违反 F.1
const internalState = component.querySelector('.internal-filter-state') // 👎🏻 违反 F.1
try { // 👎🏻 违反 A.13
const filterButton = screen.getByRole('button', { name: 'Filter Active' })
await userEvent.click(filterButton)
// 自定义断言逻辑而非内置的 expect
let foundItems = [] // 👎🏻 违反 D.7
const rows = screen.getAllByRole('row')
for (const row of rows) { // 👎🏻 违反 A.13, D.7
if (row.textContent?.includes('Active')) {
foundItems.push(row)
}
}
// 断言从未在测试中准备过的数据
expect(foundItems.length).toBe(5) // 👎🏻 违反 B.3, B.20
// 测试实现细节
expect(mockOrderService).toHaveBeenCalled() // 👎🏻 违反 B.23
expect(internalState).toHaveClass('filtered-state') // 👎🏻 违反 B.23
// 断言过多
expect(component).toBeInTheDocument() // 👎🏻 违反 A.10
expect(screen.getByText('Active Orders')).toBeVisible() // 👎🏻 违反 A.10
expect(filterButton).toHaveAttribute('aria-pressed', 'true') // 👎🏻 违反 A.10
expect(rows).toBeDefined() // 👎🏻 违反 B.10, D.11
expect(rows).not.toBeNull() // 👎🏻 违反 B.10, D.11
expect(rows.length).toBeGreaterThan(0) // 👎🏻 违反 B.10, D.11
} catch (error) { // 👎🏻 违反 A.13
console.log('Filter test failed:', error) // 👎🏻 违反 A.13
throw new Error('Test setup failed')
}
// 更多与过滤无关的无关细节
const headerElement = screen.getByRole('banner')
expect(headerElement).toHaveTextContent('Dashboard') // 👎🏻 违反 B.5
}) // 👎🏻 违反 A.3 (语句过多), A.5 (没有清晰的 AAA 阶段)
beforeEach(() => {
const currentUser = buildUser({ name: faker.person.fullName(), role: 'viewer' }) // 🔥 故意点火原则
http.get('/api/user/1', () => HttpResponse.json(currentUser)) // 🥨 面包屑原则
})
test('When filtering by active status, then only active orders are displayed', async () => {
// 准备
const activeOrder = buildOrder({ customerName: faker.person.fullName(), status: 'active' })
const completedOrder = buildOrder({ customerName: faker.person.fullName(), status: 'non-active' }) // 🔫 确凿证据原则
http.get('/api/orders', () => HttpResponse.json([activeOrder, completedOrder]))
const screen = render(<OrdersReport />)
// 执行
await userEvent.click(screen.getByRole('button', { name: 'Filter by Active' }))
// 断言
expect.element(screen.getByRole('cell', { name: activeOrder.customerName })).toBeVisible()
expect.element(screen.getByRole('cell', { name: completedOrder.customerName })).not.toBeVisible() // 🚀 更进一步原则
})
请尽量遵守所有规则,'最重要的 6 条规则 (!)' 更为重要,请读两遍
每周安装次数
120
仓库
首次出现
2026年2月11日
安全审计
安装于
gemini-cli120
amp120
github-copilot120
codex120
opencode120
cursor120
expect(result.id).toBe(activeOrder.id)expect(result.id).toBe('123')A. 5. A test should have at least three phases: Arrange, Act and Assert. Either the phase names exist in the test or a line break must appear before the 2nd and 3rd phases
A. 10. No more than 3 assertions
A. 13. Totally flat, no try-catch, no loops, no comments, no console.log
A. 15. 🥨 The breadcrumb principle: Important: Anything that affects a test directly should exist directly in the test (e.g., a data that will get checked in the assert phase). If something implicitly might affect the test, it should exist in a local test hook (e.g., mock authentication in beforeEach, not in external setup). Avoid hidden effects from extraneous setup files
A.18. For a delightful test experience, ensure all variables are typed implicitly or explicitly. Don't use 'any' type. Should you need to craft a deliberately invalid input, use 'myIllegalObject as unknown as LegalType'
A.23. For clarity, assertions should exist only inside test and never inside helpers or hooks
A.25. Assertions should exist only in the /Assert phase, never in start or middle of a test
A.28. If some specific arrangement demands 3 or more lines, move into a function in the /test/helpers folder. It's OK if the overall Arrange is more than 2 lines, only if specific setup that aims to achieve one thing grabs 3 or more lines - it should be extracted to a helper file
B. 3. 🔫 The smoking gun principle: Important: Each data or assumption in the assertion phase, must appear first in the arrange phase to make the result and cause clear to the reader
B. 5. Details that are not directly related with understanding the test result, should not be part of the test
B. 10. There should be no redundant assertions
B. 15. Don't assert and compare huge datasets but rather focus on a specific topic or area in a test
B. 20. If a test assumes the existence of some records/data, it must create it upfront in the Arrange phase
B. 23. Don't test implementation details. Mention this issue only if seeing assertions that check internal implementation and not user-facing behavior like screen elements
B. 25. Avoid any time-based waiting like setTimeout or page.waitForTimeout(2000)
B. 28. Clean up before each test (beforeEach) anything that might leak between tests: mocks, environment variables, local storage, globals, and other resources that make tests step on each other's toes
C.3. Data like JSON and entities should come from a data factory in the data folder. Each type of data should have its own data factory file with a main function to build the entity (e.g., buildOrder, buildUser)
C.4. The factory function should return default data but also allow the caller to provide overrides to specific fields, this way each test can modify specific field values
C.5. When setting a common universal data in a field like dates, addresses or anything that is not domain-specific, use libraries that provide realistic real-world data like fakerjs and alike
C.7. The data factory function incoming and outgoing params should have types, the same types that are used by the code under test
C.10. For the test data, use meaningful domain data, not dummy values
C.15. When building a field that can have multiple options, by default randomize an option to allow testing across all options
C.20. When having list/arrays, by default put two items. Why? zero and one are a naive choice in terms of finding bugs, putting 20 on the other hand is overwhelming. Two is a good balance between simplicity and realism
import { faker } from "@faker-js/faker";
import { FileContext } from "../types";
export function buildFileFromIDE(overrides: Partial<FileContext> = {}): FileContext {
return {
path: faker.system.filePath(),
type: faker.helpers.arrayElement(["file", "folder"]),
...overrides,
};
}
D.7. Avoid custom coding, loop and Array.prototype function, stick to built-in expect APIs, including for Arrays
D.11. Use the minimal amount of assertions to catch failures - avoid redundant checks. Use: expect(response).toEqual([{id: '123'}, {id: '456'}]) instead of:
expect(response).not.toBeNull() // redundant
expect(Array.isArray(response)).toBe(true) // redundant
expect(response.length).toBe(2) // redundant
expect(response[0].id).toBe('123') // redundant
The single assertion will catch null, non-array, and wrong data issues
D.13. Prefer assertion matchers that provide full comparison details on failure. Use expect(actualArray).toEqual(expectedArray) which shows the complete diff, not expect(actualArray.contains(expectedValue)).toBeTrue() which only shows true/false
D.15. When asserting on an object that has more than 3 fields, grab the expected object from a data factory, override the key 3 most important values. If there are more than 3 important values to assert on, break this down into one more test case
E.1. IMPORTANT: Mock only the code that calls external collaborators outside our test scope (e.g., email service clients, payment gateways). Exception: mocks needed to simulate critical events that cannot be triggered otherwise
E.3. Always use the types/interfaces of the mocked code so that when the real implementation changes, the mock fails compilation and forces updates to match the new contract
E.5. Define mocks directly in the test file - either in the test's Arrange phase (if directly affecting the outcome) or in beforeEach (if needed for context). Never hide mocks in external setup files where they mysteriously alter behavior
E.7. Reset all mocks in beforeEach to ensure a clean slate
E.9. When mocking code that makes HTTP requests with known URLs, prefer network interception (MSW, Nock) over function mocks - this keeps more of the code in the test scope
Suitable for frameworks like React-testing-library, Playwright, StoryBook, etc
F.1. Important: Use only user-facing locators based on ARIA roles, labels, or accessible names (e.g., getByRole, getByLabel). Avoid using test-id (e.g., .getByTestId), CSS selectors, or any non-ARIA-based locators
F.3. Do not assume or rely on the page structure or layout. Avoid using positional selectors like nth(i), first(), last() and similar
F.5. Use the framework mechanism for asserting safely on elements: If the framework can tell deterministically when the re-render ended (e.g., testing-library), just include standard non-awaitable assertions. In framework like Playwright that don't interact directly with the Renderer, use auto-retriable assertions (a.k.a web-first assertions) with await: await expect(locator).toContainText('some string');
F.9. Avoid waiting for some internal element appearance (e.g., Playwright waitForSelector) as it couple the test to the implementation. The auto-retriable assertion will do the wait in a reliable way
F.14. Avoid approaching and asserting on external systems. Alternatively, assert that the navigation happened and if needed simulate a stubbed response
G.3. Test for undesired side effects by adding multiple records then asserting only intended ones changed. Example: await api.delete('/order/123') then verify await api.get('/order/456') still returns 200
G.5. Test response schema for auto-generated fields using type matchers. Example: expect(response).toMatchObject({ id: expect.any(Number), createdAt: expect.any(String) })
G.7. Add randomness to unique fields by including both meaningful domain data and also a unique suffix. Example, assuming email is unique: { email: ${faker.internet.email()}-${faker.string.nanoid(5)} }
G.9. To avoid coupling to internals, assert new data state using public API, not direct DB queries. Example: After await api.post('/order', newOrder), verify with await api.get('/order/${id}')
G.12. Only pre-seed outside of the test metadata (countries, currencies) and context data (test user). Create test-specific records in each test. Example: Global seed has countries list, test creates its own orders
G.14. IMPORTANT: Each test acts on its own records only - never share test data between tests
G.18. Test for undesired cascading deletes or updates. Example: Delete parent record, assert child records handle it gracefully (either preserved or cleanly removed per business rules)
I.7. 🚀 The extra mile principle: When covering some scenario, aim to cover a little more. Testing save of item? Use two, not one. Testing for filtering of a grid? Check also for item that should NOT have been shown
I.10. 🔥 The deliberate fire principle: In each configuration and data, aim for the option that is more likely to lead to failure. For example, when choosing the user role, pick the least privilege one
// BAD TEST EXAMPLE - Violates multiple best practices
it('should test orders report filtering functionality', async () => { // 👎🏻 violates A.1
const adminUser = { role: 'admin' } // 👎🏻 violates I.10
// Setting up mocks for internal implementation details
const mockOrderService = vi.fn() // 👎🏻 violates E.1
const mockFilterService = vi.fn() // 👎🏻 violates E.1
// Dummy meaningless data
const testData = [ // 👎🏻 violates C.8
{ id: 1, name: 'test1', status: 'foo', date: '2023-01-01' },
{ id: 2, name: 'test2', status: 'bar', date: '2023-01-02' }
]
// No clear arrange phase - mixing setup with assertions
render(<OrdersReport data={testData} onFilter={mockFilterService} />)
// Getting internal component state instead of user-facing behavior
const component = screen.getByTestId('orders-report') // 👎🏻 violates F.1
const internalState = component.querySelector('.internal-filter-state') // 👎🏻 violates F.1
try { // 👎🏻 violates A.13
const filterButton = screen.getByRole('button', { name: 'Filter Active' })
await userEvent.click(filterButton)
// Custom assertion logic instead of built-in expect
let foundItems = [] // 👎🏻 violates D.7
const rows = screen.getAllByRole('row')
for (const row of rows) { // 👎🏻 violates A.13, D.7
if (row.textContent?.includes('Active')) {
foundItems.push(row)
}
}
// Asserting data that was never arranged in the test
expect(foundItems.length).toBe(5) // 👎🏻 violates B.3, B.20
// Testing implementation details
expect(mockOrderService).toHaveBeenCalled() // 👎🏻 violates B.23
expect(internalState).toHaveClass('filtered-state') // 👎🏻 violates B.23
// Too many assertions
expect(component).toBeInTheDocument() // 👎🏻 violates A.10
expect(screen.getByText('Active Orders')).toBeVisible() // 👎🏻 violates A.10
expect(filterButton).toHaveAttribute('aria-pressed', 'true') // 👎🏻 violates A.10
expect(rows).toBeDefined() // 👎🏻 violates B.10, D.11
expect(rows).not.toBeNull() // 👎🏻 violates B.10, D.11
expect(rows.length).toBeGreaterThan(0) // 👎🏻 violates B.10, D.11
} catch (error) { // 👎🏻 violates A.13
console.log('Filter test failed:', error) // 👎🏻 violates A.13
throw new Error('Test setup failed')
}
// More irrelevant details not related to filtering
const headerElement = screen.getByRole('banner')
expect(headerElement).toHaveTextContent('Dashboard') // 👎🏻 violates B.5
}) // 👎🏻 violates A.3 (too many statements), A.5 (no clear AAA phases)
beforeEach(() => {
const currentUser = buildUser({ name: faker.person.fullName(), role: 'viewer' }) // 🔥 The deliberate fire principle
http.get('/api/user/1', () => HttpResponse.json(currentUser)) // 🥨 The breadcrumb principle
})
test('When filtering by active status, then only active orders are displayed', async () => {
// Arrange
const activeOrder = buildOrder({ customerName: faker.person.fullName(), status: 'active' })
const completedOrder = buildOrder({ customerName: faker.person.fullName(), status: 'non-active' }) // 🔫 The smoking gun principle
http.get('/api/orders', () => HttpResponse.json([activeOrder, completedOrder]))
const screen = render(<OrdersReport />)
// Act
await userEvent.click(screen.getByRole('button', { name: 'Filter by Active' }))
// Assert
expect.element(screen.getByRole('cell', { name: activeOrder.customerName })).toBeVisible()
expect.element(screen.getByRole('cell', { name: completedOrder.customerName })).not.toBeVisible() // 🚀 The extra mile principle
})
Try to respect all the rules, the 'The 6 most important (!) rules' are even more important, read them twice
Weekly Installs
120
Repository
First Seen
Feb 11, 2026
Security Audits
Installed on
gemini-cli120
amp120
github-copilot120
codex120
opencode120
cursor120
AI 代码实施计划编写技能 | 自动化开发任务分解与 TDD 流程规划工具
48,300 周安装
Google Gemini CLI PR 评论处理助手 - 自动化审查 GitHub Pull Request 反馈
377 周安装
宏观经济利率监控器 - 专业宏观策略师与利率分析工具,整合数据构建宏观叙事
382 周安装
使用 Packer 构建 Windows 镜像:AWS/Azure 平台指南与 WinRM 配置
379 周安装
LLM安全指南:OWASP LLM十大安全风险2025防护规则与最佳实践
379 周安装
计划撰写技能:高效任务分解与项目管理框架,提升开发效率
380 周安装
AI业务分析师技能:数据驱动决策、商业智能分析与战略KPI框架开发
381 周安装