This commit is contained in:
mario
2025-03-07 13:47:44 +07:00
commit c4efec5a14
3358 changed files with 303774 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
/**
* Add tests to ensure image consistency and quality
*/
const testPixel = (dx, dy, expectedPixel) => {
cy.get('.cornerstone-canvas').then(v => {
const canvas = v[0];
cy.log(
'testPixel canvas',
dx,
dy,
expectedPixel,
canvas.width,
canvas.height,
canvas.style.width,
canvas.style.height
);
const ctx = canvas.getContext('2d');
cy.window()
.its('cornerstone')
.then(cornerstone => {
const { viewport } = cornerstone.getEnabledElements()[0];
const imageData = viewport.getImageData();
// cy.log("imageData", imageData);
const origin = viewport.worldToCanvas(imageData?.origin);
const orX = origin[0] * devicePixelRatio;
const orY = origin[1] * devicePixelRatio;
const x = Math.round(orX + dx);
const y = Math.round(orY + dy);
cy.log('testPixel origin x,y point x,y', orX, orY, x, y);
// cy.log('world origin', imageData.origin);
// cy.log('focal', viewport.getCamera().focalPoint,
// viewport.worldToCanvas(viewport.getCamera().focalPoint));
const pixelData = ctx.getImageData(x, y, 1, 1);
expect(pixelData.data[0]).closeTo(expectedPixel, 1);
});
});
};
describe('CS3D Image Consistency and Quality', () => {
const setupStudySeries = (studyUID, seriesUID) => {
cy.checkStudyRouteInViewer(
studyUID,
`&seriesInstanceUID=${seriesUID}&hangingProtocolId=@ohif/hpScale`
);
cy.initCornerstoneToolsAliases();
const skipMarkers = true;
cy.initCommonElementsAliases(skipMarkers);
};
it('TG18 Resolution Test Displayed 1:1', () => {
setupStudySeries(
'2.16.124.113543.6004.101.103.20021117.061159.1',
'2.16.124.113543.6004.101.103.20021117.061159.1.004'
);
cy.wait(2000);
testPixel(1018, 1028, 255);
// Horizontal and vertical delta from this should not be contaminated
// by values from center
testPixel(1019, 1028, 0);
testPixel(1018, 1029, 0);
testPixel(1017, 1028, 0);
testPixel(1018, 1027, 0);
});
// Missing test data - todo
it.skip('8 bit image displayable', () => {
setupStudySeries('1.3.46.670589.17.1.7.1.1.7', '1.3.46.670589.17.1.7.2.1.7');
cy.wait(1000);
// Compare with dcm2jpg generated values or by manually computing WL values
testPixel(258, 257, 171);
testPixel(259, 257, 166);
});
it.skip('12 bit image displayable and zoom with pixel spacing', () => {
setupStudySeries(
'1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1',
'1.3.6.1.4.1.25403.345050719074.3824.20170125113608.5'
);
cy.wait(1000);
// Compare with dcm2jpg generated values or by manually computing WL values
testPixel(258, 277, 120);
testPixel(259, 277, 122);
});
});

View File

@@ -0,0 +1,26 @@
describe('OHIF Multi Study', () => {
const beforeSetup = () => {
cy.initViewer(
'1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1,1.2.840.113619.2.5.1762583153.215519.978957063.78',
{
params: '&hangingProtocolId=@ohif/hpCompare',
minimumThumbnails: 3,
}
);
};
it('Should display 2 comparison up', () => {
beforeSetup();
cy.get('[data-cy="viewport-pane"]').as('viewportPane');
cy.get('@viewportPane').its('length').should('be.eq', 4);
cy.get('[data-cy="viewport-overlay-top-left"] [title="Study date"]').as('studyDate');
cy.get('@studyDate').should(studyDate => {
expect(studyDate.length).to.be.eq(4);
expect(studyDate.text()).to.contain('2014').contain('2001');
expect(studyDate.text().indexOf('2014')).to.be.lessThan(studyDate.text().indexOf('2001'));
});
});
});

View File

@@ -0,0 +1,9 @@
describe('OHIF PDF Display', function () {
beforeEach(function () {
cy.openStudyInViewer('2.25.317377619501274872606137091638706705333');
});
it('checks if series thumbnails are being displayed', function () {
cy.get('[data-cy="study-browser-thumbnail-no-image"]').its('length').should('be.gt', 0);
});
});

View File

@@ -0,0 +1,16 @@
describe('OHIF Video Display', function () {
beforeEach(function () {
cy.openStudyInViewer('2.25.96975534054447904995905761963464388233');
});
it('checks if series thumbnails are being displayed', function () {
cy.get('[data-cy="study-browser-thumbnail-no-image"]').its('length').should('be.gt', 1);
});
it('performs double-click to load thumbnail in active viewport', () => {
cy.get('[data-cy="study-browser-thumbnail-no-image"]:nth-child(2)').dblclick();
//const expectedText = 'Ser: 3';
//cy.get('@viewportInfoBottomLeft').should('contains.text', expectedText);
});
});

View File

@@ -0,0 +1,42 @@
describe('OHIF HP', () => {
beforeEach(() => {
cy.checkStudyRouteInViewer(
'1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1',
'&hangingProtocolId=@ohif/mnGrid'
);
cy.expectMinimumThumbnails(3);
cy.initCornerstoneToolsAliases();
cy.initCommonElementsAliases();
cy.waitDicomImage();
});
it('Should display 3 up', () => {
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', 4);
});
it('Should navigate next/previous stage', () => {
cy.get('body').type(',');
cy.wait(250);
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', 4);
cy.get('body').type('..');
cy.wait(250);
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', 2);
});
it('Should navigate to display set specified', () => {
Cypress.on('uncaught:exception', () => false);
// This filters by series instance UID, meaning there will only be 1 thumbnail
// It applies the initial SOP instance, navigating to that image
cy.checkStudyRouteInViewer(
'1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1',
'&SeriesInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125113545.4&initialSopInstanceUID=1.3.6.1.4.1.25403.345050719074.3824.20170125113546.1'
);
cy.expectMinimumThumbnails(1);
cy.initCornerstoneToolsAliases();
cy.initCommonElementsAliases();
// The specified series/sop UID's are index 101, so ensure that image is displayed
cy.get('@viewportInfoBottomRight').should('contains.text', 'I:6');
});
});

View File

@@ -0,0 +1,54 @@
describe('OHIF Double Click', () => {
beforeEach(() => {
cy.checkStudyRouteInViewer(
'1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1',
'&hangingProtocolId=@ohif/mnGrid'
);
cy.expectMinimumThumbnails(3);
cy.initCornerstoneToolsAliases();
cy.initCommonElementsAliases();
});
it('Should double click each viewport to one up and back', () => {
const numExpectedViewports = 4;
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', numExpectedViewports);
for (let i = 0; i < 3; i += 1) {
cy.wait(1000);
// For whatever reason, with Cypress tests, we have to activate the
// viewport we are double clicking first.
cy.get('[data-cy="viewport-pane"]')
.eq(i)
.trigger('mousedown', 'center', {
force: true,
})
.trigger('mouseup', 'center', {
force: true,
});
// Wait for the viewport to be 'active'.
// TODO Is there a better way to do this?
cy.get('[data-cy="viewport-pane"]')
.eq(i)
.parent()
.find('[data-cy="viewport-pane"]')
.not('.pointer-events-none');
// The actual double click.
cy.get('[data-cy="viewport-pane"]').eq(i).trigger('dblclick', 'center');
cy.get('[data-cy="viewport-pane"]').its('length').should('be.eq', 1);
cy.get('[data-cy="viewport-pane"]')
.trigger('mousedown', 'center', {
force: true,
})
.trigger('mouseup', 'center', {
force: true,
});
cy.get('[data-cy="viewport-pane"]').eq(0).trigger('dblclick', 'center');
}
});
});

View File

@@ -0,0 +1,35 @@
describe('OHIF Context Menu', function () {
beforeEach(function () {
cy.checkStudyRouteInViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78');
cy.expectMinimumThumbnails(3);
cy.initCommonElementsAliases();
cy.initCornerstoneToolsAliases();
cy.waitDicomImage();
});
it('checks context menu customization', function () {
// Add length measurement
cy.addLengthMeasurement();
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').as('yesBtn').click();
cy.get('[data-cy="data-row"]').as('measurementItem').click();
const [x1, y1] = [150, 100];
cy.get('@viewport')
.trigger('mousedown', x1, y1, {
which: 3,
})
.trigger('mouseup', x1, y1, {
which: 3,
});
// Contextmenu is visible
cy.get('[data-cy="context-menu"]').as('contextMenu').should('be.visible');
// Click "Finding" subMenu
cy.get('[data-cy="context-menu-item"]').as('item').contains('Finding').click();
// Click "Finding" subMenu
cy.get('[data-cy="context-menu-item"]').as('item').contains('Aortic insufficiency').click();
cy.get('[data-cy="data-row"]').as('measure-item').contains('Aortic insufficiency');
});
});

View File

