@jmruthers/pace-core 0.4.1 → 0.5.1

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 (601) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/README.md +231 -229
  3. package/dist/{DataTable-2LB6HI6V.js → DataTable-GX3XERFJ.js} +14 -17
  4. package/dist/{DataTable-BDBqkU-i.d.ts → DataTable-ltTFXHS3.d.ts} +25 -51
  5. package/dist/{Table-CIm9IWqk.d.ts → PublicLoadingSpinner-DztrzuJr.d.ts} +635 -122
  6. package/dist/UnifiedAuthProvider-w66zSCUf.d.ts +160 -0
  7. package/dist/{api-AIJ3IJX3.js → api-ETQ6YJ3C.js} +6 -4
  8. package/dist/{appConfig-fB1pP_v3.d.ts → appConfig-BVGyuvI7.d.ts} +1 -1
  9. package/dist/appNameResolver-7GHF5ED2.js +22 -0
  10. package/dist/{audit-PD5L5ZSC.js → audit-BUW3LMJB.js} +3 -3
  11. package/dist/chunk-5EL3KHOQ.js +388 -0
  12. package/dist/chunk-5EL3KHOQ.js.map +1 -0
  13. package/dist/{chunk-4MCJAK7J.js → chunk-6CR3MRZN.js} +1827 -4886
  14. package/dist/chunk-6CR3MRZN.js.map +1 -0
  15. package/dist/{chunk-YNU5QJ4S.js → chunk-7BNPOCLL.js} +22 -5
  16. package/dist/chunk-7BNPOCLL.js.map +1 -0
  17. package/dist/chunk-AUE24LVR.js +268 -0
  18. package/dist/chunk-AUE24LVR.js.map +1 -0
  19. package/dist/chunk-C5G2A4PO.js +1349 -0
  20. package/dist/chunk-C5G2A4PO.js.map +1 -0
  21. package/dist/{chunk-4ZTIEYU2.js → chunk-CDQ3PX7L.js} +1 -1
  22. package/dist/chunk-CDQ3PX7L.js.map +1 -0
  23. package/dist/chunk-COBPIXXQ.js +379 -0
  24. package/dist/chunk-COBPIXXQ.js.map +1 -0
  25. package/dist/chunk-GSNM5D6H.js +5441 -0
  26. package/dist/chunk-GSNM5D6H.js.map +1 -0
  27. package/dist/chunk-MZBUOP4P.js +119 -0
  28. package/dist/chunk-MZBUOP4P.js.map +1 -0
  29. package/dist/chunk-N2EUGZRW.js +98 -0
  30. package/dist/chunk-N2EUGZRW.js.map +1 -0
  31. package/dist/chunk-NQ4TOOO6.js +20 -0
  32. package/dist/chunk-NQ4TOOO6.js.map +1 -0
  33. package/dist/{chunk-KK6WIDK6.js → chunk-OEGRKULD.js} +12 -2
  34. package/dist/{chunk-KK6WIDK6.js.map → chunk-OEGRKULD.js.map} +1 -1
  35. package/dist/chunk-OYRY44Q2.js +62 -0
  36. package/dist/chunk-OYRY44Q2.js.map +1 -0
  37. package/dist/{chunk-DC5AMYBS.js → chunk-PLDDJCW6.js} +15 -5
  38. package/dist/chunk-PLDDJCW6.js.map +1 -0
  39. package/dist/{chunk-WHLSWC6W.js → chunk-SS3E6QLB.js} +16 -61
  40. package/dist/chunk-SS3E6QLB.js.map +1 -0
  41. package/dist/chunk-T3XIA4AJ.js +3295 -0
  42. package/dist/chunk-T3XIA4AJ.js.map +1 -0
  43. package/dist/{chunk-H4PZ4B3Y.js → chunk-TGDCLPP2.js} +129 -28
  44. package/dist/chunk-TGDCLPP2.js.map +1 -0
  45. package/dist/{chunk-IOX76PSM.js → chunk-U6JDHVC2.js} +273 -29
  46. package/dist/chunk-U6JDHVC2.js.map +1 -0
  47. package/dist/{chunk-JUUNUW3O.js → chunk-XJK2J4N6.js} +17 -6
  48. package/dist/chunk-XJK2J4N6.js.map +1 -0
  49. package/dist/chunk-YDJW5XTN.js +84 -0
  50. package/dist/chunk-YDJW5XTN.js.map +1 -0
  51. package/dist/components.d.ts +906 -10
  52. package/dist/components.js +3263 -84
  53. package/dist/components.js.map +1 -1
  54. package/dist/{database-CAMsquLm.d.ts → database-C3Szpi5J.d.ts} +28 -11
  55. package/dist/hooks.d.ts +7 -6
  56. package/dist/hooks.js +35 -11
  57. package/dist/hooks.js.map +1 -1
  58. package/dist/index.d.ts +245 -111
  59. package/dist/index.js +195 -185
  60. package/dist/index.js.map +1 -1
  61. package/dist/{organisation-DLNNQhPB.d.ts → organisation-CO3Sh3_D.d.ts} +1 -1
  62. package/dist/providers.d.ts +4 -4
  63. package/dist/providers.js +21 -6
  64. package/dist/rbac/index.d.ts +862 -806
  65. package/dist/rbac/index.js +953 -1032
  66. package/dist/rbac/index.js.map +1 -1
  67. package/dist/styles/core.css +422 -0
  68. package/dist/styles/fonts/georama-italic.woff2 +0 -0
  69. package/dist/styles/fonts/georama.woff2 +0 -0
  70. package/dist/styles/fonts/open-sans-italic.woff2 +0 -0
  71. package/dist/styles/fonts/open-sans.woff2 +0 -0
  72. package/dist/styles/fonts/reddit-mono.woff2 +0 -0
  73. package/dist/styles/index.d.ts +36 -0
  74. package/dist/styles/index.js +24 -0
  75. package/dist/styles/index.js.map +1 -0
  76. package/dist/theming/runtime.d.ts +73 -0
  77. package/dist/theming/runtime.js +16 -0
  78. package/dist/theming/runtime.js.map +1 -0
  79. package/dist/{types-Bavn44NW.d.ts → types-BRDU7N6w.d.ts} +79 -33
  80. package/dist/types.d.ts +5 -5
  81. package/dist/types.js +7 -2
  82. package/dist/types.js.map +1 -1
  83. package/dist/{unified-BtRpPbmp.d.ts → unified-CM7T0aTK.d.ts} +1 -2
  84. package/dist/usePublicRouteParams-B6i0KtXW.d.ts +477 -0
  85. package/dist/utils.d.ts +83 -60
  86. package/dist/utils.js +301 -55657
  87. package/dist/utils.js.map +1 -1
  88. package/dist/validation.d.ts +1 -1
  89. package/dist/validation.js +1 -1
  90. package/docs/INDEX.md +192 -0
  91. package/docs/README.md +46 -32
  92. package/docs/api/README.md +231 -229
  93. package/docs/api/classes/ErrorBoundary.md +1 -1
  94. package/docs/api/classes/PublicErrorBoundary.md +132 -0
  95. package/docs/api/interfaces/AggregateConfig.md +4 -4
  96. package/docs/api/interfaces/ButtonProps.md +2 -2
  97. package/docs/api/interfaces/CardProps.md +2 -2
  98. package/docs/api/interfaces/ColorPalette.md +1 -1
  99. package/docs/api/interfaces/ColorShade.md +1 -1
  100. package/docs/api/interfaces/DataTableAction.md +98 -7
  101. package/docs/api/interfaces/DataTableColumn.md +131 -12
  102. package/docs/api/interfaces/DataTableProps.md +77 -274
  103. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  104. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  105. package/docs/api/interfaces/EventContextType.md +7 -7
  106. package/docs/api/interfaces/EventLogoProps.md +152 -0
  107. package/docs/api/interfaces/EventProviderProps.md +2 -2
  108. package/docs/api/interfaces/FileSizeLimits.md +7 -0
  109. package/docs/api/interfaces/FileUploadProps.md +154 -0
  110. package/docs/api/interfaces/FooterProps.md +1 -1
  111. package/docs/api/interfaces/InactivityWarningModalProps.md +115 -0
  112. package/docs/api/interfaces/InputProps.md +2 -2
  113. package/docs/api/interfaces/LabelProps.md +1 -1
  114. package/docs/api/interfaces/LoginFormProps.md +1 -1
  115. package/docs/api/interfaces/NavigationItem.md +1 -1
  116. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  117. package/docs/api/interfaces/Organisation.md +1 -1
  118. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  119. package/docs/api/interfaces/OrganisationMembership.md +2 -2
  120. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  121. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  122. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -26
  123. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  124. package/docs/api/interfaces/PaletteData.md +1 -1
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +94 -0
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +68 -0
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +86 -0
  128. package/docs/api/interfaces/PublicPageFooterProps.md +112 -0
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +138 -0
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +138 -0
  131. package/docs/api/interfaces/StorageConfig.md +41 -0
  132. package/docs/api/interfaces/StorageFileInfo.md +74 -0
  133. package/docs/api/interfaces/StorageFileMetadata.md +140 -0
  134. package/docs/api/interfaces/StorageListOptions.md +86 -0
  135. package/docs/api/interfaces/StorageListResult.md +41 -0
  136. package/docs/api/interfaces/StorageUploadOptions.md +88 -0
  137. package/docs/api/interfaces/StorageUploadResult.md +63 -0
  138. package/docs/api/interfaces/StorageUrlOptions.md +47 -0
  139. package/docs/api/interfaces/StyleImport.md +2 -2
  140. package/docs/api/interfaces/ToastActionElement.md +1 -1
  141. package/docs/api/interfaces/ToastProps.md +1 -1
  142. package/docs/api/interfaces/UnifiedAuthContextType.md +447 -46
  143. package/docs/api/interfaces/UnifiedAuthProviderProps.md +95 -9
  144. package/docs/api/interfaces/UseInactivityTrackerOptions.md +136 -0
  145. package/docs/api/interfaces/UseInactivityTrackerReturn.md +123 -0
  146. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  147. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  148. package/docs/api/interfaces/UsePublicEventOptions.md +34 -0
  149. package/docs/api/interfaces/UsePublicEventReturn.md +68 -0
  150. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +94 -0
  151. package/docs/api/interfaces/UserEventAccess.md +14 -14
  152. package/docs/api/interfaces/UserMenuProps.md +6 -6
  153. package/docs/api/interfaces/UserProfile.md +1 -1
  154. package/docs/api/modules.md +1626 -768
  155. package/docs/api-reference/components.md +761 -43
  156. package/docs/api-reference/hooks.md +126 -0
  157. package/docs/api-reference/providers.md +141 -65
  158. package/docs/api-reference/types.md +66 -36
  159. package/docs/api-reference/utilities.md +1 -1
  160. package/docs/architecture/README.md +1 -2
  161. package/docs/best-practices/README.md +400 -0
  162. package/docs/consuming-app-example.md +42 -96
  163. package/docs/consuming-app-vite-config.md +233 -0
  164. package/docs/core-concepts/events.md +3 -3
  165. package/docs/core-concepts/organisations.md +0 -1
  166. package/docs/core-concepts/rbac-system.md +23 -10
  167. package/docs/documentation-style-checklist.md +8 -2
  168. package/docs/examples/navigation-menu-auth-fix.md +344 -0
  169. package/docs/getting-started/examples/README.md +15 -1
  170. package/docs/getting-started/examples/basic-auth-app.md +444 -119
  171. package/docs/getting-started/examples/full-featured-app.md +6 -6
  172. package/docs/getting-started/installation.md +231 -52
  173. package/docs/getting-started/quick-start.md +121 -24
  174. package/docs/implementation-guides/app-layout.md +133 -108
  175. package/docs/implementation-guides/data-tables.md +1011 -29
  176. package/docs/implementation-guides/forms.md +3 -3
  177. package/docs/implementation-guides/hierarchical-datatable.md +850 -0
  178. package/docs/implementation-guides/large-datasets.md +2 -2
  179. package/docs/implementation-guides/navigation.md +1 -1
  180. package/docs/implementation-guides/permission-enforcement.md +4 -4
  181. package/docs/implementation-guides/public-pages.md +752 -0
  182. package/docs/migration/README.md +18 -8
  183. package/docs/migration/quick-migration-guide.md +320 -0
  184. package/docs/migration/rbac-migration.md +50 -0
  185. package/docs/migration/v0.4.15-tailwind-scanning.md +272 -0
  186. package/docs/migration/v0.4.16-css-first-approach.md +306 -0
  187. package/docs/migration/v0.4.17-source-path-fix.md +229 -0
  188. package/docs/migration-guide.md +51 -104
  189. package/docs/performance/README.md +1 -4
  190. package/docs/print-components/README.md +258 -0
  191. package/docs/print-components/api-reference.md +636 -0
  192. package/docs/print-components/examples/README.md +204 -0
  193. package/docs/print-components/examples/basic-report.tsx +92 -0
  194. package/docs/print-components/examples/card-catalog.tsx +149 -0
  195. package/docs/print-components/examples/cover-page-report.tsx +163 -0
  196. package/docs/print-components/quick-start.md +363 -0
  197. package/docs/quick-reference.md +53 -36
  198. package/docs/rbac/README.md +136 -69
  199. package/docs/rbac/api-reference.md +39 -8
  200. package/docs/rbac/examples.md +237 -66
  201. package/docs/rbac/getting-started.md +131 -16
  202. package/docs/rbac/quick-start.md +499 -323
  203. package/docs/rbac/troubleshooting.md +240 -262
  204. package/docs/security/README.md +50 -1
  205. package/docs/styles/README.md +143 -117
  206. package/docs/testing/README.md +6 -10
  207. package/docs/troubleshooting/README.md +497 -0
  208. package/docs/troubleshooting/common-issues.md +604 -14
  209. package/docs/troubleshooting/styling-issues.md +219 -0
  210. package/docs/troubleshooting/tailwind-content-scanning.md +213 -0
  211. package/docs/usage.md +28 -90
  212. package/docs/visual-testing.md +0 -7
  213. package/package.json +46 -24
  214. package/src/__mocks__/lucide-react.ts +181 -0
  215. package/src/__tests__/REBUILD_PLAN.md +223 -0
  216. package/src/__tests__/TESTING_GUIDELINES.md +341 -0
  217. package/src/__tests__/fixtures/mocks.ts +93 -0
  218. package/src/__tests__/helpers/component-test-utils.tsx +145 -0
  219. package/src/__tests__/helpers/test-utils.tsx +117 -0
  220. package/src/__tests__/integration/UserProfile.test.tsx +128 -0
  221. package/src/__tests__/setup.ts +71 -0
  222. package/src/__tests__/templates/accessibility.test.template.tsx +279 -0
  223. package/src/__tests__/templates/component.test.template.tsx +144 -0
  224. package/src/__tests__/templates/hook.test.template.ts +173 -0
  225. package/src/__tests__/templates/integration.test.template.tsx +199 -0
  226. package/src/__tests__/types/test.types.ts +106 -0
  227. package/src/components/Alert/Alert.test.tsx +496 -0
  228. package/src/components/Alert/Alert.tsx +134 -0
  229. package/src/components/Alert/index.ts +2 -0
  230. package/src/components/Avatar/Avatar.test.tsx +484 -0
  231. package/src/components/Avatar/Avatar.tsx +84 -0
  232. package/src/components/Avatar/index.ts +2 -0
  233. package/src/components/Button/Button.test.tsx +662 -0
  234. package/src/components/Button/Button.tsx +270 -0
  235. package/src/components/Button/index.ts +2 -0
  236. package/src/components/Card/Card.test.tsx +593 -0
  237. package/src/components/Card/Card.tsx +271 -0
  238. package/src/components/Card/index.ts +1 -0
  239. package/src/components/Checkbox/Checkbox.test.tsx +461 -0
  240. package/src/components/Checkbox/Checkbox.tsx +75 -0
  241. package/src/components/Checkbox/__mocks__/Checkbox.tsx +2 -0
  242. package/src/components/Checkbox/index.ts +2 -0
  243. package/src/components/DataTable/DataTable.tsx +446 -0
  244. package/src/components/DataTable/__tests__/README.md +145 -0
  245. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +66 -0
  246. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +103 -0
  247. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +381 -0
  248. package/src/components/DataTable/__tests__/test-utils.ts +94 -0
  249. package/src/components/DataTable/components/AccessDeniedPage.tsx +168 -0
  250. package/src/components/DataTable/components/ActionButtons.tsx +194 -0
  251. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +160 -0
  252. package/src/components/DataTable/components/ColumnFilter.tsx +114 -0
  253. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +100 -0
  254. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  255. package/src/components/DataTable/components/DataTableCore.tsx +1027 -0
  256. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +214 -0
  257. package/src/components/DataTable/components/DataTableModals.tsx +87 -0
  258. package/src/components/DataTable/components/DataTableToolbar.tsx +262 -0
  259. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  260. package/src/components/DataTable/components/EditableRow.tsx +159 -0
  261. package/src/components/DataTable/components/EmptyState.tsx +64 -0
  262. package/src/components/DataTable/components/ExpandButton.tsx +113 -0
  263. package/src/components/DataTable/components/FilterRow.tsx +100 -0
  264. package/src/components/DataTable/components/GroupHeader.tsx +42 -0
  265. package/src/components/DataTable/components/GroupingDropdown.tsx +96 -0
  266. package/src/components/DataTable/components/ImportModal.tsx +345 -0
  267. package/src/components/DataTable/components/LoadingState.tsx +12 -0
  268. package/src/components/DataTable/components/PaginationControls.tsx +332 -0
  269. package/src/components/DataTable/components/UnifiedTableBody.tsx +742 -0
  270. package/src/components/DataTable/components/ViewRowModal.tsx +68 -0
  271. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  272. package/src/components/DataTable/components/index.ts +16 -0
  273. package/src/components/DataTable/context/DataTableContext.tsx +97 -0
  274. package/src/components/DataTable/core/ActionManager.ts +235 -0
  275. package/src/components/DataTable/core/ColumnFactory.ts +268 -0
  276. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  277. package/src/components/DataTable/core/DataManager.ts +188 -0
  278. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  279. package/src/components/DataTable/core/LocalDataAdapter.ts +264 -0
  280. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  281. package/src/components/DataTable/core/StateManager.ts +311 -0
  282. package/src/components/DataTable/core/index.ts +8 -0
  283. package/src/components/DataTable/core/interfaces.ts +338 -0
  284. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +419 -0
  285. package/src/components/DataTable/examples/HierarchicalExample.tsx +475 -0
  286. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +176 -0
  287. package/src/components/DataTable/examples/PerformanceExample.tsx +505 -0
  288. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +95 -0
  289. package/src/components/DataTable/hooks/useColumnReordering.ts +110 -0
  290. package/src/components/DataTable/hooks/useDataTableState.ts +325 -0
  291. package/src/components/DataTable/hooks/useHierarchicalState.ts +174 -0
  292. package/src/components/DataTable/index.ts +68 -0
  293. package/src/components/DataTable/styles.ts +171 -0
  294. package/src/components/DataTable/types.ts +511 -0
  295. package/src/components/DataTable/utils/debugTools.ts +583 -0
  296. package/src/components/DataTable/utils/errorHandling.ts +494 -0
  297. package/src/components/DataTable/utils/exportUtils.ts +126 -0
  298. package/src/components/DataTable/utils/flexibleImport.ts +510 -0
  299. package/src/components/DataTable/utils/hierarchicalSorting.ts +151 -0
  300. package/src/components/DataTable/utils/hierarchicalUtils.ts +218 -0
  301. package/src/components/DataTable/utils/index.ts +1 -0
  302. package/src/components/DataTable/utils/performanceUtils.ts +351 -0
  303. package/src/components/Dialog/Dialog.test.tsx +1139 -0
  304. package/src/components/Dialog/Dialog.tsx +782 -0
  305. package/src/components/Dialog/README.md +804 -0
  306. package/src/components/Dialog/examples/BasicHtmlTest.tsx +55 -0
  307. package/src/components/Dialog/examples/DebugHtmlExample.tsx +68 -0
  308. package/src/components/Dialog/examples/HtmlDialogExample.tsx +202 -0
  309. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +61 -0
  310. package/src/components/Dialog/examples/SmartDialogExample.tsx +322 -0
  311. package/src/components/Dialog/index.ts +12 -0
  312. package/src/components/Dialog/utils/safeHtml.ts +185 -0
  313. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +752 -0
  314. package/src/components/ErrorBoundary/ErrorBoundary.tsx +312 -0
  315. package/src/components/ErrorBoundary/index.ts +8 -0
  316. package/src/components/EventSelector/EventSelector.tsx +360 -0
  317. package/src/components/EventSelector/index.ts +3 -0
  318. package/src/components/EventSelector/types.ts +79 -0
  319. package/src/components/FileUpload/FileUpload.example.tsx +218 -0
  320. package/src/components/FileUpload/FileUpload.test.tsx +665 -0
  321. package/src/components/FileUpload/FileUpload.tsx +237 -0
  322. package/src/components/FileUpload/index.ts +6 -0
  323. package/src/components/Footer/Footer.tsx +197 -0
  324. package/src/components/Footer/index.ts +17 -0
  325. package/src/components/Form/Form.tsx +166 -0
  326. package/src/components/Form/FormErrorSummary.tsx +113 -0
  327. package/src/components/Form/FormField.tsx +249 -0
  328. package/src/components/Form/FormFieldset.tsx +127 -0
  329. package/src/components/Form/FormLiveRegion.tsx +198 -0
  330. package/src/components/Form/index.ts +26 -0
  331. package/src/components/Header/Header.tsx +301 -0
  332. package/src/components/Header/index.ts +4 -0
  333. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +164 -0
  334. package/src/components/InactivityWarningModal/index.ts +9 -0
  335. package/src/components/Input/Input.tsx +201 -0
  336. package/src/components/Input/__mocks__/Input.tsx +2 -0
  337. package/src/components/Input/index.ts +9 -0
  338. package/src/components/Label/Label.tsx +186 -0
  339. package/src/components/Label/index.ts +2 -0
  340. package/src/components/LoadingSpinner/LoadingSpinner.tsx +98 -0
  341. package/src/components/LoadingSpinner/index.ts +3 -0
  342. package/src/components/LoginForm/LoginForm.tsx +273 -0
  343. package/src/components/LoginForm/index.ts +3 -0
  344. package/src/components/NavigationMenu/NavigationMenu.tsx +698 -0
  345. package/src/components/NavigationMenu/index.ts +10 -0
  346. package/src/components/NavigationMenu/types.ts +85 -0
  347. package/src/components/OrganisationSelector/OrganisationSelector.tsx +304 -0
  348. package/src/components/OrganisationSelector/index.ts +9 -0
  349. package/src/components/PaceAppLayout/PaceAppLayout.tsx +699 -0
  350. package/src/components/PaceAppLayout/README.md +278 -0
  351. package/src/components/PaceAppLayout/index.ts +1 -0
  352. package/src/components/PaceLoginPage/PaceLoginPage.tsx +221 -0
  353. package/src/components/PaceLoginPage/index.ts +1 -0
  354. package/src/components/PasswordReset/PasswordChangeForm.tsx +186 -0
  355. package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
  356. package/src/components/PasswordReset/index.ts +4 -0
  357. package/src/components/PrintButton/PrintButton.tsx +321 -0
  358. package/src/components/PrintButton/PrintButtonGroup.tsx +84 -0
  359. package/src/components/PrintButton/PrintToolbar.tsx +94 -0
  360. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +438 -0
  361. package/src/components/PrintButton/index.ts +33 -0
  362. package/src/components/PrintButton/types.ts +173 -0
  363. package/src/components/PrintCard/PrintCard.tsx +154 -0
  364. package/src/components/PrintCard/PrintCardContent.tsx +57 -0
  365. package/src/components/PrintCard/PrintCardFooter.tsx +60 -0
  366. package/src/components/PrintCard/PrintCardGrid.tsx +91 -0
  367. package/src/components/PrintCard/PrintCardHeader.tsx +78 -0
  368. package/src/components/PrintCard/PrintCardImage.tsx +81 -0
  369. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +239 -0
  370. package/src/components/PrintCard/index.ts +34 -0
  371. package/src/components/PrintCard/types.ts +171 -0
  372. package/src/components/PrintDataTable/PrintDataTable.tsx +215 -0
  373. package/src/components/PrintDataTable/PrintTableGroup.tsx +90 -0
  374. package/src/components/PrintDataTable/PrintTableRow.tsx +76 -0
  375. package/src/components/PrintDataTable/index.ts +25 -0
  376. package/src/components/PrintDataTable/types.ts +67 -0
  377. package/src/components/PrintFooter/PrintFooter.tsx +183 -0
  378. package/src/components/PrintFooter/PrintFooterContent.tsx +71 -0
  379. package/src/components/PrintFooter/PrintFooterInfo.tsx +86 -0
  380. package/src/components/PrintFooter/PrintPageNumber.tsx +90 -0
  381. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +390 -0
  382. package/src/components/PrintFooter/index.ts +30 -0
  383. package/src/components/PrintFooter/types.ts +149 -0
  384. package/src/components/PrintGrid/PrintGrid.tsx +180 -0
  385. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +109 -0
  386. package/src/components/PrintGrid/PrintGridContainer.tsx +128 -0
  387. package/src/components/PrintGrid/PrintGridItem.tsx +220 -0
  388. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +359 -0
  389. package/src/components/PrintGrid/index.ts +31 -0
  390. package/src/components/PrintGrid/types.ts +159 -0
  391. package/src/components/PrintHeader/PrintCoverHeader.tsx +230 -0
  392. package/src/components/PrintHeader/PrintHeader.tsx +150 -0
  393. package/src/components/PrintHeader/index.ts +17 -0
  394. package/src/components/PrintHeader/types.ts +42 -0
  395. package/src/components/PrintLayout/PrintLayout.tsx +122 -0
  396. package/src/components/PrintLayout/PrintLayoutContext.tsx +66 -0
  397. package/src/components/PrintLayout/PrintPageBreak.tsx +52 -0
  398. package/src/components/PrintLayout/examples/PrintShowcase.tsx +230 -0
  399. package/src/components/PrintLayout/index.ts +19 -0
  400. package/src/components/PrintLayout/types.ts +37 -0
  401. package/src/components/PrintPageBreak/PrintPageBreak.tsx +120 -0
  402. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +90 -0
  403. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +112 -0
  404. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +279 -0
  405. package/src/components/PrintPageBreak/index.ts +23 -0
  406. package/src/components/PrintPageBreak/types.ts +94 -0
  407. package/src/components/PrintSection/PrintColumn.tsx +104 -0
  408. package/src/components/PrintSection/PrintDivider.tsx +101 -0
  409. package/src/components/PrintSection/PrintSection.tsx +129 -0
  410. package/src/components/PrintSection/PrintSectionContent.tsx +75 -0
  411. package/src/components/PrintSection/PrintSectionHeader.tsx +97 -0
  412. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +258 -0
  413. package/src/components/PrintSection/index.ts +33 -0
  414. package/src/components/PrintSection/types.ts +155 -0
  415. package/src/components/PrintText/PrintText.tsx +116 -0
  416. package/src/components/PrintText/index.ts +16 -0
  417. package/src/components/PrintText/types.ts +24 -0
  418. package/src/components/Progress/Progress.tsx +116 -0
  419. package/src/components/Progress/index.ts +3 -0
  420. package/src/components/PublicLayout/EventLogo.tsx +287 -0
  421. package/src/components/PublicLayout/PublicErrorBoundary.tsx +279 -0
  422. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +208 -0
  423. package/src/components/PublicLayout/PublicPageContextChecker.tsx +130 -0
  424. package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
  425. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
  426. package/src/components/PublicLayout/PublicPageFooter.tsx +124 -0
  427. package/src/components/PublicLayout/PublicPageHeader.tsx +178 -0
  428. package/src/components/PublicLayout/PublicPageLayout.tsx +232 -0
  429. package/src/components/PublicLayout/PublicPageProvider.tsx +137 -0
  430. package/src/components/PublicLayout/index.ts +51 -0
  431. package/src/components/RBAC/PagePermissionGuard.tsx +287 -0
  432. package/src/components/RBAC/RBACGuard.tsx +143 -0
  433. package/src/components/RBAC/RBACProvider.tsx +186 -0
  434. package/src/components/RBAC/RoleBasedContent.tsx +129 -0
  435. package/src/components/RBAC/index.ts +23 -0
  436. package/src/components/Select/Select.tsx +660 -0
  437. package/src/components/Select/index.ts +1 -0
  438. package/src/components/SuperAdminGuard.tsx +116 -0
  439. package/src/components/Table/Table.tsx +222 -0
  440. package/src/components/Table/index.ts +11 -0
  441. package/src/components/Toast/Toast.tsx +339 -0
  442. package/src/components/Toast/index.ts +14 -0
  443. package/src/components/Tooltip/Tooltip.tsx +167 -0
  444. package/src/components/Tooltip/index.ts +7 -0
  445. package/src/components/UserMenu/UserMenu.tsx +243 -0
  446. package/src/components/UserMenu/index.ts +3 -0
  447. package/src/components/examples/PermissionExample.tsx +150 -0
  448. package/src/components/index.ts +434 -0
  449. package/src/components.ts +19 -0
  450. package/src/constants/performance.ts +14 -0
  451. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  452. package/src/examples/PublicEventPage.tsx +274 -0
  453. package/src/examples/PublicPageApp.tsx +308 -0
  454. package/src/examples/PublicPageUsageExample.tsx +216 -0
  455. package/src/hooks/index.ts +56 -0
  456. package/src/hooks/public/index.ts +34 -0
  457. package/src/hooks/public/usePublicEvent.ts +261 -0
  458. package/src/hooks/public/usePublicEventLogo.ts +285 -0
  459. package/src/hooks/public/usePublicRouteParams.ts +259 -0
  460. package/src/hooks/useAppConfig.ts +94 -0
  461. package/src/hooks/useComponentPerformance.ts +39 -0
  462. package/src/hooks/useCounter.test.ts +135 -0
  463. package/src/hooks/useDataTablePerformance.ts +387 -0
  464. package/src/hooks/useDataTableState.ts +110 -0
  465. package/src/hooks/useDebounce.ts +18 -0
  466. package/src/hooks/useFocusManagement.ts +161 -0
  467. package/src/hooks/useFocusTrap.ts +155 -0
  468. package/src/hooks/useInactivityTracker.ts +372 -0
  469. package/src/hooks/useIsMobile.ts +42 -0
  470. package/src/hooks/useKeyboardShortcuts.ts +237 -0
  471. package/src/hooks/useOrganisationPermissions.ts +208 -0
  472. package/src/hooks/useOrganisationSecurity.ts +262 -0
  473. package/src/hooks/usePerformanceMonitor.ts +128 -0
  474. package/src/hooks/usePermissionCache.ts +455 -0
  475. package/src/hooks/useRBAC.ts +262 -0
  476. package/src/hooks/useSecureDataAccess.ts +586 -0
  477. package/src/hooks/useStorage.ts +274 -0
  478. package/src/hooks/useToast.ts +242 -0
  479. package/src/hooks/useZodForm.ts +28 -0
  480. package/src/index.ts +200 -0
  481. package/src/providers/AuthProvider.tsx +369 -0
  482. package/src/providers/EventProvider.tsx +324 -0
  483. package/src/providers/InactivityProvider.tsx +238 -0
  484. package/src/providers/OrganisationProvider.tsx +588 -0
  485. package/src/providers/RBACProvider.tsx +634 -0
  486. package/src/providers/UnifiedAuthProvider.tsx +327 -0
  487. package/src/providers/index.ts +15 -0
  488. package/src/rbac/README.md +885 -0
  489. package/src/rbac/adapters.tsx +726 -0
  490. package/src/rbac/api.ts +339 -0
  491. package/src/rbac/audit-enhanced.ts +339 -0
  492. package/src/rbac/audit.ts +338 -0
  493. package/src/rbac/cache.ts +215 -0
  494. package/src/rbac/components/EnhancedNavigationMenu.tsx +294 -0
  495. package/src/rbac/components/NavigationGuard.tsx +294 -0
  496. package/src/rbac/components/NavigationProvider.tsx +314 -0
  497. package/src/rbac/components/PagePermissionGuard.tsx +430 -0
  498. package/src/rbac/components/PagePermissionProvider.tsx +274 -0
  499. package/src/rbac/components/PermissionEnforcer.tsx +307 -0
  500. package/src/rbac/components/RoleBasedRouter.tsx +425 -0
  501. package/src/rbac/components/SecureDataProvider.tsx +319 -0
  502. package/src/rbac/components/index.ts +64 -0
  503. package/src/rbac/config.ts +133 -0
  504. package/src/rbac/docs/event-based-apps.md +285 -0
  505. package/src/rbac/engine.ts +1026 -0
  506. package/src/rbac/eslint-rules.js +285 -0
  507. package/src/rbac/examples/CompleteRBACExample.tsx +323 -0
  508. package/src/rbac/examples/EventBasedApp.tsx +238 -0
  509. package/src/rbac/hooks.ts +570 -0
  510. package/src/rbac/index.ts +114 -0
  511. package/src/rbac/permissions.ts +293 -0
  512. package/src/rbac/secureClient.ts +244 -0
  513. package/src/rbac/security.ts +346 -0
  514. package/src/rbac/testing/index.tsx +340 -0
  515. package/src/rbac/types.ts +343 -0
  516. package/src/rbac/utils/eventContext.ts +83 -0
  517. package/src/styles/core.css +422 -0
  518. package/src/styles/index.ts +51 -0
  519. package/src/theming/runtime.ts +187 -0
  520. package/src/types/database.ts +472 -0
  521. package/src/types/guards.ts +30 -0
  522. package/src/types/index.ts +25 -0
  523. package/src/types/organisation.ts +184 -0
  524. package/src/types/security.ts +70 -0
  525. package/src/types/supabase.ts +166 -0
  526. package/src/types/theme.ts +6 -0
  527. package/src/types/unified.ts +262 -0
  528. package/src/types/validation.ts +164 -0
  529. package/src/types/vitest-globals.d.ts +43 -0
  530. package/src/utils/__mocks__/supabaseMock.ts +75 -0
  531. package/src/utils/__mocks__/supabaseMock.tsx +198 -0
  532. package/src/utils/appConfig.ts +47 -0
  533. package/src/utils/appIdResolver.ts +130 -0
  534. package/src/utils/appNameResolver.ts +190 -0
  535. package/src/utils/audit.ts +127 -0
  536. package/src/utils/auth-utils.ts +96 -0
  537. package/src/utils/bundleAnalysis.ts +129 -0
  538. package/src/utils/cn.ts +7 -0
  539. package/src/utils/debugLogger.ts +46 -0
  540. package/src/utils/deviceFingerprint.ts +215 -0
  541. package/src/utils/dynamicUtils.ts +105 -0
  542. package/src/utils/formatting.ts +77 -0
  543. package/src/utils/index.ts +145 -0
  544. package/src/utils/lazyLoad.tsx +44 -0
  545. package/src/utils/organisationContext.ts +135 -0
  546. package/src/utils/performanceBenchmark.ts +64 -0
  547. package/src/utils/performanceBudgets.ts +111 -0
  548. package/src/utils/permissionTypes.ts +37 -0
  549. package/src/utils/permissionUtils.ts +31 -0
  550. package/src/utils/print/PrintDataProcessor.ts +390 -0
  551. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +397 -0
  552. package/src/utils/print/index.ts +29 -0
  553. package/src/utils/print/types.ts +196 -0
  554. package/src/utils/print/usePrintOptimization.ts +272 -0
  555. package/src/utils/sanitization.ts +264 -0
  556. package/src/utils/schemaUtils.ts +37 -0
  557. package/src/utils/secureDataAccess.ts +361 -0
  558. package/src/utils/secureErrors.ts +79 -0
  559. package/src/utils/secureStorage.ts +244 -0
  560. package/src/utils/security.ts +156 -0
  561. package/src/utils/securityMonitor.ts +45 -0
  562. package/src/utils/sessionTracking.ts +170 -0
  563. package/src/utils/storage/README.md +348 -0
  564. package/src/utils/storage/config.ts +100 -0
  565. package/src/utils/storage/helpers.ts +359 -0
  566. package/src/utils/storage/index.ts +36 -0
  567. package/src/utils/storage/types.ts +90 -0
  568. package/src/utils/validation.ts +111 -0
  569. package/src/utils/validationUtils.ts +120 -0
  570. package/src/validation/common.ts +53 -0
  571. package/src/validation/csrf.ts +214 -0
  572. package/src/validation/index.ts +43 -0
  573. package/src/validation/passwordSchema.ts +125 -0
  574. package/src/validation/sanitization.ts +96 -0
  575. package/src/validation/schemaUtils.ts +42 -0
  576. package/src/validation/sqlInjectionProtection.ts +242 -0
  577. package/src/validation/user.ts +34 -0
  578. package/dist/UnifiedAuthProvider-V7y63NjT.d.ts +0 -88
  579. package/dist/chunk-4MCJAK7J.js.map +0 -1
  580. package/dist/chunk-4ZTIEYU2.js.map +0 -1
  581. package/dist/chunk-H4PZ4B3Y.js.map +0 -1
  582. package/dist/chunk-IOX76PSM.js.map +0 -1
  583. package/dist/chunk-JUUNUW3O.js.map +0 -1
  584. package/dist/chunk-U7DY5T33.js +0 -11
  585. package/dist/chunk-U7DY5T33.js.map +0 -1
  586. package/dist/chunk-WHLSWC6W.js.map +0 -1
  587. package/dist/chunk-XI7QFSSC.js +0 -790
  588. package/dist/chunk-XI7QFSSC.js.map +0 -1
  589. package/dist/chunk-XIJMMBDD.js +0 -73
  590. package/dist/chunk-XIJMMBDD.js.map +0 -1
  591. package/dist/chunk-YNU5QJ4S.js.map +0 -1
  592. package/dist/chunk-YWYCNGWH.js +0 -2070
  593. package/dist/chunk-YWYCNGWH.js.map +0 -1
  594. package/dist/chunk-ZJ3UKPIW.js +0 -952
  595. package/dist/chunk-ZJ3UKPIW.js.map +0 -1
  596. package/dist/useAppConfig-CZNJJsT_.d.ts +0 -148
  597. package/dist/{DataTable-2LB6HI6V.js.map → DataTable-GX3XERFJ.js.map} +0 -0
  598. package/dist/{api-AIJ3IJX3.js.map → api-ETQ6YJ3C.js.map} +0 -0
  599. package/dist/{audit-PD5L5ZSC.js.map → appNameResolver-7GHF5ED2.js.map} +0 -0
  600. package/dist/{chunk-DC5AMYBS.js.map → audit-BUW3LMJB.js.map} +0 -0
  601. package/dist/{validation-D2-NNCCE.d.ts → validation-PM_iOaTI.d.ts} +6 -6
