@portnet/ui 6.0.1 → 6.0.2
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/CHANGELOG.md +85 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/v2/__tests__/FieldError.test.js +0 -1
- package/dist/esm/v2/__tests__/FieldError.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FieldWidth.test.js +146 -0
- package/dist/esm/v2/__tests__/FieldWidth.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FileCard.test.js +0 -1
- package/dist/esm/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js +265 -0
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js +248 -0
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FormikRadioGroup.test.js +380 -0
- package/dist/esm/v2/__tests__/FormikRadioGroup.test.js.map +1 -0
- package/dist/esm/v2/__tests__/MobileRowCard.test.js +0 -1
- package/dist/esm/v2/__tests__/MobileRowCard.test.js.map +1 -1
- package/dist/esm/v2/__tests__/SectionErrorBoundary.test.js.map +1 -1
- package/dist/esm/v2/__tests__/labels-merge.test.js +0 -1
- package/dist/esm/v2/__tests__/labels-merge.test.js.map +1 -1
- package/dist/esm/v2/components/DateTimePicker.js +37 -4
- package/dist/esm/v2/components/DateTimePicker.js.map +1 -1
- package/dist/esm/v2/components/Field.js +63 -1
- package/dist/esm/v2/components/Field.js.map +1 -1
- package/dist/esm/v2/components/index.js +27 -0
- package/dist/esm/v2/components/index.js.map +1 -1
- package/dist/esm/v2/index.js +12 -1
- package/dist/esm/v2/index.js.map +1 -1
- package/dist/esm/v2/patterns/FavoriteColumn.js +14 -61
- package/dist/esm/v2/patterns/FavoriteColumn.js.map +1 -1
- package/dist/esm/v2/patterns/FormikCheckbox.js +140 -0
- package/dist/esm/v2/patterns/FormikCheckbox.js.map +1 -0
- package/dist/esm/v2/patterns/FormikCombobox.js +5 -2
- package/dist/esm/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDatePicker.js +13 -47
- package/dist/esm/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDateTimePicker.js +150 -0
- package/dist/esm/v2/patterns/FormikDateTimePicker.js.map +1 -0
- package/dist/esm/v2/patterns/FormikInput.js +5 -2
- package/dist/esm/v2/patterns/FormikInput.js.map +1 -1
- package/dist/esm/v2/patterns/FormikRadioGroup.js +141 -0
- package/dist/esm/v2/patterns/FormikRadioGroup.js.map +1 -0
- package/dist/esm/v2/patterns/FormikSelect.js +5 -2
- package/dist/esm/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/esm/v2/patterns/FormikTextarea.js +5 -2
- package/dist/esm/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/esm/v2/patterns/KeyboardShortcutsHelp.js +25 -8
- package/dist/esm/v2/patterns/KeyboardShortcutsHelp.js.map +1 -1
- package/dist/esm/v2/patterns/RowFavoriteToggle.js +122 -0
- package/dist/esm/v2/patterns/RowFavoriteToggle.js.map +1 -0
- package/dist/esm/v2/patterns/_pickerSerialisation.js +74 -0
- package/dist/esm/v2/patterns/_pickerSerialisation.js.map +1 -0
- package/dist/esm/v2/patterns/index.js +83 -0
- package/dist/esm/v2/patterns/index.js.map +1 -1
- package/dist/esm/v2/personalization/capabilities/gridPreferences.js +209 -0
- package/dist/esm/v2/personalization/capabilities/gridPreferences.js.map +1 -0
- package/dist/esm/v2/personalization/capabilities/index.js +5 -0
- package/dist/esm/v2/personalization/capabilities/index.js.map +1 -1
- package/dist/esm/v2/personalization/index.js +18 -0
- package/dist/esm/v2/personalization/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/v2/__tests__/FieldError.test.js +26 -30
- package/dist/v2/__tests__/FieldError.test.js.map +1 -1
- package/dist/v2/__tests__/FieldWidth.test.js +150 -0
- package/dist/v2/__tests__/FieldWidth.test.js.map +1 -0
- package/dist/v2/__tests__/FileCard.test.js +25 -29
- package/dist/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/v2/__tests__/FormikCheckbox.test.js +268 -0
- package/dist/v2/__tests__/FormikCheckbox.test.js.map +1 -0
- package/dist/v2/__tests__/FormikDateTimePicker.test.js +247 -0
- package/dist/v2/__tests__/FormikDateTimePicker.test.js.map +1 -0
- package/dist/v2/__tests__/FormikRadioGroup.test.js +381 -0
- package/dist/v2/__tests__/FormikRadioGroup.test.js.map +1 -0
- package/dist/v2/__tests__/MobileRowCard.test.js +52 -56
- package/dist/v2/__tests__/MobileRowCard.test.js.map +1 -1
- package/dist/v2/__tests__/SectionErrorBoundary.test.js.map +1 -1
- package/dist/v2/__tests__/labels-merge.test.js +20 -24
- package/dist/v2/__tests__/labels-merge.test.js.map +1 -1
- package/dist/v2/components/DateTimePicker.d.ts.map +1 -1
- package/dist/v2/components/DateTimePicker.js +37 -4
- package/dist/v2/components/DateTimePicker.js.map +1 -1
- package/dist/v2/components/Field.d.ts +59 -1
- package/dist/v2/components/Field.d.ts.map +1 -1
- package/dist/v2/components/Field.js +62 -2
- package/dist/v2/components/Field.js.map +1 -1
- package/dist/v2/components/index.d.ts +27 -0
- package/dist/v2/components/index.d.ts.map +1 -1
- package/dist/v2/components/index.js.map +1 -1
- package/dist/v2/index.d.ts.map +1 -1
- package/dist/v2/index.js.map +1 -1
- package/dist/v2/patterns/FavoriteColumn.d.ts +9 -9
- package/dist/v2/patterns/FavoriteColumn.d.ts.map +1 -1
- package/dist/v2/patterns/FavoriteColumn.js +14 -61
- package/dist/v2/patterns/FavoriteColumn.js.map +1 -1
- package/dist/v2/patterns/FormikCheckbox.d.ts +77 -0
- package/dist/v2/patterns/FormikCheckbox.d.ts.map +1 -0
- package/dist/v2/patterns/FormikCheckbox.js +147 -0
- package/dist/v2/patterns/FormikCheckbox.js.map +1 -0
- package/dist/v2/patterns/FormikCombobox.d.ts +7 -1
- package/dist/v2/patterns/FormikCombobox.d.ts.map +1 -1
- package/dist/v2/patterns/FormikCombobox.js +5 -2
- package/dist/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/v2/patterns/FormikDatePicker.d.ts +13 -1
- package/dist/v2/patterns/FormikDatePicker.d.ts.map +1 -1
- package/dist/v2/patterns/FormikDatePicker.js +33 -66
- package/dist/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/v2/patterns/FormikDateTimePicker.d.ts +111 -0
- package/dist/v2/patterns/FormikDateTimePicker.d.ts.map +1 -0
- package/dist/v2/patterns/FormikDateTimePicker.js +158 -0
- package/dist/v2/patterns/FormikDateTimePicker.js.map +1 -0
- package/dist/v2/patterns/FormikInput.d.ts +11 -1
- package/dist/v2/patterns/FormikInput.d.ts.map +1 -1
- package/dist/v2/patterns/FormikInput.js +5 -2
- package/dist/v2/patterns/FormikInput.js.map +1 -1
- package/dist/v2/patterns/FormikRadioGroup.d.ts +80 -0
- package/dist/v2/patterns/FormikRadioGroup.d.ts.map +1 -0
- package/dist/v2/patterns/FormikRadioGroup.js +148 -0
- package/dist/v2/patterns/FormikRadioGroup.js.map +1 -0
- package/dist/v2/patterns/FormikSelect.d.ts +9 -1
- package/dist/v2/patterns/FormikSelect.d.ts.map +1 -1
- package/dist/v2/patterns/FormikSelect.js +5 -2
- package/dist/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/v2/patterns/FormikTextarea.d.ts +9 -1
- package/dist/v2/patterns/FormikTextarea.d.ts.map +1 -1
- package/dist/v2/patterns/FormikTextarea.js +5 -2
- package/dist/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.d.ts +14 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.d.ts.map +1 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.js +25 -8
- package/dist/v2/patterns/KeyboardShortcutsHelp.js.map +1 -1
- package/dist/v2/patterns/RowFavoriteToggle.d.ts +92 -0
- package/dist/v2/patterns/RowFavoriteToggle.d.ts.map +1 -0
- package/dist/v2/patterns/RowFavoriteToggle.js +127 -0
- package/dist/v2/patterns/RowFavoriteToggle.js.map +1 -0
- package/dist/v2/patterns/_pickerSerialisation.d.ts +44 -0
- package/dist/v2/patterns/_pickerSerialisation.d.ts.map +1 -0
- package/dist/v2/patterns/_pickerSerialisation.js +81 -0
- package/dist/v2/patterns/_pickerSerialisation.js.map +1 -0
- package/dist/v2/patterns/index.d.ts +87 -0
- package/dist/v2/patterns/index.d.ts.map +1 -1
- package/dist/v2/patterns/index.js +34 -0
- package/dist/v2/patterns/index.js.map +1 -1
- package/dist/v2/personalization/capabilities/gridPreferences.d.ts +100 -0
- package/dist/v2/personalization/capabilities/gridPreferences.d.ts.map +1 -0
- package/dist/v2/personalization/capabilities/gridPreferences.js +215 -0
- package/dist/v2/personalization/capabilities/gridPreferences.js.map +1 -0
- package/dist/v2/personalization/capabilities/index.d.ts +6 -0
- package/dist/v2/personalization/capabilities/index.d.ts.map +1 -1
- package/dist/v2/personalization/capabilities/index.js +13 -0
- package/dist/v2/personalization/capabilities/index.js.map +1 -1
- package/dist/v2/personalization/index.d.ts +18 -0
- package/dist/v2/personalization/index.d.ts.map +1 -1
- package/dist/v2/personalization/index.js +13 -0
- package/dist/v2/personalization/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -37,6 +37,8 @@ var _exportNames = {
|
|
|
37
37
|
FAVORITES_FILTER: true,
|
|
38
38
|
FAVORITES_SORT: true,
|
|
39
39
|
useSavedFilters: true,
|
|
40
|
+
useGridPreferences: true,
|
|
41
|
+
GRID_PREFERENCES_CAPABILITY_ID: true,
|
|
40
42
|
ReferentielProvider: true,
|
|
41
43
|
ReferentielContext: true,
|
|
42
44
|
useReferentielClient: true,
|
|
@@ -62,6 +64,12 @@ Object.defineProperty(exports, "FAVORITES_SORT", {
|
|
|
62
64
|
return _personalization.FAVORITES_SORT;
|
|
63
65
|
}
|
|
64
66
|
});
|
|
67
|
+
Object.defineProperty(exports, "GRID_PREFERENCES_CAPABILITY_ID", {
|
|
68
|
+
enumerable: true,
|
|
69
|
+
get: function get() {
|
|
70
|
+
return _personalization.GRID_PREFERENCES_CAPABILITY_ID;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
65
73
|
Object.defineProperty(exports, "MODAL_POPPER_PROPS", {
|
|
66
74
|
enumerable: true,
|
|
67
75
|
get: function get() {
|
|
@@ -236,6 +244,12 @@ Object.defineProperty(exports, "useFavoritesView", {
|
|
|
236
244
|
return _personalization.useFavoritesView;
|
|
237
245
|
}
|
|
238
246
|
});
|
|
247
|
+
Object.defineProperty(exports, "useGridPreferences", {
|
|
248
|
+
enumerable: true,
|
|
249
|
+
get: function get() {
|
|
250
|
+
return _personalization.useGridPreferences;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
239
253
|
Object.defineProperty(exports, "useIsFavorite", {
|
|
240
254
|
enumerable: true,
|
|
241
255
|
get: function get() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_components","require","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_patterns","_hooks","_theme","_utils","_SkeletonPageShell","_interopRequireDefault","_modalContext","_personalization","_referentiel","_models","_types","_v","_interopRequireWildcard","v2","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","_typeof","cache","has","newObj","hasPropertyDescriptor","getOwnPropertyDescriptor","desc","set"],"sources":["../src/lib/index.ts"],"sourcesContent":["/**\r\n * @portnet/ui — root entry (MUI v9)\r\n *\r\n * The v1 Pui* surface was REMOVED in 0.3.0-mui9. The package now\r\n * exposes the modernised v2 Design System directly at its root.\r\n *\r\n * Imports\r\n * -------\r\n *\r\n * // Components (flat — preferred)\r\n * import { Button, Modal, FormGrid, Combobox, ... } from \"@portnet/ui\";\r\n *\r\n * // Theme + CSS variables + tokens + hooks (flat, or subpath entrypoints)\r\n * import { createPortnetTheme, injectCssVariables } from \"@portnet/ui\";\r\n * import { palette, spacing } from \"@portnet/ui/tokens\";\r\n * import { useFocusTrap } from \"@portnet/ui/hooks\";\r\n *\r\n * // Misc utils (flat) — class names, money formatting, WCAG contrast,\r\n * // and base64 → browser download\r\n * import { cx, fmtMoney, contrast, downloadBase64File } from \"@portnet/ui\";\r\n *\r\n * // Modal layering constants (flat)\r\n * import { MODAL_POPPER_PROPS, MODAL_ZINDEX } from \"@portnet/ui\";\r\n *\r\n * // Personalization foundation (flat, or \"@portnet/ui/personalization\")\r\n * import { UserPersonalizationProvider, createLocalStorageAdapter } from \"@portnet/ui\";\r\n *\r\n * // Referentiel data layer (flat) — backs ReferentielField /\r\n * // FormikReferentielField. Mount the provider once at the app root.\r\n * import { ReferentielProvider, useReferentielSearch } from \"@portnet/ui\";\r\n *\r\n * // Domain models + UI types (flat, type-only)\r\n * import type { FavoriteItem, SavedFilter, GridColumn } from \"@portnet/ui\";\r\n *\r\n * // Legacy `@portnet/ui/v2/*` paths still resolve transitionally\r\n * // through the v2 re-export below, deprecated and scheduled for\r\n * // removal in 0.4.0. NOTE: capability added after that deprecation\r\n * // is surfaced flat ONLY and is deliberately absent from `v2.*`.\r\n *\r\n * No v1 surface remains. Consuming modules that still import any\r\n * Pui* component will fail to resolve and must migrate per the\r\n * table in docs/migration-mui9/03-batch3-purge-v1.md.\r\n */\r\n\r\n// Flat re-export of every v2 component, pattern, hook, and the\r\n// theme factory. This is what consuming modules pin against\r\n// (`import { Button } from \"@portnet/ui\"`).\r\nexport * from \"./v2/components\";\r\nexport * from \"./v2/patterns\";\r\nexport * from \"./v2/hooks\";\r\nexport {\r\n createPortnetTheme,\r\n getCssVariables,\r\n injectCssVariables,\r\n removeCssVariables,\r\n} from \"./v2/theme\";\r\n\r\n// Theme factory typed contract, flat + type-only (capability gap G-33).\r\n//\r\n// The theme VALUES were flat-exported above while the types describing their\r\n// options were reachable ONLY from the deprecated `@portnet/ui/v2` subpath.\r\n// Every host module wraps createPortnetTheme in a local `build<Module>Theme`\r\n// helper (see the GU modules' utils/appearance), so every host needs this\r\n// contract to type its own wrapper — and had exactly two ways to get it:\r\n// import from a surface scheduled for removal in 0.4.0, or fall back to\r\n// `brand?: object` + `as Parameters<typeof createPortnetTheme>[0]`, both on\r\n// the Platform TypeScript Guidelines FORBIDDEN list. ./v2/theme's own doc\r\n// comment already names that anti-pattern as the reason these types were\r\n// published; it just never reached the surface consumers are told to migrate\r\n// TO. Closing that here removes the last reason a module needs `@portnet/ui/v2`\r\n// for the theme layer.\r\n//\r\n// Flat-only, per the `v2` policy note at the bottom of this file.\r\n// Purely additive and type-only; nothing existing changed.\r\nexport type {\r\n CreatePortnetThemeOptions,\r\n BrandTokens,\r\n BrandSecondaryTokens,\r\n} from \"./v2/theme\";\r\n\r\n// Added while migrating ms-dfd-fe to TypeScript: cx / fmtMoney / contrast had\r\n// no flat or subpath route, only the deprecated `v2.*` namespace below.\r\n// downloadBase64File + getMimeType were added later (mjcc-fe Area 5) and are\r\n// flat-only by policy — see the note on `v2` at the bottom of this file.\r\n// Purely additive re-exports; nothing existing changed.\r\n//\r\n// G-34 (caution-ui Area 6) — openBase64FileInTab + downloadBlobFile added.\r\n// These two were NOT flat-only additions: ./v2/index.ts has exported them all\r\n// along, so the FLAT ROOT — the surface the policy at the bottom of this file\r\n// tells every module to migrate TO — was a strict SUBSET of the deprecated\r\n// surface it replaces. A module obeying the migration policy lost access to\r\n// both, which is how caution-ui's Area 6 build broke:\r\n//\r\n// Attempted import error: 'downloadBlobFile' is not exported\r\n// from '@portnet/ui'\r\n//\r\n// Root cause is mechanical, and worth fixing properly rather than name by name:\r\n// ./v2/components, ./v2/patterns and ./v2/hooks are re-exported above with\r\n// `export *`, so anything added to them surfaces automatically. ./v2/utils is\r\n// re-exported by EXPLICIT NAME LIST, so every new util silently fails to reach\r\n// consumers until someone hits a build error. A wildcard is not a safe swap\r\n// here — ./v2/utils also carries `mergeLabels`, an internal label-merging\r\n// helper with no host use case, and widening a certified public surface by\r\n// accident is worse than the drift. The list stays, and the invariant is stated\r\n// instead: ANY addition to ./v2/utils intended for hosts must be added here in\r\n// the same commit.\r\nexport {\r\n cx,\r\n fmtMoney,\r\n contrast,\r\n downloadBase64File,\r\n getMimeType,\r\n openBase64FileInTab,\r\n downloadBlobFile,\r\n} from \"./v2/utils\";\r\n\r\n// Error narrowing + the network-status channel. Flat-only per the `v2` policy\r\n// note at the bottom of this file. Both were added from the\r\n// procuration-portnet-fe Area 5 gap audit (G-04, G-03):\r\n//\r\n// - getApiErrorMessage / getApiErrorStatus close the hole between two rules\r\n// the platform imposes together — `useUnknownInCatchVariables` is mandatory\r\n// and `any` / unsafe assertions are forbidden, with nothing sanctioned in\r\n// between. Every audited module had bridged it with\r\n// `error as { response?: { data?: { message?: unknown } } }`.\r\n//\r\n// - networkStatus is the feed for NetworkErrorBanner, which shipped as a\r\n// presentational component with its trigger contract left to consumers.\r\n//\r\n// G-34 — getApiErrorDetail added. Its own docstring PRESCRIBES a pairing that\r\n// was impossible to write, because the companion was never surfaced:\r\n//\r\n// toast(getApiErrorMessage(err, \"Échec de l'envoi.\"), \"error\");\r\n// console.error(\"[submit]\", getApiErrorStatus(err), getApiErrorDetail(err));\r\n//\r\n// The split exists because getApiErrorMessage deliberately SUPPRESSES transport\r\n// phrasings (G-07) — right for a toast, wrong for a console or an APM\r\n// breadcrumb, where \"Request failed with status code 502\" is exactly what an\r\n// operator needs. Without the escape hatch a host either logs the sanitised\r\n// string (losing the diagnostic) or re-reads `error.message` by hand with an\r\n// assertion (the very thing G-04 exists to prevent).\r\n//\r\n// Purely additive; nothing existing changed.\r\nexport {\r\n getApiErrorMessage,\r\n getApiErrorDetail,\r\n getApiErrorStatus,\r\n DEFAULT_API_ERROR_MESSAGE,\r\n networkStatus,\r\n createNetworkStatus,\r\n} from \"./v2/utils\";\r\nexport type { NetworkStatus, NetworkStatusListener } from \"./v2/utils\";\r\n\r\n// Route-level Suspense fallback. R-P.1 MUST requires a \"fallback skeleton page\",\r\n// and the library had every skeleton PART plus PageBusy, but nothing satisfying\r\n// the rule: PageBusy is a full-screen spinner, which R-8.1 MUST forbids for\r\n// navigation. So every module hand-built one, and to avoid the CLS a skeleton\r\n// exists to prevent it had to copy ActionBar's and PageContent's padding\r\n// literals out of this library. Owning it here keeps the three in lockstep.\r\n// Capability gap G-02 (procuration-portnet-fe Area 5). Flat-only, per the policy\r\n// note below.\r\nexport { default as SkeletonPageShell } from \"./v2/patterns/SkeletonPageShell\";\r\nexport type {\r\n SkeletonPageShellProps,\r\n SkeletonPageShellVariant,\r\n} from \"./v2/patterns/SkeletonPageShell\";\r\n\r\n// Modal/Drawer/Combobox/DatePicker layering constants - needed by any\r\n// consumer stacking a popover-ish component (Combobox, DateTimePicker)\r\n// above a Modal or Drawer. Was v2-namespace-only.\r\nexport { MODAL_POPPER_PROPS, MODAL_ZINDEX } from \"./v2/modalContext\";\r\n\r\n// Personalization foundation runtime API (favorites, saved filters).\r\n// Named re-export, not a wildcard: ./v2/personalization also carries\r\n// the Scope/FavoriteRef/SavedFilter model types for its own internal\r\n// use, which are already flat-exported canonically via ./v2/models\r\n// below - a wildcard here would re-export them a second time and\r\n// collide (TS2308). Mirrors exactly what ./v2/index.ts already does\r\n// internally for the same reason.\r\nexport {\r\n UserPersonalizationProvider,\r\n createLocalStorageAdapter,\r\n createMemoryAdapter,\r\n registerCapability,\r\n useFavorites,\r\n useIsFavorite,\r\n useFavoritesView,\r\n filterRowsByFavorites,\r\n sortRowsByFavorites,\r\n FAVORITES_FILTER,\r\n FAVORITES_SORT,\r\n useSavedFilters,\r\n} from \"./v2/personalization\";\r\n\r\n// Referentiel data layer runtime API (config provider + hooks). Backs\r\n// ReferentielField / FormikReferentielField, which are flat-exported\r\n// above via ./v2/patterns - the field UI was reachable while the data\r\n// layer that feeds it was not, so consumers had to either import from\r\n// the deprecated `@portnet/ui/v2` surface or rebuild the client\r\n// locally. Added while auditing mjcc-fe, which had done the latter.\r\n//\r\n// Named re-export, not a wildcard, for the SAME reason as\r\n// personalization above: ./v2/referentiel also re-exports\r\n// ReferentielSearchArgs, ReferentielSearchResult and\r\n// ReferentielSearchFn for its own use, and those names are already\r\n// flat-exported canonically through ./v2/models below. A wildcard\r\n// would export them twice and collide (TS2308). The type layer keeps\r\n// its single canonical route.\r\nexport {\r\n ReferentielProvider,\r\n ReferentielContext,\r\n useReferentielClient,\r\n useReferentielOptions,\r\n useReferentielSearch,\r\n} from \"./v2/referentiel\";\r\n\r\n// Domain models & shared UI/structural types, flat + type-only (no\r\n// runtime cost). Mirrors the same re-export already done inside\r\n// ./v2 — added here so consumers migrating off `v2.*` have a route\r\n// to the shared types the platform guidelines require reusing\r\n// (DrawerProps, FavoriteItem, SavedFilter, GridColumn, GridAction,\r\n// WizardStep, Notification, FormField, etc.) without falling back to\r\n// the deprecated namespace just to get a type import. Conflicting\r\n// names across the two star-exports are omitted per ES module\r\n// semantics rather than erroring.\r\nexport * from \"./v2/models\";\r\nexport * from \"./v2/types\";\r\n\r\n// Transitional alias — the `@portnet/ui/v2` subpath kept resolving\r\n// for one minor cycle so consuming modules can migrate their\r\n// imports independently of the package bump. Scheduled removal:\r\n// 0.4.0. Track removal in the Batch 5 cleanup ticket.\r\n//\r\n// POLICY: capability added after this deprecation is surfaced on the\r\n// flat root ONLY and is not added to ./v2/index.ts — adding it there\r\n// would hand consumers a new reason to stay on a retiring surface.\r\n// downloadBase64File / getMimeType are the first such additions.\r\n//\r\n// COROLLARY, learned the hard way (G-34): the policy only works if the flat\r\n// root is a strict SUPERSET of ./v2. It was not — downloadBlobFile and\r\n// openBase64FileInTab were on v2 and missing here, so \"migrate off v2\" meant\r\n// \"lose two utilities\". Before deprecating anything further, diff the two\r\n// surfaces; `npm run api:check` covers the root but does not compare it against\r\n// ./v2.\r\nexport * as v2 from \"./v2\";\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_components","require","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_patterns","_hooks","_theme","_utils","_SkeletonPageShell","_interopRequireDefault","_modalContext","_personalization","_referentiel","_models","_types","_v","_interopRequireWildcard","v2","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","_typeof","cache","has","newObj","hasPropertyDescriptor","getOwnPropertyDescriptor","desc","set"],"sources":["../src/lib/index.ts"],"sourcesContent":["/**\r\n * @portnet/ui — root entry (MUI v9)\r\n *\r\n * The v1 Pui* surface was REMOVED in 0.3.0-mui9. The package now\r\n * exposes the modernised v2 Design System directly at its root.\r\n *\r\n * Imports\r\n * -------\r\n *\r\n * // Components (flat — preferred)\r\n * import { Button, Modal, FormGrid, Combobox, ... } from \"@portnet/ui\";\r\n *\r\n * // Theme + CSS variables + tokens + hooks (flat, or subpath entrypoints)\r\n * import { createPortnetTheme, injectCssVariables } from \"@portnet/ui\";\r\n * import { palette, spacing } from \"@portnet/ui/tokens\";\r\n * import { useFocusTrap } from \"@portnet/ui/hooks\";\r\n *\r\n * // Misc utils (flat) — class names, money formatting, WCAG contrast,\r\n * // and base64 → browser download\r\n * import { cx, fmtMoney, contrast, downloadBase64File } from \"@portnet/ui\";\r\n *\r\n * // Modal layering constants (flat)\r\n * import { MODAL_POPPER_PROPS, MODAL_ZINDEX } from \"@portnet/ui\";\r\n *\r\n * // Personalization foundation (flat, or \"@portnet/ui/personalization\")\r\n * import { UserPersonalizationProvider, createLocalStorageAdapter } from \"@portnet/ui\";\r\n *\r\n * // Referentiel data layer (flat) — backs ReferentielField /\r\n * // FormikReferentielField. Mount the provider once at the app root.\r\n * import { ReferentielProvider, useReferentielSearch } from \"@portnet/ui\";\r\n *\r\n * // Domain models + UI types (flat, type-only)\r\n * import type { FavoriteItem, SavedFilter, GridColumn } from \"@portnet/ui\";\r\n *\r\n * // Legacy `@portnet/ui/v2/*` paths still resolve transitionally\r\n * // through the v2 re-export below, deprecated and scheduled for\r\n * // removal in 0.4.0. NOTE: capability added after that deprecation\r\n * // is surfaced flat ONLY and is deliberately absent from `v2.*`.\r\n *\r\n * No v1 surface remains. Consuming modules that still import any\r\n * Pui* component will fail to resolve and must migrate per the\r\n * table in docs/migration-mui9/03-batch3-purge-v1.md.\r\n */\r\n\r\n// Flat re-export of every v2 component, pattern, hook, and the\r\n// theme factory. This is what consuming modules pin against\r\n// (`import { Button } from \"@portnet/ui\"`).\r\nexport * from \"./v2/components\";\r\nexport * from \"./v2/patterns\";\r\nexport * from \"./v2/hooks\";\r\nexport {\r\n createPortnetTheme,\r\n getCssVariables,\r\n injectCssVariables,\r\n removeCssVariables,\r\n} from \"./v2/theme\";\r\n\r\n// Theme factory typed contract, flat + type-only (capability gap G-33).\r\n//\r\n// The theme VALUES were flat-exported above while the types describing their\r\n// options were reachable ONLY from the deprecated `@portnet/ui/v2` subpath.\r\n// Every host module wraps createPortnetTheme in a local `build<Module>Theme`\r\n// helper (see the GU modules' utils/appearance), so every host needs this\r\n// contract to type its own wrapper — and had exactly two ways to get it:\r\n// import from a surface scheduled for removal in 0.4.0, or fall back to\r\n// `brand?: object` + `as Parameters<typeof createPortnetTheme>[0]`, both on\r\n// the Platform TypeScript Guidelines FORBIDDEN list. ./v2/theme's own doc\r\n// comment already names that anti-pattern as the reason these types were\r\n// published; it just never reached the surface consumers are told to migrate\r\n// TO. Closing that here removes the last reason a module needs `@portnet/ui/v2`\r\n// for the theme layer.\r\n//\r\n// Flat-only, per the `v2` policy note at the bottom of this file.\r\n// Purely additive and type-only; nothing existing changed.\r\nexport type {\r\n CreatePortnetThemeOptions,\r\n BrandTokens,\r\n BrandSecondaryTokens,\r\n} from \"./v2/theme\";\r\n\r\n// Added while migrating ms-dfd-fe to TypeScript: cx / fmtMoney / contrast had\r\n// no flat or subpath route, only the deprecated `v2.*` namespace below.\r\n// downloadBase64File + getMimeType were added later (mjcc-fe Area 5) and are\r\n// flat-only by policy — see the note on `v2` at the bottom of this file.\r\n// Purely additive re-exports; nothing existing changed.\r\n//\r\n// G-34 (caution-ui Area 6) — openBase64FileInTab + downloadBlobFile added.\r\n// These two were NOT flat-only additions: ./v2/index.ts has exported them all\r\n// along, so the FLAT ROOT — the surface the policy at the bottom of this file\r\n// tells every module to migrate TO — was a strict SUBSET of the deprecated\r\n// surface it replaces. A module obeying the migration policy lost access to\r\n// both, which is how caution-ui's Area 6 build broke:\r\n//\r\n// Attempted import error: 'downloadBlobFile' is not exported\r\n// from '@portnet/ui'\r\n//\r\n// Root cause is mechanical, and worth fixing properly rather than name by name:\r\n// ./v2/components, ./v2/patterns and ./v2/hooks are re-exported above with\r\n// `export *`, so anything added to them surfaces automatically. ./v2/utils is\r\n// re-exported by EXPLICIT NAME LIST, so every new util silently fails to reach\r\n// consumers until someone hits a build error. A wildcard is not a safe swap\r\n// here — ./v2/utils also carries `mergeLabels`, an internal label-merging\r\n// helper with no host use case, and widening a certified public surface by\r\n// accident is worse than the drift. The list stays, and the invariant is stated\r\n// instead: ANY addition to ./v2/utils intended for hosts must be added here in\r\n// the same commit.\r\nexport {\r\n cx,\r\n fmtMoney,\r\n contrast,\r\n downloadBase64File,\r\n getMimeType,\r\n openBase64FileInTab,\r\n downloadBlobFile,\r\n} from \"./v2/utils\";\r\n\r\n// Error narrowing + the network-status channel. Flat-only per the `v2` policy\r\n// note at the bottom of this file. Both were added from the\r\n// procuration-portnet-fe Area 5 gap audit (G-04, G-03):\r\n//\r\n// - getApiErrorMessage / getApiErrorStatus close the hole between two rules\r\n// the platform imposes together — `useUnknownInCatchVariables` is mandatory\r\n// and `any` / unsafe assertions are forbidden, with nothing sanctioned in\r\n// between. Every audited module had bridged it with\r\n// `error as { response?: { data?: { message?: unknown } } }`.\r\n//\r\n// - networkStatus is the feed for NetworkErrorBanner, which shipped as a\r\n// presentational component with its trigger contract left to consumers.\r\n//\r\n// G-34 — getApiErrorDetail added. Its own docstring PRESCRIBES a pairing that\r\n// was impossible to write, because the companion was never surfaced:\r\n//\r\n// toast(getApiErrorMessage(err, \"Échec de l'envoi.\"), \"error\");\r\n// console.error(\"[submit]\", getApiErrorStatus(err), getApiErrorDetail(err));\r\n//\r\n// The split exists because getApiErrorMessage deliberately SUPPRESSES transport\r\n// phrasings (G-07) — right for a toast, wrong for a console or an APM\r\n// breadcrumb, where \"Request failed with status code 502\" is exactly what an\r\n// operator needs. Without the escape hatch a host either logs the sanitised\r\n// string (losing the diagnostic) or re-reads `error.message` by hand with an\r\n// assertion (the very thing G-04 exists to prevent).\r\n//\r\n// Purely additive; nothing existing changed.\r\nexport {\r\n getApiErrorMessage,\r\n getApiErrorDetail,\r\n getApiErrorStatus,\r\n DEFAULT_API_ERROR_MESSAGE,\r\n networkStatus,\r\n createNetworkStatus,\r\n} from \"./v2/utils\";\r\nexport type { NetworkStatus, NetworkStatusListener } from \"./v2/utils\";\r\n\r\n// Route-level Suspense fallback. R-P.1 MUST requires a \"fallback skeleton page\",\r\n// and the library had every skeleton PART plus PageBusy, but nothing satisfying\r\n// the rule: PageBusy is a full-screen spinner, which R-8.1 MUST forbids for\r\n// navigation. So every module hand-built one, and to avoid the CLS a skeleton\r\n// exists to prevent it had to copy ActionBar's and PageContent's padding\r\n// literals out of this library. Owning it here keeps the three in lockstep.\r\n// Capability gap G-02 (procuration-portnet-fe Area 5). Flat-only, per the policy\r\n// note below.\r\nexport { default as SkeletonPageShell } from \"./v2/patterns/SkeletonPageShell\";\r\nexport type {\r\n SkeletonPageShellProps,\r\n SkeletonPageShellVariant,\r\n} from \"./v2/patterns/SkeletonPageShell\";\r\n\r\n// Modal/Drawer/Combobox/DatePicker layering constants - needed by any\r\n// consumer stacking a popover-ish component (Combobox, DateTimePicker)\r\n// above a Modal or Drawer. Was v2-namespace-only.\r\nexport { MODAL_POPPER_PROPS, MODAL_ZINDEX } from \"./v2/modalContext\";\r\n\r\n// Personalization foundation runtime API (favorites, saved filters).\r\n// Named re-export, not a wildcard: ./v2/personalization also carries\r\n// the Scope/FavoriteRef/SavedFilter model types for its own internal\r\n// use, which are already flat-exported canonically via ./v2/models\r\n// below - a wildcard here would re-export them a second time and\r\n// collide (TS2308). Mirrors exactly what ./v2/index.ts already does\r\n// internally for the same reason.\r\nexport {\r\n UserPersonalizationProvider,\r\n createLocalStorageAdapter,\r\n createMemoryAdapter,\r\n registerCapability,\r\n useFavorites,\r\n useIsFavorite,\r\n useFavoritesView,\r\n filterRowsByFavorites,\r\n sortRowsByFavorites,\r\n FAVORITES_FILTER,\r\n FAVORITES_SORT,\r\n useSavedFilters,\r\n} from \"./v2/personalization\";\r\n\r\n// Grid preferences capability (gap G-35) — per-user, per-resource hidden\r\n// columns. FLAT-ONLY, per the policy note on `v2` at the bottom of this file:\r\n// deliberately NOT added to ./v2/index.ts.\r\n//\r\n// DataGridToolbar owns the column-visibility UI but holds no state, so hosts\r\n// persisted it themselves in a bare localStorage key — not user-scoped, unlike\r\n// this foundation's `…:{userId}:{capabilityId}` scheme, so on a shared\r\n// workstation one user inherited another's hidden columns. Observed in\r\n// onssa-export-fe (\"onssaCertificates:listing:hiddenColumns\").\r\n//\r\n// It had to land in the library rather than the host: `registerCapability` is\r\n// exported above as a seam \"for custom/host-defined capabilities\", but the two\r\n// primitives a capability hook needs (usePersonalizationStore,\r\n// useStoreSelector) are private by design (§2.8, minimum API surface), so a\r\n// host-registered capability could be declared and never read or written.\r\n// Completing that seam instead would widen the internal surface AND leave every\r\n// module re-authoring the same slice; owning the slice here does neither.\r\nexport {\r\n useGridPreferences,\r\n GRID_PREFERENCES_CAPABILITY_ID,\r\n} from \"./v2/personalization\";\r\nexport type {\r\n UseGridPreferencesResult,\r\n GridPreferencesEntry,\r\n} from \"./v2/personalization\";\r\n\r\n// Referentiel data layer runtime API (config provider + hooks). Backs\r\n// ReferentielField / FormikReferentielField, which are flat-exported\r\n// above via ./v2/patterns - the field UI was reachable while the data\r\n// layer that feeds it was not, so consumers had to either import from\r\n// the deprecated `@portnet/ui/v2` surface or rebuild the client\r\n// locally. Added while auditing mjcc-fe, which had done the latter.\r\n//\r\n// Named re-export, not a wildcard, for the SAME reason as\r\n// personalization above: ./v2/referentiel also re-exports\r\n// ReferentielSearchArgs, ReferentielSearchResult and\r\n// ReferentielSearchFn for its own use, and those names are already\r\n// flat-exported canonically through ./v2/models below. A wildcard\r\n// would export them twice and collide (TS2308). The type layer keeps\r\n// its single canonical route.\r\nexport {\r\n ReferentielProvider,\r\n ReferentielContext,\r\n useReferentielClient,\r\n useReferentielOptions,\r\n useReferentielSearch,\r\n} from \"./v2/referentiel\";\r\n\r\n// Domain models & shared UI/structural types, flat + type-only (no\r\n// runtime cost). Mirrors the same re-export already done inside\r\n// ./v2 — added here so consumers migrating off `v2.*` have a route\r\n// to the shared types the platform guidelines require reusing\r\n// (DrawerProps, FavoriteItem, SavedFilter, GridColumn, GridAction,\r\n// WizardStep, Notification, FormField, etc.) without falling back to\r\n// the deprecated namespace just to get a type import. Conflicting\r\n// names across the two star-exports are omitted per ES module\r\n// semantics rather than erroring.\r\nexport * from \"./v2/models\";\r\nexport * from \"./v2/types\";\r\n\r\n// Transitional alias — the `@portnet/ui/v2` subpath kept resolving\r\n// for one minor cycle so consuming modules can migrate their\r\n// imports independently of the package bump. Scheduled removal:\r\n// 0.4.0. Track removal in the Batch 5 cleanup ticket.\r\n//\r\n// POLICY: capability added after this deprecation is surfaced on the\r\n// flat root ONLY and is not added to ./v2/index.ts — adding it there\r\n// would hand consumers a new reason to stay on a retiring surface.\r\n// downloadBase64File / getMimeType are the first such additions.\r\n//\r\n// COROLLARY, learned the hard way (G-34): the policy only works if the flat\r\n// root is a strict SUPERSET of ./v2. It was not — downloadBlobFile and\r\n// openBase64FileInTab were on v2 and missing here, so \"migrate off v2\" meant\r\n// \"lose two utilities\". Before deprecating anything further, diff the two\r\n// surfaces; `npm run api:check` covers the root but does not compare it against\r\n// ./v2.\r\nexport * as v2 from \"./v2\";\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
3
|
require("@testing-library/jest-dom");
|
|
5
|
-
var
|
|
6
|
-
var _react2 = require("@testing-library/react");
|
|
4
|
+
var _react = require("@testing-library/react");
|
|
7
5
|
var _FieldError = _interopRequireDefault(require("../components/FieldError"));
|
|
8
6
|
var _Field = _interopRequireDefault(require("../components/Field"));
|
|
9
7
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
11
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
12
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
13
9
|
/**
|
|
14
10
|
* FieldError — contract tests, including its integration into Field.
|
|
15
11
|
*
|
|
@@ -36,60 +32,60 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
36
32
|
* FieldError.stories.tsx.
|
|
37
33
|
*/describe("FieldError — standalone", function () {
|
|
38
34
|
test("announces itself as an alert carrying the message", function () {
|
|
39
|
-
(0,
|
|
35
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_FieldError["default"], {
|
|
40
36
|
children: "Ajoutez au moins un article avant de soumettre."
|
|
41
37
|
}));
|
|
42
|
-
expect(
|
|
38
|
+
expect(_react.screen.getByRole("alert")).toHaveTextContent("Ajoutez au moins un article avant de soumettre.");
|
|
43
39
|
});
|
|
44
40
|
test("forwards id so a host can wire its own aria-describedby", function () {
|
|
45
|
-
(0,
|
|
41
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_FieldError["default"], {
|
|
46
42
|
id: "articles-error",
|
|
47
43
|
children: "Ajoutez au moins un article."
|
|
48
44
|
}));
|
|
49
|
-
expect(
|
|
45
|
+
expect(_react.screen.getByRole("alert")).toHaveAttribute("id", "articles-error");
|
|
50
46
|
});
|
|
51
47
|
test("omits id when none is supplied", function () {
|
|
52
48
|
/* The list-level case usually has nothing to bind to. Emitting an empty or
|
|
53
49
|
* generated id would create a describedby target nobody references. */
|
|
54
|
-
(0,
|
|
50
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_FieldError["default"], {
|
|
55
51
|
children: "Ajoutez au moins un article."
|
|
56
52
|
}));
|
|
57
|
-
expect(
|
|
53
|
+
expect(_react.screen.getByRole("alert")).not.toHaveAttribute("id");
|
|
58
54
|
});
|
|
59
55
|
test("the icon is hidden from assistive tech", function () {
|
|
60
56
|
/* R-Ar.2 — the message IS the announcement; an announced glyph would double
|
|
61
57
|
* it. No semantic query reaches a role-less, name-less element, hence the
|
|
62
58
|
* testid the component exposes for exactly this assertion. */
|
|
63
|
-
(0,
|
|
59
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_FieldError["default"], {
|
|
64
60
|
children: "Message"
|
|
65
61
|
}));
|
|
66
|
-
expect(
|
|
62
|
+
expect(_react.screen.getByTestId("fielderror-icon")).toHaveAttribute("aria-hidden", "true");
|
|
67
63
|
});
|
|
68
64
|
});
|
|
69
65
|
describe("FieldError — inside Field (the wiring that has no visual tell)", function () {
|
|
70
66
|
test("the error becomes the control's accessible description", function () {
|
|
71
|
-
(0,
|
|
67
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
72
68
|
label: "Num\xE9ro de titre",
|
|
73
69
|
error: "Le num\xE9ro est invalide. Format : AAAA-IM-NNNNN.",
|
|
74
70
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
75
71
|
}));
|
|
76
|
-
expect(
|
|
72
|
+
expect(_react.screen.getByRole("textbox")).toHaveAccessibleDescription("Le numéro est invalide. Format : AAAA-IM-NNNNN.");
|
|
77
73
|
});
|
|
78
74
|
test("the control is marked invalid", function () {
|
|
79
|
-
(0,
|
|
75
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
80
76
|
label: "Num\xE9ro",
|
|
81
77
|
error: "Invalide.",
|
|
82
78
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
83
79
|
}));
|
|
84
80
|
// jest-dom's toBeInvalid reads aria-invalid — R-I.3.
|
|
85
|
-
expect(
|
|
81
|
+
expect(_react.screen.getByRole("textbox")).toBeInvalid();
|
|
86
82
|
});
|
|
87
83
|
test("a host-supplied aria-describedby is PRESERVED, not replaced", function () {
|
|
88
84
|
/* The merge is the fragile part. Overwriting instead of merging silently
|
|
89
85
|
* drops a consumer's external help text, and again nothing visual changes.
|
|
90
86
|
* Asserted with two order-independent regexes rather than one exact string,
|
|
91
87
|
* so the test does not encode which fragment Field puts first. */
|
|
92
|
-
(0,
|
|
88
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
93
89
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
94
90
|
id: "host-help",
|
|
95
91
|
children: "Format attendu : AAAA-IM-NNNNN."
|
|
@@ -101,28 +97,28 @@ describe("FieldError — inside Field (the wiring that has no visual tell)", fun
|
|
|
101
97
|
})
|
|
102
98
|
})]
|
|
103
99
|
}));
|
|
104
|
-
var input =
|
|
100
|
+
var input = _react.screen.getByRole("textbox");
|
|
105
101
|
expect(input).toHaveAccessibleDescription(/Format attendu/);
|
|
106
102
|
expect(input).toHaveAccessibleDescription(/incomplet/);
|
|
107
103
|
});
|
|
108
104
|
test("the hint is suppressed while an error is shown", function () {
|
|
109
105
|
/* Two competing descriptions under one field is worse than one. The hint
|
|
110
106
|
* returns once the error clears — verified by the rerender below. */
|
|
111
|
-
var _render = (0,
|
|
107
|
+
var _render = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
112
108
|
label: "Num\xE9ro",
|
|
113
109
|
hint: "Format : AAAA-IM-NNNNN",
|
|
114
110
|
error: "Le num\xE9ro est incomplet.",
|
|
115
111
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
116
112
|
})),
|
|
117
113
|
rerender = _render.rerender;
|
|
118
|
-
expect(
|
|
119
|
-
expect(
|
|
114
|
+
expect(_react.screen.getByRole("alert")).toHaveTextContent("Le numéro est incomplet.");
|
|
115
|
+
expect(_react.screen.queryByText("Format : AAAA-IM-NNNNN")).not.toBeInTheDocument();
|
|
120
116
|
rerender(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
121
117
|
label: "Num\xE9ro",
|
|
122
118
|
hint: "Format : AAAA-IM-NNNNN",
|
|
123
119
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
124
120
|
}));
|
|
125
|
-
expect(
|
|
121
|
+
expect(_react.screen.getByText("Format : AAAA-IM-NNNNN")).toBeInTheDocument();
|
|
126
122
|
});
|
|
127
123
|
});
|
|
128
124
|
describe("FieldError — live-region mounting contract", function () {
|
|
@@ -132,33 +128,33 @@ describe("FieldError — live-region mounting contract", function () {
|
|
|
132
128
|
* a well-meaning refactor that always renders the container — to \"avoid
|
|
133
129
|
* layout shift\", say — silently kills the announcement while every pixel
|
|
134
130
|
* and every screenshot stays identical. */
|
|
135
|
-
var _render2 = (0,
|
|
131
|
+
var _render2 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
136
132
|
label: "Num\xE9ro",
|
|
137
133
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
138
134
|
})),
|
|
139
135
|
rerender = _render2.rerender;
|
|
140
|
-
expect(
|
|
136
|
+
expect(_react.screen.queryByRole("alert")).not.toBeInTheDocument();
|
|
141
137
|
rerender(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
142
138
|
label: "Num\xE9ro",
|
|
143
139
|
error: "Le num\xE9ro est incomplet.",
|
|
144
140
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
145
141
|
}));
|
|
146
|
-
expect(
|
|
142
|
+
expect(_react.screen.getByRole("alert")).toBeInTheDocument();
|
|
147
143
|
});
|
|
148
144
|
test("the alert unmounts when the error clears", function () {
|
|
149
|
-
var _render3 = (0,
|
|
145
|
+
var _render3 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
150
146
|
label: "Num\xE9ro",
|
|
151
147
|
error: "Le num\xE9ro est incomplet.",
|
|
152
148
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
153
149
|
})),
|
|
154
150
|
rerender = _render3.rerender;
|
|
155
|
-
expect(
|
|
151
|
+
expect(_react.screen.getByRole("alert")).toBeInTheDocument();
|
|
156
152
|
rerender(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
157
153
|
label: "Num\xE9ro",
|
|
158
154
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {})
|
|
159
155
|
}));
|
|
160
|
-
expect(
|
|
161
|
-
expect(
|
|
156
|
+
expect(_react.screen.queryByRole("alert")).not.toBeInTheDocument();
|
|
157
|
+
expect(_react.screen.getByRole("textbox")).not.toBeInvalid();
|
|
162
158
|
});
|
|
163
159
|
});
|
|
164
160
|
//# sourceMappingURL=FieldError.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldError.test.js","names":["require","React","_interopRequireWildcard","_react2","_FieldError","_interopRequireDefault","_Field","_jsxRuntime","obj","__esModule","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","_typeof","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","describe","test","render","jsx","children","expect","screen","getByRole","toHaveTextContent","id","toHaveAttribute","not","getByTestId","label","error","toHaveAccessibleDescription","toBeInvalid","jsxs","Fragment","input","_render","hint","rerender","queryByText","toBeInTheDocument","getByText","_render2","queryByRole","_render3"],"sources":["../../../src/lib/v2/__tests__/FieldError.test.tsx"],"sourcesContent":["import \"@testing-library/jest-dom\";\r\nimport * as React from \"react\";\r\nimport { render, screen } from \"@testing-library/react\";\r\nimport FieldError from \"../components/FieldError\";\r\nimport Field from \"../components/Field\";\r\n\r\n/**\r\n * FieldError — contract tests, including its integration into Field.\r\n *\r\n * WHY THIS FILE EXISTS\r\n * --------------------\r\n * §10.3 R-G.6 MUST. But the real reason is narrower and worth stating: the\r\n * contract this component carries is INVISIBLE. `Field` supplies an id, and that\r\n * id must reach the control's `aria-describedby` so a screen reader announces\r\n * the error when focus lands on the input. Break that wiring and NOTHING\r\n * changes: same pixels, same screenshot, same visual review — only a blind user\r\n * silently stops being told why their submit failed. There is no way to catch\r\n * that except by asserting it.\r\n *\r\n * The assertions below use `toHaveAccessibleDescription`, not id comparisons, on\r\n * purpose. It resolves aria-describedby to the text a screen reader would\r\n * actually announce, so the test states the USER-FACING outcome and stays true\r\n * if the id-generation scheme ever changes.\r\n *\r\n * NOT COVERED — deliberately\r\n * R-4.1's visual half (\"sous le champ, en rouge, avec icône\") and the\r\n * first-line icon alignment on a wrapping message are layout and colour. jsdom\r\n * resolves neither CSS variables nor flexbox, so asserting them here would pass\r\n * while the message rendered black and centred. Those live in\r\n * FieldError.stories.tsx.\r\n */\r\ndescribe(\"FieldError — standalone\", () => {\r\n test(\"announces itself as an alert carrying the message\", () => {\r\n render(<FieldError>Ajoutez au moins un article avant de soumettre.</FieldError>);\r\n expect(screen.getByRole(\"alert\")).toHaveTextContent(\r\n \"Ajoutez au moins un article avant de soumettre.\"\r\n );\r\n });\r\n\r\n test(\"forwards id so a host can wire its own aria-describedby\", () => {\r\n render(<FieldError id=\"articles-error\">Ajoutez au moins un article.</FieldError>);\r\n expect(screen.getByRole(\"alert\")).toHaveAttribute(\"id\", \"articles-error\");\r\n });\r\n\r\n test(\"omits id when none is supplied\", () => {\r\n /* The list-level case usually has nothing to bind to. Emitting an empty or\r\n * generated id would create a describedby target nobody references. */\r\n render(<FieldError>Ajoutez au moins un article.</FieldError>);\r\n expect(screen.getByRole(\"alert\")).not.toHaveAttribute(\"id\");\r\n });\r\n\r\n test(\"the icon is hidden from assistive tech\", () => {\r\n /* R-Ar.2 — the message IS the announcement; an announced glyph would double\r\n * it. No semantic query reaches a role-less, name-less element, hence the\r\n * testid the component exposes for exactly this assertion. */\r\n render(<FieldError>Message</FieldError>);\r\n expect(screen.getByTestId(\"fielderror-icon\")).toHaveAttribute(\"aria-hidden\", \"true\");\r\n });\r\n});\r\n\r\ndescribe(\"FieldError — inside Field (the wiring that has no visual tell)\", () => {\r\n test(\"the error becomes the control's accessible description\", () => {\r\n render(\r\n <Field label=\"Numéro de titre\" error=\"Le numéro est invalide. Format : AAAA-IM-NNNNN.\">\r\n <input />\r\n </Field>\r\n );\r\n\r\n expect(screen.getByRole(\"textbox\")).toHaveAccessibleDescription(\r\n \"Le numéro est invalide. Format : AAAA-IM-NNNNN.\"\r\n );\r\n });\r\n\r\n test(\"the control is marked invalid\", () => {\r\n render(\r\n <Field label=\"Numéro\" error=\"Invalide.\">\r\n <input />\r\n </Field>\r\n );\r\n // jest-dom's toBeInvalid reads aria-invalid — R-I.3.\r\n expect(screen.getByRole(\"textbox\")).toBeInvalid();\r\n });\r\n\r\n test(\"a host-supplied aria-describedby is PRESERVED, not replaced\", () => {\r\n /* The merge is the fragile part. Overwriting instead of merging silently\r\n * drops a consumer's external help text, and again nothing visual changes.\r\n * Asserted with two order-independent regexes rather than one exact string,\r\n * so the test does not encode which fragment Field puts first. */\r\n render(\r\n <>\r\n <span id=\"host-help\">Format attendu : AAAA-IM-NNNNN.</span>\r\n <Field label=\"Numéro\" error=\"Le numéro est incomplet.\">\r\n <input aria-describedby=\"host-help\" />\r\n </Field>\r\n </>\r\n );\r\n\r\n const input = screen.getByRole(\"textbox\");\r\n expect(input).toHaveAccessibleDescription(/Format attendu/);\r\n expect(input).toHaveAccessibleDescription(/incomplet/);\r\n });\r\n\r\n test(\"the hint is suppressed while an error is shown\", () => {\r\n /* Two competing descriptions under one field is worse than one. The hint\r\n * returns once the error clears — verified by the rerender below. */\r\n const { rerender } = render(\r\n <Field label=\"Numéro\" hint=\"Format : AAAA-IM-NNNNN\" error=\"Le numéro est incomplet.\">\r\n <input />\r\n </Field>\r\n );\r\n\r\n expect(screen.getByRole(\"alert\")).toHaveTextContent(\"Le numéro est incomplet.\");\r\n expect(screen.queryByText(\"Format : AAAA-IM-NNNNN\")).not.toBeInTheDocument();\r\n\r\n rerender(\r\n <Field label=\"Numéro\" hint=\"Format : AAAA-IM-NNNNN\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.getByText(\"Format : AAAA-IM-NNNNN\")).toBeInTheDocument();\r\n });\r\n});\r\n\r\ndescribe(\"FieldError — live-region mounting contract\", () => {\r\n test(\"no alert exists until an error appears\", () => {\r\n /* THE contract. `role=\\\"alert\\\"` announces on INSERTION: an element mounted\r\n * permanently with empty content announces nothing when it later fills, so\r\n * a well-meaning refactor that always renders the container — to \\\"avoid\r\n * layout shift\\\", say — silently kills the announcement while every pixel\r\n * and every screenshot stays identical. */\r\n const { rerender } = render(\r\n <Field label=\"Numéro\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.queryByRole(\"alert\")).not.toBeInTheDocument();\r\n\r\n rerender(\r\n <Field label=\"Numéro\" error=\"Le numéro est incomplet.\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.getByRole(\"alert\")).toBeInTheDocument();\r\n });\r\n\r\n test(\"the alert unmounts when the error clears\", () => {\r\n const { rerender } = render(\r\n <Field label=\"Numéro\" error=\"Le numéro est incomplet.\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.getByRole(\"alert\")).toBeInTheDocument();\r\n\r\n rerender(\r\n <Field label=\"Numéro\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.queryByRole(\"alert\")).not.toBeInTheDocument();\r\n expect(screen.getByRole(\"textbox\")).not.toBeInvalid();\r\n });\r\n});\r\n"],"mappings":";;;AAAAA,OAAA;AACA,IAAAC,KAAA,GAAAC,uBAAA,CAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,WAAA,GAAAC,sBAAA,CAAAL,OAAA;AACA,IAAAM,MAAA,GAAAD,sBAAA,CAAAL,OAAA;AAAwC,IAAAO,WAAA,GAAAP,OAAA;AAAA,SAAAK,uBAAAG,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,gBAAAA,GAAA;AAAA,SAAAE,yBAAAC,WAAA,eAAAC,OAAA,kCAAAC,iBAAA,OAAAD,OAAA,QAAAE,gBAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,yBAAAC,WAAA,WAAAA,WAAA,GAAAG,gBAAA,GAAAD,iBAAA,KAAAF,WAAA;AAAA,SAAAT,wBAAAM,GAAA,EAAAG,WAAA,SAAAA,WAAA,IAAAH,GAAA,IAAAA,GAAA,CAAAC,UAAA,WAAAD,GAAA,QAAAA,GAAA,aAAAO,OAAA,CAAAP,GAAA,yBAAAA,GAAA,uCAAAA,GAAA,UAAAQ,KAAA,GAAAN,wBAAA,CAAAC,WAAA,OAAAK,KAAA,IAAAA,KAAA,CAAAC,GAAA,CAAAT,GAAA,YAAAQ,KAAA,CAAAE,GAAA,CAAAV,GAAA,SAAAW,MAAA,WAAAC,qBAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,GAAA,IAAAhB,GAAA,QAAAgB,GAAA,kBAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAnB,GAAA,EAAAgB,GAAA,SAAAI,IAAA,GAAAR,qBAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAf,GAAA,EAAAgB,GAAA,cAAAI,IAAA,KAAAA,IAAA,CAAAV,GAAA,IAAAU,IAAA,CAAAC,GAAA,KAAAR,MAAA,CAAAC,cAAA,CAAAH,MAAA,EAAAK,GAAA,EAAAI,IAAA,YAAAT,MAAA,CAAAK,GAAA,IAAAhB,GAAA,CAAAgB,GAAA,SAAAL,MAAA,cAAAX,GAAA,MAAAQ,KAAA,IAAAA,KAAA,CAAAa,GAAA,CAAArB,GAAA,EAAAW,MAAA,YAAAA,MAAA;AAExC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACAW,QAAQ,CAAC,yBAAyB,EAAE,YAAM;EACxCC,IAAI,CAAC,mDAAmD,EAAE,YAAM;IAC9D,IAAAC,cAAM,eAAC,IAAAzB,WAAA,CAAA0B,GAAA,EAAC7B,WAAA,WAAU;MAAA8B,QAAA,EAAC;IAA+C,CAAY,CAAC,CAAC;IAChFC,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,OAAO,CAAC,CAAC,CAACC,iBAAiB,CACjD,iDACF,CAAC;EACH,CAAC,CAAC;EAEFP,IAAI,CAAC,yDAAyD,EAAE,YAAM;IACpE,IAAAC,cAAM,eAAC,IAAAzB,WAAA,CAAA0B,GAAA,EAAC7B,WAAA,WAAU;MAACmC,EAAE,EAAC,gBAAgB;MAAAL,QAAA,EAAC;IAA4B,CAAY,CAAC,CAAC;IACjFC,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,OAAO,CAAC,CAAC,CAACG,eAAe,CAAC,IAAI,EAAE,gBAAgB,CAAC;EAC3E,CAAC,CAAC;EAEFT,IAAI,CAAC,gCAAgC,EAAE,YAAM;IAC3C;AACJ;IACI,IAAAC,cAAM,eAAC,IAAAzB,WAAA,CAAA0B,GAAA,EAAC7B,WAAA,WAAU;MAAA8B,QAAA,EAAC;IAA4B,CAAY,CAAC,CAAC;IAC7DC,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,OAAO,CAAC,CAAC,CAACI,GAAG,CAACD,eAAe,CAAC,IAAI,CAAC;EAC7D,CAAC,CAAC;EAEFT,IAAI,CAAC,wCAAwC,EAAE,YAAM;IACnD;AACJ;AACA;IACI,IAAAC,cAAM,eAAC,IAAAzB,WAAA,CAAA0B,GAAA,EAAC7B,WAAA,WAAU;MAAA8B,QAAA,EAAC;IAAO,CAAY,CAAC,CAAC;IACxCC,MAAM,CAACC,cAAM,CAACM,WAAW,CAAC,iBAAiB,CAAC,CAAC,CAACF,eAAe,CAAC,aAAa,EAAE,MAAM,CAAC;EACtF,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFV,QAAQ,CAAC,gEAAgE,EAAE,YAAM;EAC/EC,IAAI,CAAC,wDAAwD,EAAE,YAAM;IACnE,IAAAC,cAAM,eACJ,IAAAzB,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;MAACqC,KAAK,EAAC,oBAAiB;MAACC,KAAK,EAAC,oDAAiD;MAAAV,QAAA,eACpF,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;IAAC,CACJ,CACT,CAAC;IAEDE,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,SAAS,CAAC,CAAC,CAACQ,2BAA2B,CAC7D,iDACF,CAAC;EACH,CAAC,CAAC;EAEFd,IAAI,CAAC,+BAA+B,EAAE,YAAM;IAC1C,IAAAC,cAAM,eACJ,IAAAzB,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;MAACqC,KAAK,EAAC,WAAQ;MAACC,KAAK,EAAC,WAAW;MAAAV,QAAA,eACrC,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;IAAC,CACJ,CACT,CAAC;IACD;IACAE,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,SAAS,CAAC,CAAC,CAACS,WAAW,CAAC,CAAC;EACnD,CAAC,CAAC;EAEFf,IAAI,CAAC,6DAA6D,EAAE,YAAM;IACxE;AACJ;AACA;AACA;IACI,IAAAC,cAAM,eACJ,IAAAzB,WAAA,CAAAwC,IAAA,EAAAxC,WAAA,CAAAyC,QAAA;MAAAd,QAAA,gBACE,IAAA3B,WAAA,CAAA0B,GAAA;QAAMM,EAAE,EAAC,WAAW;QAAAL,QAAA,EAAC;MAA+B,CAAM,CAAC,eAC3D,IAAA3B,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;QAACqC,KAAK,EAAC,WAAQ;QAACC,KAAK,EAAC,6BAA0B;QAAAV,QAAA,eACpD,IAAA3B,WAAA,CAAA0B,GAAA;UAAO,oBAAiB;QAAW,CAAE;MAAC,CACjC,CAAC;IAAA,CACR,CACJ,CAAC;IAED,IAAMgB,KAAK,GAAGb,cAAM,CAACC,SAAS,CAAC,SAAS,CAAC;IACzCF,MAAM,CAACc,KAAK,CAAC,CAACJ,2BAA2B,CAAC,gBAAgB,CAAC;IAC3DV,MAAM,CAACc,KAAK,CAAC,CAACJ,2BAA2B,CAAC,WAAW,CAAC;EACxD,CAAC,CAAC;EAEFd,IAAI,CAAC,gDAAgD,EAAE,YAAM;IAC3D;AACJ;IACI,IAAAmB,OAAA,GAAqB,IAAAlB,cAAM,eACzB,IAAAzB,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;QAACqC,KAAK,EAAC,WAAQ;QAACQ,IAAI,EAAC,wBAAwB;QAACP,KAAK,EAAC,6BAA0B;QAAAV,QAAA,eAClF,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;MAAC,CACJ,CACT,CAAC;MAJOmB,QAAQ,GAAAF,OAAA,CAARE,QAAQ;IAMhBjB,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,OAAO,CAAC,CAAC,CAACC,iBAAiB,CAAC,0BAA0B,CAAC;IAC/EH,MAAM,CAACC,cAAM,CAACiB,WAAW,CAAC,wBAAwB,CAAC,CAAC,CAACZ,GAAG,CAACa,iBAAiB,CAAC,CAAC;IAE5EF,QAAQ,cACN,IAAA7C,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;MAACqC,KAAK,EAAC,WAAQ;MAACQ,IAAI,EAAC,wBAAwB;MAAAjB,QAAA,eACjD,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;IAAC,CACJ,CACT,CAAC;IACDE,MAAM,CAACC,cAAM,CAACmB,SAAS,CAAC,wBAAwB,CAAC,CAAC,CAACD,iBAAiB,CAAC,CAAC;EACxE,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFxB,QAAQ,CAAC,4CAA4C,EAAE,YAAM;EAC3DC,IAAI,CAAC,wCAAwC,EAAE,YAAM;IACnD;AACJ;AACA;AACA;AACA;IACI,IAAAyB,QAAA,GAAqB,IAAAxB,cAAM,eACzB,IAAAzB,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;QAACqC,KAAK,EAAC,WAAQ;QAAAT,QAAA,eACnB,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;MAAC,CACJ,CACT,CAAC;MAJOmB,QAAQ,GAAAI,QAAA,CAARJ,QAAQ;IAKhBjB,MAAM,CAACC,cAAM,CAACqB,WAAW,CAAC,OAAO,CAAC,CAAC,CAAChB,GAAG,CAACa,iBAAiB,CAAC,CAAC;IAE3DF,QAAQ,cACN,IAAA7C,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;MAACqC,KAAK,EAAC,WAAQ;MAACC,KAAK,EAAC,6BAA0B;MAAAV,QAAA,eACpD,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;IAAC,CACJ,CACT,CAAC;IACDE,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,OAAO,CAAC,CAAC,CAACiB,iBAAiB,CAAC,CAAC;EACvD,CAAC,CAAC;EAEFvB,IAAI,CAAC,0CAA0C,EAAE,YAAM;IACrD,IAAA2B,QAAA,GAAqB,IAAA1B,cAAM,eACzB,IAAAzB,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;QAACqC,KAAK,EAAC,WAAQ;QAACC,KAAK,EAAC,6BAA0B;QAAAV,QAAA,eACpD,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;MAAC,CACJ,CACT,CAAC;MAJOmB,QAAQ,GAAAM,QAAA,CAARN,QAAQ;IAKhBjB,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,OAAO,CAAC,CAAC,CAACiB,iBAAiB,CAAC,CAAC;IAErDF,QAAQ,cACN,IAAA7C,WAAA,CAAA0B,GAAA,EAAC3B,MAAA,WAAK;MAACqC,KAAK,EAAC,WAAQ;MAAAT,QAAA,eACnB,IAAA3B,WAAA,CAAA0B,GAAA,aAAQ;IAAC,CACJ,CACT,CAAC;IACDE,MAAM,CAACC,cAAM,CAACqB,WAAW,CAAC,OAAO,CAAC,CAAC,CAAChB,GAAG,CAACa,iBAAiB,CAAC,CAAC;IAC3DnB,MAAM,CAACC,cAAM,CAACC,SAAS,CAAC,SAAS,CAAC,CAAC,CAACI,GAAG,CAACK,WAAW,CAAC,CAAC;EACvD,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"FieldError.test.js","names":["require","_react","_FieldError","_interopRequireDefault","_Field","_jsxRuntime","obj","__esModule","describe","test","render","jsx","children","expect","screen","getByRole","toHaveTextContent","id","toHaveAttribute","not","getByTestId","label","error","toHaveAccessibleDescription","toBeInvalid","jsxs","Fragment","input","_render","hint","rerender","queryByText","toBeInTheDocument","getByText","_render2","queryByRole","_render3"],"sources":["../../../src/lib/v2/__tests__/FieldError.test.tsx"],"sourcesContent":["import \"@testing-library/jest-dom\";\r\nimport { render, screen } from \"@testing-library/react\";\r\nimport FieldError from \"../components/FieldError\";\r\nimport Field from \"../components/Field\";\r\n\r\n/**\r\n * FieldError — contract tests, including its integration into Field.\r\n *\r\n * WHY THIS FILE EXISTS\r\n * --------------------\r\n * §10.3 R-G.6 MUST. But the real reason is narrower and worth stating: the\r\n * contract this component carries is INVISIBLE. `Field` supplies an id, and that\r\n * id must reach the control's `aria-describedby` so a screen reader announces\r\n * the error when focus lands on the input. Break that wiring and NOTHING\r\n * changes: same pixels, same screenshot, same visual review — only a blind user\r\n * silently stops being told why their submit failed. There is no way to catch\r\n * that except by asserting it.\r\n *\r\n * The assertions below use `toHaveAccessibleDescription`, not id comparisons, on\r\n * purpose. It resolves aria-describedby to the text a screen reader would\r\n * actually announce, so the test states the USER-FACING outcome and stays true\r\n * if the id-generation scheme ever changes.\r\n *\r\n * NOT COVERED — deliberately\r\n * R-4.1's visual half (\"sous le champ, en rouge, avec icône\") and the\r\n * first-line icon alignment on a wrapping message are layout and colour. jsdom\r\n * resolves neither CSS variables nor flexbox, so asserting them here would pass\r\n * while the message rendered black and centred. Those live in\r\n * FieldError.stories.tsx.\r\n */\r\ndescribe(\"FieldError — standalone\", () => {\r\n test(\"announces itself as an alert carrying the message\", () => {\r\n render(<FieldError>Ajoutez au moins un article avant de soumettre.</FieldError>);\r\n expect(screen.getByRole(\"alert\")).toHaveTextContent(\r\n \"Ajoutez au moins un article avant de soumettre.\"\r\n );\r\n });\r\n\r\n test(\"forwards id so a host can wire its own aria-describedby\", () => {\r\n render(<FieldError id=\"articles-error\">Ajoutez au moins un article.</FieldError>);\r\n expect(screen.getByRole(\"alert\")).toHaveAttribute(\"id\", \"articles-error\");\r\n });\r\n\r\n test(\"omits id when none is supplied\", () => {\r\n /* The list-level case usually has nothing to bind to. Emitting an empty or\r\n * generated id would create a describedby target nobody references. */\r\n render(<FieldError>Ajoutez au moins un article.</FieldError>);\r\n expect(screen.getByRole(\"alert\")).not.toHaveAttribute(\"id\");\r\n });\r\n\r\n test(\"the icon is hidden from assistive tech\", () => {\r\n /* R-Ar.2 — the message IS the announcement; an announced glyph would double\r\n * it. No semantic query reaches a role-less, name-less element, hence the\r\n * testid the component exposes for exactly this assertion. */\r\n render(<FieldError>Message</FieldError>);\r\n expect(screen.getByTestId(\"fielderror-icon\")).toHaveAttribute(\"aria-hidden\", \"true\");\r\n });\r\n});\r\n\r\ndescribe(\"FieldError — inside Field (the wiring that has no visual tell)\", () => {\r\n test(\"the error becomes the control's accessible description\", () => {\r\n render(\r\n <Field label=\"Numéro de titre\" error=\"Le numéro est invalide. Format : AAAA-IM-NNNNN.\">\r\n <input />\r\n </Field>\r\n );\r\n\r\n expect(screen.getByRole(\"textbox\")).toHaveAccessibleDescription(\r\n \"Le numéro est invalide. Format : AAAA-IM-NNNNN.\"\r\n );\r\n });\r\n\r\n test(\"the control is marked invalid\", () => {\r\n render(\r\n <Field label=\"Numéro\" error=\"Invalide.\">\r\n <input />\r\n </Field>\r\n );\r\n // jest-dom's toBeInvalid reads aria-invalid — R-I.3.\r\n expect(screen.getByRole(\"textbox\")).toBeInvalid();\r\n });\r\n\r\n test(\"a host-supplied aria-describedby is PRESERVED, not replaced\", () => {\r\n /* The merge is the fragile part. Overwriting instead of merging silently\r\n * drops a consumer's external help text, and again nothing visual changes.\r\n * Asserted with two order-independent regexes rather than one exact string,\r\n * so the test does not encode which fragment Field puts first. */\r\n render(\r\n <>\r\n <span id=\"host-help\">Format attendu : AAAA-IM-NNNNN.</span>\r\n <Field label=\"Numéro\" error=\"Le numéro est incomplet.\">\r\n <input aria-describedby=\"host-help\" />\r\n </Field>\r\n </>\r\n );\r\n\r\n const input = screen.getByRole(\"textbox\");\r\n expect(input).toHaveAccessibleDescription(/Format attendu/);\r\n expect(input).toHaveAccessibleDescription(/incomplet/);\r\n });\r\n\r\n test(\"the hint is suppressed while an error is shown\", () => {\r\n /* Two competing descriptions under one field is worse than one. The hint\r\n * returns once the error clears — verified by the rerender below. */\r\n const { rerender } = render(\r\n <Field label=\"Numéro\" hint=\"Format : AAAA-IM-NNNNN\" error=\"Le numéro est incomplet.\">\r\n <input />\r\n </Field>\r\n );\r\n\r\n expect(screen.getByRole(\"alert\")).toHaveTextContent(\"Le numéro est incomplet.\");\r\n expect(screen.queryByText(\"Format : AAAA-IM-NNNNN\")).not.toBeInTheDocument();\r\n\r\n rerender(\r\n <Field label=\"Numéro\" hint=\"Format : AAAA-IM-NNNNN\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.getByText(\"Format : AAAA-IM-NNNNN\")).toBeInTheDocument();\r\n });\r\n});\r\n\r\ndescribe(\"FieldError — live-region mounting contract\", () => {\r\n test(\"no alert exists until an error appears\", () => {\r\n /* THE contract. `role=\\\"alert\\\"` announces on INSERTION: an element mounted\r\n * permanently with empty content announces nothing when it later fills, so\r\n * a well-meaning refactor that always renders the container — to \\\"avoid\r\n * layout shift\\\", say — silently kills the announcement while every pixel\r\n * and every screenshot stays identical. */\r\n const { rerender } = render(\r\n <Field label=\"Numéro\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.queryByRole(\"alert\")).not.toBeInTheDocument();\r\n\r\n rerender(\r\n <Field label=\"Numéro\" error=\"Le numéro est incomplet.\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.getByRole(\"alert\")).toBeInTheDocument();\r\n });\r\n\r\n test(\"the alert unmounts when the error clears\", () => {\r\n const { rerender } = render(\r\n <Field label=\"Numéro\" error=\"Le numéro est incomplet.\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.getByRole(\"alert\")).toBeInTheDocument();\r\n\r\n rerender(\r\n <Field label=\"Numéro\">\r\n <input />\r\n </Field>\r\n );\r\n expect(screen.queryByRole(\"alert\")).not.toBeInTheDocument();\r\n expect(screen.getByRole(\"textbox\")).not.toBeInvalid();\r\n });\r\n});\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
|
+
require("@testing-library/jest-dom");
|
|
5
|
+
var _react = require("@testing-library/react");
|
|
6
|
+
var _Field = _interopRequireWildcard(require("../components/Field"));
|
|
7
|
+
var _Input = _interopRequireDefault(require("../components/Input"));
|
|
8
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
10
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
11
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
12
|
+
/**
|
|
13
|
+
* Field — largeur semantique (gap G-H) : tests de contrat.
|
|
14
|
+
*
|
|
15
|
+
* CE QUE JSDOM PEUT ET NE PEUT PAS VERIFIER
|
|
16
|
+
* -----------------------------------------
|
|
17
|
+
* Le plafond n'est pose qu'a partir du palier `sm` — le standard exigeant
|
|
18
|
+
* « 100% grid width » sur mobile. Il passe donc par une requete media
|
|
19
|
+
* qu'`emotion` injecte dans la feuille de style, et jsdom ne resout pas les
|
|
20
|
+
* requetes media : `getComputedStyle` ne rendra jamais la largeur effective au
|
|
21
|
+
* palier desktop. Un test de rendu ne PEUT pas l'assertir, et pretendre le
|
|
22
|
+
* faire donnerait un test qui passe sans rien verifier.
|
|
23
|
+
*
|
|
24
|
+
* Ce fichier epingle donc ce qui est verifiable et qui compte :
|
|
25
|
+
*
|
|
26
|
+
* 1. LES CINQ VALEURS. C'est le point sensible du tour : elles ne se lisent
|
|
27
|
+
* pas dans le standard, qui donne des FOURCHETTES — quelqu'un a choisi, et
|
|
28
|
+
* ce choix doit etre visible et protege. Si l'equipe design les revoit,
|
|
29
|
+
* c'est ce test qui doit etre mis a jour sciemment, pas un ecran qui doit
|
|
30
|
+
* bouger par surprise.
|
|
31
|
+
*
|
|
32
|
+
* 2. QUE `width` NE CASSE PAS LE CABLAGE D'ACCESSIBILITE. `Field` associe
|
|
33
|
+
* libelle, indication et erreur au controle ; ajouter une contrainte de
|
|
34
|
+
* mise en page ne doit rien y toucher. C'est la regression la plus
|
|
35
|
+
* probable d'un changement qui passe par `sx`.
|
|
36
|
+
*
|
|
37
|
+
* 3. QUE L'OMISSION RESTE NEUTRE. Sans `width`, aucun plafond : les
|
|
38
|
+
* appelants d'avant G-H ne doivent pas bouger d'un pixel.
|
|
39
|
+
*
|
|
40
|
+
* Le comportement responsive lui-meme se verifie dans la story, en
|
|
41
|
+
* redimensionnant la fenetre — c'est la que le contrat est observable.
|
|
42
|
+
*/describe("Field — les cinq gabarits (G-H)", function () {
|
|
43
|
+
test("les valeurs sont celles retenues dans la fourchette du standard", function () {
|
|
44
|
+
/* Fourchettes du standard, et valeur retenue (le HAUT, ces largeurs etant
|
|
45
|
+
* des plafonds) :
|
|
46
|
+
* xs ~80-120 -> 120 s ~160-200 -> 200
|
|
47
|
+
* m ~320-400 -> 400 l ~500-600 -> 600
|
|
48
|
+
* xl 100%
|
|
49
|
+
* Chaque valeur passe par une variable CSS pour etre revue sans toucher au
|
|
50
|
+
* code : c'est le repli qui est epingle ici. */
|
|
51
|
+
expect(_Field.FIELD_MAX_WIDTH.xs).toBe("var(--field-w-xs, 120px)");
|
|
52
|
+
expect(_Field.FIELD_MAX_WIDTH.s).toBe("var(--field-w-s, 200px)");
|
|
53
|
+
expect(_Field.FIELD_MAX_WIDTH.m).toBe("var(--field-w-m, 400px)");
|
|
54
|
+
expect(_Field.FIELD_MAX_WIDTH.l).toBe("var(--field-w-l, 600px)");
|
|
55
|
+
expect(_Field.FIELD_MAX_WIDTH.xl).toBe("100%");
|
|
56
|
+
});
|
|
57
|
+
test("les cinq gabarits du standard sont couverts, ni plus ni moins", function () {
|
|
58
|
+
/* Un gabarit ajoute ou retire est un ecart au standard, pas un detail
|
|
59
|
+
* d'implementation. */
|
|
60
|
+
expect(Object.keys(_Field.FIELD_MAX_WIDTH).sort()).toEqual(["l", "m", "s", "xl", "xs"]);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("Field — `width` ne touche pas au cablage d'accessibilite", function () {
|
|
64
|
+
test("le libelle nomme toujours le controle", function () {
|
|
65
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
66
|
+
label: "Identifiant fiscal",
|
|
67
|
+
htmlFor: "ifu",
|
|
68
|
+
width: "s",
|
|
69
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], {})
|
|
70
|
+
}));
|
|
71
|
+
expect(_react.screen.getByRole("textbox", {
|
|
72
|
+
name: /Identifiant fiscal/
|
|
73
|
+
})).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
test("l'erreur reste la description accessible du controle", function () {
|
|
76
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
77
|
+
label: "Identifiant fiscal",
|
|
78
|
+
htmlFor: "ifu",
|
|
79
|
+
width: "s",
|
|
80
|
+
error: "Quinze caract\xE8res maximum.",
|
|
81
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], {})
|
|
82
|
+
}));
|
|
83
|
+
expect(_react.screen.getByRole("textbox")).toHaveAccessibleDescription("Quinze caractères maximum.");
|
|
84
|
+
expect(_react.screen.getByRole("textbox")).toHaveAttribute("aria-invalid", "true");
|
|
85
|
+
});
|
|
86
|
+
test("l'indication reste la description accessible du controle", function () {
|
|
87
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
88
|
+
label: "Adresse",
|
|
89
|
+
htmlFor: "adresse",
|
|
90
|
+
width: "l",
|
|
91
|
+
hint: "Voie, code postal et ville.",
|
|
92
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], {})
|
|
93
|
+
}));
|
|
94
|
+
expect(_react.screen.getByRole("textbox")).toHaveAccessibleDescription("Voie, code postal et ville.");
|
|
95
|
+
});
|
|
96
|
+
test("`required` reste annonce comme tel", function () {
|
|
97
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
98
|
+
label: "Marque",
|
|
99
|
+
htmlFor: "marque",
|
|
100
|
+
width: "m",
|
|
101
|
+
required: true,
|
|
102
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], {})
|
|
103
|
+
}));
|
|
104
|
+
|
|
105
|
+
/* `toBeRequired` accepte l'attribut NATIF `required` comme `aria-required` :
|
|
106
|
+
* c'est volontaire, et c'est la bonne assertion ici.
|
|
107
|
+
*
|
|
108
|
+
* Les deux mecanismes coexistent dans la library, par des chemins
|
|
109
|
+
* differents, et viser l'un des deux nommement rendrait le test faux sans
|
|
110
|
+
* que le comportement change :
|
|
111
|
+
* — sur un controle MUI (`Input`, `Textarea`), `Field` passe `required`
|
|
112
|
+
* au `FormControl`, dont le CONTEXTE le propage jusqu'a l'input, qui
|
|
113
|
+
* porte alors l'attribut natif ;
|
|
114
|
+
* — sur un groupe (`RadioGroup`), aucun contexte ne s'applique : `Field`
|
|
115
|
+
* injecte `aria-required` sur l'enfant, que le groupe transmet a son
|
|
116
|
+
* `role="radiogroup"` (voir le test de `FormikRadioGroup`).
|
|
117
|
+
*
|
|
118
|
+
* Ce qui compte pour R-I.2 est qu'une technologie d'assistance l'annonce,
|
|
119
|
+
* pas quel attribut le porte. */
|
|
120
|
+
expect(_react.screen.getByRole("textbox")).toBeRequired();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe("Field — l'omission reste neutre", function () {
|
|
124
|
+
test("sans `width`, le champ se rend et se nomme comme avant G-H", function () {
|
|
125
|
+
/* Ce que ce test prouve, et ce qu'il ne prouve pas.
|
|
126
|
+
*
|
|
127
|
+
* L'absence de plafond n'est PAS assertable : elle se lit dans la feuille
|
|
128
|
+
* de style generee par `emotion`, que jsdom ne resout pas plus qu'une
|
|
129
|
+
* requete media. Une premiere version comparait le nombre de noeuds avec
|
|
130
|
+
* et sans `width` — ce qui exigeait un acces direct au DOM, interdit a
|
|
131
|
+
* juste titre par `testing-library/no-node-access` : compter des `<label>`
|
|
132
|
+
* teste l'implementation, pas le comportement.
|
|
133
|
+
*
|
|
134
|
+
* Ce qui EST verifiable et suffit a la retrocompatibilite : sans `width`,
|
|
135
|
+
* le controle est rendu, nomme par son libelle, et n'a herite d'aucun etat
|
|
136
|
+
* qu'il n'a pas demande. Le plafond, lui, se verifie dans la story. */
|
|
137
|
+
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Field["default"], {
|
|
138
|
+
label: "Marque",
|
|
139
|
+
htmlFor: "sans-gabarit",
|
|
140
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input["default"], {})
|
|
141
|
+
}));
|
|
142
|
+
var champ = _react.screen.getByRole("textbox", {
|
|
143
|
+
name: /Marque/
|
|
144
|
+
});
|
|
145
|
+
expect(champ).toBeInTheDocument();
|
|
146
|
+
expect(champ).not.toBeRequired();
|
|
147
|
+
expect(champ).not.toBeInvalid();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
//# sourceMappingURL=FieldWidth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldWidth.test.js","names":["require","_react","_Field","_interopRequireWildcard","_Input","_interopRequireDefault","_jsxRuntime","obj","__esModule","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","_typeof","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","describe","test","expect","FIELD_MAX_WIDTH","xs","toBe","s","m","l","xl","keys","sort","toEqual","render","jsx","label","htmlFor","width","children","screen","getByRole","name","toBeInTheDocument","error","toHaveAccessibleDescription","toHaveAttribute","hint","required","toBeRequired","champ","not","toBeInvalid"],"sources":["../../../src/lib/v2/__tests__/FieldWidth.test.tsx"],"sourcesContent":["import \"@testing-library/jest-dom\";\r\nimport { render, screen } from \"@testing-library/react\";\r\nimport Field, { FIELD_MAX_WIDTH } from \"../components/Field\";\r\nimport Input from \"../components/Input\";\r\n\r\n/**\r\n * Field — largeur semantique (gap G-H) : tests de contrat.\r\n *\r\n * CE QUE JSDOM PEUT ET NE PEUT PAS VERIFIER\r\n * -----------------------------------------\r\n * Le plafond n'est pose qu'a partir du palier `sm` — le standard exigeant\r\n * « 100% grid width » sur mobile. Il passe donc par une requete media\r\n * qu'`emotion` injecte dans la feuille de style, et jsdom ne resout pas les\r\n * requetes media : `getComputedStyle` ne rendra jamais la largeur effective au\r\n * palier desktop. Un test de rendu ne PEUT pas l'assertir, et pretendre le\r\n * faire donnerait un test qui passe sans rien verifier.\r\n *\r\n * Ce fichier epingle donc ce qui est verifiable et qui compte :\r\n *\r\n * 1. LES CINQ VALEURS. C'est le point sensible du tour : elles ne se lisent\r\n * pas dans le standard, qui donne des FOURCHETTES — quelqu'un a choisi, et\r\n * ce choix doit etre visible et protege. Si l'equipe design les revoit,\r\n * c'est ce test qui doit etre mis a jour sciemment, pas un ecran qui doit\r\n * bouger par surprise.\r\n *\r\n * 2. QUE `width` NE CASSE PAS LE CABLAGE D'ACCESSIBILITE. `Field` associe\r\n * libelle, indication et erreur au controle ; ajouter une contrainte de\r\n * mise en page ne doit rien y toucher. C'est la regression la plus\r\n * probable d'un changement qui passe par `sx`.\r\n *\r\n * 3. QUE L'OMISSION RESTE NEUTRE. Sans `width`, aucun plafond : les\r\n * appelants d'avant G-H ne doivent pas bouger d'un pixel.\r\n *\r\n * Le comportement responsive lui-meme se verifie dans la story, en\r\n * redimensionnant la fenetre — c'est la que le contrat est observable.\r\n */\r\n\r\ndescribe(\"Field — les cinq gabarits (G-H)\", () => {\r\n test(\"les valeurs sont celles retenues dans la fourchette du standard\", () => {\r\n /* Fourchettes du standard, et valeur retenue (le HAUT, ces largeurs etant\r\n * des plafonds) :\r\n * xs ~80-120 -> 120 s ~160-200 -> 200\r\n * m ~320-400 -> 400 l ~500-600 -> 600\r\n * xl 100%\r\n * Chaque valeur passe par une variable CSS pour etre revue sans toucher au\r\n * code : c'est le repli qui est epingle ici. */\r\n expect(FIELD_MAX_WIDTH.xs).toBe(\"var(--field-w-xs, 120px)\");\r\n expect(FIELD_MAX_WIDTH.s).toBe(\"var(--field-w-s, 200px)\");\r\n expect(FIELD_MAX_WIDTH.m).toBe(\"var(--field-w-m, 400px)\");\r\n expect(FIELD_MAX_WIDTH.l).toBe(\"var(--field-w-l, 600px)\");\r\n expect(FIELD_MAX_WIDTH.xl).toBe(\"100%\");\r\n });\r\n\r\n test(\"les cinq gabarits du standard sont couverts, ni plus ni moins\", () => {\r\n /* Un gabarit ajoute ou retire est un ecart au standard, pas un detail\r\n * d'implementation. */\r\n expect(Object.keys(FIELD_MAX_WIDTH).sort()).toEqual([\r\n \"l\",\r\n \"m\",\r\n \"s\",\r\n \"xl\",\r\n \"xs\",\r\n ]);\r\n });\r\n});\r\n\r\ndescribe(\"Field — `width` ne touche pas au cablage d'accessibilite\", () => {\r\n test(\"le libelle nomme toujours le controle\", () => {\r\n render(\r\n <Field label=\"Identifiant fiscal\" htmlFor=\"ifu\" width=\"s\">\r\n <Input />\r\n </Field>\r\n );\r\n\r\n expect(\r\n screen.getByRole(\"textbox\", { name: /Identifiant fiscal/ })\r\n ).toBeInTheDocument();\r\n });\r\n\r\n test(\"l'erreur reste la description accessible du controle\", () => {\r\n render(\r\n <Field\r\n label=\"Identifiant fiscal\"\r\n htmlFor=\"ifu\"\r\n width=\"s\"\r\n error=\"Quinze caractères maximum.\"\r\n >\r\n <Input />\r\n </Field>\r\n );\r\n\r\n expect(screen.getByRole(\"textbox\")).toHaveAccessibleDescription(\r\n \"Quinze caractères maximum.\"\r\n );\r\n expect(screen.getByRole(\"textbox\")).toHaveAttribute(\r\n \"aria-invalid\",\r\n \"true\"\r\n );\r\n });\r\n\r\n test(\"l'indication reste la description accessible du controle\", () => {\r\n render(\r\n <Field\r\n label=\"Adresse\"\r\n htmlFor=\"adresse\"\r\n width=\"l\"\r\n hint=\"Voie, code postal et ville.\"\r\n >\r\n <Input />\r\n </Field>\r\n );\r\n\r\n expect(screen.getByRole(\"textbox\")).toHaveAccessibleDescription(\r\n \"Voie, code postal et ville.\"\r\n );\r\n });\r\n\r\n test(\"`required` reste annonce comme tel\", () => {\r\n render(\r\n <Field label=\"Marque\" htmlFor=\"marque\" width=\"m\" required>\r\n <Input />\r\n </Field>\r\n );\r\n\r\n /* `toBeRequired` accepte l'attribut NATIF `required` comme `aria-required` :\r\n * c'est volontaire, et c'est la bonne assertion ici.\r\n *\r\n * Les deux mecanismes coexistent dans la library, par des chemins\r\n * differents, et viser l'un des deux nommement rendrait le test faux sans\r\n * que le comportement change :\r\n * — sur un controle MUI (`Input`, `Textarea`), `Field` passe `required`\r\n * au `FormControl`, dont le CONTEXTE le propage jusqu'a l'input, qui\r\n * porte alors l'attribut natif ;\r\n * — sur un groupe (`RadioGroup`), aucun contexte ne s'applique : `Field`\r\n * injecte `aria-required` sur l'enfant, que le groupe transmet a son\r\n * `role=\"radiogroup\"` (voir le test de `FormikRadioGroup`).\r\n *\r\n * Ce qui compte pour R-I.2 est qu'une technologie d'assistance l'annonce,\r\n * pas quel attribut le porte. */\r\n expect(screen.getByRole(\"textbox\")).toBeRequired();\r\n });\r\n});\r\n\r\ndescribe(\"Field — l'omission reste neutre\", () => {\r\n test(\"sans `width`, le champ se rend et se nomme comme avant G-H\", () => {\r\n /* Ce que ce test prouve, et ce qu'il ne prouve pas.\r\n *\r\n * L'absence de plafond n'est PAS assertable : elle se lit dans la feuille\r\n * de style generee par `emotion`, que jsdom ne resout pas plus qu'une\r\n * requete media. Une premiere version comparait le nombre de noeuds avec\r\n * et sans `width` — ce qui exigeait un acces direct au DOM, interdit a\r\n * juste titre par `testing-library/no-node-access` : compter des `<label>`\r\n * teste l'implementation, pas le comportement.\r\n *\r\n * Ce qui EST verifiable et suffit a la retrocompatibilite : sans `width`,\r\n * le controle est rendu, nomme par son libelle, et n'a herite d'aucun etat\r\n * qu'il n'a pas demande. Le plafond, lui, se verifie dans la story. */\r\n render(\r\n <Field label=\"Marque\" htmlFor=\"sans-gabarit\">\r\n <Input />\r\n </Field>\r\n );\r\n\r\n const champ = screen.getByRole(\"textbox\", { name: /Marque/ });\r\n expect(champ).toBeInTheDocument();\r\n expect(champ).not.toBeRequired();\r\n expect(champ).not.toBeInvalid();\r\n });\r\n});\r\n"],"mappings":"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","ignoreList":[]}
|