@@ -0,0 +1,154 @@
describe('OHIF Cornerstone Hotkeys', () => {
beforeEach(() => {
cy.checkStudyRouteInViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78');
cy.window()
.its('cornerstone')
.then(cornerstone => {
// For debugging issues where tests pass locally but fail on CI
// - Sometimes Cypress orb seems to use CPU rendering pathway
cy.log(`Cornerstone using CPU Rendering?: ${cornerstone.getShouldUseCPURendering()}`);
});
cy.expectMinimumThumbnails(3);
cy.initCornerstoneToolsAliases();
cy.initCommonElementsAliases();
cy.waitDicomImage();
});
it('checks if hotkeys "R" and "L" can rotate the image', () => {
cy.get('body').type('R');
cy.get('@viewportInfoMidLeft').should('contains.text', 'P');
cy.get('@viewportInfoMidTop').should('contains.text', 'R');
// Hotkey L
cy.get('body').type('L');
cy.get('@viewportInfoMidLeft').should('contains.text', 'R');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
});
it('checks if hotkeys "ArrowUp" and "ArrowDown" can navigate in the stack', () => {
// Hotkey ArrowDown
cy.get('body').type('{downarrow}');
cy.get('@viewportInfoBottomRight').should('contains.text', 'I:2 (2/26)');
// Hotkey ArrowUp
cy.get('body').type('{uparrow}');
cy.get('@viewportInfoBottomRight').should('contains.text', 'I:1 (1/26)');
});
it('checks if hotkeys "V" and "H" can flip the image', () => {
// Hotkey H
cy.get('body').type('h');
cy.get('@viewportInfoMidLeft').should('contains.text', 'L');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
// Hotkey V
cy.get('body').type('v');
cy.get('@viewportInfoMidLeft').should('contains.text', 'L');
cy.get('@viewportInfoMidTop').should('contains.text', 'P');
});
// it('checks if hotkeys "+", "-" and "=" can zoom in, out and fit to viewport', () => {
// //Click on button and verify if icon is active on toolbar
// cy.get('@zoomBtn')
// .click()
// .then($zoomBtn => {
// cy.wrap($zoomBtn).should('have.class', 'active');
// });
// // Hotkey +
// cy.get('body').type('+++'); // Press hotkey 3 times
// cy.get('@viewportInfoTopLeft').should('contains.text', 'Zoom:2.30x');
// // Hotkey -
// cy.get('body').type('-');
// cy.get('@viewportInfoTopLeft').should('contains.text', 'Zoom:2.09x');
// // Hotkey =
// cy.get('body').type('=');
// cy.get('@viewportInfoTopLeft').should('contains.text', 'Zoom:1.67x');
// });
it('checks if hotkey "SPACEBAR" can reset the image', () => {
// Press multiples hotkeys
cy.get('body').type('v+++i');
cy.get('@viewportInfoMidLeft').should('contains.text', 'R');
cy.get('@viewportInfoMidTop').should('contains.text', 'P');
// Hotkey SPACEBAR
cy.get('body').type(' ');
cy.get('@viewportInfoMidLeft').should('contains.text', 'R');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
});
/*
// TODO: Pretty sure this is not implemented yet
// it('uses hotkeys "RightArrow" and "LeftArrow" to navigate between multiple viewports', () => {
//Select viewport layout (3,1)
cy.setLayout(3, 1);
cy.waitViewportImageLoading();
// Press multiples hotkeys on viewport #1
cy.get('body').type('VL+++I');
cy.get('@viewportInfoMidLeft').should('contains.text', 'A');
cy.get('@viewportInfoMidTop').should('contains.text', 'R');
cy.get('@viewportInfoBottomRight').should('contains.text', 'Zoom: 134%');
// Hotkey RightArrow: Move to next viewport
cy.get('body').type('{rightarrow}');
// Get overlay information from viewport #2
cy.get(
':nth-child(2) > .viewport-wrapper > .viewport-element > .ViewportOrientationMarkers.noselect > .top-mid.orientation-marker'
).as('viewport2InfoMidTop');
cy.get(
':nth-child(2) > .viewport-wrapper > .viewport-element > .ViewportOrientationMarkers.noselect > .left-mid.orientation-marker'
).as('viewport2InfoMidLeft');
cy.get(
':nth-child(2) > .viewport-wrapper > .viewport-element > .ViewportOverlay > div.bottom-right.overlay-element > div'
).as('viewport2InfoBottomRight');
// Press multiples hotkeys on viewport #2
cy.get('body').type('RR++H+++I');
cy.get('@viewport2InfoMidLeft').should('contains.text', 'P');
cy.get('@viewport2InfoMidTop').should('contains.text', 'H');
cy.get('@viewport2InfoBottomRight').should('contains.text', 'Zoom: 120%');
// Hotkey LeftArrow: Move to previous viewport
cy.get('body').type('{leftarrow}');
// Hotkey SPACEBAR: Reset viewport #1
cy.get('body').type(' ');
cy.get('@viewportInfoMidLeft').should('contains.text', 'R');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
cy.get('@viewportInfoBottomRight').should('contains.text', 'Zoom: 89%');
// Hotkey RightArrow: Move to next viewport
cy.get('body').type('{rightarrow}');
// Hotkey SPACEBAR: Reset viewport #2
cy.get('body').type(' ');
cy.get('@viewport2InfoMidLeft').should('contains.text', 'A');
cy.get('@viewport2InfoMidTop').should('contains.text', 'H');
cy.get('@viewport2InfoBottomRight').should('contains.text', 'Zoom: 45%');
//Select viewport layout (1,1)
cy.setLayout(1, 1);
});*/
//TO-DO: This test is blocked by issue #1095 (https://github.com/OHIF/Viewers/issues/1095)
//Once issue is fixed, this test can be uncommented
// it('checks if hotkey "Z" activates zoom tool', () => {
// // Hotkey Z
// cy.get('body').type('Z');
// // Verify if icon is active on toolbar
// cy.get('@zoomBtn').should('have.class', 'active');
// });
//TO-DO: This test is blocked by issue #1095 (https://github.com/OHIF/Viewers/issues/1095)
//Once issue is fixed, this test can be uncommented
// it('checks if hotkeys "PageDown" and "PageUp" can navigate in the series thumbnails', () => {
// // Hotkey PageDown
// cy.get('body').type('{pagedown}{pagedown}'); // press hotkey twice
// cy.get('@viewportInfoBottomLeft').should('contains.text', 'Ser: 3');
// // Hotkey PageUp
// cy.get('body').type('{pageup}');
// cy.get('@viewportInfoBottomLeft').should('contains.text', 'Ser: 2');
// });
});

View File

