104 lines
4.2 KiB
TypeScript
104 lines
4.2 KiB
TypeScript
import {
|
|
test,
|
|
expect,
|
|
visitStudy,
|
|
getViewportCanvasStats,
|
|
waitForViewportsRendered,
|
|
waitForViewportRenderCycle,
|
|
} from './utils';
|
|
|
|
// Ultrasound cine study: one series, nine instances, all but one multiframe.
|
|
// The first display set is the InstanceNumber=1 instance with 94 frames.
|
|
const usMultiframeStudyUID = '1.2.840.113663.1500.1.248223208.1.1.20110323.105903.687';
|
|
|
|
// NM brain SPECT study: one series of five multiframe instances whose per-frame
|
|
// positions come from DetectorInformationSequence rather than per-frame groups.
|
|
const nmMultiframeStudyUID = '1.2.276.0.7230010.3.1.2.447481088.1.1669202398.851612';
|
|
|
|
// A rendered frame must have some visible content; cine/SPECT frames are mostly
|
|
// dark background, so the bar is intentionally low. A blank or black viewport
|
|
// scores 0.
|
|
const minimumNonBlackRatio = 0.01;
|
|
|
|
test.describe('Multiframe ultrasound rendering', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await visitStudy(page, usMultiframeStudyUID, 'viewer', 2000);
|
|
await waitForViewportsRendered(page);
|
|
});
|
|
|
|
test('should render a multiframe instance as a stack of all its frames', async ({
|
|
page,
|
|
viewportPageObject,
|
|
}) => {
|
|
const activeViewport = await viewportPageObject.active;
|
|
|
|
// All 94 frames of the instance must be enumerated as the stack size.
|
|
await expect(activeViewport.overlayText.bottomRight.instanceNumber).toContainText('(1/94)', {
|
|
timeout: 10000,
|
|
});
|
|
|
|
// The first frame must actually be painted, not a blank/black canvas.
|
|
const stats = await getViewportCanvasStats({ page });
|
|
expect(stats.nonBlackRatio).toBeGreaterThan(minimumNonBlackRatio);
|
|
});
|
|
|
|
test('should render distinct content when navigating through frames', async ({
|
|
page,
|
|
viewportPageObject,
|
|
}) => {
|
|
const activeViewport = await viewportPageObject.active;
|
|
await expect(activeViewport.overlayText.bottomRight.instanceNumber).toContainText('(1/94)', {
|
|
timeout: 10000,
|
|
});
|
|
const firstFrameStats = await getViewportCanvasStats({ page });
|
|
expect(firstFrameStats.nonBlackRatio).toBeGreaterThan(minimumNonBlackRatio);
|
|
|
|
// Advance one frame: the overlay must track the frame index and the canvas
|
|
// must not go black (a past regression rendered black from the 2nd frame on).
|
|
let renderCycle = waitForViewportRenderCycle(page);
|
|
await activeViewport.sliceNavigation.scrollBy(1);
|
|
await renderCycle;
|
|
|
|
await expect(activeViewport.overlayText.bottomRight.instanceNumber).toContainText('(2/94)');
|
|
const secondFrameStats = await getViewportCanvasStats({ page });
|
|
expect(secondFrameStats.nonBlackRatio).toBeGreaterThan(minimumNonBlackRatio);
|
|
|
|
// Jump to the last frame: the canvas content must differ from frame 1,
|
|
// which fails if the stack is stuck rendering the first frame.
|
|
renderCycle = waitForViewportRenderCycle(page);
|
|
await activeViewport.sliceNavigation.toLastSlice();
|
|
await renderCycle;
|
|
|
|
await expect(activeViewport.overlayText.bottomRight.instanceNumber).toContainText('(94/94)');
|
|
const lastFrameStats = await getViewportCanvasStats({ page });
|
|
expect(lastFrameStats.nonBlackRatio).toBeGreaterThan(minimumNonBlackRatio);
|
|
expect(lastFrameStats.digest).not.toBe(firstFrameStats.digest);
|
|
});
|
|
});
|
|
|
|
test.describe('Multiframe NM rendering', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await visitStudy(page, nmMultiframeStudyUID, 'viewer', 2000);
|
|
await waitForViewportsRendered(page);
|
|
});
|
|
|
|
test('should render a multiframe NM instance with all frames enumerated', async ({
|
|
page,
|
|
viewportPageObject,
|
|
}) => {
|
|
const activeViewport = await viewportPageObject.active;
|
|
const instanceNumberOverlay = activeViewport.overlayText.bottomRight.instanceNumber;
|
|
|
|
await expect(instanceNumberOverlay).toContainText('(1/', { timeout: 10000 });
|
|
|
|
// The stack size shown by the overlay must be the instance's frame count,
|
|
// not 1 (which is what a broken multiframe split would produce).
|
|
const overlayText = await instanceNumberOverlay.textContent();
|
|
const stackSize = Number(overlayText.match(/\(1\/(\d+)\)/)?.[1]);
|
|
expect(stackSize).toBeGreaterThan(1);
|
|
|
|
const stats = await getViewportCanvasStats({ page });
|
|
expect(stats.nonBlackRatio).toBeGreaterThan(minimumNonBlackRatio);
|
|
});
|
|
});
|