|
23 | 23 | * 2. every leaf of the four committed `objects` bundles; |
24 | 24 | * 3. the type-level `label` / `description` of the four `metadataForms` |
25 | 25 | * bundles — the sentence a Setup metadata page (Positions, Capabilities, |
26 | | - * Permission Sets) shows under its title. Section descriptions and field |
27 | | - * `helpText` of those forms are the spec's form copy and are not judged |
28 | | - * here; |
| 26 | + * Permission Sets) shows under its title, plus the six form leaves named |
| 27 | + * in `FORM_HELP_LEAVES` (the Permission Sets and Positions help texts and |
| 28 | + * the view form's End-user controls description). The other section |
| 29 | + * descriptions and field `helpText` of those forms are the spec's form |
| 30 | + * copy and are not judged here; |
29 | 31 | * 4. `SETUP_APP` and this package's `SETUP_NAV_CONTRIBUTIONS`, and the |
30 | 32 | * hand-authored `apps.setup` subtree of each locale. |
31 | 33 | * |
@@ -172,6 +174,55 @@ describe('Setup copy carries no design-record vocabulary', () => { |
172 | 174 | expect(offenders(strings)).toEqual([]); |
173 | 175 | }); |
174 | 176 |
|
| 177 | + // The help texts an admin reads on Setup's Permission Sets and Positions edit |
| 178 | + // forms, and the view form's End-user controls section. Each one carried a |
| 179 | + // decision-record reference until the spec form source moved it into the |
| 180 | + // comment beside the row; `en` is regenerated from that source, so judging |
| 181 | + // the four bundles judges the source too. |
| 182 | + const FORM_HELP_LEAVES = [ |
| 183 | + ['permission', 'fields', 'isDefault', 'helpText'], |
| 184 | + ['permission', 'fields', 'managedBy', 'helpText'], |
| 185 | + ['permission', 'fields', 'packageId', 'helpText'], |
| 186 | + ['permission', 'fields', 'adminScope', 'helpText'], |
| 187 | + ['position', 'fields', 'delegatable', 'helpText'], |
| 188 | + ['view', 'sections', 'end_user_controls', 'description'], |
| 189 | + ] as const; |
| 190 | + |
| 191 | + function formHelpLeaves(bundle: unknown, locale: string): Array<[string, string]> { |
| 192 | + return FORM_HELP_LEAVES.map((path) => { |
| 193 | + const value = path.reduce<unknown>((node, key) => (node as Record<string, unknown> | undefined)?.[key], bundle); |
| 194 | + const at = `${locale}.metadataForms.${path.join('.')}`; |
| 195 | + expect(value, `${at} is in the population`).toBeTypeOf('string'); |
| 196 | + return [at, value as string]; |
| 197 | + }); |
| 198 | + } |
| 199 | + |
| 200 | + it.each(Object.keys(FORM_BUNDLES))('the Permission Set, Position and view form help texts of the %s metadataForms bundle', (locale) => { |
| 201 | + const strings = formHelpLeaves(FORM_BUNDLES[locale as keyof typeof FORM_BUNDLES], locale); |
| 202 | + expect(strings).toHaveLength(FORM_HELP_LEAVES.length); |
| 203 | + expect(offenders(strings)).toEqual([]); |
| 204 | + }); |
| 205 | + |
| 206 | + it('the form help-text assertion fires on the prose it replaced', () => { |
| 207 | + // Dark leg: the same walk over a bundle carrying the replaced wording must |
| 208 | + // name every leaf, so a walk that reaches nothing cannot pass above. |
| 209 | + const replaced = { |
| 210 | + permission: { fields: { |
| 211 | + isDefault: { helpText: 'App baseline for the everyone position (ADR-0090 D5): an app-level set is auto-bound at boot.' }, |
| 212 | + managedBy: { helpText: 'Record provenance (ADR-0086 D3): who owns this set across upgrades.' }, |
| 213 | + packageId: { helpText: 'Owning package id for a package-shipped set (ADR-0086 D3).' }, |
| 214 | + adminScope: { helpText: 'Delegated administration (ADR-0090 D12): lets holders of this set administer one business-unit subtree.' }, |
| 215 | + } }, |
| 216 | + position: { fields: { |
| 217 | + delegatable: { helpText: 'Holders may delegate this position themselves, time-boxed and with a reason (ADR-0091 D3).' }, |
| 218 | + } }, |
| 219 | + view: { sections: { |
| 220 | + end_user_controls: { description: 'What end users can do on this view (ADR-0047, Airtable Interface parity).' }, |
| 221 | + } }, |
| 222 | + }; |
| 223 | + expect(offenders(formHelpLeaves(replaced, 'replaced'))).toHaveLength(FORM_HELP_LEAVES.length); |
| 224 | + }); |
| 225 | + |
175 | 226 | it('the Setup app, its nav contributions, and every locale\'s apps.setup translations', () => { |
176 | 227 | const strings: Array<[string, string]> = []; |
177 | 228 | copyStrings(SETUP_APP, 'SETUP_APP', strings); |
|
0 commit comments