ohif-viewer/extensions/cornerstone/src/utils/promptHydrationDialog.test.ts

491 lines
15 KiB
TypeScript

import promptHydrationDialog, { HydrationType } from './promptHydrationDialog';
describe('promptHydrationDialog', () => {
const mockUIViewportDialogService = {
show: jest.fn(),
hide: jest.fn(),
};
const mockCustomizationService = {
getCustomization: jest.fn(),
};
const mockExtensionManager = {
appConfig: {
measurementTrackingMode: 'standard',
disableConfirmationPrompts: false,
},
};
const mockServicesManager = {
services: {
uiViewportDialogService: mockUIViewportDialogService,
customizationService: mockCustomizationService,
},
_extensionManager: mockExtensionManager,
};
const mockDisplaySet = {
displaySetInstanceUID: 'test-display-set-uid',
SeriesInstanceUID: 'test-series-uid',
};
const mockHydrateCallback = jest.fn();
const mockPreHydrateCallback = jest.fn();
const defaultParameters = {
servicesManager: mockServicesManager as unknown as AppTypes.ServicesManager,
viewportId: 'test-viewport-id',
displaySet: mockDisplaySet as unknown as AppTypes.DisplaySet,
preHydrateCallbacks: [mockPreHydrateCallback],
hydrateCallback: mockHydrateCallback,
type: HydrationType.SEG,
};
beforeEach(() => {
jest.clearAllMocks();
mockCustomizationService.getCustomization.mockReturnValue('Test message');
mockHydrateCallback.mockResolvedValue(true);
jest.spyOn(window, 'setTimeout').mockImplementation((callback: () => void) => {
callback();
return 0 as unknown as NodeJS.Timeout;
});
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should return HYDRATE response when disableConfirmationPrompts is true for non-SR types', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
const result = await promptHydrationDialog(defaultParameters);
expect(mockUIViewportDialogService.show).not.toHaveBeenCalled();
expect(mockPreHydrateCallback).toHaveBeenCalled();
expect(mockHydrateCallback).toHaveBeenCalledWith({
segDisplaySet: mockDisplaySet,
viewportId: defaultParameters.viewportId,
});
expect(result).toBe(true);
});
it('should show dialog when disableConfirmationPrompts is false for non-SR types', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog(defaultParameters);
expect(mockUIViewportDialogService.show).toHaveBeenCalledWith({
id: 'promptHydrateSEG',
viewportId: defaultParameters.viewportId,
type: 'info',
message: 'Test message',
actions: [
{
id: 'no-hydrate',
type: 'secondary',
text: 'No',
value: 0,
},
{
id: 'yes-hydrate',
type: 'primary',
text: 'Yes',
value: 5,
},
],
onSubmit: expect.any(Function),
onOutsideClick: expect.any(Function),
onKeyPress: expect.any(Function),
});
const onSubmit = mockUIViewportDialogService.show.mock.calls[0][0].onSubmit;
onSubmit(5);
const result = await promise;
expect(result).toBe(true);
});
it('should handle CANCEL response', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog(defaultParameters);
const onSubmit = mockUIViewportDialogService.show.mock.calls[0][0].onSubmit;
onSubmit(0);
const result = await promise;
expect(result).toBe(false);
expect(mockHydrateCallback).not.toHaveBeenCalled();
});
it('should handle onOutsideClick', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog(defaultParameters);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
const result = await promise;
expect(result).toBe(false);
expect(mockUIViewportDialogService.hide).toHaveBeenCalled();
});
it('should handle onKeyPress Enter', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog(defaultParameters);
const onKeyPress = mockUIViewportDialogService.show.mock.calls[0][0].onKeyPress;
onKeyPress({ key: 'Enter' });
const result = await promise;
expect(result).toBe(true);
expect(mockUIViewportDialogService.hide).toHaveBeenCalled();
});
it('should handle onKeyPress non-Enter key', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog(defaultParameters);
const onKeyPress = mockUIViewportDialogService.show.mock.calls[0][0].onKeyPress;
onKeyPress({ key: 'Escape' });
expect(mockUIViewportDialogService.hide).not.toHaveBeenCalled();
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
const result = await promise;
expect(result).toBe(false);
});
it('should handle SEG type hydration with setTimeout', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
await promptHydrationDialog({
...defaultParameters,
type: HydrationType.SEG,
});
expect(window.setTimeout).toHaveBeenCalledWith(expect.any(Function), 0);
expect(mockHydrateCallback).toHaveBeenCalledWith({
segDisplaySet: mockDisplaySet,
viewportId: defaultParameters.viewportId,
});
});
it('should handle RTSTRUCT type hydration', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
const result = await promptHydrationDialog({
...defaultParameters,
type: HydrationType.RTSTRUCT,
});
expect(mockHydrateCallback).toHaveBeenCalledWith({
rtDisplaySet: mockDisplaySet,
viewportId: defaultParameters.viewportId,
servicesManager: mockServicesManager,
});
expect(result).toBe(true);
});
it('should handle SR type hydration when standardMode is true', async () => {
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
const mockHydrationResult = {
StudyInstanceUID: 'test-study-uid',
SeriesInstanceUIDs: ['series-1', 'series-2'],
};
mockHydrateCallback.mockResolvedValue(mockHydrationResult);
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.SR,
});
const onSubmit = mockUIViewportDialogService.show.mock.calls[0][0].onSubmit;
onSubmit(5);
const result = await promise;
expect(result).toEqual({
userResponse: 5,
displaySetInstanceUID: mockDisplaySet.displaySetInstanceUID,
srSeriesInstanceUID: mockDisplaySet.SeriesInstanceUID,
viewportId: defaultParameters.viewportId,
StudyInstanceUID: mockHydrationResult.StudyInstanceUID,
SeriesInstanceUIDs: mockHydrationResult.SeriesInstanceUIDs,
});
});
it('should handle SR type hydration when standardMode is false', async () => {
mockExtensionManager.appConfig.measurementTrackingMode = 'other';
const result = await promptHydrationDialog({
...defaultParameters,
type: HydrationType.SR,
});
expect(mockUIViewportDialogService.show).not.toHaveBeenCalled();
expect(result).toEqual({
userResponse: 5,
displaySetInstanceUID: mockDisplaySet.displaySetInstanceUID,
srSeriesInstanceUID: mockDisplaySet.SeriesInstanceUID,
viewportId: defaultParameters.viewportId,
StudyInstanceUID: undefined,
SeriesInstanceUIDs: undefined,
});
});
it('should handle SR type with CANCEL response', async () => {
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.SR,
});
const onSubmit = mockUIViewportDialogService.show.mock.calls[0][0].onSubmit;
onSubmit(0);
const result = await promise;
expect(result).toEqual({
userResponse: 0,
displaySetInstanceUID: mockDisplaySet.displaySetInstanceUID,
srSeriesInstanceUID: mockDisplaySet.SeriesInstanceUID,
viewportId: defaultParameters.viewportId,
});
});
it('should handle undefined preHydrateCallbacks', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
await promptHydrationDialog({
...defaultParameters,
preHydrateCallbacks: undefined,
});
expect(mockHydrateCallback).toHaveBeenCalled();
});
it('should handle empty preHydrateCallbacks array', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
await promptHydrationDialog({
...defaultParameters,
preHydrateCallbacks: [],
});
expect(mockHydrateCallback).toHaveBeenCalled();
});
it('should execute multiple preHydrateCallbacks', async () => {
const mockPreHydrateCallback2 = jest.fn();
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
await promptHydrationDialog({
...defaultParameters,
preHydrateCallbacks: [mockPreHydrateCallback, mockPreHydrateCallback2],
});
expect(mockPreHydrateCallback).toHaveBeenCalled();
expect(mockPreHydrateCallback2).toHaveBeenCalled();
});
it('should get correct customization message key for SEG type', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.SEG,
});
expect(mockCustomizationService.getCustomization).toHaveBeenCalledWith(
'viewportNotification.hydrateSEGMessage'
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
it('should get correct customization message key for RTSTRUCT type', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.RTSTRUCT,
});
expect(mockCustomizationService.getCustomization).toHaveBeenCalledWith(
'viewportNotification.hydrateRTMessage'
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
it('should get correct customization message key for SR type', async () => {
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.SR,
});
expect(mockCustomizationService.getCustomization).toHaveBeenCalledWith(
'viewportNotification.hydrateSRMessage'
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
it('should get default customization message key for unknown type', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog({
...defaultParameters,
type: 'UNKNOWN_TYPE',
});
expect(mockCustomizationService.getCustomization).toHaveBeenCalledWith(
'viewportNotification.hydrateMessage'
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
it('should get correct dialog id for SEG type', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.SEG,
});
expect(mockUIViewportDialogService.show).toHaveBeenCalledWith(
expect.objectContaining({
id: 'promptHydrateSEG',
})
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
it('should get correct dialog id for SR type', async () => {
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.SR,
});
expect(mockUIViewportDialogService.show).toHaveBeenCalledWith(
expect.objectContaining({
id: 'promptHydrateSR',
})
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
it('should get default dialog id for unknown type', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog({
...defaultParameters,
type: 'UNKNOWN_TYPE',
});
expect(mockUIViewportDialogService.show).toHaveBeenCalledWith(
expect.objectContaining({
id: 'promptHydrate',
})
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
it('should handle hydrateCallback returning false for SEG', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
mockHydrateCallback.mockResolvedValue(false);
const result = await promptHydrationDialog({
...defaultParameters,
type: HydrationType.SEG,
});
expect(result).toBe(false);
});
it('should handle hydrateCallback returning false for RTSTRUCT', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = true;
mockHydrateCallback.mockResolvedValue(false);
const result = await promptHydrationDialog({
...defaultParameters,
type: HydrationType.RTSTRUCT,
});
expect(result).toBe(false);
});
it('should handle SR hydration with null result', async () => {
mockExtensionManager.appConfig.measurementTrackingMode = 'standard';
mockHydrateCallback.mockResolvedValue(null);
const promise = promptHydrationDialog({
...defaultParameters,
type: HydrationType.SR,
});
const onSubmit = mockUIViewportDialogService.show.mock.calls[0][0].onSubmit;
onSubmit(5);
const result = await promise;
expect(result).toEqual({
userResponse: 5,
displaySetInstanceUID: mockDisplaySet.displaySetInstanceUID,
srSeriesInstanceUID: mockDisplaySet.SeriesInstanceUID,
viewportId: defaultParameters.viewportId,
StudyInstanceUID: undefined,
SeriesInstanceUIDs: undefined,
});
});
it('should handle RTSTRUCT type in getDialogId', async () => {
mockExtensionManager.appConfig.disableConfirmationPrompts = false;
const promise = promptHydrationDialog({
...defaultParameters,
type: 'RTSTRUCT',
});
expect(mockUIViewportDialogService.show).toHaveBeenCalledWith(
expect.objectContaining({
id: 'promptHydrateRT',
})
);
const onOutsideClick = mockUIViewportDialogService.show.mock.calls[0][0].onOutsideClick;
onOutsideClick();
await promise;
});
});