@@ -0,0 +1,341 @@
1
+ # 🧪 Testing Guidelines & Best Practices
2
+
3
+ ## 📋 Table of Contents
4
+ - [Testing Philosophy](#testing-philosophy)
5
+ - [Test Structure](#test-structure)
6
+ - [Naming Conventions](#naming-conventions)
7
+ - [Test Categories](#test-categories)
8
+ - [Best Practices](#best-practices)
9
+ - [Common Patterns](#common-patterns)
10
+ - [Anti-Patterns](#anti-patterns)
11
+ - [Code Coverage](#code-coverage)
12
+
13
+ ## 🎯 Testing Philosophy
14
+
15
+ ### The Testing Pyramid
16
+ ```
17
+ /\
18
+ / \ E2E Tests (Few)
19
+ /____\
20
+ / \ Integration Tests (Some)
21
+ /________\
22
+ Unit Tests (Many)
23
+ ```
24
+
25
+ ### Test Principles
26
+ 1. **Fast** - Tests should run quickly
27
+ 2. **Independent** - Tests should not depend on each other
28
+ 3. **Repeatable** - Tests should produce the same results every time
29
+ 4. **Self-Validating** - Tests should have a clear pass/fail result
30
+ 5. **Timely** - Tests should be written close to the code they test
31
+
32
+ ## 🏗️ Test Structure
33
+
34
+ ### File Organization
35
+ Tests should be colocated with the component, hook, or utility they test (e.g., Button.test.tsx next to Button.tsx).
36
+ Use src/__tests__/integration/ only for multi-feature tests that span across modules.
37
+
38
+ ```
39
+ src/
40
+ ├── components/
41
+ │ ├── Button/
42
+ │ │ ├── Button.tsx
43
+ │ │ └── Button.test.tsx ✅ ← colocated unit/component test
44
+ ├── hooks/
45
+ │ ├── useAuth.ts
46
+ │ └── useAuth.test.ts ✅
47
+ ├── utils/
48
+ │ ├── formatDate.ts
49
+ │ └── formatDate.test.ts ✅
50
+ ├── __tests__/integration/ ✅ ← multi-module tests, auth flows, user journeys
51
+ ├── __tests__/fixtures/ ✅ ← factories, mock data
52
+ ├── __tests__/helpers/ ✅ ← shared test utilities
53
+ ```
54
+
55
+ ### Test File Naming
56
+ - `ComponentName.test.tsx` - Component tests
57
+ - `hookName.test.ts` - Hook tests
58
+ - `utilityName.test.ts` - Utility tests
59
+ - `feature.integration.test.tsx` - Integration tests
60
+
61
+ ## 📝 Naming Conventions
62
+
63
+ ### Describe Blocks
64
+ ```typescript
65
+ describe('ComponentName', () => {
66
+ describe('Rendering', () => {
67
+ // Rendering tests
68
+ });
69
+
70
+ describe('Event Handling', () => {
71
+ // Event tests
72
+ });
73
+
74
+ describe('State Management', () => {
75
+ // State tests
76
+ });
77
+ });
78
+ ```
79
+
80
+ ### Test Names
81
+ ```typescript
82
+ // ✅ Good
83
+ it('renders with text content', () => {});
84
+ it('handles click events', () => {});
85
+ it('can be disabled', () => {});
86
+
87
+ // ❌ Bad
88
+ it('works', () => {});
89
+ it('test button', () => {});
90
+ it('should do something', () => {});
91
+ ```
92
+
93
+ ## 🎭 Test Categories
94
+
95
+ ### 1. Unit Tests
96
+ - Test individual functions/components in isolation
97
+ - Fast, focused, and numerous
98
+ - Mock all dependencies
99
+
100
+ ### 2. Integration Tests
101
+ - Test how multiple units work together
102
+ - Test data flow between components
103
+ - Use real implementations where possible
104
+
105
+ ### 3. Component Tests
106
+ - Test React components in isolation
107
+ - Test rendering, props, events, and state
108
+ - Use React Testing Library
109
+
110
+ ### 4. Hook Tests
111
+ - Test custom hooks in isolation
112
+ - Use `renderHook` from React Testing Library
113
+ - Test state changes and side effects
114
+
115
+ ## ✅ Best Practices
116
+
117
+ ### 1. Test Structure (AAA Pattern)
118
+ ```typescript
119
+ it('should increment counter when clicked', () => {
120
+ // Arrange
121
+ const { getByRole } = render(<Counter />);
122
+ const button = getByRole('button');
123
+
124
+ // Act
125
+ fireEvent.click(button);
126
+
127
+ // Assert
128
+ expect(button).toHaveTextContent('1');
129
+ });
130
+ ```
131
+
132
+ ### 2. Use Semantic Queries
133
+ ```typescript
134
+ // ✅ Good - Semantic queries
135
+ screen.getByRole('button', { name: 'Submit' });
136
+ screen.getByLabelText('Email address');
137
+ screen.getByText('Welcome back');
138
+
139
+ // ❌ Bad - Implementation details
140
+ screen.getByClassName('btn-primary');
141
+ screen.getByTestId('submit-button');
142
+ ```
143
+
144
+ ### 3. Test User Behavior
145
+ ```typescript
146
+ // ✅ Good - Test what users see/do
147
+ expect(screen.getByText('Welcome, John')).toBeInTheDocument();
148
+ await user.click(screen.getByRole('button'));
149
+
150
+ // ❌ Bad - Test implementation details
151
+ expect(component.state.isVisible).toBe(true);
152
+ expect(component.props.onClick).toHaveBeenCalled();
153
+ ```
154
+
155
+ ### 4. Mock External Dependencies
156
+ ```typescript
157
+ // Mock API calls
158
+ vi.mock('../api/users', () => ({
159
+ fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'John' })
160
+ }));
161
+
162
+ // Mock modules
163
+ vi.mock('react-router-dom', () => ({
164
+ useNavigate: () => vi.fn()
165
+ }));
166
+ ```
167
+
168
+ ### 5. Clean Up After Tests
169
+ ```typescript
170
+ afterEach(() => {
171
+ cleanup();
172
+ vi.clearAllMocks();
173
+ });
174
+ ```
175
+
176
+ ## 🔄 Common Patterns
177
+
178
+ ### 1. Component Testing Pattern
179
+ ```typescript
180
+ describe('Button Component', () => {
181
+ describe('Rendering', () => {
182
+ it('renders with text', () => {
183
+ render(<Button>Click me</Button>);
184
+ expect(screen.getByRole('button')).toBeInTheDocument();
185
+ });
186
+ });
187
+
188
+ describe('Event Handling', () => {
189
+ it('handles click events', async () => {
190
+ const handleClick = vi.fn();
191
+ const user = userEvent.setup();
192
+
193
+ render(<Button onClick={handleClick}>Click me</Button>);
194
+ await user.click(screen.getByRole('button'));
195
+
196
+ expect(handleClick).toHaveBeenCalledTimes(1);
197
+ });
198
+ });
199
+ });
200
+ ```
201
+
202
+ ### 2. Hook Testing Pattern
203
+ ```typescript
204
+ describe('useCounter Hook', () => {
205
+ it('initializes with default value', () => {
206
+ const { result } = renderHook(() => useCounter());
207
+ expect(result.current.count).toBe(0);
208
+ });
209
+
210
+ it('increments count', () => {
211
+ const { result } = renderHook(() => useCounter(0));
212
+
213
+ act(() => {
214
+ result.current.increment();
215
+ });
216
+
217
+ expect(result.current.count).toBe(1);
218
+ });
219
+ });
220
+ ```
221
+
222
+ ### 3. Integration Testing Pattern
223
+ ```typescript
224
+ describe('User Profile Integration', () => {
225
+ it('loads and displays user data', async () => {
226
+ render(<UserProfile userId="1" />);
227
+
228
+ await waitFor(() => {
229
+ expect(screen.getByText('John Doe')).toBeInTheDocument();
230
+ });
231
+ });
232
+ });
233
+ ```
234
+
235
+ ## ❌ Anti-Patterns
236
+
237
+ ### 1. Testing Implementation Details
238
+ ```typescript
239
+ // ❌ Bad
240
+ expect(component.state.isVisible).toBe(true);
241
+ expect(component.props.onClick).toHaveBeenCalled();
242
+
243
+ // ✅ Good
244
+ expect(screen.getByText('Visible content')).toBeInTheDocument();
245
+ await user.click(screen.getByRole('button'));
246
+ ```
247
+
248
+ ### 2. Over-Mocking
249
+ ```typescript
250
+ // ❌ Bad - Mocking everything
251
+ vi.mock('../utils/formatDate');
252
+ vi.mock('../hooks/useAuth');
253
+ vi.mock('../components/Button');
254
+
255
+ // ✅ Good - Mock only what's necessary
256
+ vi.mock('../api/users');
257
+ ```
258
+
259
+ ### 3. Testing Multiple Things in One Test
260
+ ```typescript
261
+ // ❌ Bad
262
+ it('renders button and handles click and shows loading', () => {
263
+ // Too many assertions
264
+ });
265
+
266
+ // ✅ Good
267
+ it('renders button', () => {});
268
+ it('handles click', () => {});
269
+ it('shows loading state', () => {});
270
+ ```
271
+
272
+ ### 4. Brittle Selectors
273
+ ```typescript
274
+ // ❌ Bad - Fragile selectors
275
+ screen.getByClassName('btn-primary');
276
+ screen.getByTestId('submit-button');
277
+
278
+ // ✅ Good - Semantic selectors
279
+ screen.getByRole('button', { name: 'Submit' });
280
+ screen.getByLabelText('Email address');
281
+ ```
282
+
283
+ ## 📊 Code Coverage
284
+
285
+ ### Coverage Targets
286
+ - **Statements**: 80%
287
+ - **Branches**: 80%
288
+ - **Functions**: 80%
289
+ - **Lines**: 80%
290
+
291
+ ### What to Test
292
+ - ✅ Happy paths
293
+ - ✅ Error conditions
294
+ - ✅ Edge cases
295
+ - ✅ User interactions
296
+ - ✅ State changes
297
+
298
+ ### What NOT to Test
299
+ - ❌ Third-party library code
300
+ - ❌ Generated code
301
+ - ❌ Configuration files
302
+ - ❌ Type definitions
303
+
304
+ ## 🚀 Running Tests
305
+
306
+ ### Commands
307
+ ```bash
308
+ # Run all tests
309
+ npm test
310
+
311
+ # Run tests in watch mode
312
+ npm test -- --watch
313
+
314
+ # Run tests with coverage
315
+ npm test -- --coverage
316
+
317
+ # Run specific test file
318
+ npm test -- Button.test.tsx
319
+
320
+ # Run tests matching pattern
321
+ npm test -- --grep "Button"
322
+ ```
323
+
324
+ ### Debugging Tests
325
+ ```typescript
326
+ // Debug output
327
+ screen.debug();
328
+
329
+ // Debug specific element
330
+ screen.debug(screen.getByRole('button'));
331
+
332
+ // Log all queries
333
+ screen.logTestingPlaygroundURL();
334
+ ```
335
+
336
+ ## 📚 Resources
337
+
338
+ - [React Testing Library Docs](https://testing-library.com/docs/react-testing-library/intro/)
339
+ - [Vitest Docs](https://vitest.dev/)
340
+ - [Testing Best Practices](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)
341
+ - [Jest DOM Matchers](https://github.com/testing-library/jest-dom)
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @file Test Mocks and Fixtures
3
+ * @description Centralized mocks and test data
4
+ */
5
+
6
+ import { vi } from 'vitest';
7
+
8
+ // API Mocks
9
+ export const apiMocks = {
10
+ success: (data: any) => Promise.resolve({ data, status: 200 }),
11
+ error: (message = 'API Error') => Promise.reject(new Error(message)),
12
+ loading: () => new Promise(() => {}), // Never resolves
13
+ };
14
+
15
+ // React Query Mocks
16
+ export const queryMocks = {
17
+ useQuery: vi.fn(),
18
+ useMutation: vi.fn(),
19
+ useQueryClient: vi.fn(),
20
+ };
21
+
22
+ // Router Mocks
23
+ export const routerMocks = {
24
+ useNavigate: vi.fn(),
25
+ useLocation: vi.fn(() => ({ pathname: '/', search: '', hash: '', state: null })),
26
+ useParams: vi.fn(() => ({})),
27
+ };
28
+
29
+ // Local Storage Mock
30
+ export const localStorageMock = {
31
+ getItem: vi.fn(),
32
+ setItem: vi.fn(),
33
+ removeItem: vi.fn(),
34
+ clear: vi.fn(),
35
+ };
36
+
37
+ // Window Mocks
38
+ export const windowMocks = {
39
+ matchMedia: vi.fn(() => ({
40
+ matches: false,
41
+ addListener: vi.fn(),
42
+ removeListener: vi.fn(),
43
+ })),
44
+ scrollTo: vi.fn(),
45
+ getComputedStyle: vi.fn(() => ({
46
+ getPropertyValue: vi.fn().mockReturnValue(''),
47
+ })),
48
+ };
49
+
50
+ // Test Data
51
+ export const testData = {
52
+ users: [
53
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
54
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' },
55
+ ],
56
+
57
+ products: [
58
+ { id: '1', name: 'Product 1', price: 10.99 },
59
+ { id: '2', name: 'Product 2', price: 19.99 },
60
+ ],
61
+
62
+ events: [
63
+ { id: '1', title: 'Event 1', date: '2024-01-01' },
64
+ { id: '2', title: 'Event 2', date: '2024-01-02' },
65
+ ],
66
+ };
67
+
68
+ // Mock Functions
69
+ export const mockFunctions = {
70
+ console: {
71
+ log: vi.fn(),
72
+ warn: vi.fn(),
73
+ error: vi.fn(),
74
+ },
75
+
76
+ timers: {
77
+ setTimeout: vi.fn(),
78
+ clearTimeout: vi.fn(),
79
+ setInterval: vi.fn(),
80
+ clearInterval: vi.fn(),
81
+ },
82
+
83
+ fetch: vi.fn(),
84
+
85
+ // Custom mock creators
86
+ createMock: <T extends (...args: any[]) => any>(implementation?: T) => {
87
+ return vi.fn(implementation) as T & ReturnType<typeof vi.fn>;
88
+ },
89
+
90
+ createAsyncMock: <T extends (...args: any[]) => Promise<any>>(implementation?: T) => {
91
+ return vi.fn(implementation) as T & ReturnType<typeof vi.fn>;
92
+ },
93
+ };
@@ -0,0 +1,145 @@
1
+ /**
2
+ * @file Component Test Utilities
3
+ * @description Specialized utilities for component testing
4
+ */
5
+
6
+ import { render, screen, RenderResult } from '@testing-library/react';
7
+ import userEvent from '@testing-library/user-event';
8
+ import { vi } from 'vitest';
9
+ import { renderWithProviders } from './test-utils';
10
+
11
+ // Component test patterns
12
+ export const componentTestPatterns = {
13
+ // Test component renders without crashing
14
+ testRenders: (Component: React.ComponentType<any>, props = {}) => {
15
+ return () => {
16
+ renderWithProviders(<Component {...props} />);
17
+ expect(screen.getByRole('generic')).toBeInTheDocument();
18
+ };
19
+ },
20
+
21
+ // Test component handles props correctly
22
+ testProps: (Component: React.ComponentType<any>, testCases: Array<{
23
+ name: string;
24
+ props: Record<string, any>;
25
+ expectedBehavior: () => void;
26
+ }>) => {
27
+ return testCases.map(({ name, props, expectedBehavior }) => ({
28
+ name: `handles ${name}`,
29
+ test: () => {
30
+ renderWithProviders(<Component {...props} />);
31
+ expectedBehavior();
32
+ },
33
+ }));
34
+ },
35
+
36
+ // Test component handles events
37
+ testEvents: (Component: React.ComponentType<any>, eventTests: Array<{
38
+ name: string;
39
+ action: (element: HTMLElement) => Promise<void>;
40
+ expectedBehavior: () => void;
41
+ }>) => {
42
+ return eventTests.map(({ name, action, expectedBehavior }) => ({
43
+ name: `handles ${name}`,
44
+ test: async () => {
45
+ const user = userEvent.setup();
46
+ renderWithProviders(<Component />);
47
+
48
+ const element = screen.getByRole('button');
49
+ await action(element);
50
+ expectedBehavior();
51
+ },
52
+ }));
53
+ },
54
+
55
+ // Test accessibility
56
+ testAccessibility: (Component: React.ComponentType<any>, props = {}) => {
57
+ return () => {
58
+ renderWithProviders(<Component {...props} />);
59
+
60
+ // Basic accessibility checks
61
+ const element = screen.getByRole('button');
62
+ expect(element).toBeInTheDocument();
63
+ expect(element).toBeVisible();
64
+ };
65
+ },
66
+ };
67
+
68
+ // Common component test scenarios
69
+ export const commonScenarios = {
70
+ // Button component scenarios
71
+ button: {
72
+ renders: (Component: React.ComponentType<any>) => [
73
+ {
74
+ name: 'renders with text',
75
+ test: () => {
76
+ renderWithProviders(<Component>Click me</Component>);
77
+ expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
78
+ },
79
+ },
80
+ {
81
+ name: 'handles click events',
82
+ test: async () => {
83
+ const handleClick = vi.fn();
84
+ const user = userEvent.setup();
85
+ renderWithProviders(<Component onClick={handleClick}>Click me</Component>);
86
+
87
+ await user.click(screen.getByRole('button'));
88
+ expect(handleClick).toHaveBeenCalledTimes(1);
89
+ },
90
+ },
91
+ {
92
+ name: 'can be disabled',
93
+ test: () => {
94
+ renderWithProviders(<Component disabled>Disabled</Component>);
95
+ expect(screen.getByRole('button')).toBeDisabled();
96
+ },
97
+ },
98
+ ],
99
+ },
100
+
101
+ // Form component scenarios
102
+ form: {
103
+ renders: (Component: React.ComponentType<any>) => [
104
+ {
105
+ name: 'renders form elements',
106
+ test: () => {
107
+ renderWithProviders(<Component />);
108
+ expect(screen.getByRole('form')).toBeInTheDocument();
109
+ },
110
+ },
111
+ {
112
+ name: 'handles form submission',
113
+ test: async () => {
114
+ const handleSubmit = vi.fn();
115
+ const user = userEvent.setup();
116
+ renderWithProviders(<Component onSubmit={handleSubmit} />);
117
+
118
+ await user.click(screen.getByRole('button', { name: /submit/i }));
119
+ expect(handleSubmit).toHaveBeenCalledTimes(1);
120
+ },
121
+ },
122
+ ],
123
+ },
124
+ };
125
+
126
+ // Test data factories
127
+ export const createTestData = {
128
+ button: (overrides = {}) => ({
129
+ children: 'Test Button',
130
+ onClick: vi.fn(),
131
+ ...overrides,
132
+ }),
133
+
134
+ form: (overrides = {}) => ({
135
+ onSubmit: vi.fn(),
136
+ ...overrides,
137
+ }),
138
+
139
+ user: (overrides = {}) => ({
140
+ id: '1',
141
+ name: 'Test User',
142
+ email: 'test@example.com',
143
+ ...overrides,
144
+ }),
145
+ };
@@ -0,0 +1,117 @@
1
+ /**
2
+ * @file Test Utilities
3
+ * @description Comprehensive testing utilities and helpers
4
+ */
5
+
6
+ import React, { ReactElement } from 'react';
7
+ import { render, RenderOptions } from '@testing-library/react';
8
+ import userEvent from '@testing-library/user-event';
9
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
10
+ import { vi } from 'vitest';
11
+
12
+ // Mock providers for testing
13
+ const createTestQueryClient = () =>
14
+ new QueryClient({
15
+ defaultOptions: {
16
+ queries: {
17
+ retry: false,
18
+ cacheTime: 0,
19
+ },
20
+ mutations: {
21
+ retry: false,
22
+ },
23
+ },
24
+ });
25
+
26
+ // Custom render function with providers
27
+ interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
28
+ queryClient?: QueryClient;
29
+ withQueryClient?: boolean;
30
+ }
31
+
32
+ export function renderWithProviders(
33
+ ui: ReactElement,
34
+ options: CustomRenderOptions = {}
35
+ ): ReturnType<typeof render> {
36
+ const {
37
+ queryClient = createTestQueryClient(),
38
+ withQueryClient = true,
39
+ ...renderOptions
40
+ } = options;
41
+
42
+ const Wrapper = ({ children }: { children: React.ReactNode }) => {
43
+ if (withQueryClient) {
44
+ return (
45
+ <QueryClientProvider client={queryClient}>
46
+ {children}
47
+ </QueryClientProvider>
48
+ );
49
+ }
50
+ return <>{children}</>;
51
+ };
52
+
53
+ return render(ui, { wrapper: Wrapper, ...renderOptions });
54
+ }
55
+
56
+ // Re-export everything from testing-library
57
+ export * from '@testing-library/react';
58
+ export { userEvent };
59
+
60
+ // Mock data generators
61
+ export const mockData = {
62
+ user: (overrides = {}) => ({
63
+ id: '1',
64
+ email: 'test@example.com',
65
+ name: 'Test User',
66
+ ...overrides,
67
+ }),
68
+
69
+ button: (overrides = {}) => ({
70
+ children: 'Click me',
71
+ onClick: vi.fn(),
72
+ ...overrides,
73
+ }),
74
+
75
+ form: (overrides = {}) => ({
76
+ onSubmit: vi.fn(),
77
+ ...overrides,
78
+ }),
79
+ };
80
+
81
+ // Common test helpers
82
+ export const testHelpers = {
83
+ // Wait for async operations
84
+ waitFor: (callback: () => void, timeout = 1000) => {
85
+ return new Promise((resolve, reject) => {
86
+ const startTime = Date.now();
87
+
88
+ const check = () => {
89
+ try {
90
+ callback();
91
+ resolve(undefined);
92
+ } catch (error) {
93
+ if (Date.now() - startTime > timeout) {
94
+ reject(error);
95
+ } else {
96
+ setTimeout(check, 10);
97
+ }
98
+ }
99
+ };
100
+
101
+ check();
102
+ });
103
+ },
104
+
105
+ // Mock function with better typing
106
+ createMockFn: <T extends (...args: any[]) => any>(implementation?: T) => {
107
+ return vi.fn(implementation) as T & ReturnType<typeof vi.fn>;
108
+ },
109
+
110
+ // Generate test props
111
+ createTestProps: <T extends Record<string, any>>(defaults: T) => {
112
+ return (overrides: Partial<T> = {}) => ({
113
+ ...defaults,
114
+ ...overrides,
115
+ });
116
+ },
117
+ };