@jmruthers/pace-core 0.6.6 → 0.6.8

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 (292) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +240 -0
  4. package/audit-tool/audits/03-architecture.cjs +224 -0
  5. package/audit-tool/audits/04-code-quality.cjs +149 -0
  6. package/audit-tool/audits/05-styling.cjs +224 -0
  7. package/audit-tool/audits/06-security-rbac.cjs +554 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
  9. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  10. package/audit-tool/audits/09-operations.cjs +208 -0
  11. package/audit-tool/index.cjs +295 -0
  12. package/audit-tool/utils/code-utils.cjs +218 -0
  13. package/audit-tool/utils/file-utils.cjs +230 -0
  14. package/audit-tool/utils/report-utils.cjs +380 -0
  15. package/cursor-rules/00-standards-overview.mdc +156 -0
  16. package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
  17. package/cursor-rules/02-project-structure.mdc +37 -5
  18. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
  19. package/cursor-rules/04-code-quality.mdc +419 -0
  20. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
  21. package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
  22. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  23. package/cursor-rules/08-testing-documentation.mdc +324 -0
  24. package/cursor-rules/09-operations.mdc +365 -0
  25. package/dist/DataTable-6RMSCQJ6.js +15 -0
  26. package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  27. package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
  28. package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
  29. package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
  30. package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
  31. package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
  32. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  33. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  34. package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
  35. package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
  36. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  37. package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
  38. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  39. package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
  40. package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
  41. package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
  42. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  43. package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
  44. package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
  45. package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
  46. package/dist/components.d.ts +5 -4
  47. package/dist/components.js +29 -34
  48. package/dist/eslint-rules/index.cjs +22 -9
  49. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  50. package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
  51. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  52. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
  53. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
  54. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  55. package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
  56. package/dist/hooks.d.ts +5 -5
  57. package/dist/hooks.js +8 -8
  58. package/dist/index.d.ts +7 -7
  59. package/dist/index.js +21 -20
  60. package/dist/providers.js +2 -2
  61. package/dist/rbac/index.d.ts +1 -1
  62. package/dist/rbac/index.js +8 -8
  63. package/dist/theming/runtime.d.ts +61 -1
  64. package/dist/theming/runtime.js +1 -1
  65. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  66. package/dist/types.d.ts +2 -2
  67. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  68. package/dist/utils.d.ts +2 -2
  69. package/dist/utils.js +8 -8
  70. package/docs/README.md +1 -1
  71. package/docs/api/modules.md +106 -41
  72. package/docs/api-reference/components.md +18 -20
  73. package/docs/api-reference/hooks.md +80 -80
  74. package/docs/api-reference/types.md +1 -1
  75. package/docs/api-reference/utilities.md +1 -1
  76. package/docs/architecture/README.md +1 -1
  77. package/docs/core-concepts/events.md +3 -3
  78. package/docs/core-concepts/organisations.md +6 -6
  79. package/docs/core-concepts/permissions.md +6 -6
  80. package/docs/documentation-index.md +12 -18
  81. package/docs/getting-started/dependencies.md +23 -0
  82. package/docs/getting-started/documentation-index.md +1 -1
  83. package/docs/getting-started/examples/README.md +4 -4
  84. package/docs/getting-started/examples/full-featured-app.md +1 -1
  85. package/docs/getting-started/faq.md +2 -2
  86. package/docs/getting-started/quick-reference.md +4 -4
  87. package/docs/implementation-guides/app-layout.md +1 -1
  88. package/docs/implementation-guides/authentication.md +15 -15
  89. package/docs/implementation-guides/component-styling.md +1 -1
  90. package/docs/implementation-guides/data-tables.md +127 -34
  91. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  92. package/docs/implementation-guides/dynamic-colors.md +3 -3
  93. package/docs/implementation-guides/file-upload-storage.md +2 -2
  94. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  95. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  96. package/docs/implementation-guides/large-datasets.md +3 -2
  97. package/docs/implementation-guides/organisation-security.md +2 -2
  98. package/docs/implementation-guides/performance.md +2 -2
  99. package/docs/implementation-guides/permission-enforcement.md +1 -1
  100. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  101. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  102. package/docs/rbac/README.md +5 -5
  103. package/docs/rbac/advanced-patterns.md +6 -6
  104. package/docs/rbac/api-reference.md +20 -20
  105. package/docs/rbac/event-based-apps.md +3 -3
  106. package/docs/rbac/examples.md +41 -41
  107. package/docs/rbac/getting-started.md +37 -37
  108. package/docs/rbac/performance.md +1 -1
  109. package/docs/rbac/quick-start.md +52 -52
  110. package/docs/rbac/secure-client-protection.md +1 -1
  111. package/docs/rbac/troubleshooting.md +1 -1
  112. package/docs/security/README.md +5 -5
  113. package/docs/standards/0-standards-overview.md +220 -0
  114. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
  115. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  116. package/docs/standards/3-architecture-standards.md +606 -0
  117. package/docs/standards/4-code-quality-standards.md +728 -0
  118. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  119. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  120. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  121. package/docs/standards/8-testing-documentation-standards.md +401 -0
  122. package/docs/standards/9-operations-standards.md +1102 -0
  123. package/docs/standards/README.md +203 -104
  124. package/docs/troubleshooting/README.md +4 -4
  125. package/docs/troubleshooting/common-issues.md +2 -2
  126. package/docs/troubleshooting/debugging.md +9 -9
  127. package/docs/troubleshooting/migration.md +4 -4
  128. package/eslint-config-pace-core.cjs +50 -20
  129. package/package.json +50 -19
  130. package/scripts/eslint-audit.cjs +123 -0
  131. package/scripts/install-cursor-rules.cjs +11 -243
  132. package/scripts/install-eslint-config.cjs +349 -0
  133. package/scripts/validate-dependencies.cjs +248 -0
  134. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  135. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  136. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
  137. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  138. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  139. package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
  140. package/src/__tests__/templates/component.test.template.tsx +18 -15
  141. package/src/components/AddressField/AddressField.tsx +26 -1
  142. package/src/components/Alert/Alert.test.tsx +86 -22
  143. package/src/components/Alert/Alert.tsx +19 -11
  144. package/src/components/Badge/Badge.tsx +1 -1
  145. package/src/components/Calendar/Calendar.tsx +201 -47
  146. package/src/components/Checkbox/Checkbox.test.tsx +2 -1
  147. package/src/components/ContextSelector/ContextSelector.tsx +108 -126
  148. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  149. package/src/components/DataTable/DataTable.tsx +1 -19
  150. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
  151. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
  152. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
  153. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  154. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  155. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  156. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  157. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  158. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  159. package/src/components/DataTable/components/EmptyState.tsx +11 -10
  160. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  161. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  162. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  163. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  164. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  165. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  166. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  167. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  168. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  169. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
  170. package/src/components/DataTable/components/index.ts +2 -1
  171. package/src/components/DataTable/types.ts +0 -18
  172. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  173. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
  174. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  175. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  176. package/src/components/Dialog/Dialog.test.tsx +1 -0
  177. package/src/components/Dialog/Dialog.tsx +25 -8
  178. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  179. package/src/components/FileUpload/FileUpload.test.tsx +45 -16
  180. package/src/components/FileUpload/FileUpload.tsx +141 -130
  181. package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
  182. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
  183. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
  184. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
  185. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
  186. package/src/components/Progress/Progress.tsx +2 -4
  187. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  188. package/src/components/Select/Select.tsx +86 -77
  189. package/src/components/Select/types.ts +3 -0
  190. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  191. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  192. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
  193. package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
  194. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
  195. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
  196. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
  197. package/src/hooks/public/usePublicEvent.ts +5 -5
  198. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  199. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  200. package/src/hooks/public/usePublicRouteParams.ts +13 -9
  201. package/src/hooks/useAddressAutocomplete.test.ts +18 -18
  202. package/src/hooks/useAppConfig.ts +2 -2
  203. package/src/hooks/useEventTheme.test.ts +7 -7
  204. package/src/hooks/useEventTheme.ts +2 -1
  205. package/src/hooks/useFileDisplay.ts +2 -2
  206. package/src/hooks/useFileUrl.ts +52 -8
  207. package/src/hooks/useOrganisationSecurity.test.ts +2 -1
  208. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  209. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  210. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  211. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  212. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  213. package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
  214. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  215. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  216. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  217. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
  218. package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
  219. package/src/rbac/api.test.ts +104 -0
  220. package/src/rbac/engine.ts +1 -1
  221. package/src/rbac/hooks/useCan.test.ts +2 -2
  222. package/src/rbac/secureClient.ts +1 -1
  223. package/src/rbac/types/functions.ts +1 -1
  224. package/src/styles/core.css +7 -0
  225. package/src/theming/__tests__/parseEventColours.test.ts +118 -3
  226. package/src/theming/parseEventColours.ts +77 -11
  227. package/src/types/supabase.ts +2 -3
  228. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
  229. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  230. package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
  231. package/src/utils/formatting/formatDate.test.ts +3 -2
  232. package/src/utils/formatting/formatDateTime.test.ts +2 -2
  233. package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
  234. package/src/utils/storage/README.md +1 -1
  235. package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
  236. package/src/utils/storage/helpers.test.ts +69 -3
  237. package/cursor-rules/01-standards-compliance.mdc +0 -285
  238. package/cursor-rules/04-testing-standards.mdc +0 -270
  239. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  240. package/cursor-rules/06-code-quality.mdc +0 -311
  241. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  242. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  243. package/cursor-rules/11-performance-optimization.mdc +0 -169
  244. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  245. package/dist/DataTable-LRJL4IRV.js +0 -15
  246. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  247. package/dist/eslint-rules/rules/components.cjs +0 -113
  248. package/dist/eslint-rules/rules/imports.cjs +0 -102
  249. package/docs/best-practices/README.md +0 -472
  250. package/docs/best-practices/accessibility.md +0 -604
  251. package/docs/best-practices/common-patterns.md +0 -516
  252. package/docs/best-practices/deployment.md +0 -1103
  253. package/docs/best-practices/performance.md +0 -1328
  254. package/docs/best-practices/security.md +0 -940
  255. package/docs/best-practices/testing.md +0 -1034
  256. package/docs/rbac/compliance/compliance-guide.md +0 -544
  257. package/docs/standards/01-standards-compliance.md +0 -188
  258. package/docs/standards/03-solid-principles.md +0 -39
  259. package/docs/standards/04-testing-standards.md +0 -36
  260. package/docs/standards/05-bug-reports-and-features.md +0 -27
  261. package/docs/standards/06-code-quality.md +0 -34
  262. package/docs/standards/07-tech-stack-compliance.md +0 -30
  263. package/docs/standards/10-error-handling-patterns.md +0 -401
  264. package/docs/standards/11-performance-optimization.md +0 -348
  265. package/docs/standards/12-ci-cd-integration.md +0 -370
  266. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  267. package/scripts/audit/audit-compliance.cjs +0 -1295
  268. package/scripts/audit/audit-components.cjs +0 -260
  269. package/scripts/audit/audit-rbac.cjs +0 -954
  270. package/scripts/audit/audit-standards.cjs +0 -1268
  271. package/scripts/audit/index.cjs +0 -1927
  272. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  273. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  274. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  275. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  276. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  277. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  278. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  279. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  280. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  281. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  282. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  284. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  285. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  286. package/src/components/DataTable/utils/debugTools.ts +0 -514
  287. package/src/eslint-rules/index.cjs +0 -22
  288. package/src/eslint-rules/rules/components.cjs +0 -113
  289. package/src/eslint-rules/rules/imports.cjs +0 -102
  290. package/src/eslint-rules/rules/rbac.cjs +0 -790
  291. package/src/eslint-rules/utils/helpers.cjs +0 -42
  292. package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