@@ -0,0 +1,462 @@
describe('OHIF Cornerstone Toolbar', () => {
beforeEach(() => {
cy.checkStudyRouteInViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78');
cy.expectMinimumThumbnails(3);
cy.initCornerstoneToolsAliases();
cy.initCommonElementsAliases();
cy.get('[data-cy="study-browser-thumbnail"]').eq(1).click();
//const expectedText = 'Ser: 1';
//cy.get('@viewportInfoBottomLeft').should('contains.text', expectedText);
cy.waitDicomImage();
});
it('checks if all primary buttons are being displayed', () => {
cy.get('@zoomBtn').should('be.visible');
cy.get('@wwwcBtnPrimary').should('be.visible');
cy.get('@wwwcBtnSecondary').should('be.visible');
cy.get('@panBtn').should('be.visible');
cy.get('@measurementToolsBtnPrimary').should('be.visible');
cy.get('@measurementToolsBtnSecondary').should('be.visible');
cy.get('@moreBtnPrimary').should('be.visible');
cy.get('@moreBtnSecondary').should('be.visible');
cy.get('@layoutBtn').should('be.visible');
});
/*it('checks if Stack Scroll tool will navigate across all series in the viewport', () => {
//Click on button and verify if icon is active on toolbar
cy.get('@stackScrollBtn')
.click()
.then($stackScrollBtn => {
cy.wrap($stackScrollBtn).should('have.class', 'active');
});
//drags the mouse inside the viewport to be able to interact with series
cy.get('@viewport')
.trigger('mousedown', 'center', { buttons: 1 })
.trigger('mousemove', 'top', { buttons: 1 })
.trigger('mouseup');
const expectedText =
'Ser: 1Img: 1 1/26256 x 256Loc: -30.00 mm Thick: 5.00 mm';
cy.get('@viewportInfoBottomLeft').should('have.text', expectedText);
});*/
// it('checks if Zoom tool will zoom in/out an image in the viewport', () => {
// //Click on button and verify if icon is active on toolbar
// cy.get('@zoomBtn')
// .click()
// .then($zoomBtn => {
// cy.wrap($zoomBtn).should('have.class', 'active');
// });
// // IMPORTANT: Cypress sends out a mouseEvent which doesn't have the buttons
// // property. This is a workaround to simulate a mouseEvent with the buttons property
// // which is consumed by cornerstone
// cy.get('@viewport')
// .trigger('mousedown', 'center', { buttons: 1 })
// .trigger('mousemove', 'top', {
// buttons: 1,
// })
// .trigger('mouseup', {
// buttons: 1,
// });
// const expectedText = 'Zoom:0.96x';
// cy.get('@viewportInfoTopLeft').should('have.text', expectedText);
// });
it('checks if Levels tool will change the window width and center of an image', () => {
// Wait for the DICOM image to load
// Assign an alias to the button element
cy.get('@wwwcBtnPrimary').as('wwwcButton');
cy.get('@wwwcButton').click();
cy.get('@wwwcButton').should('have.class', 'bg-primary-light');
//drags the mouse inside the viewport to be able to interact with series
cy.get('@viewport')
.trigger('mousedown', 'center', { buttons: 1 })
// Since we have scrollbar on the right side of the viewport, we need to
// force the mousemove since it goes to another element
.trigger('mousemove', 'right', { buttons: 1, force: true })
.trigger('mouseup', { buttons: 1 });
// The exact text is slightly dependent on the viewport resolution, so leave a range
cy.get('@viewportInfoBottomLeft').should($txt => {
const text = $txt.text();
expect(text).to.include('L:479');
});
});
it('checks if Pan tool will move the image inside the viewport', () => {
// Assign an alias to the button element
cy.get('@panBtn').as('panButton');
// Click on the button
cy.get('@panButton').click();
// Assert that the button has the 'active' class
cy.get('@panButton').should('have.class', 'bg-primary-light');
// Trigger the pan actions on the viewport
cy.get('@viewport')
.trigger('mousedown', 'center', { buttons: 1 })
.trigger('mousemove', 'bottom', { buttons: 1 })
.trigger('mouseup', 'bottom');
});
it('checks if Length annotation can be added to viewport and shows up in the measurements panel', () => {
//Click on button and verify if icon is active on toolbar
cy.addLengthMeasurement();
cy.get('[data-cy="viewport-notification"]').as('notif').should('exist');
// cy.get('[data-cy="viewport-notification"]').as('notif').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').as('yesBtn').click();
//Verify the measurement exists in the table
cy.get('@measurementsPanel').should('be.visible');
cy.get('[data-cy="data-row"]').as('measure').its('length').should('be.at.least', 1);
});
/*it('checks if angle annotation can be added on viewport without causing any errors', () => {
//Click on button and verify if icon is active on toolbar
cy.get('@angleBtn')
.click()
.then($angleBtn => {
cy.wrap($angleBtn).should('have.class', 'active'); // TODO: should we just add the 'active' class back? Or use a data property?
});
//Add annotation on the viewport
const initPos = [180, 390];
const midPos = [300, 410];
const finalPos = [180, 450];
cy.addAngle('@viewport', initPos, midPos, finalPos);
});*/
it('checks if Reset tool will reset all changes made on the image', () => {
//Make some changes by zooming in and rotating the image
cy.imageZoomIn();
cy.imageContrast();
//Click on reset button
cy.resetViewport();
const expectedText = 'W:958L:479';
cy.get('@viewportInfoBottomLeft').should('have.text', expectedText);
});
/*it('checks if CINE tool will prompt a modal with working controls', () => {
cy.server();
cy.route('GET', '/!**!/studies/!**!/').as('studies');
//Click on button
cy.get('@cineBtn').click();
// Verify if cine control overlay is being displayed
cy.get('.cine-controls')
.as('cineControls')
.should('be.visible');
//Test PLAY button
cy.get('[title="Play / Stop"]').then($btn => {
$btn.click();
cy.wait(100);
$btn.click();
});
let expectedText = 'Img: 1 1/26';
cy.get('@viewportInfoBottomLeft', { timeout: 15000 }).should(
'not.have.text',
expectedText
);
//Test SKIP TO FIRST IMAGE button
cy.get('[title="Skip to first Image"]')
.click()
.wait(1000);
cy.get('@viewportInfoBottomLeft', { timeout: 15000 }).should(
'contain.text',
expectedText
);
//Test NEXT IMAGE button
cy.get('[title="Next Image"]')
.click()
.wait(1000);
expectedText = 'Img: 2 2/26';
cy.get('@viewportInfoBottomLeft', { timeout: 15000 }).should(
'contain.text',
expectedText
);
//Test SKIP TO LAST IMAGE button
cy.get('[title="Skip to last Image"]')
.click()
.wait(2000);
expectedText = 'Img: 27 26/26';
cy.get('@viewportInfoBottomLeft', { timeout: 15000 }).should(
'contain.text',
expectedText
);
//Test PREVIOUS IMAGE button
cy.get('[title="Previous Image"]')
.click()
.wait(1000);
expectedText = 'Img: 26 25/26';
cy.get('@viewportInfoBottomLeft', { timeout: 15000 }).should(
'contain.text',
expectedText
);
//Click on Cine button
cy.get('@cineBtn')
.click()
.then(() => {
// Verify that cine control overlay is hidden
cy.get('@cineControls').should('not.exist');
});
});*/
/**
it('checks if More button will prompt a modal with secondary tools', () => {
//Click on More button
cy.get('@moreBtnSecondary').click();
//Verify if overlay is displayed
cy.get('[data-cy="MoreTools-list-menu"]')
.as('toolbarOverlay')
.should('be.visible');
// Click on one of the secondary tools from the overlay
cy.get('[data-cy="Magnify"]').click();
// Check if More button is active and if it has same icon as the secondary tool selected
cy.get('@moreBtnPrimary').then($moreBtn => {
cy.wrap($moreBtn)
.should('have.class', 'active')
.should('have.attr', 'data-tool', 'Magnify');
});
// Verify if overlay is hidden
cy.get('@toolbarOverlay').should('not.be.visible');
});
*/
/*it('checks if Layout tool will multiply the number of viewports displayed', () => {
//Click on Layout button and verify if overlay is displayed
cy.get('@layoutBtn')
.click()
.then(() => {
cy.get('.layoutChooser')
.as('layoutChooser')
.should('be.visible')
.find('td')
.its('length')
.should('be.eq', 9);
cy.get('@layoutBtn').click();
});
//verify if layout has changed to 2 viewports
cy.setLayout(1, 2);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 2);
});
cy.setLayout(2, 1);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 2);
});
//verify if layout has changed to 3 viewports
cy.setLayout(1, 3);
cy.get('.viewport-container').then($viewport => {
cy.wait(1000);
cy.wrap($viewport)
.its('length')
.should('be.eq', 3);
});
cy.setLayout(3, 1);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 3);
});
//verify if layout has changed to 4 viewports
cy.setLayout(2, 2);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 4);
});
//verify if layout has changed to 6 viewports
cy.setLayout(2, 3);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 6);
});
cy.setLayout(3, 2);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 6);
});
//verify if layout has changed to 9 viewports
cy.setLayout(3, 3);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 9);
});
//verify if layout has changed to 1 viewport
cy.setLayout(1, 1);
cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport)
.its('length')
.should('be.eq', 1);
});
});
it('checks if the available viewport was set to active when layout is decreased', () => {
cy.setLayout(3, 3);
// activate the ninth viewport
cy.get('[data-cy=viewport-container-8]')
.click()
.should('have.class', 'active');
cy.setLayout(1, 1);
// first viewport should be active
cy.get('[data-cy=viewport-container-0]').should('have.class', 'active');
});
it('checks if Clear tool will delete all measurements added in the viewport', () => {
//Add measurements in the viewport
cy.addLengthMeasurement();
cy.addAngleMeasurement();
//Verify if measurement annotation was added into the measurements panel
cy.get('@measurementsBtn').click();
cy.get('[data-cy="data-row"]')
.its('length')
.should('be.at.least', 2);
//Click on More button
cy.get('@moreBtn').click();
//Verify if overlay is displayed
cy.get('.tooltip-toolbar-overlay')
.as('toolbarOverlay')
.should('be.visible');
//Click on Clear button
cy.get('[data-cy="clear"]').click();
//Verify if measurements were removed from the measurements panel
//cy.get('.measurementItem'); //.should('not.exist');
//Close More button overlay
cy.get('@moreBtn').click();
//Close the measurements panel
cy.get('@measurementsBtn').then($btn => {
$btn.click();
cy.get('@measurementsPanel').should('not.be.enabled');
});
});
it('check if Rotate tool will change the image orientation in the viewport', () => {
//Click on More button
cy.get('@moreBtn').click();
//Verify if overlay is displayed
cy.get('.tooltip-toolbar-overlay')
.should('be.visible')
.then(() => {
//Click on Rotate button
cy.get('[data-cy="rotate right"]').click({ force: true });
cy.get('@viewportInfoMidLeft').should('contains.text', 'F');
cy.get('@viewportInfoMidTop').should('contains.text', 'R');
});
//Click on More button to close it
cy.get('@moreBtn').click();
});
it('check if Flip H tool will flip the image horizontally in the viewport', () => {
//Click on More button
cy.get('@moreBtn').click();
//Verify if overlay is displayed
cy.get('.tooltip-toolbar-overlay').should('be.visible');
//Click on Flip H button
cy.get('[data-cy="flip h"]').click();
cy.get('@viewportInfoMidLeft').should('contains.text', 'L');
cy.get('@viewportInfoMidTop').should('contains.text', 'H');
//Click on More button to close it
cy.get('@moreBtn').click();
cy.get('.tooltip-toolbar-overlay').should('not.exist');
});
*/
it('check if Flip tool will flip the image in the viewport', () => {
cy.get('@viewportInfoMidLeft').should('contains.text', 'R');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
//Click on More button
cy.get('@moreBtnSecondary').click();
//Click on Flip button
cy.get('[data-cy="flipHorizontal"]').click();
cy.waitDicomImage();
cy.get('@viewportInfoMidLeft').should('contains.text', 'L');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
});
// it('checks if stack sync is preserved on new display set and uses FOR', () => {
// // Active stack image sync and reference lines
// cy.get('[data-cy="MoreTools-split-button-secondary"]').click();
// cy.get('[data-cy="ImageSliceSync"]').click();
// // Add reference lines as that sometimes throws an exception
// cy.get('[data-cy="MoreTools-split-button-secondary"]').click();
// cy.get('[data-cy="ReferenceLines"]').click();
// cy.get('[data-cy="study-browser-thumbnail"]:nth-child(2)').dblclick();
// cy.get('body').type('{downarrow}{downarrow}');
// // Change the layout and double load the first
// cy.setLayout(2, 1);
// cy.get('body').type('{rightarrow}');
// cy.get('[data-cy="study-browser-thumbnail"]:nth-child(2)').dblclick();
// cy.waitDicomImage();
// // Now navigate down once and check that the left hand pane navigated
// cy.get('body').focus().type('{downarrow}');
// // The following lines assist in troubleshooting when/if this test were to fail.
// cy.get('[data-cy="viewport-pane"]')
// .eq(0)
// .find('[data-cy="viewport-overlay-top-right"]')
// .should('contains.text', 'I:2 (2/20)');
// cy.get('[data-cy="viewport-pane"]')
// .eq(1)
// .find('[data-cy="viewport-overlay-top-right"]')
// .should('contains.text', 'I:2 (2/20)');
// cy.get('body').type('{leftarrow}');
// cy.setLayout(1, 1);
// cy.get('@viewportInfoTopRight').should('contains.text', 'I:2 (2/20)');
// });
});

