diff --git a/extensions/cornerstone/src/commandsModule.ts b/extensions/cornerstone/src/commandsModule.ts index 9926d9811..adbab06f9 100644 --- a/extensions/cornerstone/src/commandsModule.ts +++ b/extensions/cornerstone/src/commandsModule.ts @@ -140,19 +140,16 @@ function commandsModule({ )?.[0]; if (previousReferencedDisplaySetStoreKey) { - if (referencedImageId) { - setPositionPresentation(previousReferencedDisplaySetStoreKey, { - viewReference: { - referencedImageId, - }, - }); - } else { - setPositionPresentation( - previousReferencedDisplaySetStoreKey, - presentations.positionPresentation - ); - } + const presentationData = referencedImageId + ? { + ...presentations.positionPresentation, + viewReference: { + referencedImageId, + }, + } + : presentations.positionPresentation; + setPositionPresentation(previousReferencedDisplaySetStoreKey, presentationData); return; } diff --git a/extensions/default/src/DicomTagBrowser/DicomTagTable.tsx b/extensions/default/src/DicomTagBrowser/DicomTagTable.tsx index 4677fa02f..ecafdb768 100644 --- a/extensions/default/src/DicomTagBrowser/DicomTagTable.tsx +++ b/extensions/default/src/DicomTagBrowser/DicomTagTable.tsx @@ -47,9 +47,19 @@ const RowComponent = ({ {isChildOrParent && (
{row.areChildrenVisible ? ( - +
+ +
) : ( - +
+ +
)}
)} diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx index fd1590019..e587c128d 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.tsx @@ -88,7 +88,8 @@ function TrackedMeasurementsContextProvider( m => trackedStudy === m.referenceStudyUID && trackedSeries.includes(m.referenceSeriesUID) ); - const trackedMeasurement = trackedMeasurements[0]; + // Jump to the last tracked measurement - most recent + const trackedMeasurement = trackedMeasurements[trackedMeasurements.length - 1]; const referencedDisplaySetUID = trackedMeasurement.displaySetInstanceUID; // update the previously stored positionPresentation with the new viewportId @@ -166,11 +167,13 @@ function TrackedMeasurementsContextProvider( hydrateStructuredReport: hydrateStructuredReport.bind(null, { servicesManager, extensionManager, + commandsManager, appConfig, }), promptLabelAnnotation: promptLabelAnnotation.bind(null, { servicesManager, extensionManager, + commandsManager, }), }); machineOptions.guards = Object.assign({}, machineOptions.guards, { diff --git a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx index cdba84141..d60e1ccc5 100644 --- a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx +++ b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.tsx @@ -216,7 +216,7 @@ export default function PanelStudyBrowserTracking({ thumbnailSrc = await displaySet.getThumbnailSrc(); } if (!thumbnailSrc) { - let thumbnailSrc = await getImageSrc(imageId); + const thumbnailSrc = await getImageSrc(imageId); displaySet.thumbnailSrc = thumbnailSrc; } newImageSrcEntry[dSet.displaySetInstanceUID] = thumbnailSrc; diff --git a/package.json b/package.json index 59dd5c009..035f3774a 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "test:e2e:ci": "npx playwright test", "test:e2e:ui": "npx playwright test --ui", "test:e2e:headed": "npx playwright test --headed", + "test:e2e:debug": "npx playwright test --debug", "test:e2e:dist": "lerna run test:e2e:dist --stream", "test:e2e:serve": "yarn test:data && lerna run test:e2e:serve --stream", "see-changed": "lerna changed", diff --git a/tests/RTHydration2.spec.ts b/tests/RTHydration2.spec.ts new file mode 100644 index 000000000..b73cda160 --- /dev/null +++ b/tests/RTHydration2.spec.ts @@ -0,0 +1,42 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = '1.3.6.1.4.1.5962.99.1.2968617883.1314880426.1493322302363.3.0'; + const mode = 'viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should hydrate RT reports correctly', async ({ page }) => { + await page.getByTestId('side-panel-header-right').click(); + await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); + + await checkForScreenshot(page, page, screenShotPaths.rtHydration2.rtPreHydration); + // wait for 3 seconds + await page.evaluate(() => { + // Access cornerstone directly from the window object + const cornerstone = window.cornerstone; + if (!cornerstone) { + return; + } + + const enabledElements = cornerstone.getEnabledElements(); + if (enabledElements.length === 0) { + return; + } + + const viewport = enabledElements[0].viewport; + if (viewport) { + viewport.setZoom(4); + viewport.render(); + } + }); + + await page.waitForTimeout(3000); + + // + + // should preserve zoom and pan and scroll position after hydration + await page.getByTestId('yes-hydrate-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.rtHydration.rtPostHydration); +}); diff --git a/tests/SEGHydration.spec.ts b/tests/SEGHydration.spec.ts index b812290d2..876e75945 100644 --- a/tests/SEGHydration.spec.ts +++ b/tests/SEGHydration.spec.ts @@ -11,8 +11,26 @@ test('should hydrate SEG reports correctly', async ({ page }) => { await page.getByTestId('side-panel-header-right').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); await checkForScreenshot(page, page, screenShotPaths.segHydration.segPreHydration); + + await page.evaluate(() => { + // Access cornerstone directly from the window object + const cornerstone = window.cornerstone; + if (!cornerstone) { + return; + } + + const enabledElements = cornerstone.getEnabledElements(); + if (enabledElements.length === 0) { + return; + } + + const viewport = enabledElements[0].viewport; + if (viewport) { + viewport.setZoom(4); + viewport.render(); + } + }); + await page.getByTestId('yes-hydrate-btn').click(); await checkForScreenshot(page, page, screenShotPaths.segHydration.segPostHydration); - await page.getByText('Esophagus').click(); - await checkForScreenshot(page, page, screenShotPaths.segHydration.segJumpToSegment); }); diff --git a/tests/SEGHydrationMPR.spec.ts b/tests/SEGHydrationMPR.spec.ts new file mode 100644 index 000000000..8094089ad --- /dev/null +++ b/tests/SEGHydrationMPR.spec.ts @@ -0,0 +1,25 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } 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 properly display MPR for MR', async ({ page }) => { + await page.getByTestId('side-panel-header-right').click(); + await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); + + await page.getByTestId('yes-hydrate-btn').click(); + await checkForScreenshot(page, page, screenShotPaths.segHydrationMPR.segPostHydration); + + await page.getByTestId('Layout').click(); + await page.getByTestId('Axial Primary').click(); + + await checkForScreenshot( + page, + page, + screenShotPaths.segHydrationMPR.segPostHydrationMPRAxialPrimary + ); +}); diff --git a/tests/SRHydration.spec.ts b/tests/SRHydration.spec.ts index 76f532a1a..deb9cf50c 100644 --- a/tests/SRHydration.spec.ts +++ b/tests/SRHydration.spec.ts @@ -12,8 +12,48 @@ test('should hydrate SR reports correctly', async ({ page }) => { await page.getByTestId('trackedMeasurements-btn').click(); await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); await checkForScreenshot(page, page, screenShotPaths.srHydration.srPreHydration); + + await page.evaluate(() => { + // Access cornerstone directly from the window object + const cornerstone = window.cornerstone; + if (!cornerstone) { + return; + } + + const enabledElements = cornerstone.getEnabledElements(); + if (enabledElements.length === 0) { + return; + } + + const viewport = enabledElements[0].viewport; + if (viewport) { + viewport.setZoom(4); + viewport.render(); + } + }); + await page.getByTestId('yes-hydrate-btn').click(); await checkForScreenshot(page, page, screenShotPaths.srHydration.srPostHydration); + + await page.evaluate(() => { + // Access cornerstone directly from the window object + const cornerstone = window.cornerstone; + if (!cornerstone) { + return; + } + + const enabledElements = cornerstone.getEnabledElements(); + if (enabledElements.length === 0) { + return; + } + + const viewport = enabledElements[0].viewport; + if (viewport) { + viewport.scroll(20); + viewport.render(); + } + }); + await page.getByTestId('data-row').first().click(); await checkForScreenshot(page, page, screenShotPaths.srHydration.srJumpToMeasurement); }); diff --git a/tests/mpr2.spec.ts b/tests/mpr2.spec.ts new file mode 100644 index 000000000..050f8eb50 --- /dev/null +++ b/tests/mpr2.spec.ts @@ -0,0 +1,39 @@ +import { test } from '@playwright/test'; +import { visitStudy, checkForScreenshot, screenShotPaths } from './utils'; + +test.beforeEach(async ({ page }) => { + const studyInstanceUID = + '1.3.12.2.1107.5.2.32.35162.30000015050317233592200000046&hangingprotocolid=mpr'; + const mode = 'viewer'; + await visitStudy(page, studyInstanceUID, mode, 2000); +}); + +test('should properly display MPR for MR', async ({ page }) => { + await page.getByTestId('side-panel-header-right').click(); + // await page.getByTestId('study-browser-thumbnail-no-image').dblclick(); + await checkForScreenshot(page, page, screenShotPaths.mpr2.mprDisplayedCorrectly); + + await page.evaluate(() => { + // Access cornerstone directly from the window object + const cornerstone = window.cornerstone; + if (!cornerstone) { + return; + } + + const enabledElements = cornerstone.getEnabledElements(); + if (enabledElements.length === 0) { + return; + } + + // Apply zoom to all viewports + for (let i = 0; i < enabledElements.length; i++) { + const viewport = enabledElements[i].viewport; + if (viewport) { + viewport.setZoom(4); + viewport.render(); + } + } + }); + + await checkForScreenshot(page, page, screenShotPaths.mpr2.mprDisplayedCorrectlyZoomed); +}); diff --git a/tests/screenshots/chromium/RTHydration2.spec.ts/rtPostHydration.png b/tests/screenshots/chromium/RTHydration2.spec.ts/rtPostHydration.png new file mode 100644 index 000000000..5695b9a9b Binary files /dev/null and b/tests/screenshots/chromium/RTHydration2.spec.ts/rtPostHydration.png differ diff --git a/tests/screenshots/chromium/RTHydration2.spec.ts/rtPreHydration.png b/tests/screenshots/chromium/RTHydration2.spec.ts/rtPreHydration.png new file mode 100644 index 000000000..c9f33a520 Binary files /dev/null and b/tests/screenshots/chromium/RTHydration2.spec.ts/rtPreHydration.png differ diff --git a/tests/screenshots/chromium/SEGHydration.spec.ts/segPostHydration.png b/tests/screenshots/chromium/SEGHydration.spec.ts/segPostHydration.png index 56921657a..b22bd63ba 100644 Binary files a/tests/screenshots/chromium/SEGHydration.spec.ts/segPostHydration.png and b/tests/screenshots/chromium/SEGHydration.spec.ts/segPostHydration.png differ diff --git a/tests/screenshots/chromium/SEGHydration.spec.ts/segPreHydration.png b/tests/screenshots/chromium/SEGHydration.spec.ts/segPreHydration.png index 3c1aef137..05f7201c4 100644 Binary files a/tests/screenshots/chromium/SEGHydration.spec.ts/segPreHydration.png and b/tests/screenshots/chromium/SEGHydration.spec.ts/segPreHydration.png differ diff --git a/tests/screenshots/chromium/SEGHydrationMPR.spec.ts/segPostHydration.png b/tests/screenshots/chromium/SEGHydrationMPR.spec.ts/segPostHydration.png new file mode 100644 index 000000000..d3ef8ef53 Binary files /dev/null and b/tests/screenshots/chromium/SEGHydrationMPR.spec.ts/segPostHydration.png differ diff --git a/tests/screenshots/chromium/SEGHydrationMPR.spec.ts/segPostHydrationMPRAxialPrimary.png b/tests/screenshots/chromium/SEGHydrationMPR.spec.ts/segPostHydrationMPRAxialPrimary.png new file mode 100644 index 000000000..6f5d77295 Binary files /dev/null and b/tests/screenshots/chromium/SEGHydrationMPR.spec.ts/segPostHydrationMPRAxialPrimary.png differ diff --git a/tests/screenshots/chromium/SRHydration.spec.ts/srJumpToMeasurement.png b/tests/screenshots/chromium/SRHydration.spec.ts/srJumpToMeasurement.png index fc10b9e8b..5383cc87d 100644 Binary files a/tests/screenshots/chromium/SRHydration.spec.ts/srJumpToMeasurement.png and b/tests/screenshots/chromium/SRHydration.spec.ts/srJumpToMeasurement.png differ diff --git a/tests/screenshots/chromium/SRHydration.spec.ts/srPostHydration.png b/tests/screenshots/chromium/SRHydration.spec.ts/srPostHydration.png index 16120a8b5..7cb17180f 100644 Binary files a/tests/screenshots/chromium/SRHydration.spec.ts/srPostHydration.png and b/tests/screenshots/chromium/SRHydration.spec.ts/srPostHydration.png differ diff --git a/tests/screenshots/chromium/SRHydration.spec.ts/srPreHydration.png b/tests/screenshots/chromium/SRHydration.spec.ts/srPreHydration.png index f02c9368c..01ab6dda2 100644 Binary files a/tests/screenshots/chromium/SRHydration.spec.ts/srPreHydration.png and b/tests/screenshots/chromium/SRHydration.spec.ts/srPreHydration.png differ diff --git a/tests/screenshots/chromium/mpr2.spec.ts/mprDisplayedCorrectly.png b/tests/screenshots/chromium/mpr2.spec.ts/mprDisplayedCorrectly.png new file mode 100644 index 000000000..90d27f49a Binary files /dev/null and b/tests/screenshots/chromium/mpr2.spec.ts/mprDisplayedCorrectly.png differ diff --git a/tests/screenshots/chromium/mpr2.spec.ts/mprDisplayedCorrectlyZoomed.png b/tests/screenshots/chromium/mpr2.spec.ts/mprDisplayedCorrectlyZoomed.png new file mode 100644 index 000000000..c4c314fb3 Binary files /dev/null and b/tests/screenshots/chromium/mpr2.spec.ts/mprDisplayedCorrectlyZoomed.png differ diff --git a/tests/utils/checkForScreenshot.ts b/tests/utils/checkForScreenshot.ts index 694b9661b..d67591850 100644 --- a/tests/utils/checkForScreenshot.ts +++ b/tests/utils/checkForScreenshot.ts @@ -17,19 +17,24 @@ const checkForScreenshot = async ( delay = 100 ) => { await page.waitForLoadState('networkidle'); - for (let i = 1; i < attempts; i++) { + + for (let i = 0; i < attempts; i++) { try { await expect(locator).toHaveScreenshot(screenshotPath, { maxDiffPixelRatio: 0.1, }); return true; } catch (error) { - if (i === attempts) { - throw new Error('Screenshot does not match.'); + if (i === attempts - 1) { + console.debug('Screenshot comparison failed after all attempts'); + throw error; // Throw the original error with details instead of a generic message } await new Promise(resolve => setTimeout(resolve, delay)); } } + + // This is a fallback in case the loop exits unexpectedly + throw new Error('Screenshot comparison failed: loop exited without match or proper error'); }; export { checkForScreenshot }; diff --git a/tests/utils/screenShotPaths.ts b/tests/utils/screenShotPaths.ts index c2d3efd72..f493107dd 100644 --- a/tests/utils/screenShotPaths.ts +++ b/tests/utils/screenShotPaths.ts @@ -26,6 +26,10 @@ const screenShotPaths = { mpr: { mprDisplayedCorrectly: 'mprDisplayedCorrectly.png', }, + mpr2: { + mprDisplayedCorrectly: 'mprDisplayedCorrectly.png', + mprDisplayedCorrectlyZoomed: 'mprDisplayedCorrectlyZoomed.png', + }, threeDFourUp: { threeDFourUpDisplayedCorrectly: 'threeDFourUpDisplayedCorrectly.png', }, @@ -75,11 +79,19 @@ const screenShotPaths = { segPreHydration: 'segPreHydration.png', segJumpToSegment: 'segJumpToSegment.png', }, + segHydrationMPR: { + segPostHydration: 'segPostHydration.png', + segPostHydrationMPRAxialPrimary: 'segPostHydrationMPRAxialPrimary.png', + }, rtHydration: { rtPostHydration: 'rtPostHydration.png', rtPreHydration: 'rtPreHydration.png', rtJumpToStructure: 'rtJumpToStructure.png', }, + rtHydration2: { + rtPostHydration: 'rtPostHydration.png', + rtPreHydration: 'rtPreHydration.png', + }, crosshairs: { crosshairsRendered: 'crosshairsRendered.png', crosshairsRotated: 'crosshairsRotated.png',