@@ -41,32 +41,32 @@ vi.mock('../fixtures/test-data', () => ({
41
41
 
42
42
  describe('[helpers] renderWithProviders', () => {
43
43
  it('renders component with QueryClient provider by default', () => {
44
- const TestComponent = () => <div data-testid="test-component">Test</div>;
44
+ const TestComponent = () => <p data-testid="test-component">Test</p>;
45
45
 
46
46
  renderWithProviders(<TestComponent />);
47
47
 
48
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
48
+ expect(screen.getByTestId('test-component')).toBeDefined();
49
49
  });
50
50
 
51
51
  it('renders component without QueryClient when withQueryClient is false', () => {
52
- const TestComponent = () => <div data-testid="test-component">Test</div>;
52
+ const TestComponent = () => <p data-testid="test-component">Test</p>;
53
53
 
54
54
  renderWithProviders(<TestComponent />, { withQueryClient: false });
55
55
 
56
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
56
+ expect(screen.getByTestId('test-component')).toBeDefined();
57
57
  });
58
58
 
59
59
  it('uses custom QueryClient when provided', () => {
60
60
  const customQueryClient = new QueryClient();
61
- const TestComponent = () => <div data-testid="test-component">Test</div>;
61
+ const TestComponent = () => <p data-testid="test-component">Test</p>;
62
62
 
63
63
  renderWithProviders(<TestComponent />, { queryClient: customQueryClient });
64
64
 
65
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
65
+ expect(screen.getByTestId('test-component')).toBeDefined();
66
66
  });
67
67
 
68
68
  it('forwards additional render options', () => {
69
- const TestComponent = () => <div data-testid="test-component">Test</div>;
69
+ const TestComponent = () => <p data-testid="test-component">Test</p>;
70
70
 
71
71
  const { container } = renderWithProviders(<TestComponent />, {
72
72
  container: document.body
@@ -273,7 +273,7 @@ describe('[helpers] createMockSupabaseClient', () => {
273
273
 
274
274
  it('creates mock query builder with chaining methods', () => {
275
275
  const mockClient = createMockSupabaseClient();
276
- const queryBuilder = mockClient.from('test_table');
276
+ const queryBuilder = (mockClient.from as any)('test_table');
277
277
 
278
278
  expect(queryBuilder).toHaveProperty('select');
279
279
  expect(queryBuilder).toHaveProperty('insert');
@@ -302,7 +302,7 @@ describe('[helpers] createMockSupabaseClient', () => {
302
302
 
303
303
  describe('[helpers] TestWrapper', () => {
304
304
  it('renders children with QueryClient provider', () => {
305
- const TestComponent = () => <div data-testid="test-component">Test</div>;
305
+ const TestComponent = () => <p data-testid="test-component">Test</p>;
306
306
 
307
307
  render(
308
308
  <TestWrapper>
@@ -310,7 +310,7 @@ describe('[helpers] TestWrapper', () => {
310
310
  </TestWrapper>
311
311
  );
312
312
 
313
- expect(screen.getByTestId('test-component')).toBeInTheDocument();
313
+ expect(screen.getByTestId('test-component')).toBeDefined();
314
314
  });
315
315
  });
316
316
 
@@ -405,14 +405,20 @@ describe('[helpers] createComponentTestStructure', () => {
405
405
  expect(typeof structure.describe).toBe('function');
406
406
  });
407
407
 
408
- it('executes test function within describe block', () => {
408
+ it('provides describe function that can be called', () => {
409
409
  const testFn = vi.fn();
410
410
  const structure = createComponentTestStructure('TestComponent');
411
411
 
412
- structure.describe(testFn);
412
+ // Verify the describe function exists and is callable
413
+ expect(typeof structure.describe).toBe('function');
413
414
 
414
- // The test function should be callable
415
- expect(typeof testFn).toBe('function');
415
+ // Verify we can call it (but don't actually execute describe inside a test)
416
+ // The actual describe block execution should happen at the top level
417
+ expect(() => {
418
+ // Just verify the function signature is correct
419
+ const fn = structure.describe;
420
+ expect(fn).toBeDefined();
421
+ }).not.toThrow();
416
422
  });
417
423
  });
418
424
 
@@ -424,13 +430,19 @@ describe('[helpers] createHookTestStructure', () => {
424
430
  expect(typeof structure.describe).toBe('function');
425
431
  });
426
432
 
427
- it('executes test function within describe block', () => {
433
+ it('provides describe function that can be called', () => {
428
434
  const testFn = vi.fn();
429
435
  const structure = createHookTestStructure('useTestHook');
430
436
 
431
- structure.describe(testFn);
437
+ // Verify the describe function exists and is callable
438
+ expect(typeof structure.describe).toBe('function');
432
439
 
433
- // The test function should be callable
434
- expect(typeof testFn).toBe('function');
440
+ // Verify we can call it (but don't actually execute describe inside a test)
441
+ // The actual describe block execution should happen at the top level
442
+ expect(() => {
443
+ // Just verify the function signature is correct
444
+ const fn = structure.describe;
445
+ expect(fn).toBeDefined();
446
+ }).not.toThrow();
435
447
  });
436
448
  });
@@ -37,18 +37,18 @@ const UserProfile = ({ userId }: { userId: string }) => {
37
37
  fetchUser();
38
38
  }, [userId]);
39
39
 
40
- if (loading) return <div>Loading...</div>;
41
- if (error) return <div>Error: {error}</div>;
42
- if (!user) return <div>No user found</div>;
40
+ if (loading) return <p>Loading...</p>;
41
+ if (error) return <p>Error: {error}</p>;
42
+ if (!user) return <p>No user found</p>;
43
43
 
44
44
  return (
45
- <div data-testid="user-profile">
45
+ <section data-testid="user-profile">
46
46
  <h1>{user.name}</h1>
47
47
  <p>{user.email}</p>
48
48
  <button onClick={() => setUser({ ...user, name: 'Updated Name' })}>
49
49
  Update Name
50
50
  </button>
51
- </div>
51
+ </section>
52
52
  );
53
53
  };
54
54
 
@@ -59,17 +59,17 @@ describe('User Profile Integration Tests', () => {
59
59
 
60
60
  // The component loads data synchronously in this mock, so we just check the final state
61
61
  await waitFor(() => {
62
- expect(screen.getByText('John Doe')).toBeInTheDocument();
62
+ expect(screen.getByText('John Doe')).toBeDefined();
63
63
  });
64
64
 
65
- expect(screen.getByText('john@example.com')).toBeInTheDocument();
65
+ expect(screen.getByText('john@example.com')).toBeDefined();
66
66
  });
67
67
 
68
68
  it('handles user not found', async () => {
69
69
  renderWithProviders(<UserProfile userId="999" />);
70
70
 
71
71
  await waitFor(() => {
72
- expect(screen.getByText('Error: User not found')).toBeInTheDocument();
72
+ expect(screen.getByText('Error: User not found')).toBeDefined();
73
73
  });
74
74
  });
75
75
  });
@@ -80,13 +80,13 @@ describe('User Profile Integration Tests', () => {
80
80
  renderWithProviders(<UserProfile userId="1" />);
81
81
 
82
82
  await waitFor(() => {
83
- expect(screen.getByText('John Doe')).toBeInTheDocument();
83
+ expect(screen.getByText('John Doe')).toBeDefined();
84
84
  });
85
85
 
86
86
  await user.click(screen.getByText('Update Name'));
87
87
 
88
- expect(screen.getByText('Updated Name')).toBeInTheDocument();
89
- expect(screen.queryByText('John Doe')).not.toBeInTheDocument();
88
+ expect(screen.getByText('Updated Name')).toBeDefined();
89
+ expect(screen.queryByText('John Doe')).toBeNull();
90
90
  });
91
91
  });
92
92
 
@@ -95,12 +95,12 @@ describe('User Profile Integration Tests', () => {
95
95
  const { rerender } = renderWithProviders(<UserProfile userId="1" />);
96
96
 
97
97
  await waitFor(() => {
98
- expect(screen.getByText('John Doe')).toBeInTheDocument();
98
+ expect(screen.getByText('John Doe')).toBeDefined();
99
99
  });
100
100
 
101
101
  rerender(<UserProfile userId="1" />);
102
102
 
103
- expect(screen.getByText('John Doe')).toBeInTheDocument();
103
+ expect(screen.getByText('John Doe')).toBeDefined();
104
104
  });
105
105
  });
106
106
  });
@@ -117,7 +117,7 @@ describe('User Profile - Different Users', () => {
117
117
  renderWithProviders(<UserProfile userId={userId} />);
118
118
 
119
119
  await waitFor(() => {
120
- expect(screen.getByText(expectedName)).toBeInTheDocument();
120
+ expect(screen.getByText(expectedName)).toBeDefined();
121
121
  });
122
122
  });
123
123
  });
@@ -78,7 +78,7 @@ describe('PagePermissionGuard', () => {
78
78
  operation="read"
79
79
  scope={mockScope}
80
80
  >
81
- <div>Protected Content</div>
81
+ <p>Protected Content</p>
82
82
  </PagePermissionGuard>
83
83
  );
84
84
 
@@ -103,7 +103,7 @@ describe('PagePermissionGuard', () => {
103
103
  operation="read"
104
104
  scope={mockScope}
105
105
  >
106
- <div>Protected Content</div>
106
+ <p>Protected Content</p>
107
107
  </PagePermissionGuard>
108
108
  );
109
109
 
@@ -128,7 +128,7 @@ describe('PagePermissionGuard', () => {
128
128
  operation="read"
129
129
  scope={mockScope}
130
130
  >
131
- <div>Protected Content</div>
131
+ <p>Protected Content</p>
132
132
  </PagePermissionGuard>
133
133
  );
134
134
 
@@ -153,7 +153,7 @@ describe('PagePermissionGuard', () => {
153
153
  operation="read"
154
154
  scope={mockScope}
155
155
  >
156
- <div>Protected Content</div>
156
+ <p>Protected Content</p>
157
157
  </PagePermissionGuard>
158
158
  );
159
159
 
@@ -176,7 +176,7 @@ describe('PagePermissionGuard', () => {
176
176
  operation="read"
177
177
  scope={mockScope}
178
178
  >
179
- <div>Protected Content</div>
179
+ <p>Protected Content</p>
180
180
  </PagePermissionGuard>
181
181
  );
182
182
  };
@@ -207,7 +207,7 @@ describe('PagePermissionGuard', () => {
207
207
  operation="read"
208
208
  scope={mockScope}
209
209
  >
210
- <div>Protected Content</div>
210
+ <p>Protected Content</p>
211
211
  </PagePermissionGuard>
212
212
  );
213
213
 
@@ -32,14 +32,15 @@ describe('ComponentName Accessibility Tests', () => {
32
32
  renderWithProviders(<ComponentName>Content</ComponentName>);
33
33
 
34
34
  // Check for proper semantic elements
35
- expect(screen.getByRole('main')).toBeInTheDocument();
36
- // or: expect(screen.getByRole('button')).toBeInTheDocument();
37
- // or: expect(screen.getByRole('textbox')).toBeInTheDocument();
35
+ expect(screen.getByRole('main')).toBeDefined();
36
+ // or: expect(screen.getByRole('button')).toBeDefined();
37
+ // or: expect(screen.getByRole('textbox')).toBeDefined();
38
38
  });
39
39
 
40
40
  it('has proper heading hierarchy', () => {
41
41
  renderWithProviders(<ComponentName title="Main Title" subtitle="Subtitle" />);
42
42
 
43
+ // Note: Heading levels can skip when semantically appropriate (e.g., h2 → h5)
43
44
  const mainHeading = screen.getByRole('heading', { level: 1 });
44
45
  const subHeading = screen.getByRole('heading', { level: 2 });
45
46
 
@@ -53,13 +54,13 @@ describe('ComponentName Accessibility Tests', () => {
53
54
  renderWithProviders(<ComponentName aria-label="Component description" />);
54
55
 
55
56
  const component = screen.getByLabelText('Component description');
56
- expect(component).toBeInTheDocument();
57
+ expect(component).toBeDefined();
57
58
  });
58
59
 
59
60
  it('has proper ARIA roles', () => {
60
61
  renderWithProviders(<ComponentName role="dialog" />);
61
62
 
62
- expect(screen.getByRole('dialog')).toBeInTheDocument();
63
+ expect(screen.getByRole('dialog')).toBeDefined();
63
64
  });
64
65
 
65
66
  it('uses ARIA describedby for additional information', () => {
@@ -92,10 +93,10 @@ describe('ComponentName Accessibility Tests', () => {
92
93
  describe('Keyboard Navigation', () => {
93
94
  it('supports tab navigation', async () => {
94
95
  renderWithProviders(
95
- <div>
96
+ <section>
96
97
  <ComponentName />
97
98
  <button>Next focusable element</button>
98
- </div>
99
+ </section>
99
100
  );
100
101
 
101
102
  const firstElement = screen.getByRole('button', { name: /component/i });
@@ -179,7 +180,7 @@ describe('ComponentName Accessibility Tests', () => {
179
180
  renderWithProviders(<ComponentName type="form" />);
180
181
 
181
182
  const input = screen.getByLabelText('Input Label');
182
- expect(input).toBeInTheDocument();
183
+ expect(input).toBeDefined();
183
184
  });
184
185
 
185
186
  it('announces loading states', () => {
@@ -204,7 +205,7 @@ describe('ComponentName Accessibility Tests', () => {
204
205
  renderWithProviders(<ComponentName status="error" />);
205
206
 
206
207
  // Should have text indicator, not just color
207
- expect(screen.getByText(/error/i)).toBeInTheDocument();
208
+ expect(screen.getByText(/error/i)).toBeDefined();
208
209
  });
209
210
 
210
211
  it('maintains focus indicators', async () => {
@@ -8,6 +8,7 @@ import React from 'react';
8
8
  import { screen } from '@testing-library/react';
9
9
  import userEvent from '@testing-library/user-event';
10
10
  import { describe, it, expect, vi, beforeEach } from 'vitest';
11
+ // @ts-ignore - Template file: Replace with your actual component import
11
12
  import { ComponentName } from '../../components/ComponentName/ComponentName';
12
13
  import { renderWithProviders } from '../helpers/test-utils';
13
14
 
@@ -20,21 +21,21 @@ describe('ComponentName Component', () => {
20
21
  describe('Rendering', () => {
21
22
  it('renders with default props', () => {
22
23
  renderWithProviders(<ComponentName />);
23
- expect(screen.getByRole('generic')).toBeInTheDocument();
24
+ expect(screen.getByRole('generic')).toBeDefined();
24
25
  });
25
26
 
26
27
  it('renders with custom props', () => {
27
28
  renderWithProviders(<ComponentName customProp="value" />);
28
- expect(screen.getByRole('generic')).toBeInTheDocument();
29
+ expect(screen.getByRole('generic')).toBeDefined();
29
30
  });
30
31
 
31
32
  it('renders with children', () => {
32
33
  renderWithProviders(
33
34
  <ComponentName>
34
- <span>Child content</span>
35
+ <p>Child content</p>
35
36
  </ComponentName>
36
37
  );
37
- expect(screen.getByText('Child content')).toBeInTheDocument();
38
+ expect(screen.getByText('Child content')).toBeDefined();
38
39
  });
39
40
  });
40
41
 
@@ -69,15 +70,15 @@ describe('ComponentName Component', () => {
69
70
  <ComponentName value="initial" />
70
71
  );
71
72
 
72
- expect(screen.getByDisplayValue('initial')).toBeInTheDocument();
73
+ expect(screen.getByDisplayValue('initial')).toBeDefined();
73
74
 
74
75
  rerender(<ComponentName value="updated" />);
75
- expect(screen.getByDisplayValue('updated')).toBeInTheDocument();
76
+ expect(screen.getByDisplayValue('updated')).toBeDefined();
76
77
  });
77
78
 
78
79
  it('handles uncontrolled state', () => {
79
80
  renderWithProviders(<ComponentName defaultValue="default" />);
80
- expect(screen.getByDisplayValue('default')).toBeInTheDocument();
81
+ expect(screen.getByDisplayValue('default')).toBeDefined();
81
82
  });
82
83
  });
83
84
 
@@ -85,12 +86,14 @@ describe('ComponentName Component', () => {
85
86
  describe('Accessibility', () => {
86
87
  it('has proper ARIA attributes', () => {
87
88
  renderWithProviders(<ComponentName aria-label="Test component" />);
88
- expect(screen.getByRole('generic')).toHaveAttribute('aria-label', 'Test component');
89
+ const element = screen.getByRole('generic');
90
+ expect(element.getAttribute('aria-label')).toBe('Test component');
89
91
  });
90
92
 
91
93
  it('is keyboard accessible', () => {
92
94
  renderWithProviders(<ComponentName />);
93
- expect(screen.getByRole('generic')).not.toHaveAttribute('tabindex', '-1');
95
+ const element = screen.getByRole('generic');
96
+ expect(element.getAttribute('tabindex')).not.toBe('-1');
94
97
  });
95
98
 
96
99
  it('supports screen readers', () => {
@@ -102,25 +105,25 @@ describe('ComponentName Component', () => {
102
105
  // Error handling tests
103
106
  describe('Error Handling', () => {
104
107
  it('handles invalid props gracefully', () => {
105
- // @ts-expect-error Testing invalid prop
108
+ // @ts-ignore Testing invalid prop
106
109
  renderWithProviders(<ComponentName invalidProp="test" />);
107
- expect(screen.getByRole('generic')).toBeInTheDocument();
110
+ expect(screen.getByRole('generic')).toBeDefined();
108
111
  });
109
112
 
110
113
  it('displays error states', () => {
111
114
  renderWithProviders(<ComponentName error="Something went wrong" />);
112
- expect(screen.getByText('Something went wrong')).toBeInTheDocument();
115
+ expect(screen.getByText('Something went wrong')).toBeDefined();
113
116
  });
114
117
  });
115
118
 
116
119
  // Integration tests
117
120
  describe('Integration', () => {
118
121
  it('works with other components', () => {
119
- renderWithProviders(
120
- <div>
122
+ renderWithProviders(
123
+ <p>
121
124
  <ComponentName />
122
125
  <ComponentName />
123
- </div>
126
+ </p>
124
127
  );
125
128
 
126
129
  expect(screen.getAllByRole('generic')).toHaveLength(2);
@@ -83,6 +83,7 @@ const AddressField = React.forwardRef<HTMLInputElement, AddressFieldProps>(
83
83
  const inputRef = React.useRef<HTMLInputElement>(null);
84
84
  const suggestionsRef = React.useRef<HTMLDListElement>(null);
85
85
  const containerRef = React.useRef<HTMLFormElement>(null);
86
+ const blurTimeoutRef = React.useRef<NodeJS.Timeout | null>(null);
86
87
 
87
88
  // Use controlled or uncontrolled value
88
89
  const value = controlledValue !== undefined ? controlledValue : internalValue;
@@ -194,17 +195,41 @@ const AddressField = React.forwardRef<HTMLInputElement, AddressFieldProps>(
194
195
  // Handle blur
195
196
  const handleBlur = React.useCallback(
196
197
  (e: React.FocusEvent<HTMLInputElement>) => {
198
+ // Clear any existing timeout
199
+ if (blurTimeoutRef.current) {
200
+ clearTimeout(blurTimeoutRef.current);
201
+ blurTimeoutRef.current = null;
202
+ }
203
+
197
204
  // Delay to allow click events on suggestions
198
- setTimeout(() => {
205
+ blurTimeoutRef.current = setTimeout(() => {
206
+ // Check if window/document is available (for test environments)
207
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
208
+ blurTimeoutRef.current = null;
209
+ return;
210
+ }
211
+
212
+ // Close if focus moved outside the container
199
213
  if (!containerRef.current?.contains(document.activeElement)) {
200
214
  setInputFocused(false);
201
215
  setIsOpen(false);
202
216
  setSelectedIndex(-1);
203
217
  }
218
+ blurTimeoutRef.current = null;
204
219
  }, 200);
205
220
  },
206
221
  []
207
222
  );
223
+
224
+ // Cleanup timeout on unmount
225
+ React.useEffect(() => {
226
+ return () => {
227
+ if (blurTimeoutRef.current) {
228
+ clearTimeout(blurTimeoutRef.current);
229
+ blurTimeoutRef.current = null;
230
+ }
231
+ };
232
+ }, []);
208
233
 
209
234
  // Click outside handler
210
235
  React.useEffect(() => {