@codyswann/lisa 1.47.1 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/all/copy-overwrite/.claude/rules/lisa.md +23 -10
  2. package/all/copy-overwrite/.claude/settings.json +10 -252
  3. package/all/deletions.json +67 -1
  4. package/cdk/copy-overwrite/.claude/settings.json +80 -0
  5. package/cdk/create-only/.github/workflows/ci.yml +1 -1
  6. package/cdk/create-only/.github/workflows/deploy.yml +1 -1
  7. package/dist/core/lisa.d.ts +14 -0
  8. package/dist/core/lisa.d.ts.map +1 -1
  9. package/dist/core/lisa.js +47 -0
  10. package/dist/core/lisa.js.map +1 -1
  11. package/expo/copy-overwrite/.claude/settings.json +80 -0
  12. package/expo/copy-overwrite/eslint.expo.ts +2 -2
  13. package/expo/create-only/.github/workflows/ci.yml +1 -1
  14. package/expo/create-only/.github/workflows/deploy.yml +1 -1
  15. package/expo/deletions.json +33 -0
  16. package/expo/package-lisa/package.lisa.json +2 -2
  17. package/nestjs/copy-overwrite/.claude/settings.json +80 -0
  18. package/nestjs/create-only/.github/workflows/ci.yml +1 -1
  19. package/nestjs/create-only/.github/workflows/deploy.yml +1 -1
  20. package/nestjs/deletions.json +8 -0
  21. package/package.json +8 -4
  22. package/rails/copy-overwrite/.claude/settings.json +80 -0
  23. package/rails/create-only/.github/workflows/ci.yml +1 -1
  24. package/rails/deletions.json +11 -1
  25. package/typescript/copy-overwrite/.claude/settings.json +13 -253
  26. package/typescript/copy-overwrite/eslint.typescript.ts +1 -1
  27. package/typescript/create-only/.github/workflows/ci.yml +1 -1
  28. package/typescript/deletions.json +12 -1
  29. package/typescript/package-lisa/package.lisa.json +1 -1
  30. package/all/copy-overwrite/.claude/agents/agent-architect.md +0 -310
  31. package/all/copy-overwrite/.claude/agents/architecture-specialist.md +0 -53
  32. package/all/copy-overwrite/.claude/agents/debug-specialist.md +0 -204
  33. package/all/copy-overwrite/.claude/agents/git-history-analyzer.md +0 -183
  34. package/all/copy-overwrite/.claude/agents/hooks-expert.md +0 -74
  35. package/all/copy-overwrite/.claude/agents/implementer.md +0 -54
  36. package/all/copy-overwrite/.claude/agents/learner.md +0 -44
  37. package/all/copy-overwrite/.claude/agents/performance-specialist.md +0 -95
  38. package/all/copy-overwrite/.claude/agents/product-specialist.md +0 -72
  39. package/all/copy-overwrite/.claude/agents/quality-specialist.md +0 -55
  40. package/all/copy-overwrite/.claude/agents/security-specialist.md +0 -58
  41. package/all/copy-overwrite/.claude/agents/skill-evaluator.md +0 -246
  42. package/all/copy-overwrite/.claude/agents/slash-command-architect.md +0 -87
  43. package/all/copy-overwrite/.claude/agents/test-specialist.md +0 -64
  44. package/all/copy-overwrite/.claude/agents/verification-specialist.md +0 -189
  45. package/all/copy-overwrite/.claude/agents/web-search-researcher.md +0 -112
  46. package/all/copy-overwrite/.claude/commands/git/commit-and-submit-pr.md +0 -7
  47. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-and-verify.md +0 -7
  48. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-deploy-and-verify.md +0 -7
  49. package/all/copy-overwrite/.claude/commands/git/commit.md +0 -7
  50. package/all/copy-overwrite/.claude/commands/git/prune.md +0 -6
  51. package/all/copy-overwrite/.claude/commands/git/submit-pr.md +0 -7
  52. package/all/copy-overwrite/.claude/commands/jira/create.md +0 -7
  53. package/all/copy-overwrite/.claude/commands/jira/sync.md +0 -7
  54. package/all/copy-overwrite/.claude/commands/jira/verify.md +0 -7
  55. package/all/copy-overwrite/.claude/commands/lisa/review-implementation.md +0 -7
  56. package/all/copy-overwrite/.claude/commands/plan/add-test-coverage.md +0 -7
  57. package/all/copy-overwrite/.claude/commands/plan/create.md +0 -6
  58. package/all/copy-overwrite/.claude/commands/plan/execute.md +0 -7
  59. package/all/copy-overwrite/.claude/commands/plan/fix-linter-error.md +0 -7
  60. package/all/copy-overwrite/.claude/commands/plan/local-code-review.md +0 -6
  61. package/all/copy-overwrite/.claude/commands/plan/lower-code-complexity.md +0 -6
  62. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines-per-function.md +0 -7
  63. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines.md +0 -7
  64. package/all/copy-overwrite/.claude/commands/pull-request/review.md +0 -7
  65. package/all/copy-overwrite/.claude/commands/security/zap-scan.md +0 -6
  66. package/all/copy-overwrite/.claude/commands/sonarqube/check.md +0 -6
  67. package/all/copy-overwrite/.claude/commands/sonarqube/fix.md +0 -6
  68. package/all/copy-overwrite/.claude/commands/tasks/load.md +0 -7
  69. package/all/copy-overwrite/.claude/commands/tasks/sync.md +0 -7
  70. package/all/copy-overwrite/.claude/hooks/check-tired-boss.sh +0 -61
  71. package/all/copy-overwrite/.claude/hooks/debug-hook.sh +0 -47
  72. package/all/copy-overwrite/.claude/hooks/enforce-plan-rules.sh +0 -15
  73. package/all/copy-overwrite/.claude/hooks/notify-ntfy.sh +0 -183
  74. package/all/copy-overwrite/.claude/hooks/setup-jira-cli.sh +0 -52
  75. package/all/copy-overwrite/.claude/hooks/sync-tasks.sh +0 -107
  76. package/all/copy-overwrite/.claude/hooks/ticket-sync-reminder.sh +0 -23
  77. package/all/copy-overwrite/.claude/hooks/track-plan-sessions.sh +0 -164
  78. package/all/copy-overwrite/.claude/hooks/verify-completion.sh +0 -77
  79. package/all/copy-overwrite/.claude/rules/coding-philosophy.md +0 -428
  80. package/all/copy-overwrite/.claude/rules/verfication.md +0 -596
  81. package/all/copy-overwrite/.claude/skills/agent-design-best-practices/SKILL.md +0 -219
  82. package/all/copy-overwrite/.claude/skills/git-commit/SKILL.md +0 -48
  83. package/all/copy-overwrite/.claude/skills/git-commit-and-submit-pr/SKILL.md +0 -8
  84. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-and-verify/SKILL.md +0 -7
  85. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-deploy-and-verify/SKILL.md +0 -7
  86. package/all/copy-overwrite/.claude/skills/git-prune/SKILL.md +0 -35
  87. package/all/copy-overwrite/.claude/skills/git-submit-pr/SKILL.md +0 -44
  88. package/all/copy-overwrite/.claude/skills/jira-create/SKILL.md +0 -41
  89. package/all/copy-overwrite/.claude/skills/jira-sync/SKILL.md +0 -63
  90. package/all/copy-overwrite/.claude/skills/jira-verify/SKILL.md +0 -29
  91. package/all/copy-overwrite/.claude/skills/lisa-review-implementation/SKILL.md +0 -209
  92. package/all/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -44
  93. package/all/copy-overwrite/.claude/skills/plan-execute/SKILL.md +0 -89
  94. package/all/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  95. package/all/copy-overwrite/.claude/skills/plan-local-code-review/SKILL.md +0 -88
  96. package/all/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -44
  97. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -45
  98. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  99. package/all/copy-overwrite/.claude/skills/pull-request-review/SKILL.md +0 -68
  100. package/all/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  101. package/all/copy-overwrite/.claude/skills/skill-creator/LICENSE.txt +0 -202
  102. package/all/copy-overwrite/.claude/skills/skill-creator/SKILL.md +0 -210
  103. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
  104. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/init_skill.py +0 -305
  105. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/package_skill.py +0 -112
  106. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/quick_validate.py +0 -67
  107. package/all/copy-overwrite/.claude/skills/sonarqube-check/SKILL.md +0 -11
  108. package/all/copy-overwrite/.claude/skills/sonarqube-fix/SKILL.md +0 -8
  109. package/all/copy-overwrite/.claude/skills/tasks-load/SKILL.md +0 -88
  110. package/all/copy-overwrite/.claude/skills/tasks-sync/SKILL.md +0 -108
  111. package/eslint-plugin-code-organization/README.md +0 -149
  112. package/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  113. package/eslint-plugin-code-organization/index.js +0 -28
  114. package/eslint-plugin-code-organization/package.json +0 -10
  115. package/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
  116. package/expo/copy-overwrite/.claude/agents/ops-specialist.md +0 -124
  117. package/expo/copy-overwrite/.claude/rules/expo-verification.md +0 -261
  118. package/expo/copy-overwrite/.claude/skills/apollo-client/SKILL.md +0 -238
  119. package/expo/copy-overwrite/.claude/skills/apollo-client/references/mutation-patterns.md +0 -360
  120. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/SKILL.md +0 -360
  121. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/atomic-levels.md +0 -417
  122. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/folder-structure.md +0 -257
  123. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/gluestack-mapping.md +0 -233
  124. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +0 -329
  125. package/expo/copy-overwrite/.claude/skills/container-view-pattern/SKILL.md +0 -299
  126. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/examples.md +0 -749
  127. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/patterns.md +0 -318
  128. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/create_component.py +0 -200
  129. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/validate_component.py +0 -209
  130. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/SKILL.md +0 -268
  131. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/common-issues.md +0 -619
  132. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/file-extensions.md +0 -340
  133. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/platform-api.md +0 -276
  134. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +0 -416
  135. package/expo/copy-overwrite/.claude/skills/directory-structure/SKILL.md +0 -202
  136. package/expo/copy-overwrite/.claude/skills/directory-structure/scripts/validate_structure.py +0 -445
  137. package/expo/copy-overwrite/.claude/skills/expo-env-config/SKILL.md +0 -309
  138. package/expo/copy-overwrite/.claude/skills/expo-env-config/references/validation-patterns.md +0 -417
  139. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/SKILL.md +0 -431
  140. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/references/official-docs.md +0 -290
  141. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/scripts/generate-route.py +0 -171
  142. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/SKILL.md +0 -411
  143. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/color-tokens.md +0 -343
  144. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/component-mapping.md +0 -307
  145. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/spacing-scale.md +0 -300
  146. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/scripts/validate_styling.py +0 -315
  147. package/expo/copy-overwrite/.claude/skills/local-state/SKILL.md +0 -362
  148. package/expo/copy-overwrite/.claude/skills/local-state/references/async-storage.md +0 -505
  149. package/expo/copy-overwrite/.claude/skills/local-state/references/persistence-patterns.md +0 -711
  150. package/expo/copy-overwrite/.claude/skills/local-state/references/reactive-variables.md +0 -446
  151. package/expo/copy-overwrite/.claude/skills/ops-browser-uat/SKILL.md +0 -124
  152. package/expo/copy-overwrite/.claude/skills/ops-check-logs/SKILL.md +0 -211
  153. package/expo/copy-overwrite/.claude/skills/ops-db-ops/SKILL.md +0 -119
  154. package/expo/copy-overwrite/.claude/skills/ops-deploy/SKILL.md +0 -119
  155. package/expo/copy-overwrite/.claude/skills/ops-monitor-errors/SKILL.md +0 -99
  156. package/expo/copy-overwrite/.claude/skills/ops-performance/SKILL.md +0 -165
  157. package/expo/copy-overwrite/.claude/skills/ops-run-local/SKILL.md +0 -166
  158. package/expo/copy-overwrite/.claude/skills/ops-verify-health/SKILL.md +0 -101
  159. package/expo/copy-overwrite/.claude/skills/owasp-zap/SKILL.md +0 -56
  160. package/expo/copy-overwrite/.claude/skills/playwright-selectors/SKILL.md +0 -223
  161. package/expo/copy-overwrite/.claude/skills/testing-library/SKILL.md +0 -314
  162. package/expo/copy-overwrite/.claude/skills/testing-library/references/async-patterns.md +0 -420
  163. package/expo/copy-overwrite/.claude/skills/testing-library/references/expo-router-testing.md +0 -556
  164. package/expo/copy-overwrite/.claude/skills/testing-library/references/mocking-patterns.md +0 -590
  165. package/expo/copy-overwrite/.claude/skills/testing-library/references/query-priority.md +0 -291
  166. package/expo/copy-overwrite/eslint-plugin-component-structure/README.md +0 -234
  167. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/plugin-index.test.js +0 -89
  168. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/require-memo-in-view.test.js +0 -201
  169. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/single-component-per-file.test.js +0 -294
  170. package/expo/copy-overwrite/eslint-plugin-component-structure/index.js +0 -37
  171. package/expo/copy-overwrite/eslint-plugin-component-structure/package.json +0 -10
  172. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/enforce-component-structure.js +0 -235
  173. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/no-return-in-view.js +0 -96
  174. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/require-memo-in-view.js +0 -183
  175. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/single-component-per-file.js +0 -243
  176. package/expo/copy-overwrite/eslint-plugin-ui-standards/README.md +0 -192
  177. package/expo/copy-overwrite/eslint-plugin-ui-standards/index.js +0 -31
  178. package/expo/copy-overwrite/eslint-plugin-ui-standards/package.json +0 -10
  179. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-classname-outside-ui.js +0 -56
  180. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-direct-rn-imports.js +0 -60
  181. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/SKILL.md +0 -176
  182. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/advanced-features.md +0 -527
  183. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/project-patterns.md +0 -483
  184. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/quick-start.md +0 -257
  185. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/resolvers-mutations.md +0 -413
  186. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/types-scalars.md +0 -513
  187. package/nestjs/copy-overwrite/.claude/skills/nestjs-rules/SKILL.md +0 -536
  188. package/nestjs/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  189. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/SKILL.md +0 -275
  190. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/configuration-patterns.md +0 -487
  191. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/entity-patterns.md +0 -450
  192. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/observability-patterns.md +0 -536
  193. package/rails/copy-overwrite/.claude/skills/action-controller-best-practices/SKILL.md +0 -374
  194. package/rails/copy-overwrite/.claude/skills/action-view-best-practices/SKILL.md +0 -335
  195. package/rails/copy-overwrite/.claude/skills/active-record-model-best-practices/SKILL.md +0 -166
  196. package/rails/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -45
  197. package/rails/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  198. package/rails/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -48
  199. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -46
  200. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  201. package/typescript/copy-overwrite/.claude/hooks/format-on-edit.sh +0 -76
  202. package/typescript/copy-overwrite/.claude/hooks/install-pkgs.sh +0 -64
  203. package/typescript/copy-overwrite/.claude/hooks/lint-on-edit.sh +0 -81
  204. package/typescript/copy-overwrite/.claude/hooks/sg-scan-on-edit.sh +0 -68
  205. package/typescript/copy-overwrite/.claude/skills/jsdoc-best-practices/SKILL.md +0 -432
  206. package/typescript/copy-overwrite/eslint-plugin-code-organization/README.md +0 -149
  207. package/typescript/copy-overwrite/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  208. package/typescript/copy-overwrite/eslint-plugin-code-organization/index.js +0 -28
  209. package/typescript/copy-overwrite/eslint-plugin-code-organization/package.json +0 -10
  210. package/typescript/copy-overwrite/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
