@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.
- package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +240 -0
- package/audit-tool/audits/03-architecture.cjs +224 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +554 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +295 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +380 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-6RMSCQJ6.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
- package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
- package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
- package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
- package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
- package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
- package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
- package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
- package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
- package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
- package/dist/components.d.ts +5 -4
- package/dist/components.js +29 -34
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +8 -8
- package/dist/index.d.ts +7 -7
- package/dist/index.js +21 -20
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +1 -1
- package/dist/rbac/index.js +8 -8
- package/dist/theming/runtime.d.ts +61 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +106 -41
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/dependencies.md +23 -0
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/app-layout.md +1 -1
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +127 -34
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +50 -20
- package/package.json +50 -19
- package/scripts/eslint-audit.cjs +123 -0
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +349 -0
- package/scripts/validate-dependencies.cjs +248 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/AddressField/AddressField.tsx +26 -1
- package/src/components/Alert/Alert.test.tsx +86 -22
- package/src/components/Alert/Alert.tsx +19 -11
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/Checkbox/Checkbox.test.tsx +2 -1
- package/src/components/ContextSelector/ContextSelector.tsx +108 -126
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/DataTable.tsx +1 -19
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +11 -10
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +45 -16
- package/src/components/FileUpload/FileUpload.tsx +141 -130
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +13 -9
- package/src/hooks/useAddressAutocomplete.test.ts +18 -18
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +2 -1
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/hooks/useFileUrl.ts +52 -8
- package/src/hooks/useOrganisationSecurity.test.ts +2 -1
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
- package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
- package/src/rbac/api.test.ts +104 -0
- package/src/rbac/engine.ts +1 -1
- package/src/rbac/hooks/useCan.test.ts +2 -2
- package/src/rbac/secureClient.ts +1 -1
- package/src/rbac/types/functions.ts +1 -1
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +118 -3
- package/src/theming/parseEventColours.ts +77 -11
- package/src/types/supabase.ts +2 -3
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
- package/src/utils/formatting/formatDate.test.ts +3 -2
- package/src/utils/formatting/formatDateTime.test.ts +2 -2
- package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
- package/src/utils/storage/README.md +1 -1
- package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
- package/src/utils/storage/helpers.test.ts +69 -3
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce compliance with all pace-core standards across architecture, API, components, code style, security, testing, and RBAC/RLS
|
|
3
|
-
globs: ["src/**/*.{ts,tsx,js,jsx}", "supabase/migrations/**/*.sql"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
paceCoreVersion: "0.6.x"
|
|
6
|
-
rulesVersion: "2025-01-28"
|
|
7
|
-
---
|
|
8
|
-
# Standards Compliance Guide
|
|
9
|
-
|
|
10
|
-
This guide ensures consuming apps comply with all pace-core standards. Follow these standards to maintain quality, security, and consistency.
|
|
11
|
-
|
|
12
|
-
## MUST: Include Complete Cursor Ruleset
|
|
13
|
-
|
|
14
|
-
Consuming apps **MUST** include the complete pace-core ruleset in the repository so audits are deterministic and repeatable.
|
|
15
|
-
|
|
16
|
-
- **MUST** include these files under `.cursor/rules/` (exact filenames):
|
|
17
|
-
- `00-pace-core-compliance.mdc`
|
|
18
|
-
- `01-standards-compliance.mdc`
|
|
19
|
-
- `02-project-structure.mdc`
|
|
20
|
-
- `03-solid-principles.mdc`
|
|
21
|
-
- `06-code-quality.mdc`
|
|
22
|
-
- `07-tech-stack-compliance.mdc`
|
|
23
|
-
- `08-markup-quality.mdc`
|
|
24
|
-
- `09-rbac-compliance.mdc`
|
|
25
|
-
- `10-error-handling-patterns.mdc`
|
|
26
|
-
- `11-performance-optimization.mdc`
|
|
27
|
-
- **MUST NOT** rename or partially copy rules files.
|
|
28
|
-
- If a rule does not apply to a given app, document the exception and the reason, but keep the rule file present.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
## Architecture Standard
|
|
32
|
-
|
|
33
|
-
### MUST: Follow Architecture Principles
|
|
34
|
-
|
|
35
|
-
**MUST adhere to:**
|
|
36
|
-
- Composition over complexity
|
|
37
|
-
- Separation of concerns
|
|
38
|
-
- Domain-agnostic design
|
|
39
|
-
- Extensible, stable APIs
|
|
40
|
-
- Secure by default
|
|
41
|
-
- Performance-conscious
|
|
42
|
-
|
|
43
|
-
### MUST: Use Helper Functions in RLS Policies
|
|
44
|
-
|
|
45
|
-
**RLS policies MUST use helper functions, NEVER subqueries.**
|
|
46
|
-
|
|
47
|
-
```sql
|
|
48
|
-
-- ❌ WRONG: Subquery in RLS policy (causes N+1 queries)
|
|
49
|
-
CREATE POLICY rbac_select_users ON users FOR SELECT USING (
|
|
50
|
-
organisation_id IN (SELECT organisation_id FROM organisation_memberships WHERE user_id = auth.uid())
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
-- ✅ CORRECT: Helper function with STABLE SECURITY DEFINER
|
|
54
|
-
CREATE OR REPLACE FUNCTION get_user_organisation_ids() RETURNS uuid[] LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO public AS $$
|
|
55
|
-
BEGIN RETURN ARRAY(SELECT organisation_id FROM organisation_memberships WHERE user_id = get_effective_user_id()); END;
|
|
56
|
-
$$;
|
|
57
|
-
CREATE POLICY rbac_select_users ON users FOR SELECT USING (organisation_id = ANY(get_user_organisation_ids()));
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### MUST: Test Database Migrations
|
|
61
|
-
|
|
62
|
-
**MUST verify migrations don't cause query timeouts or performance degradation.**
|
|
63
|
-
|
|
64
|
-
## API & RPC Standard
|
|
65
|
-
|
|
66
|
-
### MUST: Follow RPC Naming Convention
|
|
67
|
-
|
|
68
|
-
**RPCs MUST follow pattern: `<family>_<domain>_<verb>`**
|
|
69
|
-
|
|
70
|
-
- `data_*` prefix for read operations: `data_cake_dishes_list`, `data_file_reference_list`
|
|
71
|
-
- `app_*` prefix for write operations: `app_cake_dish_create`, `app_cake_dish_update`
|
|
72
|
-
- CRUD verbs only: `create`, `read`, `update`, `delete`, `list`, `get`
|
|
73
|
-
- Bulk operations: `_bulk` suffix (e.g., `app_cake_dish_create_bulk`)
|
|
74
|
-
|
|
75
|
-
```sql
|
|
76
|
-
-- ✅ CORRECT: data_cake_dishes_list, app_cake_dish_create, app_cake_dish_create_bulk
|
|
77
|
-
-- ❌ WRONG: getDishes, create_dish (wrong naming pattern)
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### MUST: Use ApiResult Shape
|
|
81
|
-
|
|
82
|
-
**All RPCs MUST return ApiResult shape:**
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
type ApiResult<T> = { ok: true; data: T } | { ok: false; error: ApiError };
|
|
86
|
-
type ApiError = { code: string; message: string; details?: object };
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### MUST: Enforce RLS in RPCs
|
|
90
|
-
|
|
91
|
-
**RPCs MUST enforce RLS and tenant boundaries.** Never bypass RLS.
|
|
92
|
-
|
|
93
|
-
### SHOULD: Make Write RPCs Idempotent
|
|
94
|
-
|
|
95
|
-
**Write RPCs SHOULD be idempotent when possible.**
|
|
96
|
-
|
|
97
|
-
## Component Standard
|
|
98
|
-
|
|
99
|
-
### MUST: Follow Component Principles
|
|
100
|
-
|
|
101
|
-
**Components MUST:**
|
|
102
|
-
- Be stateless when possible
|
|
103
|
-
- Use composable structure
|
|
104
|
-
- Be accessible by default
|
|
105
|
-
- Be fully typed
|
|
106
|
-
- Have small surface area
|
|
107
|
-
|
|
108
|
-
### MUST NOT: Add Domain Logic to Components
|
|
109
|
-
|
|
110
|
-
**Components MUST NOT:**
|
|
111
|
-
- Include domain-specific logic
|
|
112
|
-
- Fetch data directly (use hooks/services)
|
|
113
|
-
- Include business workflows
|
|
114
|
-
|
|
115
|
-
### MUST: Ensure Accessibility
|
|
116
|
-
|
|
117
|
-
**Components MUST:**
|
|
118
|
-
- Be keyboard operable
|
|
119
|
-
- Have correct ARIA roles
|
|
120
|
-
- Have visible focus states
|
|
121
|
-
- Avoid inaccessible interactions
|
|
122
|
-
|
|
123
|
-
## Code Style Standard
|
|
124
|
-
|
|
125
|
-
### MUST: Follow TypeScript Rules
|
|
126
|
-
|
|
127
|
-
**MUST:**
|
|
128
|
-
- Use strict mode (`strict: true` in tsconfig)
|
|
129
|
-
- Prefer discriminated unions
|
|
130
|
-
- Use ReadonlyArray where possible
|
|
131
|
-
- Avoid boolean mode flags (use unions instead)
|
|
132
|
-
|
|
133
|
-
**MUST NOT:**
|
|
134
|
-
- Use `any` (use `unknown` if type is truly unknown)
|
|
135
|
-
- Use implicit any
|
|
136
|
-
- Use unnecessary type assertions
|
|
137
|
-
|
|
138
|
-
### MUST: Follow Naming Conventions
|
|
139
|
-
|
|
140
|
-
- Hooks: `useSomething`
|
|
141
|
-
- Providers: `SomethingProvider`
|
|
142
|
-
- Utilities: `camelCase`
|
|
143
|
-
- Components: `PascalCase`
|
|
144
|
-
|
|
145
|
-
### SHOULD: Use Preferred Patterns
|
|
146
|
-
|
|
147
|
-
**SHOULD:**
|
|
148
|
-
- Use pure functions
|
|
149
|
-
- Prefer composition over inheritance
|
|
150
|
-
- Use early returns
|
|
151
|
-
- Extract large functions into small helpers
|
|
152
|
-
|
|
153
|
-
## Security Standard
|
|
154
|
-
|
|
155
|
-
### MUST: Never Bypass RLS
|
|
156
|
-
|
|
157
|
-
**MUST enforce RLS on all tables.** Never bypass RLS policies.
|
|
158
|
-
|
|
159
|
-
### MUST: Validate All Inputs
|
|
160
|
-
|
|
161
|
-
**MUST validate all inputs using Zod schemas or similar.**
|
|
162
|
-
|
|
163
|
-
### MUST: Sanitize Logs
|
|
164
|
-
|
|
165
|
-
**MUST NOT log:**
|
|
166
|
-
- Passwords
|
|
167
|
-
- Tokens
|
|
168
|
-
- Sensitive data (PII)
|
|
169
|
-
|
|
170
|
-
**MAY log:**
|
|
171
|
-
- IDs
|
|
172
|
-
- Non-PII metadata
|
|
173
|
-
|
|
174
|
-
### MUST: Use Safe Error Messaging
|
|
175
|
-
|
|
176
|
-
**MUST NOT expose internal details in error messages.**
|
|
177
|
-
|
|
178
|
-
### MUST: Use Helper Functions in RLS
|
|
179
|
-
|
|
180
|
-
**RLS policies MUST use STABLE SECURITY DEFINER helper functions:**
|
|
181
|
-
- `STABLE` - Results consistent within transaction
|
|
182
|
-
- `SECURITY DEFINER` - Bypass RLS to avoid recursion
|
|
183
|
-
- `SET search_path TO 'public'` - Prevent search path injection
|
|
184
|
-
|
|
185
|
-
## Testing Standard
|
|
186
|
-
|
|
187
|
-
### MUST: Meet Coverage Requirements
|
|
188
|
-
|
|
189
|
-
**MUST achieve:**
|
|
190
|
-
- ≥90% coverage for utils & hooks
|
|
191
|
-
- ≥70% coverage for components
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
### MUST: Enforce Coverage Thresholds in Tooling
|
|
195
|
-
|
|
196
|
-
Coverage requirements must be **machine-enforced**, not aspirational:
|
|
197
|
-
|
|
198
|
-
- **MUST** provide a script: `npm run test:coverage`
|
|
199
|
-
- **MUST** configure the test runner (Vitest/Jest) to enforce the thresholds:
|
|
200
|
-
- ≥90% for utils & hooks
|
|
201
|
-
- ≥70% for components
|
|
202
|
-
- **MUST** fail the command when thresholds are not met (CI or local execution).
|
|
203
|
-
|
|
204
|
-
**Verification:**
|
|
205
|
-
- `npm run test:coverage` exits non-zero when below threshold.
|
|
206
|
-
- A coverage summary artifact is produced (e.g., `coverage/coverage-summary.json` or equivalent).
|
|
207
|
-
|
|
208
|
-
### MUST: Use React Testing Library
|
|
209
|
-
|
|
210
|
-
**MUST use React Testing Library + userEvent for component tests.**
|
|
211
|
-
|
|
212
|
-
### SHOULD: Colocate Tests
|
|
213
|
-
|
|
214
|
-
**Tests SHOULD be colocated: `*.test.ts` or `*.test.tsx`**
|
|
215
|
-
|
|
216
|
-
### SHOULD: Test Critical Paths
|
|
217
|
-
|
|
218
|
-
**SHOULD test:**
|
|
219
|
-
- Key user interactions
|
|
220
|
-
- Error handling
|
|
221
|
-
- Edge cases
|
|
222
|
-
- Critical business logic
|
|
223
|
-
|
|
224
|
-
## RBAC & RLS Standard
|
|
225
|
-
|
|
226
|
-
### MUST: Use Helper Functions
|
|
227
|
-
|
|
228
|
-
**All RLS policies MUST use helper functions with:**
|
|
229
|
-
- `STABLE` attribute
|
|
230
|
-
- `SECURITY DEFINER` attribute
|
|
231
|
-
- `SET search_path TO 'public'`
|
|
232
|
-
|
|
233
|
-
### MUST: Follow Policy Naming
|
|
234
|
-
|
|
235
|
-
**RLS policies MUST follow pattern: `rbac_{operation}_{table_name}_{scope}`**
|
|
236
|
-
|
|
237
|
-
Example: `rbac_select_users_organisation`
|
|
238
|
-
|
|
239
|
-
### MUST: Include Organisation Context
|
|
240
|
-
|
|
241
|
-
**RLS policies MUST include `organisation_id` for multi-tenant isolation.**
|
|
242
|
-
|
|
243
|
-
### MUST: Include Super Admin Checks
|
|
244
|
-
|
|
245
|
-
**RLS policies SHOULD include super admin checks where appropriate.**
|
|
246
|
-
|
|
247
|
-
## Standards Precedence
|
|
248
|
-
|
|
249
|
-
When standards conflict, follow this order:
|
|
250
|
-
1. Security Standard (highest priority)
|
|
251
|
-
2. API & RPC Standard
|
|
252
|
-
3. Component Standard
|
|
253
|
-
4. Code Style Standard
|
|
254
|
-
5. Testing Standard
|
|
255
|
-
6. Documentation Standard
|
|
256
|
-
|
|
257
|
-
## Compliance Checklist
|
|
258
|
-
|
|
259
|
-
Before committing code, verify:
|
|
260
|
-
- [ ] RLS policies use helper functions (no subqueries)
|
|
261
|
-
- [ ] RPCs follow naming convention
|
|
262
|
-
- [ ] Components are accessible and typed
|
|
263
|
-
- [ ] No `any` types used
|
|
264
|
-
- [ ] Inputs are validated
|
|
265
|
-
- [ ] Tests meet coverage requirements
|
|
266
|
-
- [ ] No sensitive data in logs
|
|
267
|
-
- [ ] Error messages are safe
|
|
268
|
-
|
|
269
|
-
## Reference
|
|
270
|
-
|
|
271
|
-
**📚 Human-Readable Standard**: See [01-standards-compliance.md](../../packages/core/docs/standards/01-standards-compliance.md) for complete documentation.
|
|
272
|
-
|
|
273
|
-
**Related Standards** (all have corresponding cursor rules):
|
|
274
|
-
- **00-pace-core-compliance.mdc** - pace-core usage patterns
|
|
275
|
-
- **02-project-structure.mdc** - Project structure and organization
|
|
276
|
-
- **03-solid-principles.mdc** - SOLID architecture principles
|
|
277
|
-
- **04-testing-standards.mdc** - Testing framework standards
|
|
278
|
-
- **05-bug-reports-and-features.mdc** - Issue reporting templates
|
|
279
|
-
- **06-code-quality.mdc** - Code quality and TypeScript standards
|
|
280
|
-
- **07-tech-stack-compliance.mdc** - Tech stack and API/RPC standards
|
|
281
|
-
- **08-markup-quality.mdc** - Markup and styling standards
|
|
282
|
-
- **09-rbac-compliance.mdc** - RBAC and RLS standards
|
|
283
|
-
- **10-error-handling-patterns.mdc** - Error handling patterns
|
|
284
|
-
- **11-performance-optimization.mdc** - Performance optimization
|
|
285
|
-
- **12-ci-cd-integration.mdc** - CI/CD integration patterns
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce testing framework consistency and standards for consuming apps
|
|
3
|
-
globs: ["**/*.{test,spec}.{ts,tsx}"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
paceCoreVersion: "0.6.x"
|
|
6
|
-
rulesVersion: "2025-01-28"
|
|
7
|
-
---
|
|
8
|
-
# Testing Standards Guide
|
|
9
|
-
|
|
10
|
-
**📚 Human-Readable Standard**: See [04-testing-standards.md](../../packages/core/docs/standards/04-testing-standards.md) for complete documentation.
|
|
11
|
-
|
|
12
|
-
This guide ensures consistent, high-quality testing across consuming apps in the PACE suite.
|
|
13
|
-
|
|
14
|
-
## MUST: Meet Coverage Requirements
|
|
15
|
-
|
|
16
|
-
**MUST achieve minimum coverage:**
|
|
17
|
-
- ≥90% coverage for utils & hooks
|
|
18
|
-
- ≥70% coverage for components
|
|
19
|
-
|
|
20
|
-
**Verify coverage:**
|
|
21
|
-
```bash
|
|
22
|
-
npm run test:coverage
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## MUST: Use React Testing Library
|
|
26
|
-
|
|
27
|
-
**MUST use React Testing Library + userEvent for all component tests.**
|
|
28
|
-
|
|
29
|
-
```tsx
|
|
30
|
-
// ✅ CORRECT: React Testing Library + userEvent
|
|
31
|
-
import { render, screen } from '@testing-library/react';
|
|
32
|
-
import userEvent from '@testing-library/user-event';
|
|
33
|
-
test('button clicks work', async () => {
|
|
34
|
-
const user = userEvent.setup();
|
|
35
|
-
const handleClick = vi.fn();
|
|
36
|
-
render(<Button onClick={handleClick}>Click me</Button>);
|
|
37
|
-
await user.click(screen.getByRole('button', { name: /click me/i }));
|
|
38
|
-
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// ❌ WRONG: Enzyme or other testing libraries
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## MUST: Colocate Tests
|
|
45
|
-
|
|
46
|
-
**Tests MUST be colocated with source files:**
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
src/
|
|
50
|
-
├── components/
|
|
51
|
-
│ └── EventCard/
|
|
52
|
-
│ ├── EventCard.tsx
|
|
53
|
-
│ └── EventCard.test.tsx
|
|
54
|
-
├── hooks/
|
|
55
|
-
│ ├── useEventData.ts
|
|
56
|
-
│ └── useEventData.test.ts
|
|
57
|
-
└── utils/
|
|
58
|
-
├── formatEvent.ts
|
|
59
|
-
└── formatEvent.test.ts
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## MUST: Use Vitest
|
|
63
|
-
|
|
64
|
-
**MUST use Vitest for all testing:**
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
// vitest.config.ts
|
|
68
|
-
import { defineConfig } from 'vitest/config';
|
|
69
|
-
|
|
70
|
-
export default defineConfig({
|
|
71
|
-
test: {
|
|
72
|
-
environment: 'jsdom',
|
|
73
|
-
setupFiles: ['./vitest.setup.ts'],
|
|
74
|
-
coverage: {
|
|
75
|
-
provider: 'v8',
|
|
76
|
-
reporter: ['text', 'json', 'html'],
|
|
77
|
-
thresholds: {
|
|
78
|
-
lines: 80,
|
|
79
|
-
functions: 80,
|
|
80
|
-
branches: 80,
|
|
81
|
-
statements: 80,
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## MUST: Test User Behavior, Not Implementation
|
|
89
|
-
|
|
90
|
-
**Tests MUST focus on what users see and do:**
|
|
91
|
-
|
|
92
|
-
```tsx
|
|
93
|
-
// ❌ WRONG: Testing implementation (component.state.count)
|
|
94
|
-
test('calls setState', () => { const component = render(<Counter />); expect(component.state.count).toBe(0); });
|
|
95
|
-
|
|
96
|
-
// ✅ CORRECT: Testing user behavior (what user sees and does)
|
|
97
|
-
test('displays count and increments on button click', async () => {
|
|
98
|
-
const user = userEvent.setup();
|
|
99
|
-
render(<Counter />);
|
|
100
|
-
expect(screen.getByText('Count: 0')).toBeInTheDocument();
|
|
101
|
-
await user.click(screen.getByRole('button', { name: /increment/i }));
|
|
102
|
-
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
103
|
-
});
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## MUST: Use Accessible Queries
|
|
107
|
-
|
|
108
|
-
**MUST prefer accessible queries (byRole, byLabelText, etc.):**
|
|
109
|
-
|
|
110
|
-
```tsx
|
|
111
|
-
// ✅ CORRECT: Accessible queries (byRole, byLabelText, byText)
|
|
112
|
-
screen.getByRole('button', { name: /submit/i });
|
|
113
|
-
screen.getByLabelText(/email address/i);
|
|
114
|
-
|
|
115
|
-
// ❌ AVOID: Non-accessible queries (getByTestId, getByClassName - use as last resort)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## SHOULD: Test Critical Paths
|
|
119
|
-
|
|
120
|
-
**SHOULD test:**
|
|
121
|
-
- User workflows and interactions
|
|
122
|
-
- Error handling and edge cases
|
|
123
|
-
- Form validation
|
|
124
|
-
- Permission checks (RBAC)
|
|
125
|
-
- Data loading states
|
|
126
|
-
- Error states
|
|
127
|
-
|
|
128
|
-
## SHOULD: Use Descriptive Test Names
|
|
129
|
-
|
|
130
|
-
**Test names SHOULD describe behavior:**
|
|
131
|
-
|
|
132
|
-
```tsx
|
|
133
|
-
// ❌ WRONG - Vague
|
|
134
|
-
test('button works', () => { ... });
|
|
135
|
-
|
|
136
|
-
// ✅ CORRECT - Descriptive
|
|
137
|
-
test('increments counter when increment button is clicked', () => { ... });
|
|
138
|
-
test('displays error message when API call fails', () => { ... });
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## SHOULD: Group Related Tests
|
|
142
|
-
|
|
143
|
-
**SHOULD use `describe` blocks to group related tests:**
|
|
144
|
-
|
|
145
|
-
```tsx
|
|
146
|
-
describe('EventCard', () => {
|
|
147
|
-
describe('rendering', () => {
|
|
148
|
-
test('displays event title', () => { ... });
|
|
149
|
-
test('displays event date', () => { ... });
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
describe('interactions', () => {
|
|
153
|
-
test('calls onEdit when edit button clicked', () => { ... });
|
|
154
|
-
test('calls onDelete when delete button clicked', () => { ... });
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## MUST: Avoid Unnecessary Mocks
|
|
160
|
-
|
|
161
|
-
**MUST NOT mock unless necessary:**
|
|
162
|
-
|
|
163
|
-
```tsx
|
|
164
|
-
// ❌ WRONG: Unnecessary mock (global.fetch = mockFetch)
|
|
165
|
-
// ✅ CORRECT: Use real implementation or MSW
|
|
166
|
-
import { server } from './mocks/server';
|
|
167
|
-
server.use(rest.get('/api/events', (req, res, ctx) => res(ctx.json([{ id: '1', name: 'Event' }]))));
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## MUST: Test Async Code Properly
|
|
171
|
-
|
|
172
|
-
**MUST handle async operations correctly:**
|
|
173
|
-
|
|
174
|
-
```tsx
|
|
175
|
-
// ✅ CORRECT: Async testing with waitFor
|
|
176
|
-
test('loads and displays events', async () => {
|
|
177
|
-
render(<EventList />);
|
|
178
|
-
expect(screen.getByText(/loading/i)).toBeInTheDocument();
|
|
179
|
-
await waitFor(() => expect(screen.getByText('Event 1')).toBeInTheDocument());
|
|
180
|
-
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
|
|
181
|
-
});
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## MUST: Clean Up After Tests
|
|
185
|
-
|
|
186
|
-
**MUST clean up resources:**
|
|
187
|
-
|
|
188
|
-
```tsx
|
|
189
|
-
// ✅ CORRECT: Cleanup after tests
|
|
190
|
-
afterEach(() => { cleanup(); vi.clearAllMocks(); });
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## SHOULD: Use Test Utilities
|
|
194
|
-
|
|
195
|
-
**SHOULD create reusable test utilities:**
|
|
196
|
-
|
|
197
|
-
```tsx
|
|
198
|
-
// ✅ CORRECT: Reusable test utilities
|
|
199
|
-
export function renderWithProviders(ui: React.ReactElement) {
|
|
200
|
-
return render(<UnifiedAuthProvider supabaseClient={mockSupabase} appName="Test App">{ui}</UnifiedAuthProvider>);
|
|
201
|
-
}
|
|
202
|
-
// Usage: renderWithProviders(<MyComponent />);
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## MUST: Include Timeout Parameters
|
|
206
|
-
|
|
207
|
-
**Tests MUST include timeout parameters to prevent hanging:**
|
|
208
|
-
|
|
209
|
-
```tsx
|
|
210
|
-
// ✅ CORRECT: Include timeout parameters to prevent hanging
|
|
211
|
-
test('async operation completes', async () => {
|
|
212
|
-
await waitFor(() => expect(screen.getByText('Loaded')).toBeInTheDocument(), { timeout: 5000 });
|
|
213
|
-
}, { timeout: 10000 });
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## Testing Checklist
|
|
217
|
-
|
|
218
|
-
Before committing tests, verify:
|
|
219
|
-
- [ ] Coverage meets requirements (≥90% utils, ≥70% components)
|
|
220
|
-
- [ ] Using React Testing Library + userEvent
|
|
221
|
-
- [ ] Tests are colocated with source files
|
|
222
|
-
- [ ] Testing user behavior, not implementation
|
|
223
|
-
- [ ] Using accessible queries (byRole, byLabelText)
|
|
224
|
-
- [ ] Test names are descriptive
|
|
225
|
-
- [ ] Related tests grouped with describe
|
|
226
|
-
- [ ] No unnecessary mocks
|
|
227
|
-
- [ ] Async code tested properly
|
|
228
|
-
- [ ] Cleanup after tests
|
|
229
|
-
- [ ] Timeout parameters included
|
|
230
|
-
|
|
231
|
-
## Test Structure Template
|
|
232
|
-
|
|
233
|
-
```tsx
|
|
234
|
-
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
235
|
-
import { render, screen, waitFor } from '@testing-library/react';
|
|
236
|
-
import userEvent from '@testing-library/user-event';
|
|
237
|
-
import { ComponentName } from './ComponentName';
|
|
238
|
-
|
|
239
|
-
describe('ComponentName', () => {
|
|
240
|
-
beforeEach(() => {
|
|
241
|
-
// Setup
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
afterEach(() => {
|
|
245
|
-
// Cleanup
|
|
246
|
-
vi.clearAllMocks();
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe('rendering', () => {
|
|
250
|
-
test('renders correctly', () => {
|
|
251
|
-
render(<ComponentName />);
|
|
252
|
-
// Assertions
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
describe('interactions', () => {
|
|
257
|
-
test('handles user interaction', async () => {
|
|
258
|
-
const user = userEvent.setup();
|
|
259
|
-
render(<ComponentName />);
|
|
260
|
-
// Test interaction
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## Reference
|
|
267
|
-
|
|
268
|
-
- React Testing Library: https://testing-library.com/react
|
|
269
|
-
- Vitest: https://vitest.dev
|
|
270
|
-
- Testing Standards: See `06-testing-and-docs-standard.md` in pace-core docs
|