View File

@@ -0,0 +1,108 @@
describe('OHIF Download Snapshot File', () => {
beforeEach(() => {
cy.checkStudyRouteInViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78');
cy.expectMinimumThumbnails(3);
cy.openDownloadImageModal();
});
it('checks displayed information for Desktop experience', function () {
// Set Desktop resolution
// cy.viewport(1750, 720);
// Visual comparison
// cy.screenshot('Download Image Modal - Desktop experience');
//Check if all elements are displayed
// TODO: need to add this attribute to the modal
cy.get('[data-cy=modal-header]')
.as('downloadImageModal')
.should('contain.text', 'Download High Quality Image');
// Check input fields
// TODO: select2
// cy.get('[data-cy="file-type"]')
// .select('png')
// .should('have.value', 'png')
// .select('jpg')
// .should('have.value', 'jpg');
// Check image preview
cy.get('[data-cy="image-preview"]').should('contain.text', 'Image preview');
//TODO: This is a canvas now, not an img with src
// cy.get('[data-cy="viewport-preview-img"]')
// .should('have.attr', 'src')
// .and('include', 'data:image');
// Check buttons
cy.get('[data-cy="cancel-btn"]').scrollIntoView().should('be.visible');
cy.get('[data-cy="download-btn"]').scrollIntoView().should('be.visible');
cy.get('[data-cy="cancel-btn"]').click();
});
/*it('cancel changes on download modal', function() {
//Change Image Width, Filename and File Type
cy.get('[data-cy="image-width"]')
.clear()
.type('300');
cy.get('[data-cy="image-height"]') //Image Height should be the same as width
.should('have.value', '300');
cy.get('[data-cy="file-name"]')
.clear()
.type('new-filename');
cy.get('[data-cy="file-type"]').select('png');
//Click on Cancel button
cy.get('[data-cy="cancel-btn"]')
.scrollIntoView()
.click();
//Check modal is closed
cy.get('[data-cy="modal"]').should('not.exist');
//Open Modal
cy.openDownloadImageModal();
//Verify default values was restored
cy.get('[data-cy="image-width"]').should('have.value', '512');
cy.get('[data-cy="file-name"]').should('have.value', 'image');
cy.get('[data-cy=file-type]').should('have.value', 'jpg');
});*/
// TO-DO once issue is fixed: https://github.com/OHIF/Viewers/issues/1217
// it('checks error messages for empty fields', function() {
// //Clear fields Image Width and Filename
// cy.get('[data-cy="image-width"]').clear();
// cy.get('[data-cy="file-name"]').clear();
// //Click on Download button
// cy.get('[data-cy="download-btn"]')
// .scrollIntoView()
// .click();
// //Check error message
// });
/*it('checks if "Show Annotations" checkbox will display annotations', function() {
// Close modal that is initially opened
cy.get('[data-cy="close-button"]').click();
// Add measurements in the viewport
cy.addLengthMeasurement();
cy.addAngleMeasurement();
// Open Modal
cy.openDownloadImageModal();
// Select "Show Annotations" option
cy.get('[data-cy="show-annotations"]').check();
// Check image preview
cy.get('[data-cy="image-preview"]').scrollIntoView();
//Compare classes that exists on Image Preview with Annotations and Without Annotation
cy.get('[data-cy="modal-content"]')
.find('canvas')
.should('have.class', 'magnifyTool'); //Class "MagnifyTool" exists with annotations displayed on Image preview
// Uncheck "Show Annotations" option
cy.get('[data-cy="show-annotations"]')
.uncheck()
.wait(300);
// Check that class "MagnifyTool" should not exist
cy.get('[data-cy="modal-content"]')
.find('canvas')
.should('not.have.class', 'magnifyTool');
});*/
});

View File

@@ -0,0 +1,92 @@
describe('OHIF General Viewer', function () {
beforeEach(() =>
cy.initViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78', {
minimumThumbnails: 3,
})
);
it('scrolls series stack using scrollbar', function () {
cy.scrollToIndex(13);
cy.get('@viewportInfoBottomRight').should('contains.text', '14');
});
it('performs right click to zoom', function () {
// This is not used to activate the tool, it is used to ensure the
// top left viewport info shows the zoom values (it only shows up
// when the zoom tool is active)
cy.get('@zoomBtn')
.click()
.then($zoomBtn => {
cy.wrap($zoomBtn).should('have.class', 'bg-primary-light');
});
const zoomLevelInitial = cy.get('@viewportInfoTopLeft').then($viewportInfo => {
return $viewportInfo.text().substring(6, 9);
});
//Right click on viewport
cy.get('@viewport')
.trigger('mousedown', 'top', { buttons: 2 })
.trigger('mousemove', 'center', { buttons: 2 })
.trigger('mouseup');
// make sure the new zoom level is less than the initial
cy.get('@viewportInfoBottomLeft').then($viewportInfo => {
const zoomLevelFinal = $viewportInfo.text().substring(6, 9);
expect(zoomLevelFinal < zoomLevelInitial).to.eq(true);
});
});
/*it('performs middle click to pan', function() {
//Get image position from cornerstone and check if y axis was modified
let cornerstone;
let currentPan;
// TO DO: Replace the cornerstone pan check by Percy snapshot comparison
cy.window()
.its('cornerstone')
.then(c => {
cornerstone = c;
currentPan = () =>
cornerstone.getEnabledElements()[0].viewport.translation;
});
//pan image with middle click
cy.get('@viewport')
.trigger('mousedown', 'center', { buttons: 3 })
.trigger('mousemove', 'bottom', { buttons: 3 })
.trigger('mouseup', 'bottom')
.then(() => {
expect(currentPan().y > 0).to.eq(true);
});
});*/
/*it('opens About modal and verify the displayed information', function() {
cy.get('[data-cy="options-dropdown"]')
.first()
.click();
cy.get('[data-cy="about-modal"]')
.as('aboutOverlay')
.should('be.visible');
//check buttons and links
cy.get('[data-cy="about-modal"]')
.should('contains.text', 'Visit the forum')
.and('contains.text', 'Report an issue')
.and('contains.text', 'https://github.com/OHIF/Viewers/');
//check version number
cy.get('[data-cy="about-modal"]').then($modal => {
cy.get('[data-cy="header-version-info"]').should($headerVersionNumber => {
$headerVersionNumber = $headerVersionNumber.text().substring(1);
expect($modal).to.contain($headerVersionNumber);
});
});
//close modal
cy.get('[data-cy="close-button"]').click();
cy.get('@aboutOverlay').should('not.exist');
});
*/
});

View File

@@ -0,0 +1,218 @@
describe('OHIF Measurement Panel', function () {
beforeEach(function () {
cy.checkStudyRouteInViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78');
cy.expectMinimumThumbnails(3);
cy.initCommonElementsAliases();
cy.initCornerstoneToolsAliases();
cy.waitDicomImage();
});
it('checks if Measurements right panel can be hidden/displayed', function () {
cy.get('@measurementsPanel').should('exist');
cy.get('@measurementsPanel').should('be.visible');
cy.get('@RightCollapseBtn').click();
cy.get('@measurementsPanel').should('not.exist');
cy.get('@RightCollapseBtn').click();
// segmentation panel should be visible
cy.get('@segmentationPanel').should('be.visible');
// measurements panel should be clickable
cy.get('@measurementsBtn').click();
cy.get('@measurementsPanel').should('be.visible');
});
it('checks if measurement item can be Relabeled under Measurements panel', function () {
// Add length measurement
cy.addLengthMeasurement();
cy.get('[data-cy="viewport-notification"]').as('viewportNotification').should('exist');
cy.get('[data-cy="viewport-notification"]').as('viewportNotification').should('be.visible');
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').as('yesBtn').click();
cy.get('[data-cy="data-row"]').as('measurementItem').click();
cy.get('[data-cy="data-row"]').find('svg').eq(0).as('measurementItemSvg').click();
// enter Bone label
// Todo: move it to the new annotation input with drop down
// cy.get('[data-cy="input-annotation"]').should('exist');
// cy.get('[data-cy="input-annotation"]').should('be.visible');
// cy.get('[data-cy="input-annotation"]').type('Bone{enter}');
// cy.get('[data-cy="data-row"]').as('measurementItem').should('contain.text', 'Bone');
});
it('checks if image would jump when clicked on a measurement item', function () {
cy.get('[data-cy="study-browser-thumbnail"][data-series="1"]').dblclick();
cy.wait(250);
cy.scrollToIndex(0);
// Add length measurement
cy.addLengthMeasurement().wait(250);
cy.get('[data-cy="prompt-begin-tracking-yes-btn"]').as('yesBtn').click();
cy.scrollToIndex(13);
// Reset to default tool so that the new add length works
cy.addLengthMeasurement([100, 100], [200, 200]); //Adding measurement in the viewport
cy.get('@viewportInfoBottomRight').should('contains.text', '(14/');
// Click on first measurement item
cy.get('[data-cy="data-row"]').eq(0).click();
cy.get('@viewportInfoBottomRight').should('contains.text', '(1/');
cy.get('@viewportInfoBottomRight').should('not.contains.text', '(14/');
});
/*
TODO: Not sure why this is failing
it('checks if Description can be added to measurement item under Measurements panel', () => {
cy.addLengthMeasurement(); //Adding measurement in the viewport
cy.get('@measurementsBtn').click();
cy.get('.measurementItem').click();
// Click "Description"
cy.get('.btnAction')
.contains('Description')
.click();
// Enter description text
const descriptionText = 'Adding text for description test';
cy.get('#description').type(descriptionText);
// Confirm
cy.get('.btn-confirm').click();
//Verify if descriptionText was added
cy.get('.measurementLocation').should('contain.text', descriptionText);
// Remove the measurement we just added
cy.get('.btnAction')
.last()
.contains('Delete')
.click()
// Close panel
cy.get('@measurementsBtn').click();
cy.get('@measurementsPanel').should('not.be.enabled');
});
*/
/*it('checks if measurement item can be deleted through the context menu on the viewport', function() {
cy.addLengthMeasurement([100, 100], [200, 100]); //Adding measurement in the viewport
//Right click on measurement annotation
const [x1, y1] = [150, 100];
cy.get('@viewport')
.trigger('mousedown', x1, y1, {
which: 3,
})
.trigger('mouseup', x1, y1, {
which: 3,
})
.wait(300)
.then(() => {
//Contextmenu is visible
cy.get('.ToolContextMenu').should('be.visible');
});
//Click "Delete measurement"
cy.get('.form-action')
.contains('Delete measurement')
.click();
//Open measurements menu
cy.get('@measurementsBtn').click();
//Verify measurements was removed from panel
cy.get('.measurementItem')
.should('not.exist')
.log('Annotation successfully removed');
//Close panel
cy.get('@measurementsBtn').click();
cy.get('@measurementsPanel').should('not.exist');
});*/
/*it('adds relabel and description to measurement item through the context menu on the viewport', function() {
cy.addLengthMeasurement([100, 100], [200, 100]); //Adding measurement in the viewport
// Relabel
// Right click on measurement annotation
const [x1, y1] = [150, 100];
cy.get('@viewport')
.trigger('mousedown', x1, y1, {
which: 3,
})
.trigger('mouseup', x1, y1, {
which: 3,
});
// Contextmenu is visible
cy.get('.ToolContextMenu').should('be.visible');
// Click "Relabel"
cy.get('.form-action')
.contains('Relabel')
.click();
// Search for "Brain"
cy.get('.searchInput').type('Brain');
// Select "Brain" Result
cy.get('.treeInputs > .wrapperLabel')
.contains('Brain')
.click();
// Confirm Selection
cy.get('.checkIconWrapper').click();
// Description
// Right click on measurement annotation
cy.get('@viewport')
.trigger('mousedown', x1, y1, {
which: 3,
})
.trigger('mouseup', x1, y1, {
which: 3,
});
// Contextmenu is visible
cy.get('.ToolContextMenu').should('be.visible');
// Click "Description"
cy.get('.form-action')
.contains('Add Description')
.click();
// Enter description text
const descriptionText = 'Adding text for description test';
cy.get('#description').type(descriptionText);
// Confirm
cy.get('.btn-confirm').click();
//Open measurements menu
cy.get('@measurementsBtn').click();
// Verify if label was added
cy.get('.measurementLocation')
.should('contain.text', 'Brain')
.log('Relabel added with success');
//Verify if descriptionText was added
cy.get('.measurementLocation')
.should('contain.text', descriptionText)
.log('Description added with success');
// Close panel
cy.get('@measurementsBtn').click();
cy.get('@measurementsPanel').should('not.exist');
});*/
});

