test(contour): contour color change coverage (#6042)
This commit is contained in:
parent
419366bd25
commit
5955151ba1
@ -12,7 +12,7 @@ function ColorPickerDialog({ value, hide, onSave }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div data-cy="color-picker-dialog">
|
||||
<ChromePicker
|
||||
color={color}
|
||||
onChange={handleChange}
|
||||
@ -21,8 +21,14 @@ function ColorPickerDialog({ value, hide, onSave }) {
|
||||
/>
|
||||
<FooterAction>
|
||||
<FooterAction.Right>
|
||||
<FooterAction.Secondary onClick={hide}>Cancel</FooterAction.Secondary>
|
||||
<FooterAction.Secondary
|
||||
dataCY="color-picker-cancel-btn"
|
||||
onClick={hide}
|
||||
>
|
||||
Cancel
|
||||
</FooterAction.Secondary>
|
||||
<FooterAction.Primary
|
||||
dataCY="color-picker-save-btn"
|
||||
onClick={() => {
|
||||
hide();
|
||||
onSave(color);
|
||||
|
||||
@ -275,6 +275,7 @@ const DataRowComponent = React.forwardRef<HTMLDivElement, DataRowProps>(
|
||||
<span
|
||||
className="ml-2 h-2 w-2 rounded-full"
|
||||
style={{ backgroundColor: colorHex }}
|
||||
data-cy="data-row-colorhex"
|
||||
></span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
177
tests/ContourSegmentColorChange.spec.ts
Normal file
177
tests/ContourSegmentColorChange.spec.ts
Normal file
@ -0,0 +1,177 @@
|
||||
import {
|
||||
expect,
|
||||
test,
|
||||
visitStudy,
|
||||
waitForViewportsRendered,
|
||||
getSvgAttribute,
|
||||
} from './utils';
|
||||
|
||||
const NEW_HEX = '#FF00FF';
|
||||
const NEW_HEX_CSS_RGB = 'rgb(255, 0, 255)';
|
||||
const NEW_HEX_CSS_RGBA = 'rgba(255, 0, 255, 1)';
|
||||
|
||||
// Default colors baked into the RTSTRUCT in the canonical contour study.
|
||||
const THRESHOLD_CONTOUR_DEFAULT_HEX = '#00EBEB';
|
||||
const THRESHOLD_CONTOUR_DEFAULT_CSS_RGBA = 'rgba(0, 235, 235, 1)';
|
||||
const THRESHOLD_CONTOUR_DEFAULT_CSS_RGB = 'rgb(0, 235, 235)';
|
||||
|
||||
const STUDY_UID = '1.2.840.113619.2.290.3.3767434740.226.1600859119.501';
|
||||
|
||||
test.beforeEach(async ({ page, leftPanelPageObject, DOMOverlayPageObject }) => {
|
||||
await visitStudy(page, STUDY_UID, 'segmentation', 2000);
|
||||
|
||||
await leftPanelPageObject.loadSeriesByModality('RTSTRUCT');
|
||||
await waitForViewportsRendered(page);
|
||||
await expect(DOMOverlayPageObject.viewport.segmentationHydration.locator).toBeVisible();
|
||||
await DOMOverlayPageObject.viewport.segmentationHydration.yes.click();
|
||||
});
|
||||
|
||||
test('opens the color edit popup when "Change Color" is clicked', async ({
|
||||
rightPanelPageObject,
|
||||
DOMOverlayPageObject,
|
||||
}) => {
|
||||
const segment = rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(0);
|
||||
|
||||
await segment.actions.openChangeColor();
|
||||
|
||||
await expect(DOMOverlayPageObject.dialog.colorPicker.locator).toBeVisible();
|
||||
await expect(DOMOverlayPageObject.dialog.title).toHaveText('Segment Color');
|
||||
await expect(DOMOverlayPageObject.dialog.colorPicker.saveButton).toBeVisible();
|
||||
await expect(DOMOverlayPageObject.dialog.colorPicker.cancelButton).toBeVisible();
|
||||
|
||||
await expect(DOMOverlayPageObject.dialog.colorPicker.hexInput).toHaveValue(
|
||||
THRESHOLD_CONTOUR_DEFAULT_HEX
|
||||
);
|
||||
});
|
||||
|
||||
test('changes the contour color when the user saves the edits', async ({
|
||||
viewportPageObject,
|
||||
rightPanelPageObject,
|
||||
DOMOverlayPageObject,
|
||||
}) => {
|
||||
await rightPanelPageObject.contourSegmentationPanel.segmentsVisibilityToggle.click();
|
||||
const segment = rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(0);
|
||||
await segment.toggleVisibility();
|
||||
await segment.click();
|
||||
|
||||
await expect(segment.rowDataColorHex).toHaveCSS('background-color',THRESHOLD_CONTOUR_DEFAULT_CSS_RGB);
|
||||
|
||||
const svgStrokeAttributeBeforeColorChange = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'stroke',
|
||||
});
|
||||
|
||||
expect(svgStrokeAttributeBeforeColorChange, 'Expected SVG stroke attribute to be original threshold color').toBe(
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGBA
|
||||
);
|
||||
|
||||
// change color
|
||||
await segment.actions.changeColor(NEW_HEX);
|
||||
|
||||
await expect(DOMOverlayPageObject.dialog.colorPicker.locator).toBeHidden();
|
||||
await expect(segment.rowDataColorHex).toHaveCSS('background-color', NEW_HEX_CSS_RGB);
|
||||
|
||||
//check svg path stroke attribute is updated with new color
|
||||
const svgStrokeAttributeAfterColorChange = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'stroke',
|
||||
});
|
||||
|
||||
expect(svgStrokeAttributeAfterColorChange, 'Expected SVG stroke attribute to be updated with new color').toBe(
|
||||
NEW_HEX_CSS_RGBA
|
||||
);
|
||||
});
|
||||
|
||||
test('does not change the contour color when the user cancels', async ({
|
||||
rightPanelPageObject,
|
||||
DOMOverlayPageObject,
|
||||
viewportPageObject
|
||||
}) => {
|
||||
await rightPanelPageObject.contourSegmentationPanel.segmentsVisibilityToggle.click();
|
||||
const segment = rightPanelPageObject.contourSegmentationPanel.panel.nthSegment(0);
|
||||
await segment.toggleVisibility();
|
||||
await segment.click();
|
||||
|
||||
await expect(segment.rowDataColorHex).toHaveCSS(
|
||||
'background-color',
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGB
|
||||
);
|
||||
|
||||
const svgStrokeAttributeBeforeColorChange = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'stroke',
|
||||
});
|
||||
|
||||
expect(svgStrokeAttributeBeforeColorChange, 'Expected SVG stroke attribute to be original threshold color').toBe(
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGBA
|
||||
);
|
||||
|
||||
await segment.actions.cancelChangeColor(NEW_HEX);
|
||||
|
||||
await expect(DOMOverlayPageObject.dialog.colorPicker.locator).toBeHidden();
|
||||
await expect(segment.rowDataColorHex).toHaveCSS('background-color', THRESHOLD_CONTOUR_DEFAULT_CSS_RGB);
|
||||
|
||||
//check svg path stroke attribute is updated with new color
|
||||
const svgStrokeAttributeAfterColorChange = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'stroke',
|
||||
});
|
||||
|
||||
expect(svgStrokeAttributeAfterColorChange, 'Expected SVG stroke attribute to remain the original color').toBe(
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGBA
|
||||
);
|
||||
});
|
||||
|
||||
test('duplicated contour will be generated with a new color', async ({
|
||||
viewportPageObject,
|
||||
rightPanelPageObject,
|
||||
}) => {
|
||||
await rightPanelPageObject.contourSegmentationPanel.segmentsVisibilityToggle.click();
|
||||
const panel = rightPanelPageObject.contourSegmentationPanel.panel;
|
||||
const segment0 = panel.nthSegment(0);
|
||||
await segment0.toggleVisibility();
|
||||
await segment0.click();
|
||||
|
||||
await expect(segment0.rowDataColorHex).toHaveCSS(
|
||||
'background-color',
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGB
|
||||
);
|
||||
|
||||
const svgStrokeAttributeBeforeColorChange = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'stroke',
|
||||
});
|
||||
|
||||
expect(svgStrokeAttributeBeforeColorChange, 'Expected SVG stroke attribute to be original threshold color').toBe(
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGBA
|
||||
);
|
||||
|
||||
// duplicate the segment
|
||||
const initialCount = await panel.getSegmentCount();
|
||||
expect(initialCount, 'Expected to start with 4 segments').toBe(4);
|
||||
await segment0.actions.duplicate();
|
||||
await segment0.toggleVisibility(); // toggle original segment 0 visibility off to be able to grab the duplicated segment's path
|
||||
|
||||
const duplicateSegment = panel.nthSegment(4);
|
||||
await duplicateSegment.click();
|
||||
|
||||
const duplicatedSegmentSvgStrokeAttribute = await getSvgAttribute({
|
||||
viewportPageObject,
|
||||
svgInnerElement: 'path',
|
||||
attributeName: 'stroke',
|
||||
});
|
||||
|
||||
await expect(duplicateSegment.rowDataColorHex).not.toHaveCSS(
|
||||
'background-color',
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGB
|
||||
);
|
||||
|
||||
expect(duplicatedSegmentSvgStrokeAttribute, 'Expected duplicated segment to have a different stroke color').not.toBe(
|
||||
THRESHOLD_CONTOUR_DEFAULT_CSS_RGBA
|
||||
);
|
||||
});
|
||||
@ -60,6 +60,39 @@ export class DOMOverlayPageObject {
|
||||
return new DicomTagBrowserPageObject(page);
|
||||
},
|
||||
|
||||
get colorPicker() {
|
||||
const locator = page.getByTestId('color-picker-dialog');
|
||||
const hexInput = locator.getByLabel('hex');
|
||||
const saveButton = locator.getByTestId('color-picker-save-btn');
|
||||
const cancelButton = locator.getByTestId('color-picker-cancel-btn');
|
||||
return {
|
||||
locator,
|
||||
hexInput,
|
||||
saveButton,
|
||||
cancelButton,
|
||||
fillHex: async (hex: string) => {
|
||||
await hexInput.fill(hex);
|
||||
await hexInput.press('Enter');
|
||||
},
|
||||
save: async () => {
|
||||
await saveButton.click();
|
||||
},
|
||||
cancel: async () => {
|
||||
await cancelButton.click();
|
||||
},
|
||||
fillHexAndSave: async (hex: string) => {
|
||||
await hexInput.fill(hex);
|
||||
await hexInput.press('Enter');
|
||||
await saveButton.click();
|
||||
},
|
||||
fillHexAndCancel: async (hex: string) => {
|
||||
await hexInput.fill(hex);
|
||||
await hexInput.press('Enter');
|
||||
await cancelButton.click();
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
title: page.locator('[role="dialog"] h2'),
|
||||
};
|
||||
}
|
||||
|
||||
@ -73,6 +73,26 @@ export class RightPanelPageObject {
|
||||
await actionsButton.click();
|
||||
await this.page.getByTestId('Duplicate').click();
|
||||
},
|
||||
openChangeColor: async () => {
|
||||
await actionsButton.click();
|
||||
await this.page.getByTestId('Change Color').click();
|
||||
},
|
||||
changeColor: async (hex: string) => {
|
||||
await actionsButton.click();
|
||||
await this.page.getByTestId('Change Color').click();
|
||||
await this.DOMOverlayPageObject.dialog.colorPicker.fillHexAndSave(hex);
|
||||
},
|
||||
// This function assumes the user opens the change color dialog,
|
||||
// but then cancels out of it instead of saving a new color.
|
||||
cancelChangeColor: async (hex?: string) => {
|
||||
await actionsButton.click();
|
||||
await this.page.getByTestId('Change Color').click();
|
||||
if (hex) {
|
||||
await this.DOMOverlayPageObject.dialog.colorPicker.fillHexAndCancel(hex);
|
||||
} else {
|
||||
await this.DOMOverlayPageObject.dialog.colorPicker.cancel();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -86,6 +106,9 @@ export class RightPanelPageObject {
|
||||
get title() {
|
||||
return row.getByTestId('data-row-title');
|
||||
},
|
||||
get rowDataColorHex() {
|
||||
return row.getByTestId('data-row-colorhex');
|
||||
},
|
||||
click: async () => {
|
||||
await row.getByTestId('data-row-title').click();
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user