@dsivd/prestations-ng 19.1.2 → 19.2.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +186 -7
  2. package/CONTRIBUTING.md +43 -3
  3. package/GOOD_PRACTICES.md +329 -124
  4. package/UPGRADING_V18.md +1 -0
  5. package/UPGRADING_V19.md +224 -3
  6. package/dsivd-prestations-ng-19.2.0-beta.10.tgz +0 -0
  7. package/eslint/configs/spec-ts-recommended.mjs +34 -0
  8. package/eslint/configs/template-recommended.mjs +2 -0
  9. package/eslint/configs/template-rules.mjs +6 -2
  10. package/eslint/configs/ts-recommended.mjs +2 -0
  11. package/eslint/configs/ts-rules.mjs +6 -2
  12. package/eslint/index.mjs +17 -0
  13. package/eslint/rules/no-direct-signal-mutation.mjs +1 -1
  14. package/eslint/signal-names.mjs +66 -35
  15. package/fesm2022/dsivd-prestations-ng.mjs +5013 -4196
  16. package/fesm2022/dsivd-prestations-ng.mjs.map +1 -1
  17. package/package.json +1 -2
  18. package/schematics/ng-add/index.js +2 -4
  19. package/schematics/ng-update/migrations/update-13_2_0/index.js +7 -2
  20. package/schematics/utility/add-allow-synthetic-default-imports.js +2 -2
  21. package/schematics/utility/add-allowed-common-js-dependencies.js +39 -29
  22. package/schematics/utility/foehn2-bootstrap5-migration.js +20 -20
  23. package/schematics/utility/migrate-to-karma-coverage.js +2 -2
  24. package/schematics/utility/remove-emit-decorator-metadata.js +8 -9
  25. package/src/eslint/__tests__/signal-names.test.mjs +129 -0
  26. package/src/eslint/configs/__tests__/configs.test.mjs +46 -2
  27. package/src/eslint/configs/spec-ts-recommended.mjs +34 -0
  28. package/src/eslint/configs/template-recommended.mjs +2 -0
  29. package/src/eslint/configs/template-rules.mjs +6 -2
  30. package/src/eslint/configs/ts-recommended.mjs +2 -0
  31. package/src/eslint/configs/ts-rules.mjs +6 -2
  32. package/src/eslint/index.mjs +17 -0
  33. package/src/eslint/rules/no-direct-signal-mutation.mjs +1 -1
  34. package/src/eslint/signal-names.mjs +66 -35
  35. package/types/dsivd-prestations-ng.d.ts +1184 -998
  36. package/dsivd-prestations-ng-19.1.2.tgz +0 -0
package/CHANGELOG.md CHANGED
@@ -6,15 +6,194 @@
6
6
 
7
7
  ---
8
8
 
9
- ## [19.1.2]
9
+ ## [19.2.0] - should be aligned with prestations-be 19.2.x
10
10
 