View File

@@ -0,0 +1,150 @@
/*describe('OHIF Save Measurements', function() {
before(() => {
cy.checkStudyRouteInViewer(
'1.2.840.113619.2.5.1762583153.215519.978957063.78'
);
cy.expectMinimumThumbnails(3);
});
beforeEach(() => {
// Wait image to load on viewport
cy.wait(2000);
cy.resetViewport();
cy.initCommonElementsAliases();
});
it('saves new measurement annotation', function() {
// Add measurement in the viewport
cy.addLengthMeasurement();
// Verify if measurement annotation was added into the measurements panel
cy.get('@measurementsBtn').click();
cy.get('.measurementItem')
.its('length')
.should('be.at.least', 1);
// TODO: Don't save until we're using in-memory data store
// Save new measurement
// cy.get('[data-cy="save-measurements-btn"]').click();
// Verify that success message overlay is displayed
// cy.get('.sb-success')
// .should('be.visible')
// .and('contains.text', 'Measurements saved successfully');
// Visual test comparison
cy.screenshot('Save Measurements - new measurement added');
cy.percyCanvasSnapshot('Save Measurements - new measurement added');
});
// it('retrieves saved measurements', function() {
// // Add measurement in the viewport
// cy.addLengthMeasurement();
// // Verify if measurement annotation was added into the measurements panel
// cy.get('@measurementsBtn').click();
// cy.get('.measurementDisplayText') // Get label size of the recently added measurement
// .last()
// .then($measurementSizeLabel => {
// // Save new measurement
// // TODO: Do not save
// cy.get('[data-cy="save-measurements-btn"]')
// .click()
// .then(() => {
// // Verify that success message overlay is displayed
// cy.get('.sb-success').should('be.visible');
// });
// // Reload the page
// cy.reload()
// .wait(1000) //Wait page to load
// .expectMinimumThumbnails(2); //wait all thumbnails to load
// // Verify that recently added measurement was retrieved
// cy.get('@measurementsBtn').click();
// cy.get('.measurementDisplayText') // Get label size of the recently added measurement
// .last()
// .then($retrivedMeasurementSizeLabel => {
// expect($retrivedMeasurementSizeLabel.textContent).to.eq(
// $measurementSizeLabel.textContent
// );
// });
// });
// });
// it('checks error message when saving without any measurement', function() {
// // Checks that measurement list is empty
// cy.get('.numberOfItems').should('have.text', '0');
// // Click on Save Measurement button
// cy.get('[data-cy="save-measurements-btn"]').click();
// // Verify that error message overlay is displayed
// cy.get('.sb-error')
// .should('be.visible')
// .and('contains.text', 'Error while saving the measurements');
// // Close message overlay
// cy.get('.sb-closeIcon').click();
// });
it('checks if warning message is displayed on measurements of unsupported tools', function() {
// Add measurement for unsupported tool in the viewport
cy.addAngleMeasurement();
// Verify if measurement annotation was added into the measurements panel
cy.get('@measurementsBtn').click();
cy.get('.measurementItem')
.its('length')
.should('be.at.least', 1);
// Check that warning is displayed for unsupported tool
cy.get('.hasWarnings').should('be.visible');
// // Save new measurement
// cy.get('[data-cy="save-measurements-btn"]').click();
// // Verify that error message overlay is displayed
// cy.get('.sb-error')
// .should('be.visible')
// .and('contains.text', 'Error while saving the measurements');
// Close Measurements panel
cy.get('@measurementsBtn').click();
});
/*it('checks if measurements of unsupported tools were not saved', function() {
// Add measurement for supported tool in the viewport
cy.addLengthMeasurement();
// Add measurement for unsupported tool in the viewport
cy.addAngleMeasurement();
// Verify if measurement annotation was added into the measurements panel
cy.get('@measurementsBtn').click();
cy.get('.measurementItem')
.its('length')
.should('be.eq', 2);
// Check that warning is displayed for unsupported tool
cy.get('.hasWarnings').should('be.visible');
// Save new measurement
cy.get('[data-cy="save-measurements-btn"]').click();
// Verify that success message overlay is displayed
cy.get('.sb-success')
.should('be.visible')
.and('contains.text', 'Measurements saved successfully');
// Reload the page
cy.reload()
.wait(1000) //Wait page to load
.expectMinimumThumbnails(2); //wait all thumbnails to load
//Verify that measurement for unsupported tool was not saved
cy.get('@measurementsBtn').click();
cy.get('.measurementItem')
.its('length')
.should('be.eq', 1);
// Close Measurements panel
cy.get('@measurementsBtn').click();
});
});*/

View File

@@ -0,0 +1,60 @@
describe('OHIF Study Browser', function () {
beforeEach(function () {
cy.checkStudyRouteInViewer('1.2.840.113619.2.5.1762583153.215519.978957063.78');
cy.expectMinimumThumbnails(3);
cy.initCommonElementsAliases();
cy.initCornerstoneToolsAliases();
});
it('checks if series thumbnails are being displayed', function () {
cy.get('[data-cy="study-browser-thumbnail"]').its('length').should('be.gt', 1);
});
it('drags and drop a series thumbnail into viewport', function () {
// Can't use the native drag version as the element should be rerendered
// cy.get('[data-cy="study-browser-thumbnail"]:nth-child(2)') //element to be dragged
// .drag('.cornerstone-canvas'); //dropzone element
const dataTransfer = new DataTransfer();
cy.get('[data-cy="study-browser-thumbnail"]:nth-child(2)').as('seriesThumbnail');
cy.get('@seriesThumbnail')
.first()
.trigger('mousedown', { which: 1, button: 0 })
.trigger('dragstart', { dataTransfer })
.trigger('drag', {});
cy.get('.cornerstone-canvas').as('viewport');
cy.get('@viewport')
.trigger('mousemove', 'center')
.trigger('dragover', { dataTransfer, force: true })
.trigger('drop', { dataTransfer, force: true });
//const expectedText =
// 'Ser: 2Img: 1 1/13512 x 512Loc: -17.60 mm Thick: 3.00 mm';
//cy.get('@viewportInfoBottomLeft').should('contain.text', expectedText);
});
it('checks if Series left panel can be hidden/displayed', function () {
cy.get('@seriesPanel').should('exist');
cy.get('@seriesPanel').should('be.visible');
cy.get('@seriesBtn').click();
cy.get('@seriesPanel').should('not.exist');
cy.get('@seriesBtn').click();
cy.get('@seriesPanel').should('exist');
cy.get('@seriesPanel').should('be.visible');
});
it('performs double-click to load thumbnail in active viewport', () => {
// Have to finish rendering the image before this works
cy.wait(350);
cy.get('[data-cy="study-browser-thumbnail"]:nth-child(2)').dblclick();
//cy.get('@viewportInfoBottomLeft').should('contains.text', expectedText);
});
});

View File

