From 62620afb9b7d8d0302584f125704509d65ae6a2d Mon Sep 17 00:00:00 2001 From: Ghadeer Albattarni <165973963+GhadeerAlbattarni@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:32:27 -0400 Subject: [PATCH] test( zoomIn-tool): verify horizontal flip is preserved in magnified view (#5983) --- bun.lock | 330 +++++++++--------- .../cornerstone-dicom-pmap/package.json | 4 +- extensions/cornerstone-dicom-seg/package.json | 4 +- extensions/cornerstone-dicom-sr/package.json | 6 +- .../cornerstone-dynamic-volume/package.json | 4 +- extensions/cornerstone/package.json | 14 +- extensions/measurement-tracking/package.json | 4 +- extensions/usAnnotation/package.json | 4 +- modes/usAnnotation/package.json | 4 +- platform/app/package.json | 2 +- platform/core/package.json | 4 +- tests/ZoomIn.spec.ts | 34 ++ tests/pages/MagnifyGlassPageObject.ts | 48 +++ tests/pages/MainToolbarPageObject.ts | 10 + tests/pages/ViewportPageObject.ts | 63 ++++ tests/pages/index.ts | 2 + .../magnifyViewportDisplayedCorrectly.png | Bin 0 -> 21931 bytes tests/utils/screenShotPaths.ts | 3 + tests/utils/simulateDragOnElement.ts | 8 +- yarn.lock | 56 +-- 20 files changed, 384 insertions(+), 220 deletions(-) create mode 100644 tests/ZoomIn.spec.ts create mode 100644 tests/pages/MagnifyGlassPageObject.ts create mode 100644 tests/screenshots/chromium/ZoomIn.spec.ts/magnifyViewportDisplayedCorrectly.png diff --git a/bun.lock b/bun.lock index 123bb7551..6a7853c7e 100644 --- a/bun.lock +++ b/bun.lock @@ -50,7 +50,7 @@ }, "addOns/externals/devDependencies": { "name": "@externals/devDependencies", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "@kitware/vtk.js": "34.15.1", @@ -131,22 +131,22 @@ }, "addOns/externals/dicom-microscopy-viewer": { "name": "@externals/dicom-microscopy-viewer", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "dicom-microscopy-viewer": "0.48.17", }, }, "extensions/cornerstone": { "name": "@ohif/extension-cornerstone", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.21.7", - "@cornerstonejs/ai": "4.21.7", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/labelmap-interpolation": "4.21.7", - "@cornerstonejs/polymorphic-segmentation": "4.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/ai": "4.22.3", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/labelmap-interpolation": "4.22.3", + "@cornerstonejs/polymorphic-segmentation": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "@icr/polyseg-wasm": "0.4.0", "@itk-wasm/morphological-contour-interpolation": "1.1.0", "@kitware/vtk.js": "34.15.1", @@ -164,9 +164,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.21.7", - "@ohif/core": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@cornerstonejs/dicom-image-loader": "4.22.3", + "@ohif/core": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -178,18 +178,18 @@ }, "extensions/cornerstone-dicom-pmap": { "name": "@ohif/extension-cornerstone-dicom-pmap", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.21.7", - "@cornerstonejs/core": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/core": "4.22.3", "@kitware/vtk.js": "34.15.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -200,15 +200,15 @@ }, "extensions/cornerstone-dicom-rt": { "name": "@ohif/extension-cornerstone-dicom-rt", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -219,18 +219,18 @@ }, "extensions/cornerstone-dicom-seg": { "name": "@ohif/extension-cornerstone-dicom-seg", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.21.7", - "@cornerstonejs/core": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/core": "4.22.3", "@kitware/vtk.js": "34.15.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -241,19 +241,19 @@ }, "extensions/cornerstone-dicom-sr": { "name": "@ohif/extension-cornerstone-dicom-sr", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.21.7", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-measurement-tracking": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-measurement-tracking": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -263,19 +263,19 @@ }, "extensions/cornerstone-dynamic-volume": { "name": "@ohif/extension-cornerstone-dynamic-volume", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -285,7 +285,7 @@ }, "extensions/default": { "name": "@ohif/extension-default", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "@cornerstonejs/calculate-suv": "1.1.0", @@ -294,8 +294,8 @@ "react-color": "2.19.3", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", "dcmjs": "0.49.4", "dicomweb-client": "0.10.4", "prop-types": "15.8.1", @@ -309,7 +309,7 @@ }, "extensions/dicom-microscopy": { "name": "@ohif/extension-dicom-microscopy", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "@cornerstonejs/codec-charls": "1.2.3", @@ -320,10 +320,10 @@ "mathjs": "12.4.3", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "prop-types": "15.8.1", "react": "18.3.1", "react-dom": "18.3.1", @@ -334,14 +334,14 @@ }, "extensions/dicom-pdf": { "name": "@ohif/extension-dicom-pdf", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -351,14 +351,14 @@ }, "extensions/dicom-video": { "name": "@ohif/extension-dicom-video", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -368,20 +368,20 @@ }, "extensions/measurement-tracking": { "name": "@ohif/extension-measurement-tracking", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@ohif/ui": "3.13.0-beta.61", + "@ohif/ui": "3.13.0-beta.64", "@xstate/react": "3.2.2", "xstate": "4.38.3", }, "peerDependencies": { - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "classnames": "2.5.1", "dcmjs": "0.49.4", "lodash.debounce": "4.0.8", @@ -394,14 +394,14 @@ }, "extensions/test-extension": { "name": "@ohif/extension-test", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", "dcmjs": "0.49.4", "dicom-parser": "1.8.21", "hammerjs": "2.0.8", @@ -411,7 +411,7 @@ }, "extensions/tmtv": { "name": "@ohif/extension-tmtv", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "classnames": "2.5.1", @@ -428,16 +428,16 @@ }, "extensions/usAnnotation": { "name": "@ohif/extension-ultrasound-pleura-bline", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", - "@ohif/ui-next": "3.13.0-beta.61", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", + "@ohif/ui-next": "3.13.0-beta.64", }, "devDependencies": { "@babel/core": "7.28.0", @@ -476,7 +476,7 @@ }, "modes/basic": { "name": "@ohif/mode-basic", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", }, @@ -485,19 +485,19 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/extension-dicom-pdf": "3.13.0-beta.61", - "@ohif/extension-dicom-video": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/extension-dicom-pdf": "3.13.0-beta.64", + "@ohif/extension-dicom-video": "3.13.0-beta.64", }, }, "modes/basic-dev-mode": { "name": "@ohif/mode-basic-dev-mode", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -507,17 +507,17 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/extension-dicom-pdf": "3.13.0-beta.61", - "@ohif/extension-dicom-video": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/extension-dicom-pdf": "3.13.0-beta.64", + "@ohif/extension-dicom-video": "3.13.0-beta.64", }, }, "modes/basic-test-mode": { "name": "@ohif/mode-test", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -527,19 +527,19 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/extension-dicom-pdf": "3.13.0-beta.61", - "@ohif/extension-dicom-video": "3.13.0-beta.61", - "@ohif/extension-measurement-tracking": "3.13.0-beta.61", - "@ohif/extension-test": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/extension-dicom-pdf": "3.13.0-beta.64", + "@ohif/extension-dicom-video": "3.13.0-beta.64", + "@ohif/extension-measurement-tracking": "3.13.0-beta.64", + "@ohif/extension-test": "3.13.0-beta.64", }, }, "modes/longitudinal": { "name": "@ohif/mode-longitudinal", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -549,33 +549,33 @@ "webpack-merge": "5.10.0", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/extension-dicom-pdf": "3.13.0-beta.61", - "@ohif/extension-dicom-video": "3.13.0-beta.61", - "@ohif/extension-measurement-tracking": "3.13.0-beta.61", - "@ohif/mode-basic": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/extension-dicom-pdf": "3.13.0-beta.64", + "@ohif/extension-dicom-video": "3.13.0-beta.64", + "@ohif/extension-measurement-tracking": "3.13.0-beta.64", + "@ohif/mode-basic": "3.13.0-beta.64", }, }, "modes/microscopy": { "name": "@ohif/mode-microscopy", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", }, "peerDependencies": { - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-dicom-microscopy": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-dicom-microscopy": "3.13.0-beta.64", }, }, "modes/preclinical-4d": { "name": "@ohif/mode-preclinical-4d", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", }, @@ -594,7 +594,7 @@ }, "modes/segmentation": { "name": "@ohif/mode-segmentation", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -636,7 +636,7 @@ }, "modes/tmtv": { "name": "@ohif/mode-tmtv", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "i18next": "17.3.1", @@ -657,14 +657,14 @@ }, "modes/usAnnotation": { "name": "@ohif/mode-ultrasound-pleura-bline", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.61", - "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.61", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", + "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.64", "i18next": "17.3.1", }, "devDependencies": { @@ -693,34 +693,34 @@ }, "platform/app": { "name": "@ohif/app", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "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.21.7", + "@cornerstonejs/dicom-image-loader": "4.22.3", "@emotion/serialize": "1.3.3", - "@ohif/core": "3.13.0-beta.61", - "@ohif/extension-cornerstone": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.61", - "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.61", - "@ohif/extension-default": "3.13.0-beta.61", - "@ohif/extension-dicom-microscopy": "3.13.0-beta.61", - "@ohif/extension-dicom-pdf": "3.13.0-beta.61", - "@ohif/extension-dicom-video": "3.13.0-beta.61", - "@ohif/extension-test": "3.13.0-beta.61", - "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.61", - "@ohif/i18n": "3.13.0-beta.61", - "@ohif/mode-basic-dev-mode": "3.13.0-beta.61", - "@ohif/mode-longitudinal": "3.13.0-beta.61", - "@ohif/mode-microscopy": "3.13.0-beta.61", - "@ohif/mode-test": "3.13.0-beta.61", - "@ohif/mode-ultrasound-pleura-bline": "3.13.0-beta.61", - "@ohif/ui": "3.13.0-beta.61", - "@ohif/ui-next": "3.13.0-beta.61", + "@ohif/core": "3.13.0-beta.64", + "@ohif/extension-cornerstone": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-rt": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-seg": "3.13.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", + "@ohif/extension-default": "3.13.0-beta.64", + "@ohif/extension-dicom-microscopy": "3.13.0-beta.64", + "@ohif/extension-dicom-pdf": "3.13.0-beta.64", + "@ohif/extension-dicom-video": "3.13.0-beta.64", + "@ohif/extension-test": "3.13.0-beta.64", + "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.64", + "@ohif/i18n": "3.13.0-beta.64", + "@ohif/mode-basic-dev-mode": "3.13.0-beta.64", + "@ohif/mode-longitudinal": "3.13.0-beta.64", + "@ohif/mode-microscopy": "3.13.0-beta.64", + "@ohif/mode-test": "3.13.0-beta.64", + "@ohif/mode-ultrasound-pleura-bline": "3.13.0-beta.64", + "@ohif/ui": "3.13.0-beta.64", + "@ohif/ui-next": "3.13.0-beta.64", "@svgr/webpack": "8.1.0", "@types/react": "18.3.23", "classnames": "2.5.1", @@ -772,7 +772,7 @@ }, "platform/cli": { "name": "@ohif/cli", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "bin": { "ohif-cli": "src/index.js", }, @@ -796,7 +796,7 @@ }, "platform/core": { "name": "@ohif/core", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "dcmjs": "0.49.4", @@ -821,16 +821,16 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/dicom-image-loader": "4.21.7", - "@ohif/ui": "3.13.0-beta.61", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/dicom-image-loader": "4.22.3", + "@ohif/ui": "3.13.0-beta.64", "cornerstone-math": "0.1.10", "dicom-parser": "1.8.21", }, }, "platform/i18n": { "name": "@ohif/i18n", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@babel/runtime": "7.28.2", "i18next-locize-backend": "2.2.2", @@ -855,7 +855,7 @@ }, "platform/ui": { "name": "@ohif/ui", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@testing-library/react": "13.4.0", "browser-detect": "0.2.28", @@ -905,7 +905,7 @@ }, "platform/ui-next": { "name": "@ohif/ui-next", - "version": "3.13.0-beta.61", + "version": "3.13.0-beta.64", "dependencies": { "@radix-ui/react-accordion": "1.2.11", "@radix-ui/react-checkbox": "1.3.2", @@ -1242,9 +1242,9 @@ "@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="], - "@cornerstonejs/adapters": ["@cornerstonejs/adapters@4.21.7", "", { "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.7", "@cornerstonejs/tools": "4.21.7" } }, "sha512-a9lGNlcLuuk81c8H2F4rotrMxTf9EGursSVIdz7n0cQ8nJmebSZTmp5FWGLDadRxh9pIxMeC52JTcDVd3JR9MQ=="], + "@cornerstonejs/adapters": ["@cornerstonejs/adapters@4.22.3", "", { "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.22.3", "@cornerstonejs/tools": "4.22.3" } }, "sha512-58TaTUl7AmLARnKApfz9c5IWzIaPPewH8sjD0BxKu5PeVHSRSlKX7jH4pv1akapIbDqXBEW6unb45kLmm6u7dg=="], - "@cornerstonejs/ai": ["@cornerstonejs/ai@4.21.7", "", { "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.7", "@cornerstonejs/tools": "4.21.7" } }, "sha512-tVXRvGfHsZdE+eODMWD0sAAf6YlCmCRDGbQU/kX4kN27B7TwOwjzK4FFhReO6qf5MFf/7KjLfB0sQhab45t3Lw=="], + "@cornerstonejs/ai": ["@cornerstonejs/ai@4.22.3", "", { "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.22.3", "@cornerstonejs/tools": "4.22.3" } }, "sha512-NhRcQISjcDCp7rWCK9hGmCgsS36XKyT4AsCBgXuG7iU3ghI77j5kt9sUdqi0M4lRYLYZ1XMrFSDjNDCwFP+eYg=="], "@cornerstonejs/calculate-suv": ["@cornerstonejs/calculate-suv@1.1.0", "", {}, "sha512-Q9XraiDJif9aMFArD2iEuDO/HXbcRVCqB7KfaHgDrdTTjgDFovS91Psbdim7crypRSvE6dh/+HKeFNHdvNkA6w=="], @@ -1256,15 +1256,15 @@ "@cornerstonejs/codec-openjph": ["@cornerstonejs/codec-openjph@2.4.7", "", {}, "sha512-qvP4q4JDib7mi9r7LqKOwqz7YZ8gjtDX4ZCezeYf8+eb7MBXCz5uXAMeVF3yz9Axw4XiIMdB/pqXkm8tqCl13w=="], - "@cornerstonejs/core": ["@cornerstonejs/core@4.21.7", "", { "dependencies": { "@kitware/vtk.js": "34.15.1", "comlink": "4.4.2", "gl-matrix": "3.4.3", "loglevel": "1.9.2" } }, "sha512-wZkALM/P6TTODtbSeOOZvzWKXjyMRKtsyWJ6NL61BveIlNxATpBbrAIj0dqLVasdF45XcJO5Qn4TiSO/kgKRGA=="], + "@cornerstonejs/core": ["@cornerstonejs/core@4.22.3", "", { "dependencies": { "@kitware/vtk.js": "34.15.1", "comlink": "4.4.2", "gl-matrix": "3.4.3", "loglevel": "1.9.2" } }, "sha512-oxLcg24ER3HHSAEsz3iG7+cb2oHnVSzt7H8EeRtK69e6Ztjl6XkEmXeAbbJypm2QYIkPYb3oJb6zWeYOz1NtYw=="], - "@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@4.21.7", "", { "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.7" } }, "sha512-wtfKs/U+FM2M7HHiNTFJwujs8TEU2rBz03Fx4Bc//vpktasUN9bqLl/eQ/9zfmz8Cdi12BewVpORd7l4nUmhtQ=="], + "@cornerstonejs/dicom-image-loader": ["@cornerstonejs/dicom-image-loader@4.22.3", "", { "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.22.3" } }, "sha512-TVPSc3PUvy2I6+ZnWX8B2uqJZ5onUd/+e+m/BfeEdZC51GMhC4VfTmqOwOjWDNDyO35ZA9j1mqk8iIJzDpqoeA=="], - "@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@4.21.7", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "4.21.7", "@cornerstonejs/tools": "4.21.7", "@kitware/vtk.js": "34.15.1" } }, "sha512-YJGVLjcpG58joBVOWnjHdw7FKGJimryVVJOoCfjLgNsKuoKEkhneTkOMTXsM29ArpgBNOmMYaBPSyf4ZjNxDRQ=="], + "@cornerstonejs/labelmap-interpolation": ["@cornerstonejs/labelmap-interpolation@4.22.3", "", { "dependencies": { "@itk-wasm/morphological-contour-interpolation": "1.1.0", "itk-wasm": "1.0.0-b.165" }, "peerDependencies": { "@cornerstonejs/core": "4.22.3", "@cornerstonejs/tools": "4.22.3", "@kitware/vtk.js": "34.15.1" } }, "sha512-ngschi2EKr+47LWbbTiu6tt3aw4e7yp0mVCDXwJm1Z2eyugemiiAQvOT77EKSBZ//L2fAZR3Edr+qJFzPa5KUw=="], - "@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@4.21.7", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "4.21.7", "@cornerstonejs/tools": "4.21.7", "@kitware/vtk.js": "34.15.1" } }, "sha512-4qxVMY0LJ+ffJfbzvzFOwe6j1p93pawwMEVcWRZkipE0pgtlW1SWlBvePCNb25yps6GUxNFPEmdUn5x/Lw77VQ=="], + "@cornerstonejs/polymorphic-segmentation": ["@cornerstonejs/polymorphic-segmentation@4.22.3", "", { "dependencies": { "@icr/polyseg-wasm": "0.4.0" }, "peerDependencies": { "@cornerstonejs/core": "4.22.3", "@cornerstonejs/tools": "4.22.3", "@kitware/vtk.js": "34.15.1" } }, "sha512-JNmtLbuwY8de3uwFf1YqySp5wt2BCT6kpg9gcoDNMmNxGDo0uT5yph1Muh+24sG7WDaoRwyzAEvG11h9NHgoqw=="], - "@cornerstonejs/tools": ["@cornerstonejs/tools@4.21.7", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "4.4.2", "lodash.get": "4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "4.21.7", "@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-p8bWrEKdjeNzzZfN5NI6Wh7tiZyI3/lXqrdLlY+BCD1YRUdv+rybhyrg0JhpodJYEGrS4/wrkhCApOp9j9Evdg=="], + "@cornerstonejs/tools": ["@cornerstonejs/tools@4.22.3", "", { "dependencies": { "@types/offscreencanvas": "2019.7.3", "comlink": "4.4.2", "lodash.get": "4.4.2" }, "peerDependencies": { "@cornerstonejs/core": "4.22.3", "@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-2XQmUesRWiqWTh3xGnLsQ6qqKI55vSVV4UqGXiPxnMcf6azDfEhcJO8JJCH1VXaDa89jxLBdZUDehUnb0UsIxA=="], "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], diff --git a/extensions/cornerstone-dicom-pmap/package.json b/extensions/cornerstone-dicom-pmap/package.json index 8c792dbad..e42915338 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.21.7", - "@cornerstonejs/core": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/core": "4.22.3", "@kitware/vtk.js": "34.15.1" } } diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index 96fa2a876..8ce57d627 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.21.7", - "@cornerstonejs/core": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/core": "4.22.3", "@kitware/vtk.js": "34.15.1" } } diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json index 4b7b2c883..73844a2c4 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.21.7", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "classnames": "2.5.1" } } diff --git a/extensions/cornerstone-dynamic-volume/package.json b/extensions/cornerstone-dynamic-volume/package.json index 6b7eb1395..5c6fab115 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.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "classnames": "2.5.1" } } diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json index 5294fa5a8..706717766 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.21.7", + "@cornerstonejs/dicom-image-loader": "4.22.3", "@ohif/core": "3.13.0-beta.64", "@ohif/ui": "3.13.0-beta.64", "dcmjs": "0.49.4", @@ -53,12 +53,12 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/adapters": "4.21.7", - "@cornerstonejs/ai": "4.21.7", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/labelmap-interpolation": "4.21.7", - "@cornerstonejs/polymorphic-segmentation": "4.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/adapters": "4.22.3", + "@cornerstonejs/ai": "4.22.3", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/labelmap-interpolation": "4.22.3", + "@cornerstonejs/polymorphic-segmentation": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "@icr/polyseg-wasm": "0.4.0", "@itk-wasm/morphological-contour-interpolation": "1.1.0", "@kitware/vtk.js": "34.15.1", diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index 28fe1d3d1..c233a00a4 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.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "@ohif/core": "3.13.0-beta.64", "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", "@ohif/extension-default": "3.13.0-beta.64", diff --git a/extensions/usAnnotation/package.json b/extensions/usAnnotation/package.json index 186f3cd1c..4c731ffe6 100644 --- a/extensions/usAnnotation/package.json +++ b/extensions/usAnnotation/package.json @@ -42,8 +42,8 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "@ohif/core": "3.13.0-beta.64", "@ohif/extension-cornerstone": "3.13.0-beta.64", "@ohif/extension-default": "3.13.0-beta.64", diff --git a/modes/usAnnotation/package.json b/modes/usAnnotation/package.json index ed7d31030..a31c61ac4 100644 --- a/modes/usAnnotation/package.json +++ b/modes/usAnnotation/package.json @@ -34,8 +34,8 @@ }, "dependencies": { "@babel/runtime": "7.28.2", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/tools": "4.21.7", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/tools": "4.22.3", "@ohif/core": "3.13.0-beta.64", "@ohif/extension-cornerstone-dicom-sr": "3.13.0-beta.64", "@ohif/extension-ultrasound-pleura-bline": "3.13.0-beta.64", diff --git a/platform/app/package.json b/platform/app/package.json index e01f82480..523c3a0ea 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.21.7", + "@cornerstonejs/dicom-image-loader": "4.22.3", "@emotion/serialize": "1.3.3", "@ohif/core": "3.13.0-beta.64", "@ohif/extension-cornerstone": "3.13.0-beta.64", diff --git a/platform/core/package.json b/platform/core/package.json index bfa309bcb..122c9fbbc 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -37,8 +37,8 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "1.2.2", "@cornerstonejs/codec-openjpeg": "1.3.0", "@cornerstonejs/codec-openjph": "2.4.7", - "@cornerstonejs/core": "4.21.7", - "@cornerstonejs/dicom-image-loader": "4.21.7", + "@cornerstonejs/core": "4.22.3", + "@cornerstonejs/dicom-image-loader": "4.22.3", "@ohif/ui": "3.13.0-beta.64", "cornerstone-math": "0.1.10", "dicom-parser": "1.8.21" diff --git a/tests/ZoomIn.spec.ts b/tests/ZoomIn.spec.ts new file mode 100644 index 000000000..66146a02e --- /dev/null +++ b/tests/ZoomIn.spec.ts @@ -0,0 +1,34 @@ +import { checkForScreenshot, screenShotPaths, test, visitStudy } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046'; + const mode = 'viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should render the magnified region with the same horizontal flip as the source viewport', async ({ + page, + mainToolbarPageObject, + viewportPageObject, +}) => { + await mainToolbarPageObject.moreTools.flipHorizontal.click(); + + const activeViewport = await viewportPageObject.active; + + await activeViewport.sliceNavigation.toSlice(61); + + await mainToolbarPageObject.moreTools.magnify.click(); + + await activeViewport.magnifyGlass.drag({ + start: { x: 0.78, y: 0.91 }, + mouseUp: false, + }); + + await checkForScreenshot( + page, + activeViewport.magnifyGlass.locator, + screenShotPaths.zoomIn.magnifyViewportDisplayedCorrectly + ); + + await activeViewport.magnifyGlass.stopDrag(); +}); diff --git a/tests/pages/MagnifyGlassPageObject.ts b/tests/pages/MagnifyGlassPageObject.ts new file mode 100644 index 000000000..76b6c4045 --- /dev/null +++ b/tests/pages/MagnifyGlassPageObject.ts @@ -0,0 +1,48 @@ +import { Locator, Page } from '@playwright/test'; +import { simulateNormalizedDragOnElement } from '../utils'; + +type MagnifyDragParams = { + start: { x: number; y: number }; + end?: { x: number; y: number }; + mouseUp?: boolean; + button?: 'left' | 'right' | 'middle'; + delay?: number; + steps?: number; +}; + +export class MagnifyGlassPageObject { + readonly page: Page; + readonly viewport: Locator; + + constructor(page: Page, viewport: Locator) { + this.page = page; + this.viewport = viewport; + } + + get locator(): Locator { + return this.viewport.locator('.magnifyTool'); + } + + async drag({ + start, + end, + button, + delay, + steps, + mouseUp = true, + }: MagnifyDragParams): Promise { + await simulateNormalizedDragOnElement({ + locator: this.viewport, + start, + end: end ?? start, + button, + delay, + steps, + mouseUp, + }); + } + + async stopDrag(): Promise { + await this.page.mouse.up(); + } +} diff --git a/tests/pages/MainToolbarPageObject.ts b/tests/pages/MainToolbarPageObject.ts index 42e7c106e..91a855edb 100644 --- a/tests/pages/MainToolbarPageObject.ts +++ b/tests/pages/MainToolbarPageObject.ts @@ -326,6 +326,16 @@ export class MainToolbarPageObject { }, }; }, + get magnify() { + const button = page.getByTestId('Magnify'); + return { + button, + async click() { + await moreTools.click(); + await button.click(); + }, + }; + }, }; } diff --git a/tests/pages/ViewportPageObject.ts b/tests/pages/ViewportPageObject.ts index ec0e4fb52..e62da5fc2 100644 --- a/tests/pages/ViewportPageObject.ts +++ b/tests/pages/ViewportPageObject.ts @@ -8,6 +8,7 @@ import { } from '../utils'; import { DataOverlayPageObject } from './DataOverlayPageObject'; import { DOMOverlayPageObject } from './DOMOverlayPageObject'; +import { MagnifyGlassPageObject } from './MagnifyGlassPageObject'; type SvgInnerElement = 'circle' | 'path' | 'd'; @@ -91,6 +92,13 @@ export interface IViewportPageObject { click: () => Promise; }; }; + sliceNavigation: { + toSlice: (sliceIndex: number) => Promise; + toFirstSlice: () => Promise; + toLastSlice: () => Promise; + scrollBy: (delta: number) => Promise; + }; + magnifyGlass: MagnifyGlassPageObject; } export class ViewportPageObject { @@ -200,6 +208,59 @@ export class ViewportPageObject { }; } + /** + * Note: awaiting the returned methods (toSlice, toFirstSlice, toLastSlice, scrollBy) + * does not guarantee the viewport has finished rendering. Follow up with + * `waitForViewportsRendered` if you need pixel-stable state. + */ + private getSliceNavigation(viewport: Locator) { + const page = this.page; + + const jumpToImage = async (imageIndex: number) => { + const viewportId = await this.getViewportId(viewport); + await page.evaluate( + ({ commandsManager, viewportId, imageIndex }) => { + return commandsManager.runCommand('jumpToImage', { + imageIndex, + viewport: { id: viewportId }, + }); + }, + { + viewportId, + imageIndex, + commandsManager: await page.evaluateHandle('window.commandsManager'), + } + ); + }; + + const scrollBy = async (delta: number) => { + const viewportId = await this.getViewportId(viewport); + await page.evaluate( + ({ services, viewportId, delta }) => { + const cornerstoneViewport = ( + services as any + ).cornerstoneViewportService.getCornerstoneViewport(viewportId); + if (!cornerstoneViewport) { + return; + } + return cornerstoneViewport.scroll(delta); + }, + { + viewportId, + delta, + services: await page.evaluateHandle('window.services'), + } + ); + }; + + return { + toSlice: jumpToImage, + toFirstSlice: () => jumpToImage(0), + toLastSlice: () => jumpToImage(-1), + scrollBy, + }; + } + private async viewportPageObjectFactory(viewport: Locator): Promise { return { nthAnnotation: (nth: number) => this.getAnnotation(viewport, nth), @@ -244,6 +305,8 @@ export class ViewportPageObject { return this.getSvg(viewport, innerElement); }, navigationArrows: this.getNavigationArrows(viewport), + sliceNavigation: this.getSliceNavigation(viewport), + magnifyGlass: new MagnifyGlassPageObject(this.page, viewport), }; } diff --git a/tests/pages/index.ts b/tests/pages/index.ts index 4976a9bd8..de771a76b 100644 --- a/tests/pages/index.ts +++ b/tests/pages/index.ts @@ -5,6 +5,7 @@ import { RightPanelPageObject } from './RightPanelPageObject'; import { ViewportPageObject } from './ViewportPageObject'; import { NotFoundStudyPageObject } from './NotFoundStudyPageObject'; import { DicomTagBrowserPageObject } from './DicomTagBrowserPageObject'; +import { MagnifyGlassPageObject } from './MagnifyGlassPageObject'; export { DOMOverlayPageObject, @@ -14,4 +15,5 @@ export { ViewportPageObject, NotFoundStudyPageObject, DicomTagBrowserPageObject, + MagnifyGlassPageObject, }; diff --git a/tests/screenshots/chromium/ZoomIn.spec.ts/magnifyViewportDisplayedCorrectly.png b/tests/screenshots/chromium/ZoomIn.spec.ts/magnifyViewportDisplayedCorrectly.png new file mode 100644 index 0000000000000000000000000000000000000000..909c553a3566552618385c1997df66a77c26438e GIT binary patch literal 21931 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