init
This commit is contained in:
92
platform/app/cypress/integration/ImageConsistency.spec.js
Normal file
92
platform/app/cypress/integration/ImageConsistency.spec.js
Normal 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);
|
||||
});
|
||||
});
|
||||
26
platform/app/cypress/integration/MultiStudy.spec.js
Normal file
26
platform/app/cypress/integration/MultiStudy.spec.js
Normal 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'));
|
||||
});
|
||||
});
|
||||
});
|
||||
9
platform/app/cypress/integration/OHIFPdfDisplay.spec.js
Normal file
9
platform/app/cypress/integration/OHIFPdfDisplay.spec.js
Normal 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);
|
||||
});
|
||||
});
|
||||
16
platform/app/cypress/integration/OHIFVideoDisplay.spec.js
Normal file
16
platform/app/cypress/integration/OHIFVideoDisplay.spec.js
Normal 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);
|
||||
});
|
||||
});
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
@@ -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');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
@@ -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');
|
||||
// });
|
||||
});
|
||||
@@ -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)');
|
||||
// });
|
||||
});
|
||||
@@ -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');
|
||||
});*/
|
||||
});
|
||||
@@ -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');
|
||||
});
|
||||
*/
|
||||
});
|
||||
@@ -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');
|
||||
});*/
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
});*/
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
*/
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});*/
|
||||
103
platform/app/cypress/integration/volume/MPR.spec.js
Normal file
103
platform/app/cypress/integration/volume/MPR.spec.js
Normal 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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user