@@ -0,0 +1,184 @@
//We are keeping the hardcoded results values for the study list tests
//this is intended to be running in a controlled docker environment with test data.
describe('OHIF Study List', function () {
context('Desktop resolution', function () {
beforeEach(function () {
Cypress.on('uncaught:exception', () => false);
cy.window().then(win => win.sessionStorage.clear());
cy.openStudyList();
cy.viewport(1750, 720);
cy.initStudyListAliasesOnDesktop();
//Clear all text fields
cy.get('@PatientName').clear();
cy.get('@MRN').clear();
cy.get('@AccessionNumber').clear();
cy.get('@StudyDescription').clear();
});
afterEach(function () {
cy.window().then(win => win.sessionStorage.clear());
});
it('Displays several studies initially', function () {
cy.waitStudyList();
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.greaterThan(1);
expect($list).to.contain('Juno');
expect($list).to.contain('832040');
});
});
it('searches Patient Name with exact string', function () {
cy.get('@PatientName').type('Juno');
//Wait result list to be displayed
cy.waitStudyList();
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('Juno');
});
});
it('maintains Patient Name filter upon return from viewer', function () {
cy.get('@PatientName').type('Juno');
//Wait result list to be displayed
cy.waitStudyList();
cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click();
cy.get(
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click();
cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('Juno');
});
});
it('searches MRN with exact string', function () {
cy.get('@MRN').type('0000003');
//Wait result list to be displayed
cy.waitStudyList();
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('0000003');
});
});
it('maintains MRN filter upon return from viewer', function () {
cy.get('@MRN').type('0000003');
//Wait result list to be displayed
cy.waitStudyList();
cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click();
cy.get(
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click();
cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('0000003');
});
});
it('searches Accession with exact string', function () {
cy.get('@AccessionNumber').type('321');
//Wait result list to be displayed
cy.waitStudyList();
cy.wait(2000);
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('321');
});
});
it('maintains Accession filter upon return from viewer', function () {
cy.get('@AccessionNumber').type('0000155811');
//Wait result list to be displayed
cy.waitStudyList();
cy.wait(2000);
cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click();
cy.get(
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click();
cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('0000155811');
});
});
it('searches Description with exact string', function () {
cy.get('@StudyDescription').type('PETCT');
//Wait result list to be displayed
cy.waitStudyList();
cy.wait(2000);
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('PETCT');
});
});
it('maintains Description filter upon return from viewer', function () {
cy.get('@StudyDescription').type('PETCT');
//Wait result list to be displayed
cy.waitStudyList();
cy.wait(2000);
cy.get('[data-cy="studyRow-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]').click();
cy.get(
'[data-cy="mode-basic-test-1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1"]'
).click();
cy.get('[data-cy="return-to-work-list"]').click();
cy.wait(2000);
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.eq(1);
expect($list).to.contain('PETCT');
});
});
/* Todo: fix react select
it('searches Modality with camel case', function() {
cy.get('@modalities').type('Ct');
// Wait result list to be displayed
cy.waitStudyList();
cy.get('@searchResult2').should($list => {
expect($list.length).to.be.greaterThan(1);
expect($list).to.contain('CT');
});
});
it('changes Rows per page and checks the study count', function() {
//Show Rows per page options
const pageRows = [25, 50, 100];
//Check all options of Rows
pageRows.forEach(numRows => {
cy.get('select').select(numRows.toString()); //Select Rows per page option
//Wait result list to be displayed
cy.waitStudyList().then(() => {
//Compare the search result with the Study Count on the table header
cy.get('@numStudies')
.should(numStudies => {
expect(parseInt(numStudies.text())).to.be.at.most(numRows); //less than or equals to
})
.then(numStudies => {
//Compare to the number of Rows in the search result
cy.get('@searchResult2').then($searchResult => {
let countResults = $searchResult.length;
expect(numStudies.text()).to.be.eq(countResults.toString());
});
});
});
});
});
*/
});
});

View File

