@abgov/nx-adsp 13.30.0 → 13.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +41 -32
  2. package/package.json +1 -1
  3. package/src/generators/angular-app/angular-app.js +2 -2
  4. package/src/generators/angular-app/files/AGENTS.md__tmpl__ +16 -0
  5. package/src/generators/express-service/express-service.spec.ts +26 -13
  6. package/src/generators/express-service/schema.json +1 -1
  7. package/src/generators/react-app/files/AGENTS.md__tmpl__ +16 -0
  8. package/src/generators/react-app/react-app.js +2 -2
  9. package/src/generators/vue-admin-crud/files/src/views/__editViewFileName__.vue__tmpl__ +1 -3
  10. package/src/generators/vue-admin-crud/files/src/views/__listViewFileName__.vue__tmpl__ +33 -4
  11. package/src/generators/vue-admin-crud/schema.d.ts +2 -0
  12. package/src/generators/vue-admin-crud/schema.json +7 -8
  13. package/src/generators/vue-admin-crud/vue-admin-crud.js +6 -1
  14. package/src/generators/vue-admin-crud/vue-admin-crud.js.map +1 -1
  15. package/src/generators/vue-admin-crud/vue-admin-crud.spec.ts +74 -13
  16. package/src/generators/vue-app/files/AGENTS.md__tmpl__ +56 -11
  17. package/src/generators/vue-app/files/src/App.vue__tmpl__ +18 -4
  18. package/src/generators/vue-app/files/src/composables/useApi.spec.ts__tmpl__ +5 -3
  19. package/src/generators/vue-app/files/src/composables/useApi.ts__tmpl__ +14 -2
  20. package/src/generators/vue-app/vue-app.js +33 -6
  21. package/src/generators/vue-app/vue-app.js.map +1 -1
  22. package/src/generators/vue-app/vue-app.spec.ts +152 -17
  23. package/src/generators/vue-components/files/AGENTS.md__tmpl__ +35 -16
  24. package/src/generators/vue-components/files/src/index.ts__tmpl__ +3 -0
  25. package/src/generators/vue-components/files/src/lib/formatters.ts__tmpl__ +58 -0
  26. package/src/generators/vue-components/files/src/lib/patterns/AppLayout.spec.ts__tmpl__ +32 -0
  27. package/src/generators/vue-components/files/src/lib/patterns/AppLayout.vue__tmpl__ +28 -21
  28. package/src/generators/vue-components/files/src/lib/patterns/AppSideMenu.vue__tmpl__ +14 -3
  29. package/src/generators/vue-components/files/src/lib/patterns/FilterBar.vue__tmpl__ +7 -1
  30. package/src/generators/vue-components/files/src/lib/patterns/WorkspaceTable.vue__tmpl__ +7 -1
  31. package/src/generators/vue-components/vue-components.d.ts +1 -0
  32. package/src/generators/vue-components/vue-components.js +18 -39
  33. package/src/generators/vue-components/vue-components.js.map +1 -1
  34. package/src/generators/vue-components/vue-components.spec.ts +95 -2
  35. package/src/generators/vue-detail-view/files/src/views/__viewFileName__.vue__tmpl__ +51 -2
  36. package/src/generators/vue-detail-view/schema.d.ts +18 -0
  37. package/src/generators/vue-detail-view/schema.json +2 -2
  38. package/src/generators/vue-detail-view/vue-detail-view.js +4 -1
  39. package/src/generators/vue-detail-view/vue-detail-view.js.map +1 -1
  40. package/src/generators/vue-detail-view/vue-detail-view.spec.ts +36 -6
  41. package/src/generators/vue-intake-view/files/shared/src/views/__confirmationViewFileName__.vue__tmpl__ +60 -6
  42. package/src/generators/vue-intake-view/files/shared/src/views/__reviewViewFileName__.vue__tmpl__ +21 -0
  43. package/src/generators/vue-intake-view/schema.d.ts +10 -0
  44. package/src/generators/vue-intake-view/schema.json +12 -9
  45. package/src/generators/vue-intake-view/vue-intake-view.js +9 -3
  46. package/src/generators/vue-intake-view/vue-intake-view.js.map +1 -1
  47. package/src/generators/vue-intake-view/vue-intake-view.spec.ts +81 -12
  48. package/src/generators/vue-workspace-view/files/src/views/__viewFileName__.vue__tmpl__ +49 -1
  49. package/src/generators/vue-workspace-view/schema.d.ts +22 -0
  50. package/src/generators/vue-workspace-view/schema.json +8 -9
  51. package/src/generators/vue-workspace-view/vue-workspace-view.js +7 -1
  52. package/src/generators/vue-workspace-view/vue-workspace-view.js.map +1 -1
  53. package/src/generators/vue-workspace-view/vue-workspace-view.spec.ts +73 -7
  54. package/src/utils/paired-project.d.ts +10 -0
  55. package/src/utils/paired-project.js +125 -18
  56. package/src/utils/paired-project.js.map +1 -1
  57. package/src/utils/paired-project.spec.ts +126 -0
  58. package/src/utils/quality.js +43 -9
  59. package/src/utils/quality.js.map +1 -1
  60. package/src/utils/quality.spec.ts +35 -2
  61. package/src/utils/vue-eslint.d.ts +2 -0
  62. package/src/utils/vue-eslint.js +48 -0
  63. package/src/utils/vue-eslint.js.map +1 -0
  64. package/src/utils/vue-side-menu.d.ts +13 -1
  65. package/src/utils/vue-side-menu.js +50 -5
  66. package/src/utils/vue-side-menu.js.map +1 -1
  67. package/src/utils/vue-side-menu.spec.ts +100 -0
  68. package/src/utils/vue-tsconfig.d.ts +26 -0
  69. package/src/utils/vue-tsconfig.js +49 -0
  70. package/src/utils/vue-tsconfig.js.map +1 -0
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "resource": {
27
27
  "type": "string",
28
- "description": "API resource path segment -- the view fetches /api/<resource>?page=&limit=&search=&sortBy=&sortDir=."
28
+ "description": "API resource path segment -- the view fetches /api/v1/<resource>?page=&limit=&search=&sortBy=&sortDir=."
29
29
  },
