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

321 lines
8.5 KiB
TypeScript
Raw Normal View History

import { generateSegmentationCSVReport } from './generateSegmentationCSVReport';
// Mock DOM APIs
Object.defineProperty(global, 'Blob', {
writable: true,
value: jest.fn().mockImplementation((content, options) => ({
content,
options,
})),
});
Object.defineProperty(global, 'URL', {
writable: true,
value: {
createObjectURL: jest.fn().mockReturnValue('mock-url'),
revokeObjectURL: () => undefined,
},
});
const mockDocument = {
addEventListener: jest.fn(),
createElement: jest.fn().mockReturnValue({
setAttribute: jest.fn(),
click: jest.fn(),
style: {},
}),
body: {
appendChild: jest.fn(),
removeChild: jest.fn(),
},
};
Object.defineProperty(global, 'document', {
writable: true,
value: mockDocument,
});
describe('generateSegmentationCSVReport', () => {
const mockInfo = {
reference: {
SeriesNumber: '1',
SeriesInstanceUID: 'series-uid-123',
StudyInstanceUID: 'study-uid-456',
SeriesDate: '20231201',
SeriesTime: '120000',
SeriesDescription: 'Test Series',
},
};
beforeEach(() => {
jest.clearAllMocks();
});
it('should generate CSV with basic segmentation data', () => {
const segmentationData = {
segmentationId: 'seg-123',
label: 'Test Segmentation',
};
generateSegmentationCSVReport(segmentationData, mockInfo);
expect(global.Blob).toHaveBeenCalledWith([expect.stringContaining('Segmentation ID,seg-123')], {
type: 'text/csv;charset=utf-8;',
});
});
it('should handle segmentation data without id and label', () => {
const segmentationData = {};
generateSegmentationCSVReport(segmentationData, mockInfo);
expect(global.Blob).toHaveBeenCalledWith(
[expect.stringContaining('Segmentation ID,\nSegmentation Label,')],
{ type: 'text/csv;charset=utf-8;' }
);
});
it('should include reference information when provided', () => {
const segmentationData = {
segmentationId: 'seg-123',
label: 'Test Segmentation',
};
generateSegmentationCSVReport(segmentationData, mockInfo);
expect(global.Blob).toHaveBeenCalledWith(
[expect.stringContaining('reference Series Number,1')],
{ type: 'text/csv;charset=utf-8;' }
);
});
it('should skip empty reference values', () => {
const segmentationData = {
segmentationId: 'seg-123',
label: 'Test Segmentation',
};
const infoWithEmptyValues = {
reference: {
SeriesNumber: '1',
SeriesInstanceUID: '',
StudyInstanceUID: null,
SeriesDate: undefined,
SeriesTime: '120000',
SeriesDescription: 'Test Series',
},
};
generateSegmentationCSVReport(segmentationData, infoWithEmptyValues);
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
expect(csvContent).toContain('reference Series Number,1');
expect(csvContent).toContain('reference Series Time,120000');
expect(csvContent).not.toContain('reference Series Instance UID');
expect(csvContent).not.toContain('reference Study Instance UID');
expect(csvContent).not.toContain('reference Series Date');
});
it('should handle segments with basic properties', () => {
const segmentationData = {
segmentationId: 'seg-123',
label: 'Test Segmentation',
segments: {
'1': {
segmentIndex: 1,
label: 'Segment 1',
locked: true,
active: false,
},
'2': {
segmentIndex: 2,
label: 'Segment 2',
locked: false,
active: true,
},
},
};
generateSegmentationCSVReport(segmentationData, mockInfo);
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
expect(csvContent).toContain('Label,Segment 1,Segment 2');
expect(csvContent).toContain('Segment Index,1,2');
expect(csvContent).toContain('Locked,Yes,No');
expect(csvContent).toContain('Active,No,Yes');
});
it('should handle segments with statistics', () => {
const segmentationData = {
segmentationId: 'seg-123',
label: 'Test Segmentation',
segments: {
'1': {
segmentIndex: 1,
label: 'Segment 1',
locked: false,
active: true,
cachedStats: {
namedStats: {
mean: {
name: 'mean',
label: 'Mean',
value: 100.5,
unit: 'HU',
},
volume: {
name: 'volume',
label: 'Volume',
value: 250.75,
unit: 'mm³',
},
},
},
},
},
};
generateSegmentationCSVReport(segmentationData, mockInfo);
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
expect(csvContent).toContain('Mean (HU),100.5');
expect(csvContent).toContain('Volume (mm³),250.75');
});
it('should handle segments with statistics without units', () => {
const segmentationData = {
segmentationId: 'seg-123',
segments: {
'1': {
segmentIndex: 1,
label: 'Segment 1',
cachedStats: {
namedStats: {
count: {
name: 'count',
label: 'Count',
value: 42,
},
},
},
},
},
};
generateSegmentationCSVReport(segmentationData, mockInfo);
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
expect(csvContent).toContain('Count,42');
});
it('should handle segments without cachedStats', () => {
const segmentationData = {
segmentationId: 'seg-123',
segments: {
'1': {
segmentIndex: 1,
label: 'Segment 1',
locked: false,
active: true,
},
},
};
generateSegmentationCSVReport(segmentationData, mockInfo);
expect(global.Blob).toHaveBeenCalled();
});
it('should handle segments with empty namedStats', () => {
const segmentationData = {
segmentationId: 'seg-123',
segments: {
'1': {
segmentIndex: 1,
label: 'Segment 1',
cachedStats: {
namedStats: {},
},
},
},
};
generateSegmentationCSVReport(segmentationData, mockInfo);
expect(global.Blob).toHaveBeenCalled();
});
it('should escape CSV special characters', () => {
const segmentationData = {
segmentationId: 'seg,with,commas',
label: 'Test "quoted" label',
segments: {
'1': {
segmentIndex: 1,
label: 'Segment\nwith\nnewlines',
cachedStats: {
namedStats: {
test: {
name: 'test',
label: 'Test,Value',
value: 'value"with"quotes',
},
},
},
},
},
};
generateSegmentationCSVReport(segmentationData, mockInfo);
const csvContent = (global.Blob as jest.Mock).mock.calls[0][0][0];
expect(csvContent).toContain('"seg,with,commas"');
expect(csvContent).toContain('"Test ""quoted"" label"');
expect(csvContent).toContain('"Segment\nwith\nnewlines"');
});
it('should create download link with correct attributes', () => {
const mockLink = {
setAttribute: jest.fn(),
click: jest.fn(),
style: {},
};
mockDocument.createElement.mockReturnValue(mockLink);
const segmentationData = {
segmentationId: 'seg-123',
label: 'Test Segmentation',
};
generateSegmentationCSVReport(segmentationData, mockInfo);
expect(mockLink.setAttribute).toHaveBeenCalledWith('href', 'mock-url');
expect(mockLink.setAttribute).toHaveBeenCalledWith(
'download',
expect.stringMatching(/Test Segmentation_Report_\d{4}-\d{2}-\d{2}\.csv/)
);
expect(mockLink.click).toHaveBeenCalled();
expect(mockDocument.body.appendChild).toHaveBeenCalledWith(mockLink);
expect(mockDocument.body.removeChild).toHaveBeenCalledWith(mockLink);
});
it('should use default filename when label is missing', () => {
const mockLink = {
setAttribute: jest.fn(),
click: jest.fn(),
style: {},
};
mockDocument.createElement.mockReturnValue(mockLink);
const segmentationData = {
segmentationId: 'seg-123',
};
generateSegmentationCSVReport(segmentationData, mockInfo);
expect(mockLink.setAttribute).toHaveBeenCalledWith(
'download',
expect.stringMatching(/Segmentation_Report_\d{4}-\d{2}-\d{2}\.csv/)
);
});
});