@@ -0,0 +1,757 @@
/*describe('OHIF User Preferences', () => {
context('Study List Page', function() {
before(() => {
cy.visit('/');
});
beforeEach(() => {
// Open User Preferences modal
cy.openPreferences();
});
it('checks displayed information on User Preferences modal', function() {
cy.initPreferencesModalAliases();
//Check Title
cy.get('@preferencesModal').should('contain.text', 'User Preferences');
//Check tabs
cy.get('@userPreferencesHotkeysTab')
.should('have.text', 'Hotkeys')
.and('have.class', 'active');
cy.get('@userPreferencesGeneralTab').should('have.text', 'General');
cy.get('@userPreferencesWindowLevelTab').should(
'have.text',
'Window Level'
);
//Check buttons
cy.get('@restoreBtn')
.scrollIntoView()
.should('have.text', 'Reset to Defaults');
cy.get('@cancelBtn').should('have.text', 'Cancel');
cy.get('@saveBtn').should('have.text', 'Save');
cy.get('[data-cy="close-button"]').click();
});
it('checks translation by selecting Spanish language', function() {
cy.selectPreferencesTab('@userPreferencesGeneralTab');
// Language dropdown should be displayed
cy.get('#language-select').should('be.visible');
// Set language to Spanish and save
cy.setLanguage('Spanish');
// Header should be translated to Spanish
cy.get('.research-use')
.scrollIntoView()
.should('have.text', 'SOLO USO PARA INVESTIGACIÓN');
// Options menu should be translated
cy.get('[data-cy="options-menu"]')
.should('have.text', 'Opciones')
.click();
cy.get('[data-cy="dd-item-menu"]')
.first()
.should('contain.text', 'Acerca de');
cy.get('[data-cy="dd-item-menu"]')
.last()
.should('contain.text', 'Preferencias');
// Close Options menu
cy.get('[data-cy="options-menu"]').click();
});
it('checks if user can cancel the language selection and application will be in "English (USA)"', function() {
// Set language to English and save
cy.setLanguage('English (USA)');
// Set language to Spanish and cancel
cy.setLanguage('Spanish', false);
// Header should be kept in "English (USA)"
cy.get('.research-use')
.scrollIntoView()
.should('have.text', 'INVESTIGATIONAL USE ONLY');
// Options menu should be translated
cy.get('[data-cy="options-menu"]')
.should('have.text', 'Options')
.click();
cy.get('[data-cy="dd-item-menu"]')
.first()
.should('contain.text', 'About');
cy.get('[data-cy="dd-item-menu"]')
.last()
.should('contain.text', 'Preferences');
// Close Options menu
cy.get('[data-cy="options-menu"]').click();
});
it('checks if user can restore to default the language selection and application will be in "English (USA)"', function() {
// Set language to Spanish
cy.setLanguage('Spanish');
//Open Preferences again
cy.openPreferences();
// Go to general tab
cy.selectPreferencesTab('@userPreferencesGeneralTab');
cy.get('@restoreBtn')
.scrollIntoView()
.click();
// Close Success Message overlay (if displayed)
cy.get('body').then(body => {
if (body.find('.sb-closeIcon').length > 0) {
cy.get('.sb-closeIcon').click({ force: true });
}
// click on save button
cy.get('@saveBtn')
.scrollIntoView()
.click();
});
// Header should be in "English (USA)"
cy.get('.research-use')
.scrollIntoView()
.should('have.text', 'INVESTIGATIONAL USE ONLY');
// Options menu should be in "English (USA)"
cy.get('[data-cy="options-menu"]')
.should('have.text', 'Options')
.click();
cy.get('[data-cy="dd-item-menu"]')
.first()
.should('contain.text', 'About');
cy.get('[data-cy="dd-item-menu"]')
.last()
.should('contain.text', 'Preferences');
// Close options Menu
cy.get('[data-cy="options-menu"]').click();
});
it('checks if W/L Preferences table is being displayed in the Window Level tab', function() {
//Navigate to Window Level tab
cy.selectPreferencesTab('@userPreferencesWindowLevelTab');
//Check table header
cy.get('.wlRow.header')
.should('contains.text', 'Preset')
.and('contains.text', 'Description')
.and('contains.text', 'Window')
.and('contains.text', 'Level');
//Check table has more than 1 row (more than header)
cy.get('.wlRow')
.its('length')
.should('be.greaterThan', 1);
});
it('checks if Preferences set in Study List Page will be consistent on Viewer Page', function() {
// Go go hotkeys tab
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
// Set new hotkey for 'Rotate Right' function
cy.setNewHotkeyShortcutOnUserPreferencesModal('Rotate Right', '{shift}Q');
// Close Success Message overlay (if displayed)
cy.get('body').then(body => {
if (body.find('.sb-closeIcon').length > 0) {
cy.get('.sb-closeIcon').click({ force: true });
}
// click on save button
cy.get('@saveBtn')
.scrollIntoView()
.click();
});
// Open User Preferences modal again
cy.openPreferences();
// Go to General tab
cy.selectPreferencesTab('@userPreferencesGeneralTab');
// Set language to Spanish
cy.setLanguage('Spanish');
// Go to Study Viewer page
cy.checkStudyRouteInViewer(
'1.2.840.113619.2.5.1762583153.215519.978957063.78'
);
cy.expectMinimumThumbnails(3);
cy.initCommonElementsAliases();
// Check if application is in Spanish
// Header should be translated to Spanish
cy.get('.research-use')
.scrollIntoView()
.should('have.text', 'SOLO USO PARA INVESTIGACIÓN');
// Options menu should be translated
cy.get('[data-cy="options-menu"]')
.should('have.text', 'Opciones')
.click();
cy.get('[data-cy="dd-item-menu"]')
.first()
.should('contain.text', 'Acerca de');
cy.get('[data-cy="dd-item-menu"]')
.last()
.should('contain.text', 'Preferencias');
// Check if new hotkey is working on viewport
cy.get('body').type('{shift}Q', {
release: false,
});
cy.get('@viewportInfoMidTop').should('contains.text', 'R');
});
});
context('Study Viewer Page', function() {
before(() => {
cy.checkStudyRouteInViewer(
'1.2.840.113619.2.5.1762583153.215519.978957063.78'
);
cy.expectMinimumThumbnails(3);
});
beforeEach(() => {
cy.initCommonElementsAliases();
cy.resetViewport();
cy.resetUserHotkeyPreferences();
cy.resetUserGeneralPreferences();
// Open User Preferences modal
cy.openPreferences();
});
afterEach(() => {
// Close User Preferences Modal (if displayed)
cy.get('body').then(body => {
if (body.find('.OHIFModal__header').length > 0) {
cy.get('[data-cy="close-button"]').click({ force: true });
}
});
});
it('checks displayed information on User Preferences modal', function() {
cy.get('@preferencesModal').should('contain.text', 'User Preferences');
cy.get('@userPreferencesHotkeysTab')
.should('have.text', 'Hotkeys')
.and('have.class', 'active');
cy.get('@userPreferencesGeneralTab').should('have.text', 'General');
cy.get('@userPreferencesWindowLevelTab').should(
'have.text',
'Window Level'
);
cy.get('@restoreBtn')
.scrollIntoView()
.should('have.text', 'Reset to Defaults');
cy.get('@cancelBtn').should('have.text', 'Cancel');
cy.get('@saveBtn').should('have.text', 'Save');
});
it('checks translation by selecting Spanish language', function() {
cy.selectPreferencesTab('@userPreferencesGeneralTab');
// Language dropdown should be displayed
cy.get('#language-select').should('be.visible');
// Set language to Spanish
cy.setLanguage('Spanish');
// Header should be translated to Spanish
cy.get('.research-use')
.scrollIntoView()
.should('have.text', 'SOLO USO PARA INVESTIGACIÓN');
// Options menu should be translated
cy.get('[data-cy="options-menu"]')
.should('have.text', 'Opciones')
.click();
cy.get('[data-cy="dd-item-menu"]')
.first()
.should('contain.text', 'Acerca de');
cy.get('[data-cy="dd-item-menu"]')
.last()
.should('contain.text', 'Preferencias');
});
it('checks if user can cancel the language selection and application will be in "English (USA)"', function() {
// Set language to English and save
cy.setLanguage('English (USA)');
// Set language to Spanish and cancel
cy.setLanguage('Spanish', false);
// Header should be kept in "English (USA)"
cy.get('.research-use')
.scrollIntoView()
.should('have.text', 'INVESTIGATIONAL USE ONLY');
// Options menu should be translated
cy.get('[data-cy="options-menu"]')
.should('have.text', 'Options')
.click();
cy.get('[data-cy="dd-item-menu"]')
.first()
.should('contain.text', 'About');
cy.get('[data-cy="dd-item-menu"]')
.last()
.should('contain.text', 'Preferences');
});
it('checks if user can restore to default the language selection and application will be in "English (USA)', function() {
cy.selectPreferencesTab('@userPreferencesGeneralTab');
// Language dropdown should be displayed
cy.get('#language-select').should('be.visible');
// Set language to Spanish
cy.setLanguage('Spanish');
// Open User Preferences modal
cy.openPreferences();
// Go to general tab
cy.selectPreferencesTab('@userPreferencesGeneralTab');
// click on restore button
cy.get('@restoreBtn')
.scrollIntoView()
.click();
// click on save button
cy.get('@saveBtn')
.scrollIntoView()
.click();
// Header should be in "English (USA)""
cy.get('.research-use')
.scrollIntoView()
.should('have.text', 'INVESTIGATIONAL USE ONLY');
// Options menu should be in "English (USA)"
cy.get('[data-cy="options-menu"]')
.should('have.text', 'Options')
.click();
cy.get('[data-cy="dd-item-menu"]')
.first()
.should('contain.text', 'About');
cy.get('[data-cy="dd-item-menu"]')
.last()
.should('contain.text', 'Preferences');
});
it('checks new hotkeys for "Rotate Right" and "Rotate Left"', function() {
// Go go hotkeys tab
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
// Set new hotkey for 'Rotate Right' function
cy.setNewHotkeyShortcutOnUserPreferencesModal(
'Rotate Right',
'{shift}{rightarrow}'
);
// Set new hotkey for 'Rotate Left' function
cy.setNewHotkeyShortcutOnUserPreferencesModal(
'Rotate Left',
'{shift}{leftarrow}'
);
// Close Success Message overlay (if displayed)
cy.get('body').then(body => {
if (body.find('.sb-closeIcon').length > 0) {
cy.get('.sb-closeIcon').click({ force: true });
}
// click on save button
cy.get('@saveBtn')
.scrollIntoView()
.click();
});
//Rotate Right with new Hotkey
cy.get('body').type('{shift}{rightarrow}');
cy.get('@viewportInfoMidTop').should('contains.text', 'R');
//Rotate Left with new Hotkey
cy.get('body').type('{shift}{leftarrow}');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
});
it('checks new hotkeys for "Next" and "Previous" Image on Viewport', function() {
// Update hotkeys for 'Next/Previous Viewport'
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
cy.setNewHotkeyShortcutOnUserPreferencesModal(
'Next Viewport',
'{shift}{rightarrow}'
);
cy.setNewHotkeyShortcutOnUserPreferencesModal(
'Previous Viewport',
'{shift}{leftarrow}'
);
// Close Success Message overlay (if displayed)
cy.get('body').then(body => {
if (body.find('.sb-closeIcon').length > 0) {
cy.get('.sb-closeIcon').click({ force: true });
}
// click on save button
cy.get('@saveBtn')
.scrollIntoView()
.click();
});
// Set 3 viewports layout
cy.setLayout(3, 1);
cy.waitViewportImageLoading();
// Reset, Rotate Right and Invert colors on Viewport #1
cy.get('body').type(' ');
cy.get('body').type('r');
cy.get('body').type('i');
// Shift active viewport to next
// Reset, Rotate Left and Invert colors on Viewport #2
cy.get('body').type('{shift}{rightarrow}');
cy.get('body').type(' ');
cy.get('body').type('l');
cy.get('body').type('i');
// Verify 1st viewport was rotated
cy.get('@viewportInfoMidTop').should('contains.text', 'R');
// Verify 2nd viewport was rotated
cy.get(
':nth-child(2) > .viewport-wrapper > .viewport-element > .ViewportOrientationMarkers.noselect > .top-mid.orientation-marker'
).as('viewport2InfoMidTop');
cy.get('@viewport2InfoMidTop').should('contains.text', 'P');
//Move to Previous Viewport
cy.get('body').type('{shift}{leftarrow}');
// Reset viewport #1 with spacebar hotkey
cy.get('body').type(' ');
cy.get('@viewportInfoMidTop').should('contains.text', 'A');
// Set 1 viewport layout
cy.setLayout(1, 1);
});
it('checks error message when duplicated hotkeys are inserted', function() {
// Go go hotkeys tab
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
// Set duplicated hotkey for 'Rotate Right' function
cy.setNewHotkeyShortcutOnUserPreferencesModal('Rotate Right', '{i}');
// Check error message
cy.get('.HotkeysPreferences').within(() => {
cy.contains('Rotate Right') // label we're looking for
.parent()
.find('.preferencesInputErrorMessage')
.as('errorMsg')
.should('have.text', '"Invert" is already using the "i" shortcut.');
});
});
it('checks error message when invalid hotkey is inserted', function() {
// Go go hotkeys tab
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
// Set invalid hotkey for 'Rotate Right' function
cy.setNewHotkeyShortcutOnUserPreferencesModal('Rotate Right', '{ctrl}Z');
// Check error message
cy.get('.HotkeysPreferences').within(() => {
cy.contains('Rotate Right') // label we're looking for
.parent()
.find('.preferencesInputErrorMessage')
.as('errorMsg')
.should('have.text', '"ctrl+z" shortcut combination is not allowed');
});
});
it('checks error message when only modifier keys are inserted', function() {
// Go go hotkeys tab
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
// Set invalid modifier key: ctrl
cy.setNewHotkeyShortcutOnUserPreferencesModal('Zoom Out', '{ctrl}');
// Check error message
cy.get('.HotkeysPreferences').within(() => {
cy.contains('Zoom Out') // label we're looking for
.parent()
.find('.preferencesInputErrorMessage')
.as('errorMsg')
.should(
'have.text',
"It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut"
);
});
// Set invalid modifier key: shift
cy.setNewHotkeyShortcutOnUserPreferencesModal('Zoom Out', '{shift}');
// Check error message
cy.get('@errorMsg').should(
'have.text',
"It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut"
);
// Set invalid modifier key: alt
cy.setNewHotkeyShortcutOnUserPreferencesModal('Zoom Out', '{alt}');
// Check error message
cy.get('@errorMsg').should(
'have.text',
"It's not possible to define only modifier keys (ctrl, alt and shift) as a shortcut"
);
});
it('checks if user can cancel changes made on User Preferences Hotkeys tab', function() {
// Go go hotkeys tab
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
// Set new hotkey for 'Rotate Right' function
cy.setNewHotkeyShortcutOnUserPreferencesModal(
'Rotate Right',
'{ctrl}{shift}S'
);
// Close Success Message overlay (if displayed)
cy.get('body').then(body => {
if (body.find('.sb-closeIcon').length > 0) {
cy.get('.sb-closeIcon').click({ force: true });
}
//Cancel hotkeys
cy.get('@cancelBtn')
.scrollIntoView()
.click();
});
// Open User Preferences modal again
cy.openPreferences();
//Check that hotkey for 'Rotate Right' function was not changed
cy.get('.HotkeysPreferences').within(() => {
cy.contains('Rotate Right') // label we're looking for
.parent()
.find('input')
.should('have.value', 'r');
});
});
it('checks if user can reset to default values on User Preferences Hotkeys tab', function() {
// Go go hotkeys tab
cy.selectPreferencesTab('@userPreferencesHotkeysTab');
// Set new hotkey for 'Rotate Right' function
cy.setNewHotkeyShortcutOnUserPreferencesModal(
'Rotate Right',
'{ctrl}{shift}S'
);
// click on save button
cy.get('@saveBtn')
.scrollIntoView()
.click();
// Open User Preferences modal again
cy.openPreferences();
//Restore Default hotkeys
cy.get('@restoreBtn')
.scrollIntoView()
.click();
//Check that hotkey for 'Rotate Right' function was not changed
cy.get('.HotkeysPreferences').within(() => {
cy.contains('Rotate Right') // label we're looking for
.parent()
.find('input')
.should('have.value', 'r');
});
});
});
context('W/L Preset Preferences', function() {
before(() => {
cy.checkStudyRouteInViewer(
'1.2.840.113619.2.5.1762583153.215519.978957063.78'
);
cy.expectMinimumThumbnails(3);
});
beforeEach(() => {
cy.initCommonElementsAliases();
// Open User Preferences modal
cy.openPreferences();
// Navigate to Window Level tab
cy.selectPreferencesTab('@userPreferencesWindowLevelTab');
});
it('checks if W/L Preferences table is being displayed in the Window Level tab', function() {
//Check table header
cy.get('.wlRow.header')
.should('contains.text', 'Preset')
.and('contains.text', 'Description')
.and('contains.text', 'Window')
.and('contains.text', 'Level');
//Check table has more than 1 row (more than header)
cy.get('.wlRow')
.its('length')
.should('be.greaterThan', 1);
});
// //TODO: Test blocked by issue #1551: https://github.com/OHIF/Viewers/issues/1551
// it('checks if user can add a new W/L preset', function() {
// let description = ':nth-child(8) > .description > .preferencesInput';
// let window = ':nth-child(8) > .window > .preferencesInput';
// let level = ':nth-child(8) > .level > .preferencesInput';
// let new_window_value = 150;
// let new_level_value = -600;
// // Check existing preset values
// cy.get(description).should('have.value', '');
// cy.get(window).should('have.value', '');
// cy.get(level).should('have.value', '');
// // Set new preset value
// cy.setWindowLevelPreset(
// 7,
// 'New Description',
// new_window_value,
// new_level_value
// );
// cy.get('@saveBtn').click();
// // Open User Preferences modal
// cy.openPreferences();
// // Navigate to Window Level tab
// cy.selectPreferencesTab('@userPreferencesWindowLevelTab');
// // Check recently added preset values
// cy.get(description).should('have.value', 'New Description');
// cy.get(window).should('have.value', new_window_value);
// cy.get(level).should('have.value', new_level_value);
// // Close User Preferences modal
// cy.get('[data-cy="close-button"]').click();
// // Check if new hotkey preset is working on viewport
// cy.get('body').type('8');
// cy.get('@viewportInfoBottomRight').should(
// 'contains.text',
// 'W: ' + new_window_value + ' L: ' + new_level_value
// );
// });
it('checks if user can remove an existing W/L preset', function() {
let description = ':nth-child(3) > .description > .preferencesInput';
let window = ':nth-child(3) > .window > .preferencesInput';
let level = ':nth-child(3) > .level > .preferencesInput';
// Check existing preset values
cy.get(description)
.should('not.have.value', '')
.clear();
cy.get(window)
.should('not.have.value', '')
.clear();
cy.get(level)
.should('not.have.value', '')
.clear();
// Save changes
cy.get('@saveBtn').click();
// Open User Preferences modal
cy.openPreferences();
// Navigate to Window Level tab
cy.selectPreferencesTab('@userPreferencesWindowLevelTab');
// Check recently added preset values
cy.get(description).should('have.value', '');
cy.get(window).should('have.value', '');
cy.get(level).should('have.value', '');
// Close User Preferences modal
cy.get('[data-cy="close-button"]').click();
});
// //TODO: Test blocked by issue #1551: https://github.com/OHIF/Viewers/issues/1551
// it('checks if user can edit an existing W/L preset', function() {
// let description = ':nth-child(2) > .description > .preferencesInput';
// let window = ':nth-child(2) > .window > .preferencesInput';
// let level = ':nth-child(2) > .level > .preferencesInput';
// // Check existing preset values
// cy.get(description).should('have.value', 'Soft tissue');
// cy.get(window).should('have.value', '550');
// cy.get(level).should('have.value', '40');
// // Set new preset value
// cy.setWindowLevelPreset(1, 'Soft tissue New Description', 1220, 333);
// cy.get('@saveBtn').click();
// // Open User Preferences modal
// cy.openPreferences();
// // Navigate to Window Level tab
// cy.selectPreferencesTab('@userPreferencesWindowLevelTab');
// // Check recently added preset values
// cy.get(description).should('have.value', 'Soft tissue New Description');
// cy.get(window).should('have.value', '1220');
// cy.get(level).should('have.value', '333');
// });
it('checks if user can change the W/L by triggering different hotkeys with W/L presets', function() {
// Close User Preferences modal
cy.get('[data-cy="close-button"]').click();
// Check if hotkey preset is working on viewport
cy.get('body').type('3');
cy.get('@viewportInfoBottomRight').should(
'contains.text',
'W: 150 L: 90'
);
// Check if hotkey preset is working on viewport
cy.get('body').type('4');
cy.get('@viewportInfoBottomRight').should(
'contains.text',
'W: 2500 L: 480'
);
});
it('checks if user can change the W/L by triggering different hotkeys with W/L presets on multiple viewports', function() {
// Close User Preferences modal
cy.get('[data-cy="close-button"]').click();
// Set 3 viewports layout
cy.setLayout(3, 1);
cy.waitViewportImageLoading();
// Check if hotkey preset is working on viewport
cy.get('body').type('3');
cy.get('@viewportInfoBottomRight').should(
'contains.text',
'W: 150 L: 90'
);
// Overlay information from 2nd viewport
let second_viewport_overlay =
'div:nth-child(2) > div > div.viewport-element > div.ViewportOverlay > div.bottom-right.overlay-element > div';
// Shift active viewport to Viewport #2
cy.get('body').type('{rightarrow}');
// Check if hotkey preset is working on viewport #2
cy.get('body').type('4');
cy.get(second_viewport_overlay).should('contains.text', 'W: 2500 L: 480');
// Set 1 viewport layout
cy.setLayout(1, 1);
});
});
});*/