30
30
  "route": {
31
31
  "type": "string",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "columns": {
35
35
  "type": "string",
36
- "description": "JSON array of table columns, in display order -- e.g. '[{\"key\":\"status\",\"label\":\"Status\",\"type\":\"badge\",\"sortable\":true}]'. Each item: { key, label, type?: \"text\"|\"date\"|\"currency\"|\"badge\" (default \"text\"), sortable?: boolean }. A plain array is also accepted when this generator is invoked programmatically. Nx's CLI option coercion only supports comma-separated primitive lists for array-typed schema properties, not JSON -- a JSON string is the only CLI syntax that actually survives Nx's own arg parsing for a structured list like this."
36
+ "description": "JSON array of table columns, in display order -- e.g. '[{\"key\":\"status\",\"label\":\"Status\",\"type\":\"badge\",\"sortable\":true}]'. Each item: { key, label, type?: \"text\"|\"date\"|\"currency\"|\"badge\" (default \"text\"), sortable?: boolean, options?: [{value,label}], badgeMap?: {value: badgeType} }. Supply `options` for any column whose stored value is a code, or the table renders the raw code. Supply `badgeMap` on a `badge` column to give each status its colour (e.g. {\"approved\":\"success\",\"declined\":\"emergency\"}); unmapped values render neutral. A plain array is also accepted when this generator is invoked programmatically. Nx's CLI option coercion only supports comma-separated primitive lists for array-typed schema properties, not JSON -- a JSON string is the only CLI syntax that actually survives Nx's own arg parsing for a structured list like this."
37
37
  },
38
38
  "filters": {
39
39
  "type": "string",
@@ -57,18 +57,17 @@
57
57
  "description": "Whether to generate a debounced search input above the table.",
58
58
  "default": true
59
59
  },
60
+ "icon": {
61
+ "type": "string",
62
+ "description": "Ionicon name for the generated side-menu entry, e.g. `list`. goa-work-side-menu-item renders a blank item without one.",
63
+ "default": "list"
64
+ },
60
65
  "requiresAuth": {
61
66
  "type": "boolean",
62
67
  "description": "Whether the generated route requires authentication.",
63
68
  "default": true
64
69
  }
65
70
  },
66
- "required": [
67
- "project",
68
- "name",
69
- "resource",
70
- "route",
71
- "columns"
72
- ],
71
+ "required": ["project", "name", "resource", "route", "columns"],
73
72
  "additionalProperties": false
74
73
  }
@@ -51,11 +51,16 @@ function normalizeOptions(host, options) {
51
51
  }
