chore(build): try to build demo and docs (#3434)
This commit is contained in:
1 parent
869b8ced05
commit
828690cd3b
329 files changed
+1896
-1010
No files matched your search
@@ -0,0 +1,78 @@
|
||||
const dataTransfer = new DataTransfer();
|
||||
|
||||
export const DragSimulator = {
|
||||
MAX_TRIES: 1,
|
||||
DELAY_INTERVAL_MS: 10,
|
||||
counter: 0,
|
||||
rectsEqual(r1, r2) {
|
||||
return (
|
||||
r1.top === r2.top &&
|
||||
r1.right === r2.right &&
|
||||
r1.bottom === r2.bottom &&
|
||||
r1.left === r2.left
|
||||
);
|
||||
},
|
||||
get dropped() {
|
||||
const currentSourcePosition = this.source.getBoundingClientRect();
|
||||
return !this.rectsEqual(
|
||||
this.initialSourcePosition,
|
||||
currentSourcePosition
|
||||
);
|
||||
},
|
||||
get hasTriesLeft() {
|
||||
return this.counter < this.MAX_TRIES;
|
||||
},
|
||||
dragstart() {
|
||||
cy.log('**DRAG START**');
|
||||
cy.wrap(this.source)
|
||||
.trigger('mousedown', { which: 1, button: 0 })
|
||||
.trigger('dragstart', { dataTransfer })
|
||||
.trigger('drag', {});
|
||||
},
|
||||
drop() {
|
||||
cy.log('**DROP**');
|
||||
return cy
|
||||
.wrap(this.target)
|
||||
.trigger('mousemove', 'center')
|
||||
.trigger('dragover', { dataTransfer, force: true })
|
||||
.trigger('drop', { dataTransfer, force: true })
|
||||
.trigger('dragend', { dataTransfer })
|
||||
.trigger('mouseup', { which: 1, button: 0 });
|
||||
},
|
||||
dragover() {
|
||||
cy.log('**DRAGOVER**');
|
||||
if (!this.dropped && this.hasTriesLeft) {
|
||||
this.counter += 1;
|
||||
return cy
|
||||
.wrap(this.target)
|
||||
.trigger('mousemove', 'center')
|
||||
.trigger('dragover', {
|
||||
dataTransfer,
|
||||
position: this.position,
|
||||
})
|
||||
.wait(this.DELAY_INTERVAL_MS)
|
||||
.then(() => this.dragover());
|
||||
}
|
||||
return this.drop().then(() => true);
|
||||
},
|
||||
init(source, target, position) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
this.position = position;
|
||||
this.counter = 0;
|
||||
|
||||
this.dragstart();
|
||||
|
||||
return cy.wait(this.DELAY_INTERVAL_MS).then(() => {
|
||||
this.initialSourcePosition = this.source.getBoundingClientRect();
|
||||
return this.dragover();
|
||||
});
|
||||
},
|
||||
simulate(sourceWrapper, targetSelector, position = 'center') {
|
||||
return cy
|
||||
.get(targetSelector)
|
||||
.then(targetWrapper =>
|
||||
this.init(sourceWrapper.get(0), targetWrapper.get(0), position)
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
//Creating aliases for Cornerstone tools buttons
|
||||
export function initCornerstoneToolsAliases() {
|
||||
cy.get('[data-cy="StackScroll"]').as('stackScrollBtn');
|
||||
cy.get('[data-cy="Zoom"]').as('zoomBtn');
|
||||
cy.get('[data-cy="WindowLevel-split-button-primary"]').as('wwwcBtnPrimary');
|
||||
cy.get('[data-cy="WindowLevel-split-button-secondary"]').as(
|
||||
'wwwcBtnSecondary'
|
||||
);
|
||||
cy.get('[data-cy="Pan"]').as('panBtn');
|
||||
cy.get('[data-cy="MeasurementTools-split-button-primary"]').as(
|
||||
'measurementToolsBtnPrimary'
|
||||
);
|
||||
cy.get('[data-cy="MeasurementTools-split-button-secondary"]').as(
|
||||
'measurementToolsBtnSecondary'
|
||||
);
|
||||
// cy.get('[data-cy="Angle"]').as('angleBtn');
|
||||
cy.get('[data-cy="MoreTools-split-button-primary"]').as('moreBtnPrimary');
|
||||
cy.get('[data-cy="MoreTools-split-button-secondary"]').as('moreBtnSecondary');
|
||||
cy.get('[data-cy="Layout"]').as('layoutBtn');
|
||||
cy.get('.cornerstone-viewport-element').as('viewport');
|
||||
cy.get('[data-cy="MPR"]').as('mprBtn');
|
||||
}
|
||||
|
||||
//Creating aliases for Common page elements
|
||||
export function initCommonElementsAliases() {
|
||||
cy.get('[data-cy="trackedMeasurements-btn"]').as('measurementsBtn');
|
||||
cy.get('.cornerstone-viewport-element').as('viewport');
|
||||
cy.get('[data-cy="seriesList-btn"]').as('seriesBtn');
|
||||
cy.get('[data-cy="side-panel-header-right"]').as('RightCollapseBtn');
|
||||
cy.get('[data-cy="side-panel-header-left"]').as('LeftCollapseBtn');
|
||||
|
||||
// click on the measurements button
|
||||
cy.get('[data-cy="trackedMeasurements-btn"]').click();
|
||||
|
||||
// TODO: Panels are not in DOM when closed, move this somewhere else
|
||||
cy.get('[data-cy="trackedMeasurements-panel"]').as('measurementsPanel');
|
||||
cy.get('[data-cy="studyBrowser-panel"]').as('seriesPanel');
|
||||
cy.get('[data-cy="viewport-overlay-top-right"]').as('viewportInfoTopRight');
|
||||
cy.get('[data-cy="viewport-overlay-top-left"]').as('viewportInfoTopLeft');
|
||||
cy.get('[data-cy="viewport-overlay-bottom-right"]').as(
|
||||
'viewportInfoBottomRight'
|
||||
);
|
||||
cy.get('[data-cy="viewport-overlay-bottom-left"]').as(
|
||||
'viewportInfoBottomLeft'
|
||||
);
|
||||
|
||||
cy.get('.left-mid.orientation-marker').as('viewportInfoMidLeft');
|
||||
cy.get('.top-mid.orientation-marker').as('viewportInfoMidTop');
|
||||
}
|
||||
|
||||
//Creating aliases for Routes
|
||||
export function initRouteAliases() {
|
||||
cy.intercept('GET', '**/series**', { statusCode: 200, body: [] }).as(
|
||||
'getStudySeries'
|
||||
);
|
||||
|
||||
// Todo: for some reason cypress does not redirect to the correct url
|
||||
// so we intercept the request and redirect it to the correct url
|
||||
cy.intercept('/studies?limit*', req => {
|
||||
const url = req.url.replace(/\/studies\?/, '/studies/?limit');
|
||||
req.url = url;
|
||||
});
|
||||
}
|
||||
|
||||
//Creating aliases for Study List page elements on Desktop experience
|
||||
export function initStudyListAliasesOnDesktop() {
|
||||
cy.get('[data-cy="num-studies"]').as('numStudies');
|
||||
cy.get('[data-cy="input-patientName"]').as('PatientName');
|
||||
cy.get('[data-cy="input-mrn"]').as('MRN');
|
||||
cy.get('[data-cy="input-accession"]').as('AccessionNumber');
|
||||
cy.get('[data-cy="input-description"]').as('StudyDescription');
|
||||
cy.get('[data-cy="study-list-results"]').as('searchResult');
|
||||
cy.get('[data-cy="study-list-results"] > tr').as('searchResult2');
|
||||
|
||||
// We can't use data attributes (e.g. data--cy) for these since
|
||||
// they are using third party libraires (i.e. react-dates, react-select)
|
||||
cy.get('#date-range-studyDate-start-date').as('studyListStartDate');
|
||||
cy.get('#date-range-studyDate-end-date').as('studyListEndDate');
|
||||
cy.get('#input-modalities').as('modalities');
|
||||
}
|
||||
|
||||
//Creating aliases for User Preferences modal
|
||||
export function initPreferencesModalAliases() {
|
||||
cy.get('.OHIFModal').as('preferencesModal');
|
||||
cy.get('[data-cy="hotkeys"]').as('userPreferencesHotkeysTab');
|
||||
cy.get('[data-cy="general"]').as('userPreferencesGeneralTab');
|
||||
cy.get('[data-cy="window-level"]').as('userPreferencesWindowLevelTab');
|
||||
initPreferencesModalFooterBtnAliases();
|
||||
}
|
||||
|
||||
//Creating aliases for User Preferences modal
|
||||
export function initPreferencesModalFooterBtnAliases() {
|
||||
cy.get('.active [data-cy="reset-default-btn"]').as('restoreBtn');
|
||||
cy.get('.active [data-cy="cancel-btn"]').as('cancelBtn');
|
||||
cy.get('.active [data-cy="save-btn"]').as('saveBtn');
|
||||
}
|
||||
@@ -0,0 +1,647 @@
|
||||
import '@percy/cypress';
|
||||
import 'cypress-file-upload';
|
||||
import { DragSimulator } from './DragSimulator.js';
|
||||
import {
|
||||
initCornerstoneToolsAliases,
|
||||
initCommonElementsAliases,
|
||||
initRouteAliases,
|
||||
initStudyListAliasesOnDesktop,
|
||||
initStudyListAliasesOnTablet,
|
||||
initPreferencesModalAliases,
|
||||
initPreferencesModalFooterBtnAliases,
|
||||
} from './aliases.js';
|
||||
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
|
||||
/**
|
||||
* Command to search for a patient name and open his/her study.
|
||||
*
|
||||
* @param {string} PatientName - Patient name that we would like to search for
|
||||
*/
|
||||
Cypress.Commands.add('openStudy', PatientName => {
|
||||
cy.openStudyList();
|
||||
cy.get('#filter-patientNameOrId').type(PatientName);
|
||||
// cy.get('@getStudies').then(() => {
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('[data-cy="study-list-results"]', { timeout: 5000 })
|
||||
.contains(PatientName)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'checkStudyRouteInViewer',
|
||||
(StudyInstanceUID, otherParams = '') => {
|
||||
cy.location('pathname').then($url => {
|
||||
cy.log($url);
|
||||
if (
|
||||
$url == 'blank' ||
|
||||
!$url.includes(`/basic-test/${StudyInstanceUID}${otherParams}`)
|
||||
) {
|
||||
cy.openStudyInViewer(StudyInstanceUID, otherParams);
|
||||
cy.waitDicomImage();
|
||||
cy.wait(2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
'openStudyInViewer',
|
||||
(StudyInstanceUID, otherParams = '') => {
|
||||
cy.visit(`/basic-test?StudyInstanceUIDs=${StudyInstanceUID}${otherParams}`);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Command to search for a Modality and open the study.
|
||||
*
|
||||
* @param {string} Modality - Modality type that we would like to search for
|
||||
*/
|
||||
Cypress.Commands.add('openStudyModality', Modality => {
|
||||
cy.initRouteAliases();
|
||||
cy.visit('/');
|
||||
|
||||
cy.get('#filter-accessionOrModalityOrDescription')
|
||||
.type(Modality)
|
||||
.wait(2000);
|
||||
|
||||
cy.get('[data-cy="study-list-results"]')
|
||||
.contains(Modality)
|
||||
.first()
|
||||
.click();
|
||||
});
|
||||
|
||||
/**
|
||||
* Command to wait and check if a new page was loaded
|
||||
*
|
||||
* @param {string} url - part of the expected url. Default value is /basic-test
|
||||
*/
|
||||
Cypress.Commands.add('isPageLoaded', (url = '/basic-test') => {
|
||||
return cy.location('pathname', { timeout: 60000 }).should('include', url);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('openStudyList', () => {
|
||||
cy.initRouteAliases();
|
||||
cy.visit('/');
|
||||
|
||||
// For some reason cypress 12.x does not like to stub the network request
|
||||
// so we just wait herer for 1 second
|
||||
// cy.wait('@getStudies');
|
||||
cy.wait(1000);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitStudyList', () => {
|
||||
cy.get('@searchResult').should($list => {
|
||||
expect($list).to.not.have.class('no-hover');
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitViewportImageLoading', () => {
|
||||
// Wait for finish loading
|
||||
cy.get('[data-cy="viewprt-grid"]', { timeout: 30000 }).should($grid => {
|
||||
expect($grid).not.to.contain.text('Load');
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*
|
||||
* @param {*} element - Selector for element that we want to use as dropzone
|
||||
*/
|
||||
Cypress.Commands.add('drag', { prevSubject: 'element' }, (...args) =>
|
||||
DragSimulator.simulate(...args)
|
||||
);
|
||||
|
||||
/**
|
||||
* Command to perform two clicks into two different positions. Each position must be [x, y].
|
||||
* The positions are considering the element as reference, therefore, top-left of the element will be (0, 0).
|
||||
*
|
||||
* @param {*} viewport - Selector for viewport we would like to interact with
|
||||
* @param {number[]} firstClick - Click position [x, y]
|
||||
* @param {number[]} secondClick - Click position [x, y]
|
||||
*/
|
||||
Cypress.Commands.add('addLine', (viewport, firstClick, secondClick) => {
|
||||
cy.get(viewport).then($viewport => {
|
||||
const [x1, y1] = firstClick;
|
||||
const [x2, y2] = secondClick;
|
||||
|
||||
// TODO: Added a wait which appears necessary in Cornerstone Tools >4?
|
||||
cy.wrap($viewport)
|
||||
.click(x1, y1)
|
||||
.wait(100)
|
||||
.trigger('mousemove', { clientX: x2, clientY: y2 })
|
||||
.click(x2, y2)
|
||||
.wait(100);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Command to perform three clicks into three different positions. Each position must be [x, y].
|
||||
* The positions are considering the element as reference, therefore, top-left of the element will be (0, 0).
|
||||
*
|
||||
* @param {*} viewport - Selector for viewport we would like to interact with
|
||||
* @param {number[]} firstClick - Click position [x, y]
|
||||
* @param {number[]} secondClick - Click position [x, y]
|
||||
* @param {number[]} thirdClick - Click position [x, y]
|
||||
*/
|
||||
Cypress.Commands.add(
|
||||
'addAngle',
|
||||
(viewport, firstClick, secondClick, thirdClick) => {
|
||||
cy.get(viewport).then($viewport => {
|
||||
const [x1, y1] = firstClick;
|
||||
const [x2, y2] = secondClick;
|
||||
const [x3, y3] = thirdClick;
|
||||
|
||||
cy.wrap($viewport)
|
||||
.click(x1, y1, { force: true })
|
||||
.trigger('mousemove', { clientX: x2, clientY: y2 })
|
||||
.click(x2, y2, { force: true })
|
||||
.trigger('mousemove', { clientX: x3, clientY: y3 })
|
||||
.click(x3, y3, { force: true });
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('expectMinimumThumbnails', (seriesToWait = 1) => {
|
||||
cy.get('[data-cy="study-browser-thumbnail"]', { timeout: 50000 }).should(
|
||||
$itemList => {
|
||||
expect($itemList.length >= seriesToWait).to.be.true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
//Command to wait DICOM image to load into the viewport
|
||||
Cypress.Commands.add('waitDicomImage', (timeout = 50000) => {
|
||||
const loaded = cy.isPageLoaded();
|
||||
|
||||
if (loaded) {
|
||||
cy.window()
|
||||
.its('cornerstone')
|
||||
.then({ timeout }, $cornerstone => {
|
||||
return new Cypress.Promise(resolve => {
|
||||
const onEvent = renderedEvt => {
|
||||
const element = renderedEvt.detail.element;
|
||||
|
||||
element.removeEventListener(
|
||||
$cornerstone.Enums.Events.IMAGE_RENDERED,
|
||||
onEvent
|
||||
);
|
||||
$cornerstone.eventTarget.removeEventListener(
|
||||
$cornerstone.Enums.Events.IMAGE_RENDERED,
|
||||
onEvent
|
||||
);
|
||||
resolve();
|
||||
};
|
||||
const onEnabled = enabledEvt => {
|
||||
const element = enabledEvt.detail.element;
|
||||
|
||||
element.addEventListener(
|
||||
$cornerstone.Enums.Events.IMAGE_RENDERED,
|
||||
onEvent
|
||||
);
|
||||
|
||||
$cornerstone.eventTarget.removeEventListener(
|
||||
$cornerstone.Enums.Events.ELEMENT_ENABLED,
|
||||
onEnabled
|
||||
);
|
||||
};
|
||||
const enabledElements = $cornerstone.getEnabledElements();
|
||||
if (enabledElements && enabledElements.length) {
|
||||
// Sometimes the page finishes rendering before this gets run,
|
||||
// if so, just resolve immediately.
|
||||
resolve();
|
||||
} else {
|
||||
$cornerstone.eventTarget.addEventListener(
|
||||
$cornerstone.Enums.Events.ELEMENT_ENABLED,
|
||||
onEnabled
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//Command to reset and clear all the changes made to the viewport
|
||||
Cypress.Commands.add('resetViewport', () => {
|
||||
//Click on More button
|
||||
cy.get('[data-cy="MoreTools-split-button-primary"]')
|
||||
.should('have.attr', 'data-tool', 'Reset')
|
||||
.as('moreBtn')
|
||||
.click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('imageZoomIn', () => {
|
||||
cy.initCornerstoneToolsAliases();
|
||||
cy.get('@zoomBtn').click();
|
||||
|
||||
//drags the mouse inside the viewport to be able to interact with series
|
||||
cy.get('@viewport')
|
||||
.trigger('mousedown', 'top', { buttons: 1 })
|
||||
.trigger('mousemove', 'center', { buttons: 1 })
|
||||
.trigger('mouseup');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('imageContrast', () => {
|
||||
cy.initCornerstoneToolsAliases();
|
||||
cy.get('@wwwcBtnPrimary').click();
|
||||
|
||||
//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');
|
||||
});
|
||||
|
||||
//Initialize aliases for Cornerstone tools buttons
|
||||
Cypress.Commands.add('initCornerstoneToolsAliases', () => {
|
||||
initCornerstoneToolsAliases();
|
||||
});
|
||||
|
||||
//Initialize aliases for Common page elements
|
||||
Cypress.Commands.add('initCommonElementsAliases', () => {
|
||||
initCommonElementsAliases();
|
||||
});
|
||||
|
||||
//Initialize aliases for Routes
|
||||
Cypress.Commands.add('initRouteAliases', () => {
|
||||
initRouteAliases();
|
||||
});
|
||||
|
||||
//Initialize aliases for Study List page elements
|
||||
Cypress.Commands.add('initStudyListAliasesOnDesktop', () => {
|
||||
initStudyListAliasesOnDesktop();
|
||||
});
|
||||
|
||||
//Add measurements in the viewport
|
||||
Cypress.Commands.add(
|
||||
'addLengthMeasurement',
|
||||
(firstClick = [150, 100], secondClick = [130, 170]) => {
|
||||
cy.get('@measurementToolsBtnPrimary')
|
||||
.should('have.attr', 'data-tool', 'Length')
|
||||
.click()
|
||||
.then($lengthBtn => {
|
||||
cy.wrap($lengthBtn).should('have.class', 'active');
|
||||
});
|
||||
|
||||
cy.addLine('.viewport-element', firstClick, secondClick);
|
||||
}
|
||||
);
|
||||
|
||||
//Add measurements in the viewport
|
||||
Cypress.Commands.add(
|
||||
'addAngleMeasurement',
|
||||
(initPos = [180, 390], midPos = [300, 410], finalPos = [180, 450]) => {
|
||||
cy.get('[data-cy="Angle"]').click();
|
||||
cy.addAngle('.viewport-element', initPos, midPos, finalPos);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Tests if element is NOT in viewport, or does not exist in DOM
|
||||
*
|
||||
* @param {string} element - element selector string or alias
|
||||
* @returns
|
||||
*/
|
||||
Cypress.Commands.add('isNotInViewport', element => {
|
||||
cy.get(element, { timeout: 3000 }).should($el => {
|
||||
const bottom = Cypress.$(cy.state('window')).height() - 50;
|
||||
const right = Cypress.$(cy.state('window')).width() - 50;
|
||||
|
||||
// If it's not visible, it's not in the viewport
|
||||
if ($el) {
|
||||
const rect = $el[0].getBoundingClientRect();
|
||||
|
||||
// TODO: support leftOf, above
|
||||
const isBeneath = rect.top >= bottom && rect.bottom >= bottom;
|
||||
const isRightOf = rect.left >= right && rect.right >= right;
|
||||
const isNotInViewport = isBeneath && isRightOf;
|
||||
|
||||
expect(isNotInViewport).to.be.true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests if element is in viewport, or it does exist in DOM
|
||||
*
|
||||
* @param {string} element - element selector string or alias
|
||||
* @returns
|
||||
*/
|
||||
Cypress.Commands.add('isInViewport', element => {
|
||||
cy.get(element, { timeout: 3000 }).should($el => {
|
||||
const bottom = Cypress.$(cy.state('window')).height();
|
||||
const right = Cypress.$(cy.state('window')).width();
|
||||
|
||||
// If it's not visible, it's not in the viewport
|
||||
if ($el) {
|
||||
const rect = $el[0].getBoundingClientRect();
|
||||
|
||||
// TODO: support leftOf, above
|
||||
const isBeneath = rect.top < bottom && rect.bottom < bottom;
|
||||
const isRightOf = rect.left < right && rect.right < right;
|
||||
const isInViewport = isBeneath && isRightOf;
|
||||
|
||||
expect(isInViewport).to.be.true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Percy.io Canvas screenshot workaround
|
||||
*
|
||||
*/
|
||||
Cypress.Commands.add('percyCanvasSnapshot', (name, options = {}) => {
|
||||
cy.document().then(doc => {
|
||||
convertCanvas(doc);
|
||||
});
|
||||
|
||||
// `domTransformation` does not appear to be working
|
||||
// But modifying our immediate DOM does.
|
||||
cy.percySnapshot(name, { ...options }); //, domTransformation: convertCanvas });
|
||||
|
||||
cy.document().then(doc => {
|
||||
unconvertCanvas(doc);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('setLayout', (columns = 1, rows = 1) => {
|
||||
cy.get('[data-cy="layout"]').click();
|
||||
|
||||
cy.get('.layoutChooser')
|
||||
.find('tr')
|
||||
.eq(rows - 1)
|
||||
.find('td')
|
||||
.eq(columns - 1)
|
||||
.click();
|
||||
|
||||
cy.wait(1000);
|
||||
});
|
||||
|
||||
function convertCanvas(documentClone) {
|
||||
documentClone
|
||||
.querySelectorAll('canvas')
|
||||
.forEach(selector => canvasToImage(selector));
|
||||
|
||||
return documentClone;
|
||||
}
|
||||
|
||||
function unconvertCanvas(documentClone) {
|
||||
// Remove previously generated images
|
||||
documentClone
|
||||
.querySelectorAll('[data-percy-image]')
|
||||
.forEach(selector => selector.remove());
|
||||
// Restore canvas visibility
|
||||
documentClone.querySelectorAll('[data-percy-canvas]').forEach(selector => {
|
||||
selector.removeAttribute('data-percy-canvas');
|
||||
selector.style = '';
|
||||
});
|
||||
}
|
||||
|
||||
function canvasToImage(selectorOrEl) {
|
||||
let canvas =
|
||||
typeof selectorOrEl === 'object'
|
||||
? selectorOrEl
|
||||
: document.querySelector(selectorOrEl);
|
||||
let image = document.createElement('img');
|
||||
let canvasImageBase64 = canvas.toDataURL('image/png');
|
||||
|
||||
// Show Image
|
||||
image.src = canvasImageBase64;
|
||||
image.style = 'width: 100%';
|
||||
image.setAttribute('data-percy-image', true);
|
||||
// Hide Canvas
|
||||
canvas.setAttribute('data-percy-canvas', true);
|
||||
canvas.parentElement.appendChild(image);
|
||||
canvas.style = 'display: none';
|
||||
}
|
||||
|
||||
//Initialize aliases for User Preferences modal
|
||||
Cypress.Commands.add('initPreferencesModalAliases', () => {
|
||||
initPreferencesModalAliases();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('openPreferences', () => {
|
||||
cy.log('Open User Preferences Modal');
|
||||
// Open User Preferences modal
|
||||
cy.get('body').then(body => {
|
||||
if (body.find('.OHIFModal').length === 0) {
|
||||
cy.get('[data-cy="options-chevron-down-icon"]')
|
||||
.scrollIntoView()
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.get('[data-cy="options-dropdown"]')
|
||||
.last()
|
||||
.click()
|
||||
.wait(200);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('scrollToIndex', index => {
|
||||
// Workaround implemented based on Cypress issue:
|
||||
// https://github.com/cypress-io/cypress/issues/1570#issuecomment-450966053
|
||||
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
|
||||
window.HTMLInputElement.prototype,
|
||||
'value'
|
||||
).set;
|
||||
|
||||
cy.get('input.imageSlider[type=range]').then($range => {
|
||||
// get the DOM node
|
||||
const range = $range[0];
|
||||
// set the value manually
|
||||
nativeInputValueSetter.call(range, index);
|
||||
// now dispatch the event
|
||||
range.dispatchEvent(
|
||||
new Event('change', {
|
||||
value: index,
|
||||
bubbles: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('closePreferences', () => {
|
||||
cy.log('Close User Preferences Modal');
|
||||
|
||||
cy.get('body').then(body => {
|
||||
// Close notification if displayed
|
||||
if (body.find('.sb-closeIcon').length > 0) {
|
||||
cy.get('.sb-closeIcon')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
}
|
||||
|
||||
// Close User Preferences Modal (if displayed)
|
||||
if (body.find('.OHIFModal__header').length > 0) {
|
||||
cy.get('[data-cy="close-button"]').click({ force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('selectPreferencesTab', tabAlias => {
|
||||
cy.initPreferencesModalAliases();
|
||||
cy.get(tabAlias)
|
||||
.click()
|
||||
.should('have.class', 'active');
|
||||
initPreferencesModalFooterBtnAliases();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('resetUserHotkeyPreferences', () => {
|
||||
// Open User Preferences modal
|
||||
cy.openPreferences();
|
||||
|
||||
cy.selectPreferencesTab('@userPreferencesHotkeysTab').then(() => {
|
||||
cy.log('Reset Hotkeys to Default Preferences');
|
||||
cy.get('@restoreBtn').click();
|
||||
});
|
||||
|
||||
// Close Success Message overlay (if displayed)
|
||||
cy.get('body').then(body => {
|
||||
if (body.find('.sb-closeIcon').length > 0) {
|
||||
cy.get('.sb-closeIcon')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
}
|
||||
// Click on Save Button
|
||||
cy.get('@saveBtn').click();
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('resetUserGeneralPreferences', () => {
|
||||
// Open User Preferences modal
|
||||
cy.openPreferences();
|
||||
|
||||
cy.selectPreferencesTab('@userPreferencesGeneralTab').then(() => {
|
||||
cy.log('Reset Language to Default Preferences');
|
||||
cy.get('@restoreBtn').click();
|
||||
});
|
||||
|
||||
// Close Success Message overlay (if displayed)
|
||||
cy.get('body').then(body => {
|
||||
if (body.find('.sb-closeIcon').length > 0) {
|
||||
cy.get('.sb-closeIcon')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
}
|
||||
// Click on Save Button
|
||||
cy.get('@saveBtn').click();
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'setNewHotkeyShortcutOnUserPreferencesModal',
|
||||
(function_label, shortcut) => {
|
||||
// Within scopes all `.get` and `.contains` to within the matched elements
|
||||
// dom instead of checking from document
|
||||
cy.get('.HotkeysPreferences').within(() => {
|
||||
cy.contains(function_label) // label we're looking for
|
||||
.parent()
|
||||
.find('input') // closest input to that label
|
||||
.type(shortcut, { force: true }); // Set new shortcut for that function
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
'setWindowLevelPreset',
|
||||
(preset_index, description_value, window_value, level_value) => {
|
||||
let index = parseInt(preset_index) + 1;
|
||||
|
||||
// Set new Description value
|
||||
cy.get(':nth-child(' + index + ') > .description > .preferencesInput')
|
||||
.clear()
|
||||
.type(description_value, {
|
||||
force: true,
|
||||
})
|
||||
.blur();
|
||||
|
||||
// Set new Window value
|
||||
cy.get(':nth-child(' + index + ') > .window > .preferencesInput')
|
||||
.clear()
|
||||
.type(window_value, {
|
||||
force: true,
|
||||
})
|
||||
.blur();
|
||||
|
||||
// Set new Level value
|
||||
cy.get(':nth-child(' + index + ') > .level > .preferencesInput')
|
||||
.clear()
|
||||
.type(level_value, {
|
||||
force: true,
|
||||
})
|
||||
.blur();
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('openDownloadImageModal', () => {
|
||||
// Click on More button
|
||||
cy.get('[data-cy="Capture"]')
|
||||
.as('captureBtn')
|
||||
.click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('setLanguage', (language, save = true) => {
|
||||
cy.openPreferences();
|
||||
cy.initPreferencesModalAliases();
|
||||
cy.selectPreferencesTab('@userPreferencesGeneralTab');
|
||||
|
||||
// Language dropdown should be displayed
|
||||
cy.get('#language-select').should('be.visible');
|
||||
|
||||
// Select Language and Save/Cancel
|
||||
cy.get('#language-select').select(language);
|
||||
|
||||
// Close Success Message overlay (if displayed)
|
||||
cy.get('body').then(body => {
|
||||
if (body.find('.sb-closeIcon').length > 0) {
|
||||
cy.get('.sb-closeIcon')
|
||||
.first()
|
||||
.click({ force: true });
|
||||
}
|
||||
|
||||
//Click on Save/Cancel button
|
||||
const toClick = save ? '@saveBtn' : '@cancelBtn';
|
||||
cy.get(toClick)
|
||||
.scrollIntoView()
|
||||
.click();
|
||||
});
|
||||
});
|
||||
|
||||
// hide noisy logs
|
||||
// https://github.com/cypress-io/cypress/issues/7362
|
||||
// uncomment this if you really need the network logs
|
||||
const origLog = Cypress.log;
|
||||
Cypress.log = function(opts, ...other) {
|
||||
if (opts.displayName === 'script' || opts.name === 'request') {
|
||||
return;
|
||||
}
|
||||
return origLog(opts, ...other);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
import './aliases.js';
|
||||
import './commands.js';
|
||||
Reference in new issue
Block a user