diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 842802d5d..480043f52 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -104,7 +104,7 @@ jobs: if: steps.cs3d-check.outputs.enabled == 'true' && steps.cs3d-ref.outputs.type == 'version' run: | node .scripts/cs3d-set-version.mjs "${CS3D_VERSION}" - bun install + bun install --config=./bunfig.update-lockfile.toml env: CS3D_VERSION: ${{ steps.cs3d-ref.outputs.version }} diff --git a/.scripts/cs3d-check.mjs b/.scripts/cs3d-check.mjs new file mode 100644 index 000000000..5f00fc0c7 --- /dev/null +++ b/.scripts/cs3d-check.mjs @@ -0,0 +1,55 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { execSync } from 'node:child_process'; + +const workflowPath = path.resolve( + process.cwd(), + 'libs', + '@cornerstonejs', + '.github', + 'workflows', + 'ohif-downstream.yml' +); + +if (!fs.existsSync(workflowPath)) { + console.error(`[cs3d:check] Workflow file not found: ${workflowPath}`); + process.exit(1); +} + +const workflowText = fs.readFileSync(workflowPath, 'utf8'); +const ohifRefMatch = workflowText.match(/^\s*OHIF_REF:\s*["']?([^"'\r\n]+)["']?\s*$/m); + +if (!ohifRefMatch) { + console.error('[cs3d:check] Could not find OHIF_REF in ohif-downstream workflow.'); + process.exit(1); +} + +const expectedBranch = ohifRefMatch[1].trim(); +let currentBranch = ''; + +try { + currentBranch = execSync('git rev-parse --abbrev-ref HEAD', { + cwd: process.cwd(), + encoding: 'utf8', + }).trim(); +} catch (error) { + console.error('[cs3d:check] Failed to determine current git branch.'); + process.exit(1); +} + +if (currentBranch !== expectedBranch) { + console.error( + `[cs3d:check] Branch mismatch: current='${currentBranch}', expected='${expectedBranch}' from ${path.relative( + process.cwd(), + workflowPath + )}` + ); + process.exit(1); +} + +console.log( + `[cs3d:check] OK: current branch '${currentBranch}' matches OHIF_REF in ${path.relative( + process.cwd(), + workflowPath + )}` +); diff --git a/.scripts/cs3d-set-version.mjs b/.scripts/cs3d-set-version.mjs index e387c66e9..01d8da342 100644 --- a/.scripts/cs3d-set-version.mjs +++ b/.scripts/cs3d-set-version.mjs @@ -122,3 +122,9 @@ for (const pkgPath of pkgPaths) { console.log( `\nDone: ${totalChanges} version(s) updated to ${version} across ${pkgPaths.length} package files.` ); +console.log( + 'This step changes package.json; the following install must not use a frozen Bun lockfile ' + + '(OHIF+CS3D combined “version” CI does: `bun install --config=./bunfig.update-lockfile.toml`). ' + + 'Other installs stay frozen. Locally after this script, use that bun command and/or ' + + '`bun run install:update-lockfile` when you intend to commit lockfile updates.\n' +); diff --git a/bun.lock b/bun.lock index deaa8d7bc..3a245c900 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "ohif-monorepo-root", @@ -50,7 +51,7 @@ }, "addOns/externals/devDependencies": { "name": "@externals/devDependencies", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "@kitware/vtk.js": "34.15.1", @@ -131,22 +132,22 @@ }, "addOns/externals/dicom-microscopy-viewer": { "name": "@externals/dicom-microscopy-viewer", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "dicom-microscopy-viewer": "0.48.17", }, }, "extensions/cornerstone": { "name": "@ohif/extension-cornerstone", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/ai": "4.20.0", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/labelmap-interpolation": "4.20.0", - "@cornerstonejs/polymorphic-segmentation": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/ai": "4.21.2", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/labelmap-interpolation": "4.21.2", + "@cornerstonejs/polymorphic-segmentation": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "@icr/polyseg-wasm": "0.4.0", "@itk-wasm/morphological-contour-interpolation": "1.1.0", "@kitware/vtk.js": "34.15.1", @@ -164,9 +165,9 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/dicom-image-loader": "4.20.0", - "@ohif/core": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@cornerstonejs/dicom-image-loader": "4.21.2", + "@ohif/core": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -178,18 +179,18 @@ }, "extensions/cornerstone-dicom-pmap": { "name": "@ohif/extension-cornerstone-dicom-pmap", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/core": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/core": "4.21.2", "@kitware/vtk.js": "34.15.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -200,15 +201,15 @@ }, "extensions/cornerstone-dicom-rt": { "name": "@ohif/extension-cornerstone-dicom-rt", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -219,18 +220,18 @@ }, "extensions/cornerstone-dicom-seg": { "name": "@ohif/extension-cornerstone-dicom-seg", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/core": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/core": "4.21.2", "@kitware/vtk.js": "34.15.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -241,19 +242,19 @@ }, "extensions/cornerstone-dicom-sr": { "name": "@ohif/extension-cornerstone-dicom-sr", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-measurement-tracking": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-measurement-tracking": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -263,19 +264,19 @@ }, "extensions/cornerstone-dynamic-volume": { "name": "@ohif/extension-cornerstone-dynamic-volume", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -285,7 +286,7 @@ }, "extensions/default": { "name": "@ohif/extension-default", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "@cornerstonejs/calculate-suv": "1.1.0", @@ -294,8 +295,8 @@ "react-color": "2.19.3", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", "dcmjs": "0.49.4", "dicomweb-client": "0.10.4", "prop-types": "15.8.1", @@ -309,7 +310,7 @@ }, "extensions/dicom-microscopy": { "name": "@ohif/extension-dicom-microscopy", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "@cornerstonejs/codec-charls": "1.2.3", @@ -320,10 +321,10 @@ "mathjs": "12.4.3", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -334,14 +335,14 @@ }, "extensions/dicom-pdf": { "name": "@ohif/extension-dicom-pdf", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -351,14 +352,14 @@ }, "extensions/dicom-video": { "name": "@ohif/extension-dicom-video", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -368,20 +369,20 @@ }, "extensions/measurement-tracking": { "name": "@ohif/extension-measurement-tracking", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/ui": "3.13.0-beta.55", "@xstate/react": "3.2.2", "xstate": "4.38.3", }, "peerDependencies": { - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "classnames": "2.5.1", "dcmjs": "0.49.4", "lodash.debounce": "4.0.8", @@ -394,14 +395,14 @@ }, "extensions/test-extension": { "name": "@ohif/extension-test", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -411,14 +412,14 @@ }, "extensions/tmtv": { "name": "@ohif/extension-tmtv", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.54", + "@ohif/ui": "3.13.0-beta.54", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -428,16 +429,16 @@ }, "extensions/usAnnotation": { "name": "@ohif/extension-ultrasound-pleura-bline", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", - "@ohif/ui-next": "3.13.0-beta.49", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", + "@ohif/ui-next": "3.13.0-beta.55", }, "devDependencies": { "@babel/core": "7.28.0", @@ -476,7 +477,7 @@ }, "modes/basic": { "name": "@ohif/mode-basic", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", }, @@ -485,19 +486,19 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-dicom-pdf": "3.13.0-beta.49", - "@ohif/extension-dicom-video": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/extension-dicom-pdf": "3.13.0-beta.55", + "@ohif/extension-dicom-video": "3.13.0-beta.55", }, }, "modes/basic-dev-mode": { "name": "@ohif/mode-basic-dev-mode", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -507,17 +508,17 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-dicom-pdf": "3.13.0-beta.49", - "@ohif/extension-dicom-video": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/extension-dicom-pdf": "3.13.0-beta.55", + "@ohif/extension-dicom-video": "3.13.0-beta.55", }, }, "modes/basic-test-mode": { "name": "@ohif/mode-test", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -527,19 +528,19 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-dicom-pdf": "3.13.0-beta.49", - "@ohif/extension-dicom-video": "3.13.0-beta.49", - "@ohif/extension-measurement-tracking": "3.13.0-beta.49", - "@ohif/extension-test": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/extension-dicom-pdf": "3.13.0-beta.55", + "@ohif/extension-dicom-video": "3.13.0-beta.55", + "@ohif/extension-measurement-tracking": "3.13.0-beta.55", + "@ohif/extension-test": "3.13.0-beta.55", }, }, "modes/longitudinal": { "name": "@ohif/mode-longitudinal", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -549,33 +550,33 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-dicom-pdf": "3.13.0-beta.49", - "@ohif/extension-dicom-video": "3.13.0-beta.49", - "@ohif/extension-measurement-tracking": "3.13.0-beta.49", - "@ohif/mode-basic": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/extension-dicom-pdf": "3.13.0-beta.55", + "@ohif/extension-dicom-video": "3.13.0-beta.55", + "@ohif/extension-measurement-tracking": "3.13.0-beta.55", + "@ohif/mode-basic": "3.13.0-beta.55", }, }, "modes/microscopy": { "name": "@ohif/mode-microscopy", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-dicom-microscopy": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-dicom-microscopy": "3.13.0-beta.55", }, }, "modes/preclinical-4d": { "name": "@ohif/mode-preclinical-4d", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", }, @@ -584,17 +585,17 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dynamic-volume": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-tmtv": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.54", + "@ohif/extension-cornerstone": "3.13.0-beta.54", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.54", + "@ohif/extension-cornerstone-dynamic-volume": "3.13.0-beta.54", + "@ohif/extension-default": "3.13.0-beta.54", + "@ohif/extension-tmtv": "3.13.0-beta.54", }, }, "modes/segmentation": { "name": "@ohif/mode-segmentation", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -623,20 +624,20 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-dicom-pdf": "3.13.0-beta.49", - "@ohif/extension-dicom-video": "3.13.0-beta.49", - "@ohif/mode-basic": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.54", + "@ohif/extension-cornerstone": "3.13.0-beta.54", + "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.54", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.54", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.54", + "@ohif/extension-default": "3.13.0-beta.54", + "@ohif/extension-dicom-pdf": "3.13.0-beta.54", + "@ohif/extension-dicom-video": "3.13.0-beta.54", + "@ohif/mode-basic": "3.13.0-beta.54", }, }, "modes/tmtv": { "name": "@ohif/mode-tmtv", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -646,25 +647,25 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-dicom-pdf": "3.13.0-beta.49", - "@ohif/extension-dicom-video": "3.13.0-beta.49", - "@ohif/extension-measurement-tracking": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.54", + "@ohif/extension-cornerstone": "3.13.0-beta.54", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.54", + "@ohif/extension-default": "3.13.0-beta.54", + "@ohif/extension-dicom-pdf": "3.13.0-beta.54", + "@ohif/extension-dicom-video": "3.13.0-beta.54", + "@ohif/extension-measurement-tracking": "3.13.0-beta.54", }, }, "modes/usAnnotation": { "name": "@ohif/mode-ultrasound-pleura-bline", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.49", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", + "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.55", "i18next": "17.3.1", }, "devDependencies": { @@ -693,34 +694,34 @@ }, "platform/app": { "name": "@ohif/app", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "@cornerstonejs/codec-charls": "1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/dicom-image-loader": "4.20.0", + "@cornerstonejs/dicom-image-loader": "4.21.2", "@emotion/serialize": "1.3.3", - "@ohif/core": "3.13.0-beta.49", - "@ohif/extension-cornerstone": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.49", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.49", - "@ohif/extension-default": "3.13.0-beta.49", - "@ohif/extension-dicom-microscopy": "3.13.0-beta.49", - "@ohif/extension-dicom-pdf": "3.13.0-beta.49", - "@ohif/extension-dicom-video": "3.13.0-beta.49", - "@ohif/extension-test": "3.13.0-beta.49", - "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.49", - "@ohif/i18n": "3.13.0-beta.49", - "@ohif/mode-basic-dev-mode": "3.13.0-beta.49", - "@ohif/mode-longitudinal": "3.13.0-beta.49", - "@ohif/mode-microscopy": "3.13.0-beta.49", - "@ohif/mode-test": "3.13.0-beta.49", - "@ohif/mode-ultrasound-pleura-bline": "3.13.0-beta.49", - "@ohif/ui": "3.13.0-beta.49", - "@ohif/ui-next": "3.13.0-beta.49", + "@ohif/core": "3.13.0-beta.55", + "@ohif/extension-cornerstone": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.55", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", + "@ohif/extension-default": "3.13.0-beta.55", + "@ohif/extension-dicom-microscopy": "3.13.0-beta.55", + "@ohif/extension-dicom-pdf": "3.13.0-beta.55", + "@ohif/extension-dicom-video": "3.13.0-beta.55", + "@ohif/extension-test": "3.13.0-beta.55", + "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.55", + "@ohif/i18n": "3.13.0-beta.55", + "@ohif/mode-basic-dev-mode": "3.13.0-beta.55", + "@ohif/mode-longitudinal": "3.13.0-beta.55", + "@ohif/mode-microscopy": "3.13.0-beta.55", + "@ohif/mode-test": "3.13.0-beta.55", + "@ohif/mode-ultrasound-pleura-bline": "3.13.0-beta.55", + "@ohif/ui": "3.13.0-beta.55", + "@ohif/ui-next": "3.13.0-beta.55", "@svgr/webpack": "8.1.0", "@types/react": "18.3.23", "classnames": "2.5.1", @@ -772,7 +773,7 @@ }, "platform/cli": { "name": "@ohif/cli", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "bin": { "ohif-cli": "src/index.js", }, @@ -796,7 +797,7 @@ }, "platform/core": { "name": "@ohif/core", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "dcmjs": "0.49.4", @@ -821,16 +822,16 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/dicom-image-loader": "4.20.0", - "@ohif/ui": "3.13.0-beta.49", - "cornerstone-math": "0.1.9", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/dicom-image-loader": "4.21.2", + "@ohif/ui": "3.13.0-beta.55", + "cornerstone-math": "0.1.10", "dicom-parser": "1.8.21", }, }, "platform/i18n": { "name": "@ohif/i18n", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@babel/runtime": "7.28.2", "i18next-locize-backend": "2.2.2", @@ -855,7 +856,7 @@ }, "platform/ui": { "name": "@ohif/ui", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@testing-library/react": "13.4.0", "browser-detect": "0.2.28", @@ -905,7 +906,7 @@ }, "platform/ui-next": { "name": "@ohif/ui-next", - "version": "3.13.0-beta.49", + "version": "3.13.0-beta.55", "dependencies": { "@radix-ui/react-accordion": "1.2.11", "@radix-ui/react-checkbox": "1.3.2", @@ -951,7 +952,7 @@ "overrides": { "@babel/runtime-corejs2": "7.26.10", "@cornerstonejs/codec-openjpeg": "1.3.0", - "axios": "1.13.5", + "axios": "1.15.0", "body-parser": "1.20.3", "commander": "8.3.0", "core-js": "3.45.1", @@ -1241,9 +1242,9 @@ "@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="], - "@cornerstonejs/adapters": ["@cornerstonejs/adapters@4.20.0", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "ndarray": "1.0.19" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0" } }, "sha512-OxplEaHadms6mZ5fX8o9zkMVw7rSjxP6+KRovBAqLXlXsM9hj7MgencWG2JX6SR2bUXvHVusiV9cdECcDMNvsg=="], + "@cornerstonejs/adapters": ["@cornerstonejs/adapters@4.21.2", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "ndarray": "1.0.19" }, "peerDependencies": { "@cornerstonejs/core": "4.21.2", "@cornerstonejs/tools": "4.21.2" } }, "sha512-BTmj7jZDJky6XOsoueNq+qMavFLMvj46fftD08YovKWUDfoq7osOVpL9PBcnWODx05obsyagkDRyrkqTGd14wg=="], - "@cornerstonejs/ai": ["@cornerstonejs/ai@4.20.0", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "lodash.clonedeep": "4.5.0", "ndarray": "1.0.19", "onnxruntime-common": "1.17.1", "onnxruntime-web": "1.17.1" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0" } }, "sha512-65wl8mXy/N6DUjLlNZvKLgWTGWVu4kWDupxNU5p7Pd3ZxU6RnbG6d3pcM30D/bcQEuUWLEQBDodtBeJEsxJxoA=="], + "@cornerstonejs/ai": ["@cornerstonejs/ai@4.21.2", "", { "dependencies": { "@babel/runtime-corejs2": "7.26.10", "buffer": "6.0.3", "dcmjs": "0.49.4", "gl-matrix": "3.4.3", "lodash.clonedeep": "4.5.0", "ndarray": "1.0.19", "onnxruntime-common": "1.17.1", "onnxruntime-web": "1.17.1" }, "peerDependencies": { "@cornerstonejs/core": "4.21.2", "@cornerstonejs/tools": "4.21.2" } }, "sha512-I7YIOvcVnkDkkxH/88xJ0Yuemd0Qm6O9TO2nyprzwui/ZLMPD0bTcWPXks+ktxIAtz9rTRyNNodLvbF6aKk3DA=="], "@cornerstonejs/calculate-suv": ["@cornerstonejs/calculate-suv@1.1.0", "", {}, "sha512-Q9XraiDJif9aMFArD2iEuDO/HXbcRVCqB7KfaHgDrdTTjgDFovS91Psbdim7crypRSvE6dh/+HKeFNHdvNkA6w=="], @@ -1255,15 +1256,15 @@ "@cornerstonejs/codec-openjph": ["@cornerstonejs/codec-openjph@2.4.7", "", {}, "sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w=="], - "@cornerstonejs/core": ["@cornerstonejs/core@4.20.0", "", { "dependencies": { "@kitware/vtk.js": "34.15.1", "comlink": "4.4.2", "gl-matrix": "3.4.3", "loglevel": "1.9.2" } }, "sha512-rcrctEIcyyAwQ6zcVt1wbYoTPyH6YNLNBOBB/aLeJZfLqGAfca+Cgf5K+KSGFJX1gZOdQZmYGmAF9P58B9PNVw=="], + "@cornerstonejs/core": ["@cornerstonejs/core@4.21.2", "", { "dependencies": { "@kitware/vtk.js": "34.15.1", "comlink": "4.4.2", "gl-matrix": "3.4.3", "loglevel": "1.9.2" } }, "sha512-XnhMGan9Ebnu2f3W9Q2iK6ShHGCLa1UYEPRYHzILgtnTbo5qHsZPay+IO/mjGQYH3VlTUgZDqzMRNBHXmvoiLg=="], - "@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@4.20.0", "", { "dependencies": { "@cornerstonejs/codec-charls": "1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", "comlink": "4.4.2", "dicom-parser": "1.8.21", "jpeg-lossless-decoder-js": "2.1.2", "pako": "2.1.0", "uuid": "9.0.1" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0" } }, "sha512-A7N2ekKEMEEKbw0QecbmgtL89LMpLZDkyzt2a97cZM9qyUdhdETyzL8m6guVtP10Ga5l9Aq9mFt2ifGtwTw0wA=="], + "@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@4.21.2", "", { "dependencies": { "@cornerstonejs/codec-charls": "1.2.3", "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", "comlink": "4.4.2", "dicom-parser": "1.8.21", "jpeg-lossless-decoder-js": "2.1.2", "pako": "2.1.0", "uuid": "9.0.1" }, "peerDependencies": { "@cornerstonejs/core": "4.21.2" } }, "sha512-g/2qTHA1P7VLmZ7OEHkH0S4jYIJsqb8128KMmpYuea2i3WpT+gOLf82eNYFBlnOCmwRitzs1YLHZM1/nDz4K/g=="], - "@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@4.20.0", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0", "@kitware/vtk.js": "34.15.1" } }, "sha512-VDUkvRZPCk98NkBFH0qFNEfjQoyYp2Th2+0KAJtDPeA0aqSPhugh14uJQ5uKEkDzZFUG/TUpeaHi1kldx6C5Gw=="], + "@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@4.21.2", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "4.21.2", "@cornerstonejs/tools": "4.21.2", "@kitware/vtk.js": "34.15.1" } }, "sha512-giW2IVPqZj3Bn4o9KIL8QaHWGPHoFD8R9aOvqlBQgSyUJF6XFIpfQDixb9txZhmkK0xlMrn/rbnEcoeFLoM1Pw=="], - "@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@4.20.0", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@cornerstonejs/tools": "4.20.0", "@kitware/vtk.js": "34.15.1" } }, "sha512-tsMqAd/GrBeEFB2WU2K+YsGXeaP/1yD635yO1udpG2dloRaJrvFiK1dFMFCBLK3Xd768ZS1nq/MZEel00+vYxA=="], + "@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@4.21.2", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "4.21.2", "@cornerstonejs/tools": "4.21.2", "@kitware/vtk.js": "34.15.1" } }, "sha512-nY1sGmmVjKT0M7Z/rwskZmn+g90W9PACAKascjYF/LXrOyJozN4zVZn7HzkzYbH3+vcCGvwShEdLvDsDxaomsw=="], - "@cornerstonejs/tools": ["@cornerstonejs/tools@4.20.0", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "4.4.2", "lodash.get": "4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "4.20.0", "@kitware/vtk.js": "34.15.1", "@types/d3-array": "3.2.1", "@types/d3-interpolate": "3.0.4", "d3-array": "3.2.4", "d3-interpolate": "3.0.1", "gl-matrix": "3.4.3" } }, "sha512-kphlW17eohBRk8MXEgdufM2t8MC5JqdlWUCfXu5rfg0KS1ut6iSWGAxFS+12noPR5qDzfVEYnD+4NkL37jg8pw=="], + "@cornerstonejs/tools": ["@cornerstonejs/tools@4.21.2", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "4.4.2", "lodash.get": "4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "4.21.2", "@kitware/vtk.js": "34.15.1", "@types/d3-array": "3.2.1", "@types/d3-interpolate": "3.0.4", "d3-array": "3.2.4", "d3-interpolate": "3.0.1", "gl-matrix": "3.4.3" } }, "sha512-dBOFIzFLVnCEEBOaXvA+cUNP+bzkdFwLDjEX3/0dP/4hjoFkZeq+AINAJn6oG5UKycqQOLhQ5gn3z4ugYK4ujQ=="], "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], @@ -2323,7 +2324,7 @@ "axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="], - "axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="], + "axios": ["axios@1.15.0", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], @@ -5521,7 +5522,7 @@ "asn1.js/bn.js": ["bn.js@4.12.2", "", {}, "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw=="], - "axios/proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "axios/proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="], "babel-jest/babel-plugin-istanbul": ["babel-plugin-istanbul@6.1.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" } }, "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA=="], diff --git a/extensions/cornerstone-dicom-pmap/package.json b/extensions/cornerstone-dicom-pmap/package.json index d8da5480e..68799399c 100644 --- a/extensions/cornerstone-dicom-pmap/package.json +++ b/extensions/cornerstone-dicom-pmap/package.json @@ -46,8 +46,8 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/core": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/core": "4.21.2", "@kitware/vtk.js": "34.15.1" } } diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index 3fe7b0f4b..ae04e31ca 100644 --- a/extensions/cornerstone-dicom-seg/package.json +++ b/extensions/cornerstone-dicom-seg/package.json @@ -46,8 +46,8 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/core": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/core": "4.21.2", "@kitware/vtk.js": "34.15.1" } } diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json index 8360bff49..261a6530d 100644 --- a/extensions/cornerstone-dicom-sr/package.json +++ b/extensions/cornerstone-dicom-sr/package.json @@ -46,9 +46,9 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "classnames": "2.5.1" } } diff --git a/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts b/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts index f30dda6cb..6d27fa3b9 100644 --- a/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts +++ b/extensions/cornerstone-dicom-sr/src/getSopClassHandlerModule.ts @@ -200,8 +200,13 @@ async function _load( srDisplaySet.isRehydratable = isRehydratable(srDisplaySet, mappings); srDisplaySet.isLoaded = true; - /** Check currently added displaySets and add measurements if the sources exist */ - displaySetService.activeDisplaySets.forEach(activeDisplaySet => { + /** Check currently added displaySets and add measurements if the sources exist. + * Walk the SR's study first in default series order (not load order) so SCOORD3D + * FrameOfReference matching picks a stable series when several share FOR. */ + const displaySetsForSRPass = utils.sortDisplaySetsCopy(displaySetService.activeDisplaySets, { + studyInstanceUIDFirst: srDisplaySet.StudyInstanceUID, + }); + displaySetsForSRPass.forEach(activeDisplaySet => { _checkIfCanAddMeasurementsToDisplaySet( srDisplaySet, activeDisplaySet, diff --git a/extensions/cornerstone-dynamic-volume/package.json b/extensions/cornerstone-dynamic-volume/package.json index 1279efa1c..dadd35703 100644 --- a/extensions/cornerstone-dynamic-volume/package.json +++ b/extensions/cornerstone-dynamic-volume/package.json @@ -42,8 +42,8 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "classnames": "2.5.1" } } diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json index 6b5110322..3632890dc 100644 --- a/extensions/cornerstone/package.json +++ b/extensions/cornerstone/package.json @@ -40,7 +40,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/dicom-image-loader": "4.20.0", + "@cornerstonejs/dicom-image-loader": "4.21.2", "@ohif/core": "3.13.0-beta.55", "@ohif/ui": "3.13.0-beta.55", "dcmjs": "0.49.4", @@ -53,12 +53,12 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.20.0", - "@cornerstonejs/ai": "4.20.0", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/labelmap-interpolation": "4.20.0", - "@cornerstonejs/polymorphic-segmentation": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/adapters": "4.21.2", + "@cornerstonejs/ai": "4.21.2", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/labelmap-interpolation": "4.21.2", + "@cornerstonejs/polymorphic-segmentation": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "@icr/polyseg-wasm": "0.4.0", "@itk-wasm/morphological-contour-interpolation": "1.1.0", "@kitware/vtk.js": "34.15.1", diff --git a/extensions/default/src/customizations/sortingCriteriaCustomization.ts b/extensions/default/src/customizations/sortingCriteriaCustomization.ts index b42ac03b2..940cf3d46 100644 --- a/extensions/default/src/customizations/sortingCriteriaCustomization.ts +++ b/extensions/default/src/customizations/sortingCriteriaCustomization.ts @@ -1,7 +1,14 @@ import { utils } from '@ohif/core'; const { sortingCriteria } = utils; +const { seriesSortCriteria } = sortingCriteria; + +/** Stable series order for e2e (Playwright sets TEST_ENV=true via cross-env). */ +const sortingCriteriaFn = + process.env.TEST_ENV === 'true' + ? seriesSortCriteria.compareSeriesUID + : seriesSortCriteria.seriesInfoSortingCriteria; export default { - sortingCriteria: sortingCriteria.seriesSortCriteria.seriesInfoSortingCriteria, + sortingCriteria: sortingCriteriaFn, }; diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index 6114f8d0a..8c78a39fd 100644 --- a/extensions/measurement-tracking/package.json +++ b/extensions/measurement-tracking/package.json @@ -32,8 +32,8 @@ "start": "yarn run dev" }, "peerDependencies": { - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "@ohif/core": "3.13.0-beta.55", "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", "@ohif/extension-default": "3.13.0-beta.55", diff --git a/extensions/usAnnotation/package.json b/extensions/usAnnotation/package.json index c61a99137..e4b59d4da 100644 --- a/extensions/usAnnotation/package.json +++ b/extensions/usAnnotation/package.json @@ -42,8 +42,8 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "@ohif/core": "3.13.0-beta.55", "@ohif/extension-cornerstone": "3.13.0-beta.55", "@ohif/extension-default": "3.13.0-beta.55", diff --git a/modes/usAnnotation/package.json b/modes/usAnnotation/package.json index 9dcb813ca..55a512d08 100644 --- a/modes/usAnnotation/package.json +++ b/modes/usAnnotation/package.json @@ -34,8 +34,8 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/tools": "4.20.0", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/tools": "4.21.2", "@ohif/core": "3.13.0-beta.55", "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.55", "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.55", diff --git a/package.json b/package.json index a09a974f5..7f822e01b 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,10 @@ "lerna:customVersion": "node version.mjs", "link-list": "npm ls --depth=0 --link=true", "cs3d:checkout": "cd libs/@cornerstonejs && git fetch && git checkout", - "cs3d:build": "cd libs/@cornerstonejs && yarn install && yarn run build:esm", + "cs3d:check": "node .scripts/cs3d-check.mjs", + "cs3d:build": "cd libs/@cornerstonejs && yarn run build:esm", + "cs3d:watch": "cd libs/@cornerstonejs && yarn run build:esm:watch", + "cs3d:install": "cd libs/@cornerstonejs && yarn install", "cs3d:link": "node libs/@cornerstonejs/scripts/link-ohif-cornerstone-node-modules.mjs .", "cs3d:unlink": "node libs/@cornerstonejs/scripts/unlink-ohif-cornerstone-node-modules.mjs ." }, @@ -150,7 +153,7 @@ "package-json": "8.1.1", "rollup": "2.80.0", "body-parser": "1.20.3", - "axios": "1.13.5", + "axios": "1.15.0", "core-js": "3.45.1", "@babel/runtime-corejs2": "7.26.10", "tapable": "2.2.2", diff --git a/platform/app/package.json b/platform/app/package.json index 43b80cc1f..613842c1c 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -54,7 +54,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/dicom-image-loader": "4.20.0", + "@cornerstonejs/dicom-image-loader": "4.21.2", "@emotion/serialize": "1.3.3", "@ohif/core": "3.13.0-beta.55", "@ohif/extension-cornerstone": "3.13.0-beta.55", diff --git a/platform/app/src/routes/Mode/defaultRouteInit.ts b/platform/app/src/routes/Mode/defaultRouteInit.ts index 723c48231..aa98b4ed3 100644 --- a/platform/app/src/routes/Mode/defaultRouteInit.ts +++ b/platform/app/src/routes/Mode/defaultRouteInit.ts @@ -2,7 +2,7 @@ import { DicomMetadataStore, log, utils, Enums } from '@ohif/core'; import getStudies from './studiesList'; import isSeriesFilterUsed from '../../utils/isSeriesFilterUsed'; -const { seriesSortCriteria, getSplitParam } = utils; +const { getSplitParam } = utils; /** * Initialize the route. @@ -34,7 +34,10 @@ export async function defaultRouteInit( const displaySets = displaySetService.getActiveDisplaySets(); // The display sets are not necessarily in load order, even though the // series got started in load order, so re-sort them before hanging - const sortCriteria = seriesSortCriteria.default; + const sortCriteria = customizationService.getCustomization('sortingCriteria') as ( + a, + b + ) => number; if (!displaySets || !displaySets.length) { return; diff --git a/platform/core/package.json b/platform/core/package.json index 2972e8ae2..b85ae7b98 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -37,10 +37,10 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/core": "4.20.0", - "@cornerstonejs/dicom-image-loader": "4.20.0", + "@cornerstonejs/core": "4.21.2", + "@cornerstonejs/dicom-image-loader": "4.21.2", "@ohif/ui": "3.13.0-beta.55", - "cornerstone-math": "0.1.9", + "cornerstone-math": "0.1.10", "dicom-parser": "1.8.21" }, "dependencies": { diff --git a/platform/core/src/index.ts b/platform/core/src/index.ts index 91c80df56..e250e760b 100644 --- a/platform/core/src/index.ts +++ b/platform/core/src/index.ts @@ -145,5 +145,6 @@ export { export { OHIF }; export type { Types }; +export type { SortDisplaySetsCopyOptions } from './utils/sortStudy'; export default OHIF; diff --git a/platform/core/src/utils/createStudyBrowserTabs.ts b/platform/core/src/utils/createStudyBrowserTabs.ts index aea2a5e5d..263b329d7 100644 --- a/platform/core/src/utils/createStudyBrowserTabs.ts +++ b/platform/core/src/utils/createStudyBrowserTabs.ts @@ -1,7 +1,5 @@ import { useSystem } from '../contextProviders/SystemProvider'; import i18n from 'i18next'; -import { seriesSortCriteria } from './sortStudy'; - /** * Tab properties that drive which tab group is used for thumbnail display. @@ -41,7 +39,6 @@ export function createStudyBrowserTabs( const { servicesManager } = useSystem(); const { displaySetService, customizationService } = servicesManager.services; - const shouldSortBySeriesUID = process.env.TEST_ENV === 'true'; const primaryStudies = []; const allStudies = []; @@ -50,10 +47,10 @@ export function createStudyBrowserTabs( ds => ds.StudyInstanceUID === study.studyInstanceUid ); - // sort them by seriesInstanceUID - const sortCriteria = shouldSortBySeriesUID - ? seriesSortCriteria.compareSeriesUID - : (customizationService.getCustomization('sortingCriteria') as (a, b) => number); + const sortCriteria = customizationService.getCustomization('sortingCriteria') as ( + a, + b + ) => number; const sortedDisplaySets = displaySetsForStudy.sort((a, b) => { const displaySetA = displaySetService.getDisplaySetByUID(a.displaySetInstanceUID); const displaySetB = displaySetService.getDisplaySetByUID(b.displaySetInstanceUID); diff --git a/platform/core/src/utils/index.ts b/platform/core/src/utils/index.ts index 4ba124602..0ef35bc1b 100644 --- a/platform/core/src/utils/index.ts +++ b/platform/core/src/utils/index.ts @@ -34,6 +34,7 @@ import { sortStudy, sortStudySeries, sortStudyInstances, + sortDisplaySetsCopy, sortingCriteria, seriesSortCriteria, instancesSortCriteria, @@ -63,6 +64,7 @@ const utils = { sortStudy, sortStudySeries, sortStudyInstances, + sortDisplaySetsCopy, sortingCriteria, seriesSortCriteria, instancesSortCriteria, diff --git a/platform/core/src/utils/sortStudy.ts b/platform/core/src/utils/sortStudy.ts index f3c32694b..774dd15f1 100644 --- a/platform/core/src/utils/sortStudy.ts +++ b/platform/core/src/utils/sortStudy.ts @@ -132,6 +132,48 @@ export const sortingCriteria = { instancesSortCriteria, }; +export type SortDisplaySetsCopyOptions = { + /** + * Display sets for this study are sorted by series criteria and listed first; + * all other display sets follow in their original relative order. + */ + studyInstanceUIDFirst?: string; + /** Defaults to {@link seriesSortCriteria.default} (not app customization). */ + seriesSortingCriteria?: (a, b) => number; +}; + +/** + * Returns a new array of display sets sorted by default series order + * ({@link seriesSortCriteria.default} / {@link seriesInfoSortingCriteria}), not + * the app customization. Does not mutate the input. + * + * With `studyInstanceUIDFirst`, only that study's display sets are sorted; they + * are placed before the rest, which keeps source order (e.g. load order). + */ +export function sortDisplaySetsCopy( + displaySets, + options?: SortDisplaySetsCopyOptions | null +) { + const seriesSortingCriteria = + options?.seriesSortingCriteria ?? seriesSortCriteria.default; + const studyFirst = options?.studyInstanceUIDFirst; + + if (!studyFirst) { + return [...displaySets].sort(seriesSortingCriteria); + } + + const sameStudy = []; + const otherStudy = []; + for (const ds of displaySets) { + if (ds.StudyInstanceUID === studyFirst) { + sameStudy.push(ds); + } else { + otherStudy.push(ds); + } + } + return [...[...sameStudy].sort(seriesSortingCriteria), ...otherStudy]; +} + /** * Sorts given series or display sets * The default criteria is based on series number in ascending order. diff --git a/tests/Crosshairs.spec.ts b/tests/Crosshairs.spec.ts index 022cce47b..48032b230 100644 --- a/tests/Crosshairs.spec.ts +++ b/tests/Crosshairs.spec.ts @@ -1,15 +1,108 @@ import { - checkForScreenshot, initializeMousePositionTracker, - screenShotPaths, + expect, test, visitStudy, } from './utils/index.js'; -test.beforeEach(async ({ page }) => { +/** Slower than default actionTimeout (10s); MPR crosshair SVG can lag on busy CI workers. */ +const CROSSHAIRS_DOM_TIMEOUT_MS = 30_000; + +async function getLayerSignature(page, layerId: string) { + const layer = page.locator(`#${layerId}`); + const lineCount = await layer.locator('line').count(); + const circleCount = await layer.locator('circle').count(); + const rectCount = await layer.locator('rect').count(); + const signatureParts: string[] = []; + const t = { timeout: CROSSHAIRS_DOM_TIMEOUT_MS }; + + for (let i = 0; i < lineCount; i++) { + const line = layer.locator('line').nth(i); + await line.waitFor({ state: 'attached', ...t }); + const [x1, y1, x2, y2] = await Promise.all([ + line.getAttribute('x1', t), + line.getAttribute('y1', t), + line.getAttribute('x2', t), + line.getAttribute('y2', t), + ]); + signatureParts.push(`line:${x1}|${y1}|${x2}|${y2}`); + } + + for (let i = 0; i < circleCount; i++) { + const circle = layer.locator('circle').nth(i); + await circle.waitFor({ state: 'attached', ...t }); + const [cx, cy, r] = await Promise.all([ + circle.getAttribute('cx', t), + circle.getAttribute('cy', t), + circle.getAttribute('r', t), + ]); + signatureParts.push(`circle:${cx}|${cy}|${r}`); + } + + for (let i = 0; i < rectCount; i++) { + const rect = layer.locator('rect').nth(i); + await rect.waitFor({ state: 'attached', ...t }); + const [x, y, width, height] = await Promise.all([ + rect.getAttribute('x', t), + rect.getAttribute('y', t), + rect.getAttribute('width', t), + rect.getAttribute('height', t), + ]); + signatureParts.push(`rect:${x}|${y}|${width}|${height}`); + } + + return signatureParts.join(';'); +} + +async function getCrosshairsSignature(page) { + // Read layers sequentially so we are not racing three heavy SVG trees on one page (flaky on CI). + const axial = await getLayerSignature(page, 'svg-layer-mpr-axial'); + const sagittal = await getLayerSignature(page, 'svg-layer-mpr-sagittal'); + const coronal = await getLayerSignature(page, 'svg-layer-mpr-coronal'); + return `${axial}||${sagittal}||${coronal}`; +} + +async function areLayerLinesAxisAligned(page, layerId: string) { + const lines = page.locator(`#${layerId}`).locator('line'); + const lineCount = await lines.count(); + if (lineCount < 4) { + return false; + } + + const t = { timeout: CROSSHAIRS_DOM_TIMEOUT_MS }; + for (let i = 0; i < 4; i++) { + const line = lines.nth(i); + const [x1, y1, x2, y2] = await Promise.all([ + line.getAttribute('x1', t), + line.getAttribute('y1', t), + line.getAttribute('x2', t), + line.getAttribute('y2', t), + ]); + const isVertical = x1 === x2; + const isHorizontal = y1 === y2; + if (!isVertical && !isHorizontal) { + return false; + } + } + + return true; +} + +async function expectCrosshairsReady(page) { + for (const layerId of ['svg-layer-mpr-axial', 'svg-layer-mpr-sagittal', 'svg-layer-mpr-coronal']) { + const locator = page.locator(`#${layerId}`); + await locator.waitFor({ state: 'visible' }); + await expect(locator.locator('line')).toHaveCount(4); + } +} + +test.beforeEach(async ({ page, leftPanelPageObject }) => { const studyInstanceUID = '1.3.6.1.4.1.14519.5.2.1.1706.8374.643249677828306008300337414785'; const mode = 'viewer'; await visitStudy(page, studyInstanceUID, mode, 2000); + // Force a deterministic base series so thumbnail ordering changes do not + // alter which stack drives MPR/crosshairs behavior. + await leftPanelPageObject.loadSeriesByDescription('PRE LIVER'); await initializeMousePositionTracker(page); }); @@ -17,8 +110,7 @@ test.describe('Crosshairs Test', async () => { test('should render the crosshairs correctly.', async ({ page, mainToolbarPageObject }) => { await mainToolbarPageObject.layoutSelection.MPR.click(); await mainToolbarPageObject.crosshairs.click(); - - await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRendered); + await expectCrosshairsReady(page); }); test('should allow the user to rotate the crosshairs', async ({ @@ -28,12 +120,14 @@ test.describe('Crosshairs Test', async () => { }) => { await mainToolbarPageObject.layoutSelection.MPR.click(); await mainToolbarPageObject.crosshairs.click(); + await expectCrosshairsReady(page); + const beforeRotate = await getCrosshairsSignature(page); await viewportPageObject.crosshairs.axial.rotate(); await viewportPageObject.crosshairs.sagittal.rotate(); await viewportPageObject.crosshairs.coronal.rotate(); - - await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsRotated); + const afterRotate = await getCrosshairsSignature(page); + expect(afterRotate).not.toEqual(beforeRotate); }); test('should allow the user to adjust the slab thickness', async ({ @@ -43,12 +137,14 @@ test.describe('Crosshairs Test', async () => { }) => { await mainToolbarPageObject.layoutSelection.MPR.click(); await mainToolbarPageObject.crosshairs.click(); + await expectCrosshairsReady(page); + const beforeIncrease = await getLayerSignature(page, 'svg-layer-mpr-axial'); await viewportPageObject.crosshairs.axial.increase(); await viewportPageObject.crosshairs.sagittal.increase(); await viewportPageObject.crosshairs.coronal.increase(); - - await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsSlabThickness); + const afterIncrease = await getLayerSignature(page, 'svg-layer-mpr-axial'); + expect(afterIncrease).not.toEqual(beforeIncrease); }); test('should reset the crosshairs to the initial position when reset is clicked', async ({ @@ -58,14 +154,20 @@ test.describe('Crosshairs Test', async () => { }) => { await mainToolbarPageObject.layoutSelection.MPR.click(); await mainToolbarPageObject.crosshairs.click(); + await expectCrosshairsReady(page); + const initialPosition = await getCrosshairsSignature(page); await viewportPageObject.crosshairs.axial.rotate(); await viewportPageObject.crosshairs.sagittal.rotate(); await viewportPageObject.crosshairs.coronal.rotate(); + const rotatedPosition = await getCrosshairsSignature(page); + expect(rotatedPosition).not.toEqual(initialPosition); await mainToolbarPageObject.moreTools.reset.click(); - - await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsResetToolbar); + await expectCrosshairsReady(page); + expect(await areLayerLinesAxisAligned(page, 'svg-layer-mpr-axial')).toBeTruthy(); + expect(await areLayerLinesAxisAligned(page, 'svg-layer-mpr-sagittal')).toBeTruthy(); + expect(await areLayerLinesAxisAligned(page, 'svg-layer-mpr-coronal')).toBeTruthy(); }); test('should reset the crosshairs when a new displayset is loaded', async ({ @@ -76,13 +178,19 @@ test.describe('Crosshairs Test', async () => { }) => { await mainToolbarPageObject.layoutSelection.MPR.click(); await mainToolbarPageObject.crosshairs.click(); + await expectCrosshairsReady(page); + const initialPosition = await getCrosshairsSignature(page); await viewportPageObject.crosshairs.axial.rotate(); await viewportPageObject.crosshairs.sagittal.rotate(); await viewportPageObject.crosshairs.coronal.rotate(); + const rotatedPosition = await getCrosshairsSignature(page); + expect(rotatedPosition).not.toEqual(initialPosition); await leftPanelPageObject.loadSeriesByDescription('Recon 3: LIVER 3 PHASE (AP)'); - - await checkForScreenshot(page, page, screenShotPaths.crosshairs.crosshairsNewDisplayset); + await expectCrosshairsReady(page); + expect(await areLayerLinesAxisAligned(page, 'svg-layer-mpr-axial')).toBeTruthy(); + expect(await areLayerLinesAxisAligned(page, 'svg-layer-mpr-sagittal')).toBeTruthy(); + expect(await areLayerLinesAxisAligned(page, 'svg-layer-mpr-coronal')).toBeTruthy(); }); }); diff --git a/tests/DicomTagBrowser.spec.ts b/tests/DicomTagBrowser.spec.ts index 7471c8b12..92719e898 100644 --- a/tests/DicomTagBrowser.spec.ts +++ b/tests/DicomTagBrowser.spec.ts @@ -1,11 +1,29 @@ import { checkForScreenshot, screenShotPaths, test, visitStudy, expect } from './utils'; import { assertBoundingBoxIsContainedWithin } from './utils/assertions'; +async function expectSelectedSeriesExistsInOptions(seriesSelect) { + const selectedSeriesLabel = (await seriesSelect.value.innerText()).trim(); + await seriesSelect.click(); + const optionCount = await seriesSelect.options.count(); + let hasMatchingOption = false; + + for (let index = 0; index < optionCount; index++) { + const optionText = (await seriesSelect.options.nth(index).innerText()).split('\n')[0].trim(); + if (optionText === selectedSeriesLabel) { + hasMatchingOption = true; + break; + } + } + + await expect(hasMatchingOption).toBeTruthy(); +} + test('should display the dicom tag browser', async ({ page, mainToolbarPageObject }) => { const studyInstanceUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5'; const mode = 'viewer'; await visitStudy(page, studyInstanceUID, mode, 2000); + await mainToolbarPageObject.waitForVolumeLoad(); await mainToolbarPageObject.moreTools.tagBrowser.click(); await checkForScreenshot( page, @@ -22,6 +40,7 @@ test('should render the scroll bar with the correct look-and-feel', async ({ const mode = 'viewer'; await visitStudy(page, studyInstanceUID, mode, 2000); + await mainToolbarPageObject.waitForVolumeLoad(); await mainToolbarPageObject.moreTools.tagBrowser.click(); await checkForScreenshot({ page, @@ -75,6 +94,7 @@ test('should open DICOM Tag Browser from empty viewport and show default series' // Switch to 3x3 layout await mainToolbarPageObject.layoutSelection.click(); await page.getByTestId('Layout-2-2').click(); + await mainToolbarPageObject.waitForVolumeLoad(); await viewportPageObject.getNthLocator(6).click(); @@ -84,9 +104,7 @@ test('should open DICOM Tag Browser from empty viewport and show default series' await dicomTagBrowser.waitVisible(); const seriesSelect = dicomTagBrowser.seriesSelect; - const optionText = await seriesSelect.getOptionText(0); - - await expect(seriesSelect.value).toContainText(optionText); + await expectSelectedSeriesExistsInOptions(seriesSelect); }); test('should open DICOM Tag Browser with active viewport series when viewport has display set', async ({ @@ -101,6 +119,7 @@ test('should open DICOM Tag Browser with active viewport series when viewport ha await mainToolbarPageObject.layoutSelection.click(); await page.getByTestId('Layout-2-2').click(); + await mainToolbarPageObject.waitForVolumeLoad(); await (await viewportPageObject.getNth(2)).pane.click(); @@ -110,7 +129,5 @@ test('should open DICOM Tag Browser with active viewport series when viewport ha await dicomTagBrowser.waitVisible(); const seriesSelect = dicomTagBrowser.seriesSelect; - const optionText = await seriesSelect.getOptionText(2); - - await expect(seriesSelect.value).toContainText(optionText); + await expectSelectedSeriesExistsInOptions(seriesSelect); }); diff --git a/tests/pages/ViewportPageObject.ts b/tests/pages/ViewportPageObject.ts index e40015b85..ec0e4fb52 100644 --- a/tests/pages/ViewportPageObject.ts +++ b/tests/pages/ViewportPageObject.ts @@ -255,13 +255,35 @@ export class ViewportPageObject { get crosshairs() { const page = this.page; + const crosshairHoverTimeout = 20000; + + async function getSlabHandleLocator(locator: Locator) { + const startTime = Date.now(); + const rectLocator = locator.locator('rect').first(); + const circleLocator = locator.locator('circle').first(); + + while (Date.now() - startTime < crosshairHoverTimeout) { + if ((await rectLocator.count()) > 0) { + return rectLocator; + } + + if ((await circleLocator.count()) > 0) { + return circleLocator; + } + + await page.waitForTimeout(250); + } + + throw new Error('Could not find slab thickness handle for crosshairs interaction'); + } + async function increaseSlabThickness(locator: Locator, lineNumber: number, axis: string) { const lineLocator = locator.locator('line').nth(lineNumber); await lineLocator.click({ force: true }); - await lineLocator.hover({ force: true }); + await lineLocator.hover({ force: true, timeout: crosshairHoverTimeout }); - const circleLocator = locator.locator('rect').first(); - await circleLocator.hover({ force: true }); + const slabHandleLocator = await getSlabHandleLocator(locator); + await slabHandleLocator.hover({ force: true, timeout: crosshairHoverTimeout }); await page.mouse.down(); @@ -280,10 +302,11 @@ export class ViewportPageObject { async function rotateCrosshairs(locator: Locator, lineNumber: number) { const lineLocator = locator.locator('line').nth(lineNumber); await lineLocator.click({ force: true }); - await lineLocator.hover({ force: true }); + await lineLocator.hover({ force: true, timeout: crosshairHoverTimeout }); const circleLocator = locator.locator('circle').nth(1); - await circleLocator.hover({ force: true }); + await circleLocator.waitFor({ state: 'attached', timeout: crosshairHoverTimeout }); + await circleLocator.hover({ force: true, timeout: crosshairHoverTimeout }); await page.mouse.down(); diff --git a/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeDisplayedCorrectly.png b/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeDisplayedCorrectly.png index 0185cecf6..97459321d 100644 Binary files a/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeDisplayedCorrectly.png and b/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeJumpToMeasurement.png b/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeJumpToMeasurement.png index e1a152232..da1b7fbfe 100644 Binary files a/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeJumpToMeasurement.png and b/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbeJumpToMeasurement.png differ diff --git a/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbePostHydration.png b/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbePostHydration.png index deb16b5ec..1af2482ac 100644 Binary files a/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbePostHydration.png and b/tests/screenshots/chromium/Scoord3dProbe.spec.ts/scoord3dProbePostHydration.png differ diff --git a/yarn.lock b/yarn.lock index ab0e63154..0d63ef66e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1946,10 +1946,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@cornerstonejs/adapters@4.20.0": - version "4.20.0" - resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-4.20.0.tgz#94e21f2955d87d2c0ba47ebedaad77ee621f7ecf" - integrity sha512-OxplEaHadms6mZ5fX8o9zkMVw7rSjxP6+KRovBAqLXlXsM9hj7MgencWG2JX6SR2bUXvHVusiV9cdECcDMNvsg== +"@cornerstonejs/adapters@4.21.2": + version "4.21.2" + resolved "https://registry.npmjs.org/@cornerstonejs/adapters/-/adapters-4.21.2.tgz#aa4640c144bed192e5c3fb620ff32b737de35859" + integrity sha512-BTmj7jZDJky6XOsoueNq+qMavFLMvj46fftD08YovKWUDfoq7osOVpL9PBcnWODx05obsyagkDRyrkqTGd14wg== dependencies: "@babel/runtime-corejs2" "7.26.10" buffer "6.0.3" @@ -1957,10 +1957,10 @@ gl-matrix "3.4.3" ndarray "1.0.19" -"@cornerstonejs/ai@4.20.0": - version "4.20.0" - resolved "https://registry.yarnpkg.com/@cornerstonejs/ai/-/ai-4.20.0.tgz#9ee423cc99c2122360c8359f643a8e470717fcf5" - integrity sha512-65wl8mXy/N6DUjLlNZvKLgWTGWVu4kWDupxNU5p7Pd3ZxU6RnbG6d3pcM30D/bcQEuUWLEQBDodtBeJEsxJxoA== +"@cornerstonejs/ai@4.21.2": + version "4.21.2" + resolved "https://registry.npmjs.org/@cornerstonejs/ai/-/ai-4.21.2.tgz#ae49abd66e06d0e44b12935d74e7ae633bf6102d" + integrity sha512-I7YIOvcVnkDkkxH/88xJ0Yuemd0Qm6O9TO2nyprzwui/ZLMPD0bTcWPXks+ktxIAtz9rTRyNNodLvbF6aKk3DA== dependencies: "@babel/runtime-corejs2" "7.26.10" buffer "6.0.3" @@ -1996,20 +1996,20 @@ resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.7.tgz#784394d05d8cf735640e9c3baa206535ee8e0376" integrity sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w== -"@cornerstonejs/core@4.20.0": - version "4.20.0" - resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-4.20.0.tgz#9381f113879dd9fc2847c8e4d9e624602751bbef" - integrity sha512-rcrctEIcyyAwQ6zcVt1wbYoTPyH6YNLNBOBB/aLeJZfLqGAfca+Cgf5K+KSGFJX1gZOdQZmYGmAF9P58B9PNVw== +"@cornerstonejs/core@4.21.2": + version "4.21.2" + resolved "https://registry.npmjs.org/@cornerstonejs/core/-/core-4.21.2.tgz#ec9fa1e39a0e0eba27399aa950490921cb164df5" + integrity sha512-XnhMGan9Ebnu2f3W9Q2iK6ShHGCLa1UYEPRYHzILgtnTbo5qHsZPay+IO/mjGQYH3VlTUgZDqzMRNBHXmvoiLg== dependencies: "@kitware/vtk.js" "34.15.1" comlink "4.4.2" gl-matrix "3.4.3" loglevel "1.9.2" -"@cornerstonejs/dicom-image-loader@4.20.0": - version "4.20.0" - resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-4.20.0.tgz#bf6425f2829268311b3fbd6a36bb584bdc431fc6" - integrity sha512-A7N2ekKEMEEKbw0QecbmgtL89LMpLZDkyzt2a97cZM9qyUdhdETyzL8m6guVtP10Ga5l9Aq9mFt2ifGtwTw0wA== +"@cornerstonejs/dicom-image-loader@4.21.2": + version "4.21.2" + resolved "https://registry.npmjs.org/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-4.21.2.tgz#6619b3d4f827e75d4e9b479ba40f70b3e256239b" + integrity sha512-g/2qTHA1P7VLmZ7OEHkH0S4jYIJsqb8128KMmpYuea2i3WpT+gOLf82eNYFBlnOCmwRitzs1YLHZM1/nDz4K/g== dependencies: "@cornerstonejs/codec-charls" "1.2.3" "@cornerstonejs/codec-libjpeg-turbo-8bit" "1.2.2" @@ -2021,25 +2021,25 @@ pako "2.1.0" uuid "9.0.1" -"@cornerstonejs/labelmap-interpolation@4.20.0": - version "4.20.0" - resolved "https://registry.yarnpkg.com/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-4.20.0.tgz#152fea1a574f825bed2cd0a69013ebb4405dcda7" - integrity sha512-VDUkvRZPCk98NkBFH0qFNEfjQoyYp2Th2+0KAJtDPeA0aqSPhugh14uJQ5uKEkDzZFUG/TUpeaHi1kldx6C5Gw== +"@cornerstonejs/labelmap-interpolation@4.21.2": + version "4.21.2" + resolved "https://registry.npmjs.org/@cornerstonejs/labelmap-interpolation/-/labelmap-interpolation-4.21.2.tgz#b4d30cbd8b70dd2f437ab30a7c410e33cad1364c" + integrity sha512-giW2IVPqZj3Bn4o9KIL8QaHWGPHoFD8R9aOvqlBQgSyUJF6XFIpfQDixb9txZhmkK0xlMrn/rbnEcoeFLoM1Pw== dependencies: "@itk-wasm/morphological-contour-interpolation" "1.1.0" itk-wasm "1.0.0-b.165" -"@cornerstonejs/polymorphic-segmentation@4.20.0": - version "4.20.0" - resolved "https://registry.yarnpkg.com/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-4.20.0.tgz#d4981f9df051217cddf6a69730386339fe69b5d2" - integrity sha512-tsMqAd/GrBeEFB2WU2K+YsGXeaP/1yD635yO1udpG2dloRaJrvFiK1dFMFCBLK3Xd768ZS1nq/MZEel00+vYxA== +"@cornerstonejs/polymorphic-segmentation@4.21.2": + version "4.21.2" + resolved "https://registry.npmjs.org/@cornerstonejs/polymorphic-segmentation/-/polymorphic-segmentation-4.21.2.tgz#99fd727fde374729df2135f3f909a576578d49b4" + integrity sha512-nY1sGmmVjKT0M7Z/rwskZmn+g90W9PACAKascjYF/LXrOyJozN4zVZn7HzkzYbH3+vcCGvwShEdLvDsDxaomsw== dependencies: "@icr/polyseg-wasm" "0.4.0" -"@cornerstonejs/tools@4.20.0": - version "4.20.0" - resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-4.20.0.tgz#58d834f80513689c354e052b9641516a62d24ad8" - integrity sha512-kphlW17eohBRk8MXEgdufM2t8MC5JqdlWUCfXu5rfg0KS1ut6iSWGAxFS+12noPR5qDzfVEYnD+4NkL37jg8pw== +"@cornerstonejs/tools@4.21.2": + version "4.21.2" + resolved "https://registry.npmjs.org/@cornerstonejs/tools/-/tools-4.21.2.tgz#019783b87cb2c5c7e1ea86d47f042ea77e827f80" + integrity sha512-dBOFIzFLVnCEEBOaXvA+cUNP+bzkdFwLDjEX3/0dP/4hjoFkZeq+AINAJn6oG5UKycqQOLhQ5gn3z4ugYK4ujQ== dependencies: "@types/offscreencanvas" "2019.7.3" comlink "4.4.2" @@ -6319,14 +6319,14 @@ axe-core@^4.10.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.3.tgz#04145965ac7894faddbac30861e5d8f11bfd14fc" integrity sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg== -axios@1.13.5, axios@^1.12.0, axios@^1.4.0, axios@^1.6.2: - version "1.13.5" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.5.tgz#5e464688fa127e11a660a2c49441c009f6567a43" - integrity sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q== +axios@1.13.5, axios@1.15.0, axios@^1.12.0, axios@^1.4.0, axios@^1.6.2: + version "1.15.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.15.0.tgz#0fcee91ef03d386514474904b27863b2c683bf4f" + integrity sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q== dependencies: follow-redirects "^1.15.11" form-data "^4.0.5" - proxy-from-env "^1.1.0" + proxy-from-env "^2.1.0" axobject-query@^4.1.0: version "4.1.0" @@ -16489,10 +16489,10 @@ proxy-from-env@1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +proxy-from-env@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" + integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== psl@^1.1.33: version "1.15.0"