test: Visual testing for Cornerstone and VTK (#1169)

* Visual testing for Cornerstone and VTK

* Fix for CI

* Review fix: Removed cornerstone function and added snapshot description

* Added snapshot description

* Fix for CI
This commit is contained in:
Mirna Silva 2019-11-13 23:36:19 -03:00 committed by Danny Brown
parent d8055e458f
commit 79c10bb424
8 changed files with 207 additions and 70 deletions

View File

@ -46,8 +46,8 @@ describe('OHIF Cornerstone Hotkeys', () => {
// Hotkey I // Hotkey I
cy.get('body').type('I'); cy.get('body').type('I');
// Visual comparison // Visual comparison
cy.screenshot(); cy.screenshot('Hotkey I - Should Invert Image');
cy.percyCanvasSnapshot('Hotkey I - invert image'); cy.percyCanvasSnapshot('Hotkey I - Should Invert Image');
}); });
it('checks if hotkeys "+", "-" and "=" can zoom in, out and fit to viewport', () => { it('checks if hotkeys "+", "-" and "=" can zoom in, out and fit to viewport', () => {
@ -76,8 +76,8 @@ describe('OHIF Cornerstone Hotkeys', () => {
cy.get('@viewportInfoBottomRight').should('contains.text', 'Zoom: 211%'); cy.get('@viewportInfoBottomRight').should('contains.text', 'Zoom: 211%');
// Visual comparison to make sure the 'inverted' image was reset // Visual comparison to make sure the 'inverted' image was reset
cy.screenshot(); cy.screenshot('Hotkey SPACEBAR - Should Reset Image');
cy.percyCanvasSnapshot('Hotkey SPACEBAR - Reset Image'); cy.percyCanvasSnapshot('Hotkey SPACEBAR - Should Reset Image');
}); });
it('uses hotkeys "RightArrow" and "LeftArrow" to navigate between multiple viewports', () => { it('uses hotkeys "RightArrow" and "LeftArrow" to navigate between multiple viewports', () => {

View File

@ -2,7 +2,7 @@ describe('OHIF Cornerstone Toolbar', () => {
before(() => { before(() => {
cy.openStudy('MISTER^MR'); cy.openStudy('MISTER^MR');
cy.waitDicomImage(); cy.waitDicomImage();
cy.expectMinimumThumbnails(3); cy.expectMinimumThumbnails(5);
}); });
beforeEach(() => { beforeEach(() => {
@ -112,25 +112,14 @@ describe('OHIF Cornerstone Toolbar', () => {
cy.wrap($panBtn).should('have.class', 'active'); cy.wrap($panBtn).should('have.class', 'active');
}); });
//Get image position from cornerstone and check if y axis was modified
let cornerstone;
let currentPan;
cy.window()
.its('cornerstone')
.then(c => {
cornerstone = c;
currentPan = () =>
cornerstone.getEnabledElements()[0].viewport.translation;
});
cy.get('@viewport') cy.get('@viewport')
.trigger('mousedown', 'center', { which: 1 }) .trigger('mousedown', 'center', { which: 1 })
.trigger('mousemove', 'bottom', { which: 1 }) .trigger('mousemove', 'bottom', { which: 1 })
.trigger('mouseup', 'bottom') .trigger('mouseup', 'bottom');
.then(() => {
expect(currentPan().y > 0).to.eq(true); // Visual comparison
}); cy.screenshot('Pan tool moved the image inside the viewport');
cy.percyCanvasSnapshot('Pan tool moved the image inside the viewport');
}); });
it('checks if Length annotation can be added on viewport and on measurements panel', () => { it('checks if Length annotation can be added on viewport and on measurements panel', () => {
@ -312,18 +301,18 @@ describe('OHIF Cornerstone Toolbar', () => {
.find('td') .find('td')
.its('length') .its('length')
.should('be.eq', 9); .should('be.eq', 9);
cy.get('@layoutBtn').click();
}); });
//verify if layout has changed to 2 viewports //verify if layout has changed to 2 viewports
cy.get('tbody > :nth-child(1) > :nth-child(2)').click(); cy.setLayout(1, 2);
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
.should('be.eq', 2); .should('be.eq', 2);
}); });
cy.get('@layoutBtn').click(); cy.setLayout(2, 1);
cy.get('tbody > :nth-child(2) > :nth-child(1)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
@ -331,8 +320,7 @@ describe('OHIF Cornerstone Toolbar', () => {
}); });
//verify if layout has changed to 3 viewports //verify if layout has changed to 3 viewports
cy.get('@layoutBtn').click(); cy.setLayout(1, 3);
cy.get('tbody > :nth-child(1) > :nth-child(3)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wait(1000); cy.wait(1000);
cy.wrap($viewport) cy.wrap($viewport)
@ -340,8 +328,7 @@ describe('OHIF Cornerstone Toolbar', () => {
.should('be.eq', 3); .should('be.eq', 3);
}); });
cy.get('@layoutBtn').click(); cy.setLayout(3, 1);
cy.get('tbody > :nth-child(3) > :nth-child(1)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
@ -349,8 +336,7 @@ describe('OHIF Cornerstone Toolbar', () => {
}); });
//verify if layout has changed to 4 viewports //verify if layout has changed to 4 viewports
cy.get('@layoutBtn').click(); cy.setLayout(2, 2);
cy.get('tbody > :nth-child(2) > :nth-child(2)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
@ -358,16 +344,14 @@ describe('OHIF Cornerstone Toolbar', () => {
}); });
//verify if layout has changed to 6 viewports //verify if layout has changed to 6 viewports
cy.get('@layoutBtn').click(); cy.setLayout(2, 3);
cy.get('tbody > :nth-child(2) > :nth-child(3)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
.should('be.eq', 6); .should('be.eq', 6);
}); });
cy.get('@layoutBtn').click(); cy.setLayout(3, 2);
cy.get('tbody > :nth-child(3) > :nth-child(2)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
@ -375,8 +359,7 @@ describe('OHIF Cornerstone Toolbar', () => {
}); });
//verify if layout has changed to 9 viewports //verify if layout has changed to 9 viewports
cy.get('@layoutBtn').click(); cy.setLayout(3, 3);
cy.get('tbody > :nth-child(3) > :nth-child(3)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
@ -384,8 +367,7 @@ describe('OHIF Cornerstone Toolbar', () => {
}); });
//verify if layout has changed to 1 viewport //verify if layout has changed to 1 viewport
cy.get('@layoutBtn').click(); cy.setLayout(1, 1);
cy.get('tbody > :nth-child(1) > :nth-child(1)').click();
cy.get('.viewport-container').then($viewport => { cy.get('.viewport-container').then($viewport => {
cy.wrap($viewport) cy.wrap($viewport)
.its('length') .its('length')
@ -425,7 +407,9 @@ describe('OHIF Cornerstone Toolbar', () => {
.as('toolbarOverlay') .as('toolbarOverlay')
.should('be.visible'); .should('be.visible');
//Click on Clear button //Click on Clear button
cy.get('.tooltip-inner > :nth-child(10)').click(); cy.get('.tooltip-inner')
.contains('Clear')
.click();
//Verify if measurements were removed from the measurements panel //Verify if measurements were removed from the measurements panel
cy.get('.measurementItem').should('not.exist'); cy.get('.measurementItem').should('not.exist');
@ -457,8 +441,15 @@ describe('OHIF Cornerstone Toolbar', () => {
//Click More button //Click More button
cy.get('@moreBtn').click(); cy.get('@moreBtn').click();
//Verify if overlay is displayed
cy.get('.tooltip-toolbar-overlay')
.should('be.visible')
.then(() => {
//Click Eraser button //Click Eraser button
cy.get('.tooltip-inner > :nth-child(12)').click(); cy.get('.tooltip-inner')
.contains('Eraser')
.click({ force: true });
});
//Erase measurement #1 and Verify if it was removed from the measurements panel //Erase measurement #1 and Verify if it was removed from the measurements panel
const [x1, y1] = [150, 100]; const [x1, y1] = [150, 100];
@ -472,4 +463,70 @@ describe('OHIF Cornerstone Toolbar', () => {
cy.get('@viewport').click(x2, y2, { force: true }); cy.get('@viewport').click(x2, y2, { force: true });
cy.get('.measurementItem').should('not.exist'); cy.get('.measurementItem').should('not.exist');
}); });
it('check if Invert tool will change the colors of the image 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 Invert button
cy.get('.tooltip-inner')
.contains('Invert')
.click();
// Visual comparison
cy.screenshot('Invert tool - Should Invert Canvas');
cy.percyCanvasSnapshot('Invert tool - Should Invert Canvas');
});
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('.tooltip-inner')
.contains('Rotate')
.click({ force: true });
});
// Visual comparison
cy.screenshot('Rotate tool - Should Rotate Image to Right');
cy.percyCanvasSnapshot('Rotate tool - Should Rotate Image to Right');
});
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('.tooltip-inner')
.contains('Flip H')
.click();
// Visual comparison
cy.screenshot('Flip H tool - Should Flip Image on Y axis');
cy.percyCanvasSnapshot('Flip H tool - Should Flip Image on Y axis');
});
it('check if Flip V tool will flip the image vertically 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 V button
cy.get('.tooltip-inner')
.contains('Flip V')
.click();
// Visual comparison
cy.screenshot('Flip V tool - Should Flip Image on X axis');
cy.percyCanvasSnapshot('Flip V tool - Should Flip Image on X axis');
});
}); });