11
- ### Fixed
11
+ ### Added
12
+
13
+ - [eslint/configs/spec-ts-recommended.mjs](projects/prestations-ng/src/eslint/configs/spec-ts-recommended.mjs)
14
+ - New `prestationsNg.configs.specTsRecommended` ESLint config for the Vitest specs, to use in the `extends` of a
15
+ `**/*.spec.ts` block: the `recommended` config of `@vitest/eslint-plugin`, which also counts the assertions of
16
+ the `HttpTestingController` and of the helpers of the specs. It needs `@vitest/eslint-plugin` in the
17
+ devDependencies of your project, only when you use it. See
18
+ [UPGRADING_V19.md](UPGRADING_V19.md#migrate-to-eslint-flat-configuration).
19
+ - [foehn-bo-multi-upload.component.ts](projects/prestations-ng/src/foehn-upload/foehn-bo-multi-upload/foehn-bo-multi-upload.component.ts)
20
+ - New `localUpload` input. When set to `true`, selected files are kept purely local
21
+ (as `DocumentReferenceWithFile`, no `uploadUrl()` call) so they can be cancelled before
22
+ being sent. Files show up immediately in the list with a "pending" indicator (dictionary
23
+ key `foehn-uploader.pending-label`, French default provided) since they're not uploaded
24
+ yet. It is your responsibility to upload/delete them at save time,
25
+ e.g. via the new
26
+ [document-changes.helper.ts](projects/prestations-ng/src/foehn-upload/document-changes.helper.ts)
27
+ (`splitDocumentChanges`) which computes `filesToAdd`/`documentsToDelete` from the model.
28
+ - The default (direct upload) mode is unchanged.
29
+ - New `maxFileSizeInMo` input: a client-side, per-file size limit that doesn't depend on
30
+ the `fileMaxSizeInBytesByFormKey` server configuration (useful for consumers that don't
31
+ expose that config yet). When both are set, the smallest limit applies. A file too big gets
32
+ the usual `413` error, which can be customized with `customErrors` (`{fileName}`,
33
+ `{fileMaxSize}`).
34
+ - New `chooseButtonStyleModifier` input, appended to the choose button's CSS classes
35
+ (e.g. `btn-sm`), mirroring the same input already available on other uploaders.
36
+
37
+ - [foehn-input-address.component.ts](projects/prestations-ng/src/foehn-address/foehn-input-address.component.ts)
38
+ - Added `streetAllowCustomValue` input to control whether the street field allows custom values (defaults to `true`).
39
+ - Added `swissNpaLocalityBaseUrl` input to control the base URL for Swiss NPA localities (defaults to `'api/refinf/locality'`).
40
+
41
+ ### Changed
42
+
43
+ Library now runs as strict mode, which may cause some errors to appear in your project after updating.
44
+ Please check the [UPGRADING_V19.md](UPGRADING_V19.md) guide for more information.
45
+
46
+ - [foehn-list-summary.component.ts](projects/prestations-ng/src/foehn-menu-prestation/foehn-list-summary/foehn-list-summary.component.ts)
47
+ - `FoehnListSummaryComponent` is now generic: `FoehnListSummaryComponent<T extends FoehnListItem>`,
48
+ so the model, `getListItemTitle` and `listItemDescriptions` are typed with your own item class
49
+ instead of the base `FoehnListItem`
50
+ - [foehn-list-item-description.ts](projects/prestations-ng/src/foehn-menu-prestation/foehn-list-summary/foehn-list-item-description.ts)
51
+ - 🚨 `FoehnListItemDescription` now takes a type parameter: `FoehnListItemDescription<T>`.
52
+ `getFormattedValue(item: T)` and `hideIfEmpty(item: T)` receive your item type directly, no cast needed.
53
+ Replace `FoehnListItemDescription[]` with `FoehnListItemDescription<MyItem>[]` in your project.
54
+ - [uploader.helper.ts](projects/prestations-ng/src/foehn-upload/uploader.helper.ts)
55
+ - 🚨 `UploaderHelper.addCustomErrorOrDefault()` takes the limits of the uploader in an object (`UploaderErrorLimits`,
56
+ all optional) instead of its last three parameters:
57
+ `addCustomErrorOrDefault(name, errors, errorCode, fileName, customErrors, { overrideAcceptedExtensions, overrideMaxFileNameLength, overrideIllegalCharacters, maxFileSizeInMo })`.
58
+ The custom error 413 returned by the server now also displays the `maxFileSizeInMo` limit of
59
+ `foehn-bo-multi-upload`.
60
+ - 🚀 **prestations-ng is now zoneless**: its components no longer need zone.js to be refreshed. They keep
61
+ working in an application using zone.js, and your application can now drop zone.js, see
62
+ [UPGRADING_V19.md](UPGRADING_V19.md#zoneless-optional-but-recommended).
63
+ - the state displayed by the components is held by signals (`signal()`, `computed()`, `linkedSignal()`)
64
+ - what was waiting for `NgZone.onMicrotaskEmpty` or a `setTimeout()` to reach the rendered DOM (focus,
65
+ scroll, value displayed by the autocompletes, default values...) now uses `afterNextRender()`
66
+ - the short asynchronous work of the components is tracked with `PendingTasks`, so that
67
+ `ApplicationRef.whenStable()` (and `fixture.whenStable()` in your tests) waits for it: the debounced
68
+ `userInput` output of the `foehn-input-*` components, the debounced time of `foehn-input-date-time`,
69
+ the locale of `foehn-date-picker`, the default country and the sanitized model of `foehn-input-address`
70
+ - `providePrestationsNgCore()` now provides `provideBrowserGlobalErrorListeners()`: without zone.js, the
71
+ errors thrown in a timer or a promise still reach your `ErrorHandler`
72
+ - 🚨 **The inputs and outputs of the components are unchanged**, but the following public fields are now
73
+ signals. If your code reads them (e.g. through `viewChild()` or in your tests), call them (`isVisible()`
74
+ instead of `isVisible`) and write them with `.set()`. Those marked _read-only_ are `computed()` signals.
75
+ - `foehn-agenda`: `srAnnouncements`
76
+ - `foehn-agenda-timeslot-panel`: `selectedTimeSlot`, `timeInputValue`, `isClosed`, `timeSlots`
77
+ (_read-only_), `timeslotRemaining` (_read-only_), `canClose` (_read-only_)
78
+ - `foehn-autocomplete`: `searchValue`, `inputHasFocus`, `hideSuggestions`, `displayedElements`,
79
+ `notificationMessageUpdated`, `VIEW_PORT_HEIGHT` (_read-only_)
80
+ - `foehn-multiselect-autocomplete`: `autocompleteInputValue`, `showEmptyListMessage` (_read-only_), `srAnnouncements`
81
+ - `foehn-select`, `foehn-radio`, `foehn-checkbox` and the autocompletes (`FoehnCheckableGroupComponent`):
82
+ `groupedElements`
83
+ - `foehn-radio`: `inputValue`
84
+ - `foehn-confirm-modal`: `isVisible` (`content` is now a read-only field instead of a getter)
85
+ - `foehn-date-picker`: `hostId`, `weekDays`, `weeks`, `selectedDate`, `monthListItem`
86
+ - `foehn-dropdown-menu`: `isDropdownVisible`, `popupPosition`
87
+ - `foehn-header`: `connectedEsMenu` (_read-only_)
88
+ - `foehn-input-address`: `country`, `locality`, `street`, `houseNumber`, `postOfficeBoxText`,
89
+ `addressLine1`, `addressLine2` (linked to the model: they follow it and can still be set),
90
+ `streetCustomErrors`
91
+ - `foehn-input-foreign-locality`: `zipCode`, `longName`
92
+ - `foehn-input-foreign-street`: `longName`
93
+ - `foehn-input-date`: `day`, `month`, `year`, `datePickerModel`
94
+ - `foehn-input-date-time`: `date`, `time` (linked to the model: they follow it and can still be set)
95
+ - `foehn-input-time`: `hour`, `minute` (linked to the model: they follow it and can still be set)
96
+ - `foehn-input-nav13`: `part2`, `part3`, `part4`
97
+ - `foehn-input-textarea`: `isCharCountExceeded`, `charCountLeft`, `charCountLabel`, `ariaLiveStatus`
98
+ - `foehn-list` and `foehn-table`: `currentPage`, `filteredList`
99
+ - `foehn-list-summary`: `listCopyForTable`, `tableConfiguration` (_read-only_)
100
+ - `foehn-notfound`: `seconds`
101
+ - `foehn-page`: `pageTitle`
102
+ - `foehn-page-counter`: `isStable` (was an `Observable<boolean>`)
103
+ - `foehn-page-modal`: `wrongPublicModalVisible`, `formattedPublicsCibles`
104
+ - `foehn-picture-upload`: `pictureToCrop`, `croppedPictureAsBlob`, `loading`
105
+ - `foehn-status-progress-bar`: `isTransmitted`
106
+ - `gesdem-action-recovery-login`: `demandeNotFound`, `rateLimited`, `rateLimitCounter`, `otpRecipient`,
107
+ `otp`
108
+ - `gesdem-action-recovery-registration`: `mailSent`, `model` (replaced by the new `updateModel()` method,
109
+ never mutated)
110
+ - `epayment-form` (`SdkEpaymentComponent`): `failureModalDisplayed`, `redirectModalDisplayed`
111
+ - `captcha` (`SdkRecaptchaComponent`): `isLoaded`, `hasLoadingError`
112
+ - `redirector` (`RedirectComponent`): `counter`
113
+ - The lifecycle hooks that have nothing left to do are removed: `ngOnChanges()` of
114
+ `foehn-agenda-timeslot-panel`, `ngAfterViewInit()` of `foehn-list-summary`, `ngOnInit()` and `ngOnDestroy()`
115
+ of `captcha`.
116
+ - `SdkDictionaryService.getKeySync()` reads a signal: a `computed()` or a template calling it is refreshed
117
+ when the dictionary is (re)loaded, e.g. when the language changes.
118
+ - `foehn-autocomplete` and `foehn-multiselect-autocomplete`: the value to display, its reset, the default
119
+ values and the focus after a click on a suggestion are applied after the next rendering instead of in a
120
+ `setTimeout()`.
121
+ - Unit tests of the library: Karma and Jasmine are replaced by Vitest 4 in browser mode (Playwright,
122
+ headless Chromium), see [CONTRIBUTING.md](CONTRIBUTING.md#unit-testing).
123
+ - `core-js` is no longer a peer dependency: prestations-ng no longer imports it since 19.1.1, see
124
+ [UPGRADING_V19.md](UPGRADING_V19.md#core-js-is-no-longer-needed-since-1920).
125
+ - `ng add @dsivd/prestations-ng` adds `iban` and `dayjs` (the CommonJS dependencies of prestations-ng) to the
126
+ `allowedCommonJsDependencies` of `angular.json`, instead of `core-js/modules/es.array.includes`, `iban` and
127
+ `zone.js/dist/zone-error`, and no longer sets `allowSyntheticDefaultImports` (implied by the `tsconfig.json` of
128
+ Angular 21: `"module": "preserve"` or `"moduleResolution": "bundler"`).
129
+
130
+ ### Deprecated
12
131
 
13
- - [provide-prestations-ng-core.ts](projects/prestations-ng/src/provide-prestations-ng-core.ts)
14
- - `providePrestationsNgCore()` registers again the HTTP interceptors lost with `FoehnPageModule` in 19.0.0:
15
- the `foehn-transmit-waiting-modal` is displayed again during a long transmission, the warning before the
16
- expiration of the session receives its date again, and a new version of the application deployed meanwhile is
17
- detected again.
132
+ - `AbstractMenuPageComponent.ngZone` is no longer used and will be removed: `NgZone.onStable` never emits
133
+ without zone.js.
134
+
135
+ ### Fixed
136
+
137
+ - `captcha`: no more `NG0953` warning ("Unexpected emit for destroyed `OutputRef`") when the captcha script fails to
138
+ load after the component has been destroyed (e.g. the user left the page meanwhile).
139
+ - `foehn-multiselect-autocomplete`: the suggestions and the message displayed once every element is selected follow a
140
+ model changed by the project, not only by the user. Once every element was selected, a model set back to some of
141
+ them kept the message and the hidden input; a model selecting every element did not display the message; the
142
+ suggestions still contained the elements selected by the project. An empty list of elements no longer displays
143
+ the message (every element of the list has already been added).
144
+ - `providePrestationsNgCore()` registers again the HTTP interceptors lost with `FoehnPageModule` in 19.0.0: the
145
+ `foehn-transmit-waiting-modal` is displayed again during a long transmission, the warning before the expiration of
146
+ the session receives its date again, and a new version of the application deployed meanwhile is detected again.
147
+ - `foehn-select`, `foehn-radio`, `foehn-checkbox` and the autocompletes:
148
+ - the model is no longer set back to its previous value when the parent changes `elements` and `model`
149
+ at the same time
150
+ - no more error when the component is destroyed while its `elementsUrl` is loading
151
+ - with a `defaultElementValue`, the model can be emptied again (e.g. set to `null` by the parent): the
152
+ default value was set back at once
153
+ - a change of the model or of `disabled` no longer processes the elements again (the default value, the
154
+ display of the model, the grouped elements and, for the autocompletes, the matching of the model)
155
+ - `foehn-autocomplete`:
156
+ - the model is subscribed only once, whatever the number of times the elements are retrieved: the value
157
+ to display was selected again for each retrieval
158
+ - the height of the suggestion list always follows `itemHeightInSuggestionListInPx`, even before the first
159
+ search returning less than 5 suggestions
160
+ - dynamic list (`isSuggestionListDynamic`): a model already set is no longer reset, even for a moment
161
+ (`modelChange` emitted `null`, then the value again), when the loaded elements do not contain it; it is
162
+ displayed once the elements loaded for it contain it, including when they are given at once with the model
163
+ - `isSuggestionListDynamic` can change at runtime: only the matching of the current kind of list is active,
164
+ the matching of the previous kind went on
165
+ - dynamic list: a model changed by the project (another value, `null`) is displayed again; once a value had been
166
+ displayed, the display no longer followed the model. The elements loaded for the search of the user still do
167
+ not replace what they type.
168
+ - `foehn-input-address` without zone.js: an address given by the parent right after the initialization of the
169
+ component (e.g. prefilled with `SessionInfoWithApplicationService.prefillForm()` for a connected user) is no
170
+ longer overwritten by the model with the default country only; the default country and the clean-up of the model
171
+ are applied after the next rendering, from the latest model.
172
+ - `foehn-input-address`: the deferred clean-up of the model (hidden address lines and post office box) applies
173
+ to the latest model, it could restore a previous value (e.g. remove the default country); nothing is
174
+ updated anymore once the component is destroyed.
175
+ - `foehn-multi-upload` and `foehn-bo-multi-upload`:
176
+ - after a failed upload (network, HTTP error), the next files are uploaded: nothing was uploaded anymore,
177
+ without any message, until the page was reloaded
178
+ - after a failed deletion (HTTP error, readonly document), the next files are deleted: nothing was deleted
179
+ anymore, and the error also reached the `ErrorHandler` as unhandled (its message is still displayed)
180
+ - `PendingUploadService.removePendingFile()`: a file which is not pending no longer removes the last pending file.
181
+ - `foehn-multi-upload` and `foehn-bo-multi-upload`: `customErrors` is used again for the errors which have a default
182
+ message (`413`, `415`, `500`, `FILENAME_TOO_LONG`, `FILENAME_SHOULD_NOT_CONTAIN`...): the default messages
183
+ overwrote the given object. Its messages can use `{fileName}` and `{fileMaxSize}`, `{fileExtensions}`,
184
+ `{maxFileNameLength}`, `{fileNameIllegalCharacters}` (as documented) as well as `%1$s` and `%2$s`.
185
+ - `UploaderHelper`: `getDefaultCustomErrors()` and `mergeCustomErrors()` are added, `createDefaultCustomErrors()` is
186
+ deprecated as it overwrites the given custom errors.
187
+ - `foehn-agenda-timeslot-panel`: when the time slots of the day change, the panel is closed again (only the
188
+ first time slots are displayed) unless the selected slot would be hidden; the list was cut while the panel
189
+ stayed open.
190
+ - `foehn-breadcrumb`: a breadcrumb updated in place is displayed again when it is emitted.
191
+ - `fromDictionary` pipe: its subscription is released when the pipe is destroyed.
192
+ - `SdkLogsService`: a log is not sent anymore once the application is destroyed (e.g. at the end of a test),
193
+ when it made the `HttpClient` throw `NG0205`.
194
+ - `ng add @dsivd/prestations-ng` works again on the Angular workspaces created since Angular 14: it failed because
195
+ `angular.json` no longer has a `defaultProject` (the dependencies are now added to every application), then
196
+ because of the comments of `tsconfig.json` (now kept, like its formatting).
18
197
 
19
198
  ## [19.1.1]
20
199
 
package/CONTRIBUTING.md CHANGED
@@ -4,9 +4,11 @@
4
4
 
5
5
  - Node 22.18+
6
6
  - npm 10.2+
7
- - Chrome or Chromium
8
7
  - G++
9
8
 
9
+ Chromium is downloaded by Puppeteer during `npm install`: it is used by the unit tests (through Playwright)
10
+ and by the e2e tests (Cypress).
11
+
10
12
  ## Developing using the Dev Tool
11
13
 
12
14
  Since version `8`, `prestations-ng` has a standalone application that allows
@@ -92,9 +94,10 @@ This project uses a set of scripts to lint and format the code, along with pre-c
92
94
 
93
95
  Important scripts are :
94
96
 
95
- - `npm run lint` : run ESLint and Prettier on all files
97
+ - `npm run lint` : run ESLint and Prettier on all files, and check the types of the TypeScript files compiled by no
98
+ build (`lint:types`: `cypress/`, which Cypress only transpiles, and the configuration files of `tsconfig.config.json`)
96
99
  - `npm run format`: run ESLint and Prettier on all files and fix errors automatically
97
- - `npm run validate`: clean and run all tests
100
+ - `npm run validate`: clean, lint and run all tests
98
101
 
99
102
  **Husky** is used as a pre-commit hook to automatically output linting and formatting errors for staged files before committing.
100
103
  In the end, this utilitary calls `npm run lint-staged` which you can also call yourself of course. To have this pre-commit hook,
@@ -218,6 +221,43 @@ export NODE_OPTIONS=--max_old_space_size=4096
218
221
 
219
222
  Use at your own risks.
220
223
 
224
+ ## Unit testing
225
+
226
+ The unit tests run with [Vitest](https://vitest.dev/) through the `@angular/build:unit-test` builder of the
227
+ Angular CLI, in the browser mode of Vitest: [Playwright](https://playwright.dev/) drives the headless Chromium
228
+ downloaded by Puppeteer (another browser can be used by setting the `CHROME_BIN` environment variable).
229
+ Neither the library nor the Dev Tool uses zone.js: the tests are **zoneless** too.
230
+
231
+ | Command | Tests |
232
+ | ------------------------- | ---------------------------------------------------------------- |
233
+ | `npm run test:lib` | library (`projects/prestations-ng/src/**/*.spec.ts`) |
234
+ | `npm run test:devtool` | Dev Tool (`src/**/*.spec.ts`) |
235
+ | `npm run test:schematics` | schematics, in Node.js (`projects/prestations-ng/schematics`) |
236
+ | `npm run test:eslint` | ESLint plugin, in Node.js (`projects/prestations-ng/src/eslint`) |
237
+ | `npm test` | builds the library, then runs all of the above |
238
+
239
+ - `ng test prestations-ng` without `--no-watch` runs the tests in watch mode.
240
+ - Only some specs: `ng test prestations-ng --no-watch --include=foehn-table` (folder or file, relative to
241
+ `projects/prestations-ng/src`), and `--filter="FoehnTableComponent"` to filter by test name.
242
+ - The configuration is in `angular.json` (`test` targets), in the `vitest-base.config.mts` file of each project and in
243
+ the `vitest-base.config.mts` file they share, at the root.
244
+ The coverage of the library is written in `projects/prestations-ng/coverage` (read by SonarQube).
245
+ - The configuration files of the tools (`.mjs`/`.mts`, e.g. `eslint.config.mjs`, `vitest-base.config.*`) are listed in
246
+ `tsconfig.config.json`, referenced by `tsconfig.json`: the IDE checks them with the options of the project instead of
247
+ its default ones. Add any new configuration file to its `files`.
248
+
249
+ ### Writing zoneless tests
250
+
251
+ - Use `vi` (`vi.spyOn()`, `vi.fn()`...), the Jest-like API of Vitest. Unlike `spyOn()` in Jasmine,
252
+ `vi.spyOn()` calls the original method: add `.mockReturnValue(...)` or `.mockImplementation(...)` to stub it.
253
+ The spies are restored before each test.
254
+ - `fakeAsync()`, `tick()`, `flush()` and `waitForAsync()` require zone.js: use `async` tests with
255
+ `await fixture.whenStable()`, or `vi.useFakeTimers()` and `await vi.advanceTimersByTimeAsync(ms)`.
256
+ - `fixture.whenStable()` waits for the change detection and the Angular pending tasks (HTTP requests...), not
257
+ for the timers.
258
+ - Without zone.js, `fixture.detectChanges()` only refreshes the views that have been notified. A test (or a test
259
+ host component) changing the state of a component must use signals, as the components do.
260
+
221
261
  ## E2E testing
222
262
 
223
263
  `Protractor` is no longer included in new Angular projects as of Angular 12.