@hmcts/media-viewer 4.2.37 → 4.2.38-innerhtml-security-update
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/.yarn/install-state.gz +0 -0
- package/README.md +24 -19
- package/fesm2022/hmcts-media-viewer.mjs +49 -16
- package/fesm2022/hmcts-media-viewer.mjs.map +1 -1
- package/index.d.ts +3 -1
- package/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/package.tgz +0 -0
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/README.md
CHANGED
|
@@ -245,18 +245,18 @@ Stop the local processes with `Ctrl+C`, then clean up Redis from the ICP worktre
|
|
|
245
245
|
`docker compose -f docker-compose.yml down`.
|
|
246
246
|
|
|
247
247
|
### 5. Run Playwright tests
|
|
248
|
-
Media Viewer
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
coverage should be added under `playwright_tests/`.
|
|
248
|
+
Media Viewer uses the Playwright runner and reporting shape used in MC and MO.
|
|
249
|
+
The CodeceptJS and Protractor/Cucumber runners are retired. New browser coverage
|
|
250
|
+
belongs under `playwright_tests/`.
|
|
252
251
|
|
|
253
252
|
Current Playwright lanes:
|
|
254
253
|
|
|
255
254
|
| Lane | Config/project | Command | Scope |
|
|
256
255
|
| --- | --- | --- | --- |
|
|
257
256
|
| Standalone smoke | `playwright.config.ts`, project `smoke` | `yarn test:playwright:smoke` or `yarn test:smoke` | One readiness contract: loads a standalone PDF and proves the rendered viewer, first page and canvas are usable. |
|
|
258
|
-
| Migrated functional | `playwright.config.ts`, project `functional` | `yarn test:playwright:functional` |
|
|
257
|
+
| Migrated functional | `playwright.config.ts`, project `functional` | `yarn test:playwright:functional` | 84 default fixture-backed browser contracts across 13 feature files, with 86 discoverable when the two EXUI-5124 image-annotation contracts are explicitly included. Multimedia coverage is Chromium-only; external AAT/CCD contracts are separate diagnostics and are not migration assurance. See [`playwright_tests/functional/README.md`](playwright_tests/functional/README.md). |
|
|
259
258
|
| External service diagnostics | `playwright.config.ts`, opt-in project `external-service-contracts` | `yarn test:playwright:external-service-contracts` | Optional live AAT CCD/DM Store/annotation probes for a deliberate environment investigation. The default command executes 6 non-defect service contracts; four CCD browser-route contracts tagged against [EXUI-5122](https://tools.hmcts.net/jira/browse/EXUI-5122) and [EXUI-5123](https://tools.hmcts.net/jira/browse/EXUI-5123) remain discoverable but are excluded by default. Use `PLAYWRIGHT_INCLUDE_KNOWN_DEFECTS=true` to discover and execute all 10. They are never part of normal PR assurance. |
|
|
259
|
+
| Cross-browser smoke | `playwright.config.ts`, projects `smoke-firefox` and `smoke-webkit` | `yarn test:crossbrowser` | Runs the same readiness contract in Firefox and WebKit and publishes separate JUnit/Odhín output under `functional-output/tests/playwright-crossbrowser`. |
|
|
260
260
|
| Viewer support | `playwright.config.ts`, project `support` | `yarn test:playwright:support` | Proves the reusable PDF, image and unsupported-media fixtures, component objects and response diagnostics. |
|
|
261
261
|
|
|
262
262
|
The current migration slice is deliberately separated from smoke: smoke proves
|
|
@@ -274,10 +274,10 @@ route mocks. Tests must not depend on execution order or share mutable
|
|
|
274
274
|
documents; mutation-heavy AAT journeys must provision a document per test or
|
|
275
275
|
reset it before reuse.
|
|
276
276
|
|
|
277
|
-
Install
|
|
277
|
+
Install the Playwright browsers once before local runs when the browser cache is empty:
|
|
278
278
|
|
|
279
279
|
```
|
|
280
|
-
yarn test:setup:playwright-install-
|
|
280
|
+
yarn test:setup:playwright-install-browsers
|
|
281
281
|
```
|
|
282
282
|
|
|
283
283
|
Run the smoke project against a running standalone demo app. Start the app in
|
|
@@ -291,12 +291,16 @@ Then run the smoke in another terminal:
|
|
|
291
291
|
|
|
292
292
|
```
|
|
293
293
|
yarn test:playwright:smoke
|
|
294
|
+
# unified Playwright accessibility pack (Axe, WAVE-like, screen-reader-like)
|
|
295
|
+
yarn test:a11y
|
|
296
|
+
# Firefox and WebKit smoke gate
|
|
297
|
+
yarn test:crossbrowser
|
|
294
298
|
```
|
|
295
299
|
|
|
296
300
|
Override the smoke document and case id with `MV_SMOKE_PDF_DOCUMENT_URL` and
|
|
297
301
|
`MV_SMOKE_CASE_ID`. `yarn test:smoke` and `yarn test:local:aat` run the
|
|
298
302
|
Playwright smoke, so the standalone and local-AAT PDF loading journeys no longer
|
|
299
|
-
|
|
303
|
+
use only the Playwright projects.
|
|
300
304
|
|
|
301
305
|
The lane wrapper commands write Playwright evidence under `functional-output/tests`:
|
|
302
306
|
|
|
@@ -305,6 +309,8 @@ The lane wrapper commands write Playwright evidence under `functional-output/tes
|
|
|
305
309
|
| Viewer support | `functional-output/tests/playwright-support/odhin-report/xui-playwright-support.html` | `functional-output/tests/playwright-support/playwright-support-junit.xml` | `functional-output/tests/playwright-support/test-results` |
|
|
306
310
|
| Smoke | `functional-output/tests/playwright-smoke/odhin-report/xui-playwright-smoke.html` | `functional-output/tests/playwright-smoke/playwright-smoke-junit.xml` | `functional-output/tests/playwright-smoke/test-results` |
|
|
307
311
|
| Migrated functional | `functional-output/tests/playwright-functional/odhin-report/xui-playwright-functional.html` | `functional-output/tests/playwright-functional/playwright-functional-junit.xml` | `functional-output/tests/playwright-functional/test-results` |
|
|
312
|
+
| Accessibility | `functional-output/tests/playwright-accessibility/odhin-report/xui-playwright-accessibility.html` | `functional-output/tests/playwright-accessibility/playwright-accessibility-junit.xml` | `functional-output/tests/playwright-accessibility/test-results` |
|
|
313
|
+
| Cross-browser smoke | `functional-output/tests/playwright-crossbrowser/odhin-report/xui-playwright-crossbrowser.html` | `functional-output/tests/playwright-crossbrowser/playwright-crossbrowser-junit.xml` | `functional-output/tests/playwright-crossbrowser/test-results` |
|
|
308
314
|
|
|
309
315
|
Those are the default lane-specific paths. CNP keeps preview and AAT viewer
|
|
310
316
|
support evidence separate under `functional-output/tests/playwright-support/preview`
|
|
@@ -336,9 +342,10 @@ Reporting behavior follows the MC/MO pattern:
|
|
|
336
342
|
HTML Publisher links.
|
|
337
343
|
|
|
338
344
|
The Jenkins `YarnBuilder` performs its immutable dependency install before the
|
|
339
|
-
first setup task. The pipeline
|
|
340
|
-
|
|
341
|
-
`PLAYWRIGHT_SKIP_INSTALL=true` so Playwright
|
|
345
|
+
first setup task. The pipeline installs Puppeteer Chrome for Karma and the
|
|
346
|
+
functional preflight, then installs Chromium into the workspace-local
|
|
347
|
+
`PLAYWRIGHT_BROWSERS_PATH` and sets `PLAYWRIGHT_SKIP_INSTALL=true` so Playwright
|
|
348
|
+
lanes do not reinstall it.
|
|
342
349
|
|
|
343
350
|
Useful overrides:
|
|
344
351
|
- `PLAYWRIGHT_BASE_URL` or `TEST_URL`: target application URL, default `http://localhost:3000/`
|
|
@@ -384,10 +391,6 @@ Migration boundaries:
|
|
|
384
391
|
- Put new native Playwright specs under `playwright_tests/`.
|
|
385
392
|
- Keep screen interactions and reusable locators in page objects under
|
|
386
393
|
`playwright_tests/pages/`; keep assertions visible in specs.
|
|
387
|
-
- Historical CodeceptJS scenarios are retained as source traceability only;
|
|
388
|
-
their executable pipeline routing is retired once the mapped Playwright
|
|
389
|
-
contract is selected by default or is represented by a discoverable,
|
|
390
|
-
ticketed product-defect contract.
|
|
391
394
|
- Add stable report output paths for every new Playwright lane so Jenkins can
|
|
392
395
|
publish Odhín and JUnit and archive failure diagnostics without bespoke stage
|
|
393
396
|
logic.
|
|
@@ -607,7 +610,9 @@ The list of exceptions thrown by the Media Viewer are as follows:
|
|
|
607
610
|
- HttpErrorResponse
|
|
608
611
|
- PasswordException
|
|
609
612
|
|
|
610
|
-
##
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
613
|
+
## Legacy browser tests
|
|
614
|
+
|
|
615
|
+
The CodeceptJS and Protractor/Cucumber runners were retired as part of the
|
|
616
|
+
Playwright migration. Migration closure was recorded in PR #82; the active
|
|
617
|
+
browser test source is now Playwright. Use the Playwright commands above for
|
|
618
|
+
supported browser tests. No recurring legacy-parity test is retained.
|
|
@@ -3353,26 +3353,55 @@ class TextHighlightDirective {
|
|
|
3353
3353
|
highlightInputText(textToHighlight) {
|
|
3354
3354
|
this.resetHighlight();
|
|
3355
3355
|
this.textToHighlight = textToHighlight;
|
|
3356
|
-
const searchPattern = new RegExp(textToHighlight, 'gi');
|
|
3356
|
+
const searchPattern = new RegExp(this.escapeRegExp(textToHighlight), 'gi');
|
|
3357
3357
|
const hostElement = this.element.nativeElement;
|
|
3358
|
-
|
|
3359
|
-
hostElement.innerHTML = hostElement.innerHTML
|
|
3360
|
-
.replace(searchPattern, this.highlightPattern('$&'));
|
|
3361
|
-
}
|
|
3358
|
+
this.highlightTextNodes(hostElement, searchPattern);
|
|
3362
3359
|
this.textToHighlight = undefined;
|
|
3363
3360
|
}
|
|
3364
3361
|
resetHighlight() {
|
|
3365
3362
|
const hostElement = this.element.nativeElement;
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3363
|
+
Array.from(hostElement.querySelectorAll('span.mvTextHighlight')).forEach((highlightElement) => {
|
|
3364
|
+
highlightElement.replaceWith(document.createTextNode(highlightElement.textContent || ''));
|
|
3365
|
+
});
|
|
3366
|
+
hostElement.normalize();
|
|
3367
|
+
}
|
|
3368
|
+
highlightTextNodes(hostElement, searchPattern) {
|
|
3369
|
+
const walker = document.createTreeWalker(hostElement, NodeFilter.SHOW_TEXT);
|
|
3370
|
+
const textNodes = [];
|
|
3371
|
+
let currentNode = walker.nextNode();
|
|
3372
|
+
while (currentNode) {
|
|
3373
|
+
textNodes.push(currentNode);
|
|
3374
|
+
currentNode = walker.nextNode();
|
|
3375
|
+
}
|
|
3376
|
+
textNodes.forEach((textNode) => this.highlightTextNode(textNode, searchPattern));
|
|
3377
|
+
}
|
|
3378
|
+
highlightTextNode(textNode, searchPattern) {
|
|
3379
|
+
const text = textNode.textContent || '';
|
|
3380
|
+
const matches = Array.from(text.matchAll(searchPattern));
|
|
3381
|
+
if (matches.length === 0) {
|
|
3382
|
+
return;
|
|
3383
|
+
}
|
|
3384
|
+
const fragment = document.createDocumentFragment();
|
|
3385
|
+
let currentIndex = 0;
|
|
3386
|
+
matches.forEach((match) => {
|
|
3387
|
+
const matchIndex = match.index || 0;
|
|
3388
|
+
const matchText = match[0];
|
|
3389
|
+
if (matchIndex > currentIndex) {
|
|
3390
|
+
fragment.appendChild(document.createTextNode(text.slice(currentIndex, matchIndex)));
|
|
3371
3391
|
}
|
|
3392
|
+
const highlightElement = document.createElement('span');
|
|
3393
|
+
highlightElement.className = 'mvTextHighlight';
|
|
3394
|
+
highlightElement.textContent = matchText;
|
|
3395
|
+
fragment.appendChild(highlightElement);
|
|
3396
|
+
currentIndex = matchIndex + matchText.length;
|
|
3397
|
+
});
|
|
3398
|
+
if (currentIndex < text.length) {
|
|
3399
|
+
fragment.appendChild(document.createTextNode(text.slice(currentIndex)));
|
|
3372
3400
|
}
|
|
3401
|
+
textNode.replaceWith(fragment);
|
|
3373
3402
|
}
|
|
3374
|
-
|
|
3375
|
-
return
|
|
3403
|
+
escapeRegExp(value) {
|
|
3404
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3376
3405
|
}
|
|
3377
3406
|
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: TextHighlightDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
3378
3407
|
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.26", type: TextHighlightDirective, isStandalone: false, selector: "[mvTextHighlight]", inputs: { textToHighlight: "textToHighlight" }, ngImport: i0 }); }
|
|
@@ -7943,12 +7972,14 @@ class GovUkLabelComponent {
|
|
|
7943
7972
|
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.26", ngImport: i0, type: GovUkLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7944
7973
|
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.26", type: GovUkLabelComponent, isStandalone: false, selector: "mv-gov-label", inputs: { config: "config" }, ngImport: i0, template: `<h1 *ngIf="config.isPageHeading else noHeading">
|
|
7945
7974
|
<label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
|
|
7946
|
-
[for]="config.id"
|
|
7975
|
+
[for]="config.id">
|
|
7976
|
+
{{ config.label }}
|
|
7947
7977
|
</label>
|
|
7948
7978
|
</h1>
|
|
7949
7979
|
<ng-template #noHeading>
|
|
7950
7980
|
<label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
|
|
7951
|
-
[for]="config.id"
|
|
7981
|
+
[for]="config.id">
|
|
7982
|
+
{{ config.label }}
|
|
7952
7983
|
</label>
|
|
7953
7984
|
</ng-template>
|
|
7954
7985
|
`, isInline: true, dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
@@ -7959,12 +7990,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.26", ngImpo
|
|
|
7959
7990
|
selector: 'mv-gov-label',
|
|
7960
7991
|
template: `<h1 *ngIf="config.isPageHeading else noHeading">
|
|
7961
7992
|
<label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
|
|
7962
|
-
[for]="config.id"
|
|
7993
|
+
[for]="config.id">
|
|
7994
|
+
{{ config.label }}
|
|
7963
7995
|
</label>
|
|
7964
7996
|
</h1>
|
|
7965
7997
|
<ng-template #noHeading>
|
|
7966
7998
|
<label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
|
|
7967
|
-
[for]="config.id"
|
|
7999
|
+
[for]="config.id">
|
|
8000
|
+
{{ config.label }}
|
|
7968
8001
|
</label>
|
|
7969
8002
|
</ng-template>
|
|
7970
8003
|
`,
|