View File

@ -4,7 +4,7 @@ describe('OHIFStandaloneViewer', () => {
}); });
it('loads route with at least 2 rows', () => { it('loads route with at least 2 rows', () => {
cy.screenshot(); cy.screenshot('Study List');
cy.percyCanvasSnapshot('Study List'); cy.percyCanvasSnapshot('Study List');
cy.get('[data-cy="study-list-results"] tr') cy.get('[data-cy="study-list-results"] tr')

View File

@ -11,8 +11,8 @@ describe('OHIF Study Viewer Page', function() {
}); });
it('checks if series thumbnails are being displayed', function() { it('checks if series thumbnails are being displayed', function() {
cy.screenshot(); cy.screenshot('Series Thumbnails - Should Display Thumbnails');
cy.percyCanvasSnapshot('Series Thumbnails'); cy.percyCanvasSnapshot('Series Thumbnails - Should Display Thumbnails');
cy.get('[data-cy="thumbnail-list"]') cy.get('[data-cy="thumbnail-list"]')
.its('length') .its('length')
@ -291,6 +291,10 @@ describe('OHIF Study Viewer Page', function() {
}); });
}); });
// Visual comparison
cy.screenshot('About modal - Should display modal');
cy.percyCanvasSnapshot('About modal - Should display modal');
//close modal //close modal
cy.get('.close').click(); cy.get('.close').click();
cy.get('@aboutOverlay').should('not.be.enabled'); cy.get('@aboutOverlay').should('not.be.enabled');