@@ -1,420 +0,0 @@
1
- # Async Testing Patterns
2
-
3
- This reference covers best practices for handling asynchronous operations in tests.
4
-
5
- ## Core Async Utilities
6
-
7
- ### findBy Queries
8
-
9
- `findBy` queries return a Promise that resolves when the element is found. They combine `getBy` with `waitFor`.
10
-
11
- ```typescript
12
- // Wait for element to appear (default timeout: 4500ms)
13
- const alert = await screen.findByRole("alert");
14
-
15
- // Custom timeout
16
- const alert = await screen.findByRole("alert", {}, { timeout: 10000 });
17
-
18
- // Wait for element with specific text
19
- const message = await screen.findByText("Success!");
20
- ```
21
-
22
- #### When to Use findBy
23
-
24
- - After triggering an action that causes async state update
25
- - When waiting for data to load
26
- - When waiting for animations to complete
27
- - When waiting for API responses
28
-
29
- ```typescript
30
- test("displays success message after form submission", async () => {
31
- const user = userEvent.setup();
32
- render(<ContactForm />);
33
-
34
- await user.type(screen.getByLabelText("Email"), "test@example.com");
35
- await user.press(screen.getByRole("button", { name: "Submit" }));
36
-
37
- // Wait for success message to appear
38
- expect(await screen.findByRole("alert")).toHaveTextContent("Message sent!");
39
- });
40
- ```
41
-
42
- ### waitFor Utility
43
-
44
- `waitFor` repeatedly runs a callback until it stops throwing or times out.
45
-
46
- ```typescript
47
- import { waitFor } from "@testing-library/react-native";
48
-
49
- // Wait for a mock to be called
50
- await waitFor(() => {
51
- expect(mockFunction).toHaveBeenCalled();
52
- });
53
-
54
- // Wait for specific call arguments
55
- await waitFor(() => {
56
- expect(mockApi.post).toHaveBeenCalledWith("/submit", {
57
- email: "test@example.com",
58
- });
59
- });
60
- ```
61
-
62
- #### waitFor Configuration
63
-
64
- ```typescript
65
- await waitFor(
66
- () => {
67
- expect(element).toBeOnTheScreen();
68
- },
69
- {
70
- timeout: 5000, // Max wait time (default: 4500ms)
71
- interval: 100, // Check interval (default: 50ms)
72
- onTimeout: error => {
73
- // Custom error handling
74
- console.log("Timed out waiting for element");
75
- return error;
76
- },
77
- }
78
- );
79
- ```
80
-
81
- ### waitForElementToBeRemoved
82
-
83
- Wait for an element to be removed from the screen.
84
-
85
- ```typescript
86
- import { waitForElementToBeRemoved } from "@testing-library/react-native";
87
-
88
- // Wait for loading indicator to disappear
89
- await waitForElementToBeRemoved(() => screen.queryByRole("progressbar"));
90
-
91
- // Alternative pattern
92
- const loadingSpinner = screen.getByRole("progressbar");
93
- await waitForElementToBeRemoved(loadingSpinner);
94
- ```
95
-
96
- ## Common Async Patterns
97
-
98
- ### Loading States
99
-
100
- ```typescript
101
- test("displays loading state then content", async () => {
102
- render(<DataFetcher />);
103
-
104
- // Assert loading state appears
105
- expect(screen.getByRole("progressbar")).toBeOnTheScreen();
106
-
107
- // Wait for loading to complete
108
- await waitForElementToBeRemoved(() => screen.queryByRole("progressbar"));
109
-
110
- // Assert content is now displayed
111
- expect(screen.getByRole("list")).toBeOnTheScreen();
112
- });
113
- ```
114
-
115
- ### Error States
116
-
117
- ```typescript
118
- test("displays error message when API fails", async () => {
119
- mockApi.get.mockRejectedValue(new Error("Network error"));
120
- const user = userEvent.setup();
121
- render(<DataFetcher />);
122
-
123
- await user.press(screen.getByRole("button", { name: "Fetch Data" }));
124
-
125
- // Wait for error message
126
- expect(await screen.findByRole("alert")).toHaveTextContent("Network error");
127
- });
128
- ```
129
-
130
- ### Sequential Async Operations
131
-
132
- ```typescript
133
- test("completes multi-step wizard", async () => {
134
- const user = userEvent.setup();
135
- render(<Wizard />);
136
-
137
- // Step 1
138
- await user.type(screen.getByLabelText("Name"), "John Doe");
139
- await user.press(screen.getByRole("button", { name: "Next" }));
140
-
141
- // Wait for step 2 to load
142
- expect(await screen.findByText("Step 2")).toBeOnTheScreen();
143
-
144
- // Step 2
145
- await user.type(screen.getByLabelText("Email"), "john@example.com");
146
- await user.press(screen.getByRole("button", { name: "Submit" }));
147
-
148
- // Wait for completion
149
- expect(await screen.findByText("Success!")).toBeOnTheScreen();
150
- });
151
- ```
152
-
153
- ### Debounced/Throttled Operations
154
-
155
- ```typescript
156
- jest.useFakeTimers();
157
-
158
- test("debounced search executes after delay", async () => {
159
- const user = userEvent.setup();
160
- render(<SearchInput onSearch={mockSearch} />);
161
-
162
- await user.type(screen.getByRole("textbox"), "query");
163
-
164
- // Search not called yet (debounced)
165
- expect(mockSearch).not.toHaveBeenCalled();
166
-
167
- // Advance timers past debounce delay
168
- jest.runAllTimers();
169
-
170
- // Now search is called
171
- await waitFor(() => {
172
- expect(mockSearch).toHaveBeenCalledWith("query");
173
- });
174
- });
175
- ```
176
-
177
- ## Anti-Patterns
178
-
179
- ### Side Effects Inside waitFor
180
-
181
- ```typescript
182
- // Wrong - fireEvent inside waitFor
183
- await waitFor(() => {
184
- fireEvent.press(button);
185
- expect(result).toBeOnTheScreen();
186
- });
187
-
188
- // Correct - side effect before waitFor
189
- fireEvent.press(button);
190
- await waitFor(() => {
191
- expect(result).toBeOnTheScreen();
192
- });
193
- ```
194
-
195
- ### Multiple Assertions in waitFor
196
-
197
- ```typescript
198
- // Wrong - multiple assertions
199
- await waitFor(() => {
200
- expect(title).toBeOnTheScreen();
201
- expect(subtitle).toBeOnTheScreen();
202
- expect(button).toBeEnabled();
203
- });
204
-
205
- // Correct - wait for one, assert the rest synchronously
206
- expect(await screen.findByRole("heading")).toBeOnTheScreen();
207
- expect(screen.getByText("Subtitle")).toBeOnTheScreen();
208
- expect(screen.getByRole("button")).toBeEnabled();
209
- ```
210
-
211
- ### Empty Callback in waitFor
212
-
213
- ```typescript
214
- // Wrong - empty callback
215
- await waitFor(() => {});
216
-
217
- // Correct - explicit assertion
218
- await waitFor(() => {
219
- expect(element).toBeOnTheScreen();
220
- });
221
- ```
222
-
223
- ### Using waitFor When findBy Works
224
-
225
- ```typescript
226
- // Unnecessary - waitFor wrapping getBy
227
- await waitFor(() => {
228
- expect(screen.getByRole("alert")).toBeOnTheScreen();
229
- });
230
-
231
- // Better - use findBy directly
232
- expect(await screen.findByRole("alert")).toBeOnTheScreen();
233
- ```
234
-
235
- ### Wrapping Render in act()
236
-
237
- ```typescript
238
- // Wrong - unnecessary act wrapper
239
- await act(async () => {
240
- render(<Component />);
241
- });
242
-
243
- // Correct - render handles act internally
244
- render(<Component />);
245
- ```
246
-
247
- ### Ignoring Return Value of Async Queries
248
-
249
- ```typescript
250
- // Wrong - not awaiting
251
- screen.findByRole("alert");
252
- expect(screen.getByRole("alert")).toBeOnTheScreen();
253
-
254
- // Correct - await the findBy
255
- await screen.findByRole("alert");
256
- expect(screen.getByRole("alert")).toBeOnTheScreen();
257
-
258
- // Or better - use the returned element
259
- const alert = await screen.findByRole("alert");
260
- expect(alert).toBeOnTheScreen();
261
- ```
262
-
263
- ## userEvent and Async
264
-
265
- ### Setup with Fake Timers
266
-
267
- ```typescript
268
- jest.useFakeTimers();
269
-
270
- test("user interaction with fake timers", async () => {
271
- const user = userEvent.setup({
272
- advanceTimers: jest.advanceTimersByTime,
273
- });
274
-
275
- render(<Component />);
276
- await user.press(screen.getByRole("button", { name: "Click me" }));
277
-
278
- // Assertions...
279
- });
280
- ```
281
-
282
- ### Awaiting userEvent Actions
283
-
284
- All userEvent methods are async and must be awaited:
285
-
286
- ```typescript
287
- const user = userEvent.setup();
288
-
289
- // All interactions must be awaited
290
- await user.press(button);
291
- await user.type(input, "text");
292
- await user.longPress(element);
293
- await user.scroll(scrollView, { y: 100 });
294
- ```
295
-
296
- ### Sequential vs Parallel Interactions
297
-
298
- ```typescript
299
- // Sequential - wait for each action
300
- await user.type(emailInput, "test@example.com");
301
- await user.type(passwordInput, "password123");
302
- await user.press(submitButton);
303
-
304
- // Don't use Promise.all for user interactions
305
- // Users can only do one thing at a time
306
- ```
307
-
308
- ## Apollo GraphQL Async Patterns
309
-
310
- ### Mocking Query Responses
311
-
312
- ```typescript
313
- const mocks = [
314
- {
315
- request: {
316
- query: GET_USER,
317
- variables: { id: "1" },
318
- },
319
- result: {
320
- data: {
321
- user: { id: "1", name: "John" },
322
- },
323
- },
324
- },
325
- ];
326
-
327
- test("displays user data", async () => {
328
- render(
329
- <MockedProvider mocks={mocks}>
330
- <UserProfile userId="1" />
331
- </MockedProvider>
332
- );
333
-
334
- // Wait for data to load
335
- expect(await screen.findByText("John")).toBeOnTheScreen();
336
- });
337
- ```
338
-
339
- ### Handling Loading and Error States
340
-
341
- ```typescript
342
- test("shows loading then data", async () => {
343
- render(
344
- <MockedProvider mocks={mocks}>
345
- <UserProfile userId="1" />
346
- </MockedProvider>
347
- );
348
-
349
- // Initially shows loading
350
- expect(screen.getByRole("progressbar")).toBeOnTheScreen();
351
-
352
- // After data loads
353
- await waitForElementToBeRemoved(() => screen.queryByRole("progressbar"));
354
- expect(screen.getByText("John")).toBeOnTheScreen();
355
- });
356
-
357
- test("shows error on failure", async () => {
358
- const errorMocks = [
359
- {
360
- request: { query: GET_USER, variables: { id: "1" } },
361
- error: new Error("Failed to fetch"),
362
- },
363
- ];
364
-
365
- render(
366
- <MockedProvider mocks={errorMocks}>
367
- <UserProfile userId="1" />
368
- </MockedProvider>
369
- );
370
-
371
- expect(await screen.findByRole("alert")).toHaveTextContent("Failed to fetch");
372
- });
373
- ```
374
-
375
- ## Timer Patterns
376
-
377
- ### Fake Timers Setup
378
-
379
- ```typescript
380
- beforeEach(() => {
381
- jest.useFakeTimers();
382
- });
383
-
384
- afterEach(() => {
385
- jest.useRealTimers();
386
- });
387
- ```
388
-
389
- ### Advancing Timers
390
-
391
- ```typescript
392
- // Advance by specific time
393
- jest.advanceTimersByTime(1000);
394
-
395
- // Run all pending timers
396
- jest.runAllTimers();
397
-
398
- // Run only pending timers (not new ones)
399
- jest.runOnlyPendingTimers();
400
-
401
- // Advance to next timer
402
- jest.advanceTimersToNextTimer();
403
- ```
404
-
405
- ### Combining Timers with Async
406
-
407
- ```typescript
408
- test("animation completes after delay", async () => {
409
- render(<AnimatedComponent />);
410
-
411
- expect(screen.getByTestId("animation")).toHaveStyle({ opacity: 0 });
412
-
413
- // Advance past animation duration
414
- jest.advanceTimersByTime(500);
415
-
416
- await waitFor(() => {
417
- expect(screen.getByTestId("animation")).toHaveStyle({ opacity: 1 });
418
- });
419
- });
420
- ```