Skip to content

Commit 3984841

Browse files
authored
Click/drag zooming for QC plots (#1209)
1 parent 411e655 commit 3984841

5 files changed

Lines changed: 416 additions & 3 deletions

File tree

test/src/org/labkey/test/components/targetedms/QCPlotsWebPart.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,36 @@ public String toString()
904904
}
905905
}
906906

907+
public void performYAxisZoom(QCPlot qcPlot)
908+
{
909+
WebElement plotEl = qcPlot.getPlot();
910+
WebElement overlay = elementCache().yZoomOverlay.findElement(plotEl);
911+
getWrapper().scrollIntoView(overlay);
912+
913+
int clickOffset = 40;
914+
new Actions(getWrapper().getDriver())
915+
.moveToElement(overlay, 0, -clickOffset)
916+
.click()
917+
.moveToElement(overlay, 0, clickOffset)
918+
.click()
919+
.perform();
920+
921+
WebDriverWrapper.waitFor(() -> !elementCache().yZoomConfirmBtn.findElements(plotEl).isEmpty(),
922+
"Zoom buttons did not appear after y-axis clicks", WAIT_FOR_JAVASCRIPT);
923+
924+
elementCache().yZoomConfirmBtn.findElement(plotEl).click();
925+
}
926+
927+
public boolean isZoomActive(QCPlot qcPlot)
928+
{
929+
return !elementCache().yZoomBorder.findElements(qcPlot.getPlot()).isEmpty();
930+
}
931+
932+
public void clickResetZoom(QCPlot qcPlot)
933+
{
934+
elementCache().yZoomOverlay.findElement(qcPlot.getPlot()).click();
935+
}
936+
907937
public class Elements extends BodyWebPart<?>.ElementCache
908938
{
909939
WebElement startDate = Locator.css("#start-date-field input").findWhenNeeded(this);
@@ -939,6 +969,9 @@ public class Elements extends BodyWebPart<?>.ElementCache
939969
WebElement plotPanel = Locator.css("div.tiledPlotPanel").findWhenNeeded(this);
940970
WebElement paginationPanel = Locator.css("div.plotPaginationHeaderPanel").findWhenNeeded(this);
941971
Locator extFormDisplay = Locator.css("div.x4-form-display-field");
972+
Locator.CssLocator yZoomOverlay = Locator.css("svg rect.y-zoom-overlay");
973+
Locator.CssLocator yZoomConfirmBtn = Locator.css("svg g.y-zoom-btn-zoom rect");
974+
Locator.CssLocator yZoomBorder = Locator.css("svg rect.y-zoom-border");
942975
Locator.CssLocator guideSetTrainingRect = Locator.css("svg rect.training");
943976
Locator.CssLocator experimentRangeRect = Locator.css("svg rect.expRange");
944977
Locator.CssLocator guideSetSvgButton = Locator.css("svg g.guideset-svg-button text");

test/src/org/labkey/test/tests/targetedms/TargetedMSQCTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,56 @@ private void verifyRow(DataRegionTable drt, int row, String sampleName, String s
11481148
assertEquals(skylineDocName, drt.getDataAsText(row, "File"));
11491149
}
11501150

1151+
@Test
1152+
public void testQCPlotYAxisZoom()
1153+
{
1154+
PanoramaDashboard qcDashboard = new PanoramaDashboard(this);
1155+
QCPlotsWebPart qcPlotsWebPart = qcDashboard.getQcPlotsWebPart();
1156+
qcPlotsWebPart.filterQCPlotsToInitialData(PRECURSORS.length, true);
1157+
1158+
List<QCPlot> plots = qcPlotsWebPart.getPlots();
1159+
assertTrue("Expected at least 2 plots for y-axis zoom test", plots.size() >= 2);
1160+
1161+
// 1. Verify zooming is possible: drag on y-axis, confirm zoom, border appears
1162+
log("Verifying y-axis zoom can be applied");
1163+
qcPlotsWebPart.performYAxisZoom(plots.get(0));
1164+
waitForElement(Locator.css("svg rect.y-zoom-border"), WAIT_FOR_JAVASCRIPT);
1165+
1166+
plots = qcPlotsWebPart.getPlots();
1167+
QCPlot firstPlot = plots.get(0);
1168+
QCPlot secondPlot = plots.get(1);
1169+
1170+
assertTrue("Zoom border should appear on first plot after zoom", qcPlotsWebPart.isZoomActive(firstPlot));
1171+
1172+
// 2. Verify zoom is per-plot: second plot is unaffected
1173+
log("Verifying zoom is independent per plot");
1174+
assertFalse("Second plot should not be zoomed", qcPlotsWebPart.isZoomActive(secondPlot));
1175+
1176+
// 3. Verify reset works: clicking the zoomed y-axis (zoom-out cursor) resets zoom
1177+
log("Verifying clicking the y-axis resets zoom on the target plot");
1178+
qcPlotsWebPart.clickResetZoom(firstPlot);
1179+
waitForElementToDisappear(Locator.css("svg rect.y-zoom-border"), WAIT_FOR_JAVASCRIPT);
1180+
1181+
plots = qcPlotsWebPart.getPlots();
1182+
firstPlot = plots.get(0);
1183+
1184+
assertFalse("Zoom border should be gone after reset", qcPlotsWebPart.isZoomActive(firstPlot));
1185+
1186+
// 4. Verify zoom is not persisted after page reload
1187+
log("Verifying zoom state is cleared on page reload");
1188+
qcPlotsWebPart.performYAxisZoom(firstPlot);
1189+
waitForElement(Locator.css("svg rect.y-zoom-border"), WAIT_FOR_JAVASCRIPT);
1190+
1191+
refresh();
1192+
qcDashboard = new PanoramaDashboard(this);
1193+
qcPlotsWebPart = qcDashboard.getQcPlotsWebPart();
1194+
1195+
plots = qcPlotsWebPart.getPlots();
1196+
firstPlot = plots.get(0);
1197+
1198+
assertFalse("Zoom should not persist after page reload", qcPlotsWebPart.isZoomActive(firstPlot));
1199+
}
1200+
11511201
private void createAndInsertAnnotations()
11521202
{
11531203
clickTab("Annotations");

webapp/TargetedMS/css/qcTrendPlotReport.css

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,24 @@
115115

116116
.qc-combined-tree-legend .qc-tree-precursor:hover {
117117
background-color: #f0f0f0;
118-
}
118+
}
119+
120+
.y-zoom-overlay {
121+
cursor: zoom-in;
122+
}
123+
124+
.y-zoom-pending-line {
125+
stroke: rgba(20, 204, 201, 1);
126+
stroke-width: 2px;
127+
stroke-dasharray: 6, 3;
128+
}
129+
130+
.y-zoom-selection {
131+
fill: rgba(20, 204, 201, 0.3);
132+
stroke: rgba(20, 204, 201, 1);
133+
stroke-width: 1px;
134+
}
135+
136+
.y-zoom-buttons g {
137+
cursor: pointer;
138+
}

0 commit comments

Comments
 (0)