318 lines
9.5 KiB
TypeScript
318 lines
9.5 KiB
TypeScript
import { cache, imageLoadPoolManager, Enums as csEnums } from '@cornerstonejs/core';
|
|
import interleaveNthLoader from './nthLoader';
|
|
import getNthFrames from './getNthFrames';
|
|
import interleave from './interleave';
|
|
|
|
jest.mock('@cornerstonejs/core', () => ({
|
|
...jest.requireActual('@cornerstonejs/core'),
|
|
cache: {
|
|
getVolume: jest.fn(),
|
|
},
|
|
imageLoadPoolManager: {
|
|
addRequest: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
jest.mock('./getNthFrames', () => jest.fn());
|
|
jest.mock('./interleave', () => jest.fn());
|
|
|
|
describe('interleaveNthLoader', () => {
|
|
const mockVolumeInput = {
|
|
volumeId: 'test-volume-id',
|
|
};
|
|
|
|
const mockVolume = {
|
|
metadata: {
|
|
SeriesInstanceUID: 'test-series-uid',
|
|
},
|
|
getImageLoadRequests: jest.fn(),
|
|
};
|
|
|
|
const mockImageLoadRequest = {
|
|
imageId: 'test-image-id',
|
|
callLoadImage: jest.fn(),
|
|
additionalDetails: 'test-details',
|
|
imageIdIndex: 0,
|
|
options: { test: 'option' },
|
|
};
|
|
|
|
const defaultParameters = {
|
|
data: {
|
|
viewportId: 'test-viewport-id',
|
|
volumeInputArray: [mockVolumeInput],
|
|
},
|
|
displaySetsMatchDetails: {},
|
|
};
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
(cache.getVolume as jest.Mock).mockReturnValue(mockVolume);
|
|
mockVolume.getImageLoadRequests.mockReturnValue([mockImageLoadRequest]);
|
|
(getNthFrames as jest.Mock).mockImplementation(input => input);
|
|
(interleave as jest.Mock).mockImplementation(input => input.flat());
|
|
});
|
|
|
|
it('should store viewport and volume input array mapping', () => {
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
expect(cache.getVolume).toHaveBeenCalledWith(mockVolumeInput.volumeId);
|
|
});
|
|
|
|
it('should return early when volume is not found', () => {
|
|
(cache.getVolume as jest.Mock).mockReturnValue(null);
|
|
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
|
|
const result = interleaveNthLoader(defaultParameters);
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith("interleaveNthLoader::No volume, can't load it");
|
|
expect(result).toBeUndefined();
|
|
expect(mockVolume.getImageLoadRequests).not.toHaveBeenCalled();
|
|
|
|
consoleSpy.mockRestore();
|
|
});
|
|
|
|
it('should process volume input array and create image load requests', () => {
|
|
const result = interleaveNthLoader(defaultParameters);
|
|
|
|
expect(cache.getVolume).toHaveBeenCalledWith(mockVolumeInput.volumeId);
|
|
expect(mockVolume.getImageLoadRequests).toHaveBeenCalled();
|
|
expect(getNthFrames).toHaveBeenCalledWith([mockImageLoadRequest]);
|
|
expect(interleave).toHaveBeenCalledWith([[mockImageLoadRequest]]);
|
|
expect(result).toBeInstanceOf(Map);
|
|
});
|
|
|
|
it('should add requests to imageLoadPoolManager with correct parameters', () => {
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
expect(imageLoadPoolManager.addRequest).toHaveBeenCalledWith(
|
|
expect.any(Function),
|
|
csEnums.RequestType.Prefetch,
|
|
mockImageLoadRequest.additionalDetails,
|
|
0
|
|
);
|
|
});
|
|
|
|
it('should handle multiple volume inputs', () => {
|
|
const mockVolumeInput2 = {
|
|
volumeId: 'test-volume-id-2',
|
|
};
|
|
|
|
const mockVolume2 = {
|
|
metadata: {
|
|
SeriesInstanceUID: 'test-series-uid-2',
|
|
},
|
|
getImageLoadRequests: jest.fn().mockReturnValue([mockImageLoadRequest]),
|
|
};
|
|
|
|
(cache.getVolume as jest.Mock)
|
|
.mockReturnValueOnce(mockVolume)
|
|
.mockReturnValueOnce(mockVolume2)
|
|
.mockReturnValueOnce(mockVolume)
|
|
.mockReturnValueOnce(mockVolume2);
|
|
|
|
interleaveNthLoader({
|
|
...defaultParameters,
|
|
data: {
|
|
...defaultParameters.data,
|
|
volumeInputArray: [mockVolumeInput, mockVolumeInput2],
|
|
},
|
|
});
|
|
|
|
expect(cache.getVolume).toHaveBeenCalledWith(mockVolumeInput.volumeId);
|
|
expect(cache.getVolume).toHaveBeenCalledWith(mockVolumeInput2.volumeId);
|
|
expect(mockVolume.getImageLoadRequests).toHaveBeenCalled();
|
|
expect(mockVolume2.getImageLoadRequests).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle volumes without getImageLoadRequests method', () => {
|
|
const mockVolumeWithoutMethod = {
|
|
metadata: {
|
|
SeriesInstanceUID: 'test-series-uid',
|
|
},
|
|
};
|
|
|
|
(cache.getVolume as jest.Mock)
|
|
.mockReturnValueOnce(mockVolumeWithoutMethod)
|
|
.mockReturnValueOnce(mockVolumeWithoutMethod);
|
|
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
expect(getNthFrames).not.toHaveBeenCalled();
|
|
expect(interleave).toHaveBeenCalledWith([]);
|
|
});
|
|
|
|
it('should handle volumes with null getImageLoadRequests return', () => {
|
|
mockVolume.getImageLoadRequests.mockReturnValue(null);
|
|
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
expect(getNthFrames).not.toHaveBeenCalled();
|
|
expect(interleave).toHaveBeenCalledWith([]);
|
|
});
|
|
|
|
it('should filter out requests without imageId in first request', () => {
|
|
const requestWithoutImageId = {
|
|
callLoadImage: jest.fn(),
|
|
additionalDetails: 'test-details',
|
|
};
|
|
|
|
mockVolume.getImageLoadRequests
|
|
.mockReturnValueOnce([requestWithoutImageId, mockImageLoadRequest])
|
|
.mockReturnValueOnce([mockImageLoadRequest]);
|
|
|
|
interleaveNthLoader({
|
|
...defaultParameters,
|
|
data: {
|
|
...defaultParameters.data,
|
|
volumeInputArray: [mockVolumeInput, { volumeId: 'test-volume-id-2' }],
|
|
},
|
|
});
|
|
|
|
expect(getNthFrames).toHaveBeenCalledWith([mockImageLoadRequest]);
|
|
});
|
|
|
|
it('should handle empty image load requests', () => {
|
|
mockVolume.getImageLoadRequests.mockReturnValue([]);
|
|
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
expect(getNthFrames).not.toHaveBeenCalled();
|
|
expect(interleave).toHaveBeenCalledWith([]);
|
|
});
|
|
|
|
it('should bind callLoadImage with correct parameters', () => {
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
const addRequestCall = (imageLoadPoolManager.addRequest as jest.Mock).mock.calls[0];
|
|
const boundFunction = addRequestCall[0];
|
|
|
|
boundFunction();
|
|
|
|
expect(mockImageLoadRequest.callLoadImage).toHaveBeenCalledWith(
|
|
mockImageLoadRequest.imageId,
|
|
mockImageLoadRequest.imageIdIndex,
|
|
mockImageLoadRequest.options
|
|
);
|
|
});
|
|
|
|
it('should handle duplicate volume IDs by not adding them again', () => {
|
|
const duplicateVolumeInput = {
|
|
volumeId: mockVolumeInput.volumeId,
|
|
};
|
|
|
|
interleaveNthLoader({
|
|
...defaultParameters,
|
|
data: {
|
|
...defaultParameters.data,
|
|
volumeInputArray: [mockVolumeInput, duplicateVolumeInput],
|
|
},
|
|
});
|
|
|
|
expect(cache.getVolume).toHaveBeenCalledTimes(3);
|
|
expect(cache.getVolume).toHaveBeenCalledWith(mockVolumeInput.volumeId);
|
|
});
|
|
|
|
it('should clear internal maps after processing', () => {
|
|
const firstResult = interleaveNthLoader(defaultParameters);
|
|
const secondResult = interleaveNthLoader(defaultParameters);
|
|
|
|
expect(firstResult).toBeInstanceOf(Map);
|
|
expect(secondResult).toBeInstanceOf(Map);
|
|
expect(firstResult.get(defaultParameters.data.viewportId)).toEqual(
|
|
defaultParameters.data.volumeInputArray
|
|
);
|
|
});
|
|
|
|
it('should handle multiple image load requests', () => {
|
|
const mockImageLoadRequest2 = {
|
|
imageId: 'test-image-id-2',
|
|
callLoadImage: jest.fn(),
|
|
additionalDetails: 'test-details-2',
|
|
imageIdIndex: 1,
|
|
options: { test: 'option2' },
|
|
};
|
|
|
|
mockVolume.getImageLoadRequests.mockReturnValue([mockImageLoadRequest, mockImageLoadRequest2]);
|
|
|
|
(interleave as jest.Mock).mockReturnValue([mockImageLoadRequest, mockImageLoadRequest2]);
|
|
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
expect(imageLoadPoolManager.addRequest).toHaveBeenCalledTimes(2);
|
|
expect(imageLoadPoolManager.addRequest).toHaveBeenNthCalledWith(
|
|
1,
|
|
expect.any(Function),
|
|
csEnums.RequestType.Prefetch,
|
|
mockImageLoadRequest.additionalDetails,
|
|
0
|
|
);
|
|
expect(imageLoadPoolManager.addRequest).toHaveBeenNthCalledWith(
|
|
2,
|
|
expect.any(Function),
|
|
csEnums.RequestType.Prefetch,
|
|
mockImageLoadRequest2.additionalDetails,
|
|
0
|
|
);
|
|
});
|
|
|
|
it('should handle volume with undefined metadata', () => {
|
|
const mockVolumeWithoutMetadata = {
|
|
getImageLoadRequests: jest.fn().mockReturnValue([]),
|
|
};
|
|
|
|
(cache.getVolume as jest.Mock).mockReturnValueOnce(mockVolumeWithoutMetadata);
|
|
|
|
expect(() => interleaveNthLoader(defaultParameters)).toThrow();
|
|
});
|
|
|
|
it('should return copy of viewport volume input array map', () => {
|
|
const result = interleaveNthLoader(defaultParameters);
|
|
|
|
expect(result.has(defaultParameters.data.viewportId)).toBe(true);
|
|
expect(result.get(defaultParameters.data.viewportId)).toEqual(
|
|
defaultParameters.data.volumeInputArray
|
|
);
|
|
});
|
|
|
|
it('should handle requests with missing properties gracefully', () => {
|
|
const incompleteRequest = {
|
|
imageId: 'test-image-id',
|
|
callLoadImage: jest.fn(),
|
|
};
|
|
|
|
mockVolume.getImageLoadRequests.mockReturnValue([incompleteRequest]);
|
|
(interleave as jest.Mock).mockReturnValue([incompleteRequest]);
|
|
|
|
interleaveNthLoader(defaultParameters);
|
|
|
|
expect(imageLoadPoolManager.addRequest).toHaveBeenCalledWith(
|
|
expect.any(Function),
|
|
csEnums.RequestType.Prefetch,
|
|
undefined,
|
|
0
|
|
);
|
|
});
|
|
|
|
it('should process different viewport IDs separately', () => {
|
|
const firstResult = interleaveNthLoader({
|
|
...defaultParameters,
|
|
data: {
|
|
viewportId: 'viewport-1',
|
|
volumeInputArray: [mockVolumeInput],
|
|
},
|
|
});
|
|
|
|
const secondResult = interleaveNthLoader({
|
|
...defaultParameters,
|
|
data: {
|
|
viewportId: 'viewport-2',
|
|
volumeInputArray: [mockVolumeInput],
|
|
},
|
|
});
|
|
|
|
expect(firstResult.has('viewport-1')).toBe(true);
|
|
expect(secondResult.has('viewport-2')).toBe(true);
|
|
expect(firstResult.has('viewport-2')).toBe(false);
|
|
});
|
|
});
|