52
52
  function default_1(host, options) {
53
53
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
54
+ var _a;
54
55
  const normalizedOptions = normalizeOptions(host, options);
55
56
  // Idempotent -- ensures WorkspaceTable exists even in a project scaffolded
56
57
  // before vue-components carried it.
57
58
  yield (0, vue_components_1.default)(host);
58
- (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files'), normalizedOptions.projectRoot, Object.assign(Object.assign({}, normalizedOptions), { goaImportPath: (0, vue_components_1.vueComponentsImportPath)(host), tmpl: '' }));
59
+ (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files'), normalizedOptions.projectRoot, Object.assign(Object.assign({}, normalizedOptions), { goaImportPath: (0, vue_components_1.vueComponentsImportPath)(host),
60
+ // Derived here rather than tested inline in the template: EJS throws a
61
+ // ReferenceError on a bare undefined variable, so a flag the template
62
+ // reads must always be defined.
63
+ hasCodedColumns: normalizedOptions.columns.some((column) => { var _a; return (_a = column.options) === null || _a === void 0 ? void 0 : _a.length; }), hasBadgeColumns: normalizedOptions.columns.some((column) => column.type === 'badge'), tmpl: '' }));
59
64
  (0, vue_router_1.insertVueRoute)(host, normalizedOptions.projectRoot, normalizedOptions.project, {
60
65
  path: normalizedOptions.route,
61
66
  componentImportPath: `../views/${normalizedOptions.viewFileName}.vue`,
@@ -67,6 +72,7 @@ function default_1(host, options) {
67
72
  (0, vue_side_menu_1.insertSideMenuItem)(host, normalizedOptions.projectRoot, {
68
73
  label: normalizedOptions.heading,
69
74
  to: normalizedOptions.route,
75
+ icon: (_a = normalizedOptions.icon) !== null && _a !== void 0 ? _a : 'list',
70
76
  });
71
77
  yield (0, devkit_1.formatFiles)(host);
72
78
  });
@@ -1 +1 @@
1
- {"version":3,"file":"vue-workspace-view.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-workspace-view/vue-workspace-view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vue-workspace-view.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-workspace-view/vue-workspace-view.ts"],"names":[],"mappings":"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"}
@@ -125,7 +125,9 @@ describe('Vue Workspace View Generator', () => {
125
125
  expect(view).toContain('let loadSequence = 0');
126
126
  expect(view).toContain('const sequence = ++loadSequence');
127
127
  expect(view).toContain('if (sequence !== loadSequence) return;');
128
- expect(view).toContain('if (sequence === loadSequence) loading.value = false;');
128
+ expect(view).toContain(
129
+ 'if (sequence === loadSequence) loading.value = false;',
130
+ );
129
131
 
130
132
  // The debounce timer must not outlive the component.
131
133
  expect(view).toContain('onUnmounted(');
@@ -138,7 +140,7 @@ describe('Vue Workspace View Generator', () => {
138
140
  expect(view).not.toContain('Intl.');
139
141
  expect(view).not.toContain('function formatCurrency');
140
142
  expect(view).toContain(
141
- "<goa-badge type=\"information\" :content=\"String(row['status'] ?? '—')\" />",
143
+ "badgeType(columnBadgeTypes['status'], row['status'])",
142
144
  );
143
145
  // A type: 'date' column is a calendar date -- formatDate, not
144
146
  // formatDateTime, which would show an invented midnight.
@@ -205,11 +207,11 @@ describe('Vue Workspace View Generator', () => {
205
207
  await expect(
206
208
  generator(host, {
207
209
  ...baseOptions,
208
- filters: JSON.stringify([
209
- { key: 'x', label: 'X', type: 'checkbox' },
210
- ]),
210
+ filters: JSON.stringify([{ key: 'x', label: 'X', type: 'checkbox' }]),
211
211
  }),
212
- ).rejects.toThrow('--filters[].type must be "dropdown" or "date"; got "checkbox" for "x".');
212
+ ).rejects.toThrow(
213
+ '--filters[].type must be "dropdown" or "date"; got "checkbox" for "x".',
214
+ );
213
215
  });
214
216
 
215
217
  it('accepts a real array, the form a programmatic caller passes', async () => {
@@ -265,7 +267,11 @@ describe('Vue Workspace View Generator', () => {
265
267
  }, 30000);
266
268
 
267
269
  it('respects an explicit --heading and --pageSize', async () => {
268
- await generator(host, { ...baseOptions, heading: 'Grant Applications', pageSize: 50 });
270
+ await generator(host, {
271
+ ...baseOptions,
272
+ heading: 'Grant Applications',
273
+ pageSize: 50,
274
+ });
269
275
  const view = host
270
276
  .read('apps/test/src/views/ApplicationsListView.vue')
271
277
  .toString();
@@ -318,4 +324,64 @@ describe('Vue Workspace View Generator', () => {
318
324
  const after = readProjectConfiguration(host, 'test');
319
325
  expect(after).toEqual(before);
320
326
  }, 30000);
327
+
328
+ // Regression: every badge column was hardcoded type="information", so a
329
+ // declined claim rendered neutral blue -- a badge's colour is the fastest thing
330
+ // a reader takes in, so the wrong one actively misinforms.
331
+ it('maps badge values to semantic types and labels', async () => {
332
+ await generator(host, {
333
+ ...baseOptions,
334
+ columns: [
335
+ { key: 'reference', label: 'Reference' },
336
+ {
337
+ key: 'status',
338
+ label: 'Status',
339
+ type: 'badge',
340
+ options: [{ value: 'declined', label: 'Declined' }],
341
+ badgeMap: { approved: 'success', declined: 'emergency' },
342
+ },
343
+ ],
344
+ });
345
+ const view = host
346
+ .read('apps/test/src/views/ApplicationsListView.vue')
347
+ .toString();
348
+ // Quote style depends on whether formatFiles ran, so match the pairs.
349
+ expect(view).toMatch(/["']?declined["']?\s*:\s*["']emergency["']/);
350
+ expect(view).toMatch(/["']?approved["']?\s*:\s*["']success["']/);
351
+ expect(view).toContain("badgeType(columnBadgeTypes['status']");
352
+ expect(view).toContain("optionLabel(columnOptions['status']");
353
+ }, 30000);
354
+
355
+ it('renders a coded non-badge column using its label', async () => {
356
+ await generator(host, {
357
+ ...baseOptions,
358
+ columns: [
359
+ {
360
+ key: 'region',
361
+ label: 'Region',
362
+ options: [{ value: 'northwest', label: 'North west' }],
363
+ },
364
+ ],
365
+ });
366
+ const view = host
367
+ .read('apps/test/src/views/ApplicationsListView.vue')
368
+ .toString();
369
+ expect(view).toContain(
370
+ "optionLabel(columnOptions['region'], row['region'])",
371
+ );
372
+ expect(view).toContain('North west');
373
+ }, 30000);
374
+
375
+ it('omits the lookup maps entirely when no column needs them', async () => {
376
+ await generator(host, {
377
+ ...baseOptions,
378
+ columns: [{ key: 'reference', label: 'Reference' }],
379
+ });
380
+ const view = host
381
+ .read('apps/test/src/views/ApplicationsListView.vue')
382
+ .toString();
383
+ expect(view).not.toContain('columnOptions');
384
+ expect(view).not.toContain('columnBadgeTypes');
385
+ expect(view).not.toContain('optionLabel');
386
+ }, 30000);
321
387
  });
@@ -11,6 +11,16 @@ type DevProxyEntry = {
11
11
  pathRewrite: Record<string, string>;
12
12
  };
13
13
  export declare function buildDevProxyConf(nginxProxies: NginxProxyConfiguration[]): Record<string, DevProxyEntry>;
14
+ export declare const VITE_PROXY_FILENAME = "vite.proxy.cjs";
15
+ export interface ViteProxyRoute {
16
+ location: string;
17
+ target: string;
18
+ secure: boolean;
19
+ rewriteTo?: string;
20
+ }
21
+ export declare function parseViteDevProxyRoutes(source: string): ViteProxyRoute[];
22
+ export declare function viteDevProxyRoutes(nginxProxies: NginxProxyConfiguration[]): ViteProxyRoute[];
23
+ export declare function buildViteDevProxyModule(routes: ViteProxyRoute[]): string;
14
24
  export declare function resolvePairedProjectProxy(host: Tree, pairedProject: string | undefined): PairedProjectProxy | undefined;
15
25
  export interface PairedFrontendApp {
16
26
  tag: string;
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VITE_PROXY_FILENAME = void 0;
3
4
  exports.buildDevProxyConf = buildDevProxyConf;
5
+ exports.parseViteDevProxyRoutes = parseViteDevProxyRoutes;
6
+ exports.viteDevProxyRoutes = viteDevProxyRoutes;
7
+ exports.buildViteDevProxyModule = buildViteDevProxyModule;
4
8
  exports.resolvePairedProjectProxy = resolvePairedProjectProxy;
5
9
  exports.resolvePairedFrontendApp = resolvePairedFrontendApp;
6
10
  exports.applyProxyToExistingFrontend = applyProxyToExistingFrontend;
@@ -8,9 +12,10 @@ const devkit_1 = require("@nx/devkit");
8
12
  const path = require("path");
9
13
  const express_service_port_1 = require("./express-service-port");
10
14
  const frontend_app_port_1 = require("./frontend-app-port");
11
- // Builds the dev-server proxy JSON (vite.proxy.json / proxy.conf.json) from a set of nginx
12
- // proxy entries. Shared by vue-app, react-app, angular-app, and the retroactive express-service
13
- // proxy wiring so the format stays consistent.
15
+ // Builds the webpack-dev-server proxy JSON (proxy.conf.json) from a set of nginx proxy
16
+ // entries. React/Angular only -- their dev servers are webpack-based and do honour
17
+ // `pathRewrite`. Vue goes through buildViteDevProxyModule instead; see the note there for
18
+ // why a JSON file cannot work for Vite.
14
19
  function buildDevProxyConf(nginxProxies) {
15
20
  return nginxProxies.reduce((proxyConf, nginxProxy) => {
16
21
  const upstreamUrl = new URL(nginxProxy.proxyPass);
@@ -25,6 +30,82 @@ function buildDevProxyConf(nginxProxies) {
25
30
  return Object.assign(Object.assign({}, proxyConf), { [nginxProxy.location]: entry });
26
31
  }, {});
27
32
  }
33
+ // Vue's dev proxy filename. A module, not JSON -- see buildViteDevProxyModule.
34
+ exports.VITE_PROXY_FILENAME = 'vite.proxy.cjs';
35
+ // Extracts the routes out of a previously generated vite proxy module, so a second paired
36
+ // project merges into the file instead of replacing it. Regex rather than a parser because
37
+ // this module's shape is entirely generator-owned (see buildViteDevProxyModule) and never
38
+ // hand-authored -- and it returns [] on anything it doesn't recognise, so the caller can
39
+ // tell "no routes" from "not our format" by comparing against file existence.
40
+ //
41
+ // Tolerates the trailing comma and multi-line layout formatFiles introduces: the file on
42
+ // disk is the *formatted* output, not the string this module emitted, and a regex anchored
43
+ // on `}` immediately after the last field silently matches nothing there -- which would
44
+ // drop every existing route the next time a project is paired.
45
+ function parseViteDevProxyRoutes(source) {
46
+ const routes = [];
47
+ const entry = /\{\s*location:\s*'([^']+)',\s*target:\s*'([^']+)',\s*secure:\s*(true|false)(?:,\s*rewriteTo:\s*'([^']*)')?\s*,?\s*\}/g;
48
+ let match;
49
+ while ((match = entry.exec(source)) !== null) {
50
+ routes.push(Object.assign({ location: match[1], target: match[2], secure: match[3] === 'true' }, (match[4] ? { rewriteTo: match[4] } : {})));
51
+ }
52
+ return routes;
53
+ }
54
+ function viteDevProxyRoutes(nginxProxies) {
55
+ return nginxProxies.map((nginxProxy) => {
56
+ const upstreamUrl = new URL(nginxProxy.proxyPass);
57
+ return Object.assign({ location: nginxProxy.location, target: `${upstreamUrl.protocol}//localhost${upstreamUrl.port ? ':' + upstreamUrl.port : ''}`, secure: upstreamUrl.protocol === 'https:' }, (upstreamUrl.pathname.length > 1
58
+ ? { rewriteTo: upstreamUrl.pathname }
59
+ : {}));
60
+ });
61
+ }
62
+ // Builds the Vue dev-server proxy as a CommonJS module rather than JSON.
63
+ //
64
+ // Vite's proxy honours a `rewrite` FUNCTION and has nothing named `pathRewrite` -- that is
65
+ // http-proxy-middleware/webpack-dev-server syntax. Vite ignores unknown keys silently, so a
66
+ // JSON file carrying `pathRewrite` produces a dev server that proxies to the right host and
67
+ // then forwards the path unrewritten: every generated API call 404s, with no warning
68
+ // anywhere. A JSON file cannot express the fix, because the fix is a function.
69
+ //
70
+ // @nx/vite `require()`s whatever `proxyConfig` names (getViteServerProxyConfigPath only
71
+ // checks existsSync), so a module works and can hold the function. `.cjs`, not `.js`, so it
72
+ // stays CommonJS even if the consuming workspace sets `"type": "module"`.
73
+ //
74
+ // Emitted as data-plus-loop rather than a literal per entry so a second paired project can
75
+ // be merged by appending one row -- see parseViteDevProxyRoutes.
76
+ function buildViteDevProxyModule(routes) {
77
+ const rows = routes
78
+ .map(({ location, target, secure, rewriteTo }) => ` { location: '${location}', target: '${target}', secure: ${secure}` +
79
+ `${rewriteTo ? `, rewriteTo: '${rewriteTo}'` : ''} },`)
80
+ .join('\n');
81
+ return `// Vite dev-server proxy. Generated by @abgov/nx-adsp.
82
+ //
83
+ // A CommonJS module, not JSON, because Vite rewrites a proxied path with a \`rewrite\`
84
+ // function. The webpack-dev-server key for this is a different name that Vite does not
85
+ // implement, and it ignores unknown keys silently -- so a JSON proxy file forwards the
86
+ // path unrewritten and every API call 404s.
87
+ //
88
+ // Add a route by appending a row below; \`rewriteTo\` replaces the matched \`location\`
89
+ // prefix (so '/api/' -> '/my-service/' turns /api/v1/things into /my-service/v1/things).
90
+ const routes = [
91
+ ${rows}
92
+ ];
93
+
94
+ module.exports = Object.fromEntries(
95
+ routes.map(({ location, target, secure, rewriteTo }) => [
96
+ location,
97
+ {
98
+ target,
99
+ secure,
100
+ changeOrigin: false,
101
+ ...(rewriteTo
102
+ ? { rewrite: (urlPath) => urlPath.replace(new RegExp('^' + location), rewriteTo) }
103
+ : {}),
104
+ },
105
+ ]),
106
+ );
107
+ `;
108
+ }
28
109
  const PAIRED_PROJECT_LOCATION = '/api/';
29
110
  // Resolves a frontend's --pairedProject into the nginx/dev-server proxy entry that routes API
30
111
  // calls to it, plus the `adsp:proxy-service:<name>:<port>` tag the sandbox executor reads to
@@ -68,13 +149,13 @@ function resolvePairedFrontendApp(host, pairedProject) {
68
149
  // frontend generator does when the frontend runs first. Safe to call when the frontend doesn't
69
150
  // exist yet (composite generator ordering — backend is scaffolded before frontend); returns early.
70
151
  function applyProxyToExistingFrontend(host, pairedFrontend, backendProjectName) {
71
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
152
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
72
153
  const frontendName = (0, devkit_1.names)(pairedFrontend).fileName;
73
154
  let frontendConfig;
74
155
  try {
75
156
  frontendConfig = (0, devkit_1.readProjectConfiguration)(host, frontendName);
76
157
  }
77
- catch (_k) {
158
+ catch (_m) {
78
159
  // Frontend not scaffolded yet (composite generator ordering).
79
160
  return;
80
161
  }
@@ -118,33 +199,59 @@ function applyProxyToExistingFrontend(host, pairedFrontend, backendProjectName)
118
199
  existingNginx.slice(serverCloseIdx));
119
200
  }
120
201
  }
121
- // 2. Write (or merge into) the dev proxy config file.
122
- const devProxyFilename = isVue ? 'vite.proxy.json' : 'proxy.conf.json';
202
+ // 2. Write (or merge into) the dev proxy config file. Vue gets a .cjs module
203
+ // (Vite needs a `rewrite` function, which JSON cannot hold); React/Angular
204
+ // keep the webpack-dev-server JSON, which does honour `pathRewrite`.
205
+ const devProxyFilename = isVue ? exports.VITE_PROXY_FILENAME : 'proxy.conf.json';
123
206
  const devProxyPath = path.join(projectRoot, devProxyFilename);
124
- const existingProxy = host.exists(devProxyPath)
125
- ? (0, devkit_1.readJson)(host, devProxyPath)
126
- : {};
127
- if (!existingProxy[nginxProxy.location]) {
128
- (0, devkit_1.writeJson)(host, devProxyPath, Object.assign(Object.assign({}, existingProxy), buildDevProxyConf([nginxProxy])));
207
+ if (isVue) {
208
+ const existingSource = (_d = (_c = host.read(devProxyPath)) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '';
209
+ const existingRoutes = parseViteDevProxyRoutes(existingSource);
210
+ const alreadyRouted = existingRoutes.some((route) => route.location === nginxProxy.location);
211
+ // Rewrites the whole module from the union rather than splicing a row in:
212
+ // the format is generator-owned, so regenerating is safer than editing.
213
+ if (!alreadyRouted) {
214
+ host.write(devProxyPath, buildViteDevProxyModule([
215
+ ...existingRoutes,
216
+ ...viteDevProxyRoutes([nginxProxy]),
217
+ ]));
218
+ }
219
+ // A pre-existing app may still carry the inert JSON form; drop it so there
220
+ // aren't two files that look like proxy config.
221
+ const staleJsonPath = path.join(projectRoot, 'vite.proxy.json');
222
+ if (host.exists(staleJsonPath)) {
223
+ host.delete(staleJsonPath);
224
+ }
225
+ }
226
+ else {
227
+ const existingProxy = host.exists(devProxyPath)
228
+ ? (0, devkit_1.readJson)(host, devProxyPath)
229
+ : {};
230
+ if (!existingProxy[nginxProxy.location]) {
231
+ (0, devkit_1.writeJson)(host, devProxyPath, Object.assign(Object.assign({}, existingProxy), buildDevProxyConf([nginxProxy])));
232
+ }
129
233
  }
130
234
  // 3. Patch the frontend's project configuration.
131
235
  const proxyTag = `adsp:proxy-service:${backendService}:${port}`;
132
- if (!((_c = frontendConfig.tags) !== null && _c !== void 0 ? _c : []).includes(proxyTag)) {
133
- frontendConfig.tags = [...((_d = frontendConfig.tags) !== null && _d !== void 0 ? _d : []), proxyTag];
236
+ if (!((_e = frontendConfig.tags) !== null && _e !== void 0 ? _e : []).includes(proxyTag)) {
237
+ frontendConfig.tags = [...((_f = frontendConfig.tags) !== null && _f !== void 0 ? _f : []), proxyTag];
134
238
  }
135
- if (((_f = (_e = frontendConfig.targets) === null || _e === void 0 ? void 0 : _e.serve) === null || _f === void 0 ? void 0 : _f.options) &&
239
+ if (((_h = (_g = frontendConfig.targets) === null || _g === void 0 ? void 0 : _g.serve) === null || _h === void 0 ? void 0 : _h.options) &&
136
240
  !frontendConfig.targets.serve.options.proxyConfig) {
137
241
  frontendConfig.targets.serve.options = Object.assign(Object.assign({}, frontendConfig.targets.serve.options), { proxyConfig: devProxyPath });
138
242
  }
139
243
  // React/Angular only: add nginx.conf as a webpack build asset so it lands in the output root.
140
244
  // Vue's @nx/vite:build copies public/ automatically — no asset glob needed.
141
- if (isRootNginx && ((_h = (_g = frontendConfig.targets) === null || _g === void 0 ? void 0 : _g.build) === null || _h === void 0 ? void 0 : _h.options)) {
142
- const assets = (_j = frontendConfig.targets.build.options.assets) !== null && _j !== void 0 ? _j : [];
245
+ if (isRootNginx && ((_k = (_j = frontendConfig.targets) === null || _j === void 0 ? void 0 : _j.build) === null || _k === void 0 ? void 0 : _k.options)) {
246
+ const assets = (_l = frontendConfig.targets.build.options.assets) !== null && _l !== void 0 ? _l : [];
143
247
  const hasNginxAsset = assets.some((a) => typeof a === 'object' &&
144
248
  a.glob === 'nginx.conf' &&
145
249
  a.input === projectRoot);
146
250
  if (!hasNginxAsset) {
147
- frontendConfig.targets.build.options = Object.assign(Object.assign({}, frontendConfig.targets.build.options), { assets: [...assets, { glob: 'nginx.conf', input: projectRoot, output: './' }] });
251
+ frontendConfig.targets.build.options = Object.assign(Object.assign({}, frontendConfig.targets.build.options), { assets: [
252
+ ...assets,
253
+ { glob: 'nginx.conf', input: projectRoot, output: './' },
254
+ ] });
148
255
  }
149
256
  }
150
257
  (0, devkit_1.updateProjectConfiguration)(host, frontendName, frontendConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"paired-project.js","sourceRoot":"","sources":["../../../../../packages/nx-adsp/src/utils/paired-project.ts"],"names":[],"mappings":";;AA4BA,8CAmBC;AAWD,8DAiBC;AAYD,4DAWC;AAMD,oEA4GC;AApND,uCAOoB;AACpB,6BAA6B;AAC7B,iEAAsE;AACtE,2DAAgE;AAehE,2FAA2F;AAC3F,gGAAgG;AAChG,+CAA+C;AAC/C,SAAgB,iBAAiB,CAC/B,YAAuC;IAEvC,OAAO,YAAY,CAAC,MAAM,CACxB,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE;QACxB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAClD,MAAM,KAAK,GAAkB;YAC3B,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,cAAc,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7F,MAAM,EAAE,WAAW,CAAC,QAAQ,KAAK,QAAQ;YACzC,YAAY,EAAE,KAAK;YACnB,WAAW,EACT,WAAW,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAC7B,CAAC,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC,EAAE,WAAW,CAAC,QAAQ,EAAE;gBACvD,CAAC,CAAC,EAAE;SACT,CAAC;QACF,uCAAY,SAAS,KAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,KAAK,IAAG;IACxD,CAAC,EACD,EAAmC,CACpC,CAAC;AACJ,CAAC;AAED,MAAM,uBAAuB,GAAG,OAAO,CAAC;AAExC,8FAA8F;AAC9F,6FAA6F;AAC7F,uFAAuF;AACvF,2FAA2F;AAC3F,iGAAiG;AACjG,gGAAgG;AAChG,2EAA2E;AAC3E,SAAgB,yBAAyB,CACvC,IAAU,EACV,aAAiC;IAEjC,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,aAAa,GAAG,IAAA,cAAK,EAAC,aAAa,CAAC,CAAC,QAAQ,CAAC;IACpD,IAAA,iCAAwB,EAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,mDAA4B,CAAC;IAC1C,OAAO;QACL,KAAK,EAAE;YACL,QAAQ,EAAE,uBAAuB;YACjC,SAAS,EAAE,UAAU,aAAa,IAAI,IAAI,IAAI,aAAa,GAAG;SAC/D;QACD,GAAG,EAAE,sBAAsB,aAAa,IAAI,IAAI,EAAE;KACnD,CAAC;AACJ,CAAC;AAMD,8FAA8F;AAC9F,uFAAuF;AACvF,8FAA8F;AAC9F,+FAA+F;AAC/F,2FAA2F;AAC3F,+EAA+E;AAC/E,SAAgB,wBAAwB,CACtC,IAAU,EACV,aAAiC;IAEjC,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAG,IAAA,cAAK,EAAC,aAAa,CAAC,CAAC,QAAQ,CAAC;IAChD,OAAO;QACL,GAAG,EAAE,wBAAwB,SAAS,IAAI,6CAAyB,EAAE;KACtE,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,4FAA4F;AAC5F,+FAA+F;AAC/F,mGAAmG;AACnG,SAAgB,4BAA4B,CAC1C,IAAU,EACV,cAAsB,EACtB,kBAA0B;;IAE1B,MAAM,YAAY,GAAG,IAAA,cAAK,EAAC,cAAc,CAAC,CAAC,QAAQ,CAAC;IACpD,IAAI,cAAc,CAAC;IACnB,IAAI,CAAC;QACH,cAAc,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAChE,CAAC;IAAC,WAAM,CAAC;QACP,8DAA8D;QAC9D,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC;IACxC,MAAM,IAAI,GAAG,mDAA4B,CAAC;IAC1C,MAAM,cAAc,GAAG,IAAA,cAAK,EAAC,kBAAkB,CAAC,CAAC,QAAQ,CAAC;IAC1D,MAAM,UAAU,GAA4B;QAC1C,QAAQ,EAAE,uBAAuB;QACjC,SAAS,EAAE,UAAU,cAAc,IAAI,IAAI,IAAI,cAAc,GAAG;KACjE,CAAC;IAEF,6FAA6F;IAC7F,0FAA0F;IAC1F,6DAA6D;IAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1E,MAAM,WAAW,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,wFAAwF;IACxF,MAAM,aAAa,GAAG,KAAK;QACzB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC;QAChD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,0CAAE,QAAQ,EAAE,mCAAI,EAAE,CAAC;IACjE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAY,UAAU,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG;YACjB,gBAAgB,UAAU,CAAC,QAAQ,IAAI;YACvC,oBAAoB,UAAU,CAAC,SAAS,GAAG;YAC3C,oCAAoC;YACpC,oEAAoE;YACpE,mEAAmE;YACnE,OAAO;YACP,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,iFAAiF;QACjF,kEAAkE;QAClE,MAAM,cAAc,GAAG,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,cAAc,KAAK,CAAC,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,CACR,aAAa,EACb,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC;gBACpC,IAAI;gBACJ,UAAU;gBACV,aAAa,CAAC,KAAK,CAAC,cAAc,CAAC,CACtC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACvE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC9D,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;QAC7C,CAAC,CAAC,IAAA,iBAAQ,EAA0B,IAAI,EAAE,YAAY,CAAC;QACvD,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,IAAA,kBAAS,EAAC,IAAI,EAAE,YAAY,kCACvB,aAAa,GACb,iBAAiB,CAAC,CAAC,UAAU,CAAC,CAAC,EAClC,CAAC;IACL,CAAC;IAED,iDAAiD;IACjD,MAAM,QAAQ,GAAG,sBAAsB,cAAc,IAAI,IAAI,EAAE,CAAC;IAChE,IAAI,CAAC,CAAC,MAAA,cAAc,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,cAAc,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAA,cAAc,CAAC,IAAI,mCAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IACnE,CAAC;IAED,IACE,CAAA,MAAA,MAAA,cAAc,CAAC,OAAO,0CAAE,KAAK,0CAAE,OAAO;QACtC,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EACjD,CAAC;QACD,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,mCAC/B,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,KACvC,WAAW,EAAE,YAAY,GAC1B,CAAC;IACJ,CAAC;IAED,8FAA8F;IAC9F,4EAA4E;IAC5E,IAAI,WAAW,KAAI,MAAA,MAAA,cAAc,CAAC,OAAO,0CAAE,KAAK,0CAAE,OAAO,CAAA,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAc,MAAA,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,mCAAI,EAAE,CAAC;QAC5E,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,CAAC,KAAK,QAAQ;YACpB,CAAuB,CAAC,IAAI,KAAK,YAAY;YAC7C,CAAwB,CAAC,KAAK,KAAK,WAAW,CAClD,CAAC;QACF,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,mCAC/B,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,KACvC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAC9E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAA,mCAA0B,EAAC,IAAI,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;AACjE,CAAC"}
1
+ {"version":3,"file":"paired-project.js","sourceRoot":"","sources":["../../../../../packages/nx-adsp/src/utils/paired-project.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import {
2
+ buildViteDevProxyModule,
3
+ parseViteDevProxyRoutes,
4
+ viteDevProxyRoutes,
5
+ ViteProxyRoute,
6
+ } from './paired-project';
7
+
8
+ // Evaluates the emitted module the way @nx/vite does (it `require()`s the file
9
+ // named by proxyConfig), so these assert what Vite will actually receive rather
10
+ // than the text of a config that has to behave.
11
+ function loadProxy(source: string) {
12
+ const module = { exports: {} };
13
+ new Function('module', 'exports', source)(module, module.exports);
14
+ return module.exports as Record<
15
+ string,
16
+ { target: string; secure: boolean; rewrite?: (path: string) => string }
17
+ >;
18
+ }
19
+
20
+ describe('vite dev proxy module', () => {
21
+ const route: ViteProxyRoute = {
22
+ location: '/api/',
23
+ target: 'http://localhost:3333',
24
+ secure: false,
25
+ rewriteTo: '/my-service/',
26
+ };
27
+
28
+ it('rewrites the location prefix to the service mount point', () => {
29
+ const proxy = loadProxy(buildViteDevProxyModule([route]));
30
+ expect(proxy['/api/'].target).toBe('http://localhost:3333');
31
+ expect(proxy['/api/'].rewrite?.('/api/v1/things')).toBe(
32
+ '/my-service/v1/things',
33
+ );
34
+ });
35
+
36
+ it('replaces only the leading occurrence of the location', () => {
37
+ const proxy = loadProxy(buildViteDevProxyModule([route]));
38
+ expect(proxy['/api/'].rewrite?.('/api/a/api/b')).toBe('/my-service/a/api/b');
39
+ });
40
+
41
+ it('omits rewrite entirely when the upstream has no path prefix', () => {
42
+ const proxy = loadProxy(
43
+ buildViteDevProxyModule([
44
+ { location: '/api/', target: 'http://localhost:3333', secure: false },
45
+ ]),
46
+ );
47
+ expect(proxy['/api/'].rewrite).toBeUndefined();
48
+ });
49
+
50
+ it('derives routes from an nginx proxy configuration', () => {
51
+ const [derived] = viteDevProxyRoutes([
52
+ { location: '/api/', proxyPass: 'http://my-service:3333/my-service/' },
53
+ ]);
54
+ expect(derived).toEqual({
55
+ location: '/api/',
56
+ target: 'http://localhost:3333',
57
+ secure: false,
58
+ rewriteTo: '/my-service/',
59
+ });
60
+ });
61
+
62
+ describe('parseViteDevProxyRoutes', () => {
63
+ it('round-trips what buildViteDevProxyModule emits', () => {
64
+ expect(parseViteDevProxyRoutes(buildViteDevProxyModule([route]))).toEqual([
65
+ route,
66
+ ]);
67
+ });
68
+
69
+ // The file on disk is the *formatted* output, not the string the builder
70
+ // returned: formatFiles reflows each row across lines and adds a trailing
71
+ // comma. A regex anchored on `}` immediately after the last field matches
72
+ // nothing here, and the merge path would then drop every existing route --
73
+ // silently un-pairing an already-paired frontend.
74
+ it('parses the multi-line, trailing-comma layout formatFiles produces', () => {
75
+ const formatted = `const routes = [
76
+ {
77
+ location: '/api/',
78
+ target: 'http://localhost:3333',
79
+ secure: false,
80
+ rewriteTo: '/my-service/',
81
+ },
82
+ ];
83
+ `;
84
+ expect(parseViteDevProxyRoutes(formatted)).toEqual([route]);
85
+ });
86
+
87
+ it('parses a formatted row that has no rewriteTo', () => {
88
+ const formatted = `const routes = [
89
+ {
90
+ location: '/api/',
91
+ target: 'http://localhost:3333',
92
+ secure: false,
93
+ },
94
+ ];
95
+ `;
96
+ expect(parseViteDevProxyRoutes(formatted)).toEqual([
97
+ { location: '/api/', target: 'http://localhost:3333', secure: false },
98
+ ]);
99
+ });
100
+
101
+ it('preserves an existing route when a second is appended', () => {
102
+ const first = buildViteDevProxyModule([route]);
103
+ const merged = buildViteDevProxyModule([
104
+ ...parseViteDevProxyRoutes(first),
105
+ {
106
+ location: '/other/',
107
+ target: 'http://localhost:4444',
108
+ secure: false,
109
+ rewriteTo: '/other-service/',
110
+ },
111
+ ]);
112
+ const proxy = loadProxy(merged);
113
+ expect(Object.keys(proxy)).toEqual(['/api/', '/other/']);
114
+ expect(proxy['/api/'].rewrite?.('/api/v1/x')).toBe('/my-service/v1/x');
115
+ expect(proxy['/other/'].rewrite?.('/other/v1/y')).toBe(
116
+ '/other-service/v1/y',
117
+ );
118
+ });
119
+
120
+ it('returns no routes for a file that is not this format', () => {
121
+ expect(parseViteDevProxyRoutes('{ "/api/": { "target": "x" } }')).toEqual(
122
+ [],
123
+ );
124
+ });
125
+ });
126
+ });
@@ -138,17 +138,51 @@ import AxeBuilder from '@axe-core/playwright';
138
138
  // here means the WCAG 2.1 A/AA baseline, not full accessibility conformance.
139
139
  const WCAG_TAGS = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'];
140
140
 
141
- test('has no WCAG 2.1 A/AA accessibility violations', async ({ page }) => {
142
- await page.goto('/');
141
+ // ADD YOUR ROUTES HERE. Coverage is exactly this list — a route that is not in
142
+ // it is never checked, so this array, not the spec, is what decides how much of
143
+ // the app is actually held to the WCAG baseline.
144
+ //
145
+ // It ships with only '/' because that is the sole route a freshly generated app
146
+ // has. Do not read a green run against it as a meaningful result: the landing
147
+ // page is mostly app shell, so it exercises almost none of the goa-* elements
148
+ // the rest of the app is built from — tables, dropdowns, date pickers,
149
+ // steppers, side-menu items, form steps. Those are where accessibility defects
150
+ // actually live.
151
+ //
152
+ // Nothing keeps this list in sync for you. Routes arrive both from the
153
+ // \`nx g @abgov/nx-adsp:vue-*-view\` generators and from hand-editing the router,
154
+ // and no generator writes to this file — it is deliberately left alone once it
155
+ // exists so your edits survive re-running them. Adding a route to the router and
156
+ // not adding it here is the normal way this check silently stops covering the
157
+ // app.
158
+ //
159
+ // Two things to watch when you add one:
160
+ //
161
+ // - Point at a path that renders real content. A detail or edit route needs an
162
+ // id that resolves against whatever the dev server talks to; otherwise the
163
+ // view renders its error state and the check passes against an empty screen.
164
+ // - Triage a failure before assuming it is yours. Some violations come from
165
+ // inside @abgov/web-components' own shadow DOM (a decorative icon with
166
+ // \`role="img"\` and an empty \`aria-label\`, a \`role="menuitem"\` with no menu
167
+ // parent) and cannot be fixed from app code. Those need an upstream fix or a
168
+ // documented exclusion — not a workaround in your view.
169
+ const ROUTES = ['/'];
143
170
 
144
- const results = await new AxeBuilder({ page }).withTags(WCAG_TAGS).analyze();
171
+ for (const route of ROUTES) {
172
+ test(\`has no WCAG 2.1 A/AA accessibility violations: \${route}\`, async ({
173
+ page,
174
+ }) => {
175
+ await page.goto(route);
145
176
 
146
- const summary = results.violations.map(
147
- (v) =>
148
- \`[\${v.impact}] \${v.id}: \${v.help} (\${v.nodes.length} node(s)) \${v.helpUrl}\`,
149
- );
150
- expect(summary, summary.join('\\n')).toEqual([]);
151
- });
177
+ const results = await new AxeBuilder({ page }).withTags(WCAG_TAGS).analyze();
178
+
179
+ const summary = results.violations.map(
180
+ (v) =>
181
+ \`[\${v.impact}] \${v.id}: \${v.help} (\${v.nodes.length} node(s)) \${v.helpUrl}\`,
182
+ );
183
+ expect(summary, \`\${route}\\n\${summary.join('\\n')}\`).toEqual([]);
184
+ });
185
+ }
152
186
  `;
153
187
  /**
154
188
  * Writes a Playwright + axe-core accessibility spec into the generated e2e