View File

@ -21,6 +21,10 @@ describe('OHIF Microscopy Extension', () => {
.should('be.eq', 1); .should('be.eq', 1);
cy.wait(3000); //Waiting for image to render before taking the snapshot cy.wait(3000); //Waiting for image to render before taking the snapshot
cy.percyCanvasSnapshot('Microscopy Extension'); // Visual comparison
cy.screenshot('Microscopy Extension - Should display loaded canvas');
cy.percyCanvasSnapshot(
'Microscopy Extension - Should display loaded canvas'
);
}); });
}); });

View File

@ -22,6 +22,7 @@ describe('OHIF PDF Extension', () => {
// This won't work unless we switch to an extension that renders using `canvas` // This won't work unless we switch to an extension that renders using `canvas`
// Currently, we rely on the browser's built-in implementation // Currently, we rely on the browser's built-in implementation
cy.percyCanvasSnapshot('PDF Extension'); cy.screenshot('PDF Extension - Should load PDF file');
cy.percyCanvasSnapshot('PDF Extension - Should load PDF file');
}); });
}); });

View File

@ -6,37 +6,36 @@ describe('OHIF VTK Extension', () => {
}); });
beforeEach(() => { beforeEach(() => {
//TODO: Due to percy snapshot, the images inside the viewports are being resized
//and once the browser continues the test execution, the images are not centered in the viewport.
//To fix that, we need to reload the page before each test.
//https://github.com/OHIF/Viewers/issues/1168
cy.reload();
//Waiting for the desired thumbnail content to be displayed
cy.get('[data-cy="thumbnail-list"]').should($list => {
expect($list).to.contain('CT WB 5.0 B35f');
});
// TODO: We shouldn't have to drag the thumbnail // TODO: We shouldn't have to drag the thumbnail
// This is a known bug; 2D MPR button does not show until viewport // This is a known bug; 2D MPR button does not show until viewport
// has data from a drag-n-drop // has data from a drag-n-drop
// Drag and drop first thumbnail into first viewport // Drag and drop third thumbnail into first viewport
cy.get('[data-cy="thumbnail-list"]:nth-child(3)').drag( cy.get('[data-cy="thumbnail-list"]')
'.viewport-drop-target' .contains('CT WB 5.0 B35f')
); .drag('.viewport-drop-target')
.wait(1000); // TODO: Once issue #1167 is fixed, the wait command should be removed. (https://github.com/OHIF/Viewers/issues/1167)
cy.get('.PluginSwitch > .toolbar-button') //Select 2D MPR button
.as('twodmprBtn') cy.get('.PluginSwitch > .toolbar-button').click();
.should('be.visible')
.then(btn => { //Wait Reformatting Images
if (!btn.text().includes('Exit')) { cy.waitVTKReformatting();
btn.click();
}
});
cy.initVTKToolsAliases(); cy.initVTKToolsAliases();
}); });
it('checks if VTK buttons are displayed on the toolbar', () => { it('checks if VTK buttons are displayed on the toolbar', () => {
// Wait for start reformatting
cy.get('[data-cy="viewprt-grid"]', { timeout: 10000 }).should($grid => {
expect($grid).to.contain.text('Reform');
});
// Wait for finish reformatting
cy.get('[data-cy="viewprt-grid"]', { timeout: 30000 }).should($grid => {
expect($grid).not.to.contain.text('Reform');
});
cy.get('@crosshairsBtn') cy.get('@crosshairsBtn')
.should('be.visible') .should('be.visible')
.contains('Crosshairs'); .contains('Crosshairs');
@ -57,7 +56,67 @@ describe('OHIF VTK Extension', () => {
.should('be.visible') .should('be.visible')
.contains('Layout'); .contains('Layout');
cy.wait(3000); // Visual comparison
cy.percyCanvasSnapshot('VTK Extension'); cy.screenshot('VTK initial state - Should display toolbar and 3 viewports');
cy.percyCanvasSnapshot(
'VTK initial state - Should display toolbar and 3 viewports'
);
});
it('checks Crosshairs tool', () => {
cy.get('@crosshairsBtn').click();
// Click and Move the mouse inside the viewport
cy.get('[data-cy="viewport-container-0"]')
.trigger('mousedown', 'center', { which: 1 })
.trigger('mousemove', 'top', { which: 1 })
.trigger('mouseup');
// Visual comparison
cy.screenshot(
"VTK Crosshairs tool - Should display crosshairs' green lines"
);
cy.percyCanvasSnapshot(
"VTK Crosshairs tool - Should display crosshairs' green lines"
);
});
it('checks WWWC tool', () => {
cy.get('@wwwcBtn').click();
// Click and Move the mouse inside the viewport
cy.get('[data-cy="viewport-container-0"]')
.trigger('mousedown', 'center', { which: 1 })
.trigger('mousemove', 'top', { which: 1 })
.trigger('mousedown', 'center', { which: 1 })
.trigger('mousemove', 'top', { which: 1 })
.trigger('mouseup', { which: 1 })
.then(() => {
const expectedText = 'W: 350 L: -1044';
cy.get('.ViewportOverlay > div.bottom-right.overlay-element').should(
'contains.text',
expectedText
);
});
// Visual comparison
cy.screenshot('VTK WWWC tool - Canvas should be bright');
cy.percyCanvasSnapshot('VTK WWWC tool - Canvas should be bright');
});
it('checks Rotate tool', () => {
cy.get('@rotateBtn').click();
// Click and Move the mouse inside the viewport
cy.get('[data-cy="viewport-container-0"]')
.trigger('mousedown', 'center', { which: 1 })
.trigger('mousemove', 'top', { which: 1 })
.trigger('mousedown', 'center', { which: 1 })
.trigger('mousemove', 'top', { which: 1 })
.trigger('mouseup', { which: 1 });
// Visual comparison
cy.screenshot('VTK Rotate tool - Should rotate image');
cy.percyCanvasSnapshot('VTK Rotate tool - Should rotate image');
}); });
}); });

View File

@ -90,6 +90,18 @@ Cypress.Commands.add('waitStudyList', () => {
}); });
}); });
Cypress.Commands.add('waitVTKReformatting', () => {
// Wait for start reformatting
cy.get('[data-cy="viewprt-grid"]', { timeout: 10000 }).should($grid => {
expect($grid).to.contain.text('Reform');
});
// Wait for finish reformatting
cy.get('[data-cy="viewprt-grid"]', { timeout: 30000 }).should($grid => {
expect($grid).not.to.contain.text('Reform');
});
});
/** /**
* Command to perform a drag and drop action. Before using this command, we must get the element that should be dragged first. * Command to perform a drag and drop action. Before using this command, we must get the element that should be dragged first.
* Example of usage: cy.get(element-to-be-dragged).drag(dropzone-element) * Example of usage: cy.get(element-to-be-dragged).drag(dropzone-element)