View File

@@ -0,0 +1,103 @@
describe('OHIF MPR', () => {
beforeEach(() => {
cy.checkStudyRouteInViewer('1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1');
cy.expectMinimumThumbnails(3);
cy.initCornerstoneToolsAliases();
cy.initCommonElementsAliases();
});
it('should not go MPR for non reconstructible displaySets', () => {
cy.get('[data-cy="MPR"]').should('have.class', 'ohif-disabled');
});
it('should go MPR for reconstructible displaySets and come back', () => {
cy.wait(250);
cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick();
cy.wait(250);
cy.get('[data-cy="MPR"]').click();
cy.get('.cornerstone-canvas').should('have.length', 3);
cy.get('[data-cy="MPR"]').click();
cy.get('.cornerstone-canvas').should('have.length', 1);
});
it('should render correctly the MPR', () => {
cy.wait(250);
cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick();
cy.wait(250);
cy.get('[data-cy="MPR"]').click();
cy.get('.cornerstone-canvas').should('have.length', 3);
// check cornerstone to see if each has images
// we can later do visual testing to match the images with a baseline
cy.window()
.its('cornerstone')
.then(cornerstone => {
const viewports = cornerstone.getRenderingEngines()[0].getViewports();
// The stack viewport still exists after the changes to viewportId and inde
const imageData1 = viewports[0].getImageData();
const imageData2 = viewports[1].getImageData();
const imageData3 = viewports[2].getImageData();
// for some reason map doesn't work here
cy.wrap(imageData1).should('not.be', undefined);
cy.wrap(imageData2).should('not.be', undefined);
cy.wrap(imageData3).should('not.be', undefined);
cy.wrap(imageData1.dimensions).should('deep.equal', imageData2.dimensions);
cy.wrap(imageData1.origin).should('deep.equal', imageData2.origin);
});
cy.get('[data-cy="MPR"]').click();
cy.get('.cornerstone-canvas').should('have.length', 1);
});
it('should correctly render Crosshairs for MPR', () => {
cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick();
cy.get('[data-cy="MPR"]').click();
cy.get('[data-cy="Crosshairs"]').click();
cy.wait(250);
// check cornerstone to see if each has crosshairs
// we can later do visual testing to match the images with a baseline
cy.window()
.its('cornerstoneTools')
.then(cornerstoneTools => {
const state = cornerstoneTools.annotation.state.getAnnotationManager();
const fORMap = state.annotations;
const fOR = Object.keys(fORMap)[0];
const fORAnnotation = fORMap[fOR];
// it should have crosshairs as the only key (references lines make this 2)
expect(Object.keys(fORAnnotation)).to.have.length(2);
const crosshairs = fORAnnotation.Crosshairs;
// it should have three
expect(crosshairs).to.have.length(3);
expect(crosshairs[0].data.handles.toolCenter).to.deep.equal(
crosshairs[1].data.handles.toolCenter
);
});
});
it('should activate window level when the active Crosshairs tool for MPR is clicked', () => {
cy.get('[data-cy="study-browser-thumbnail"][data-series="4"]').dblclick();
cy.get('[data-cy="MPR"]').click();
cy.get('[data-cy="Crosshairs"]').click();
// Click the crosshairs button to deactivate it.
cy.get('[data-cy="Crosshairs"]').click();
});
});