From 7bc7243a84842a1969f8295aab309d8585fabc41 Mon Sep 17 00:00:00 2001 From: Trey Chadick Date: Wed, 9 Jul 2025 09:56:32 -0700 Subject: [PATCH 1/3] Use `WebElement.getDomProperty` for element `src` (#2538) --- src/org/labkey/test/tests/SimpleModuleTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/org/labkey/test/tests/SimpleModuleTest.java b/src/org/labkey/test/tests/SimpleModuleTest.java index c9fd31e412..0e21664401 100644 --- a/src/org/labkey/test/tests/SimpleModuleTest.java +++ b/src/org/labkey/test/tests/SimpleModuleTest.java @@ -850,7 +850,7 @@ private void validateThumbnails(String thumbnailImage, @Nullable String thumbnai Locator popup = Locator.tag("div").withAttribute("id", "helpDiv").descendant("img").withAttributeContaining("src", popupImage). withAttributeContaining("style", popupWidth != null ? "width:" + popupWidth : "max-width:300px"); shortWait().until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#helpDiv"))); - String src = StringUtils.trimToEmpty(popup.findElement(getDriver()).getDomAttribute("src")); + String src = StringUtils.trimToEmpty(popup.findElement(getDriver()).getDomProperty("src")); fireEvent(thumbnail, SeleniumEvent.mouseout); Locator.tagWithClass("th", "labkey-selectors").findElement(getDriver()).click(); // safe out-click in the first header cell @@ -1230,7 +1230,7 @@ private void verifyReportThumbnail(@LoggedParam String reportTitle) WebElement reportLink = waitForElement(Locator.xpath("//a[text()='" + reportTitle + "']")); mouseOver(reportLink); WebElement thumbnail = waitForElement(Locator.xpath("//div[@class='thumbnail']/img").notHidden()); - String thumbnailData = WebTestHelper.getHttpResponse(thumbnail.getDomAttribute("src")).getResponseBody(); + String thumbnailData = WebTestHelper.getHttpResponse(thumbnail.getDomProperty("src")).getResponseBody(); int lengthToCompare = 5000; int diff = LevenshteinDistance.getDefaultInstance().apply(expectedThumbnail.substring(0, lengthToCompare), thumbnailData.substring(0, lengthToCompare)); From 6e4d1bacc13591bc196bb12b158173556c69a245 Mon Sep 17 00:00:00 2001 From: Trey Chadick Date: Wed, 9 Jul 2025 13:23:45 -0700 Subject: [PATCH 2/3] Create `TestFileUtils.getMD5Hash` to compare binary files (#2547) --- src/org/labkey/test/TestFileUtils.java | 20 +++++++++++++++++++ .../test/tests/FileAttachmentColumnTest.java | 12 +++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/org/labkey/test/TestFileUtils.java b/src/org/labkey/test/TestFileUtils.java index b9a1228ceb..ca119a4c68 100644 --- a/src/org/labkey/test/TestFileUtils.java +++ b/src/org/labkey/test/TestFileUtils.java @@ -64,6 +64,8 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.security.Security; import java.util.ArrayList; import java.util.Arrays; @@ -105,6 +107,9 @@ public static String getFileContents(final File file) return getFileContents(path); } + /** + * Get text content of a file. Will throw an error for non-text files (e.g. PDF). + */ public static String getFileContents(Path path) { try @@ -117,6 +122,21 @@ public static String getFileContents(Path path) } } + /** + * Compute MD5 hash for the given file. Useful checking file equivalence. + */ + public static String getMD5Hash(Path path) + { + try + { + return new String(MessageDigest.getInstance("MD5").digest(Files.readAllBytes(path)), StandardCharsets.UTF_8); + } + catch (IOException | NoSuchAlgorithmException fail) + { + throw new RuntimeException(fail); + } + } + public static String getStreamContentsAsString(InputStream is) throws IOException { return StringUtils.join(IOUtils.readLines(is, Charset.defaultCharset()).toArray(), System.lineSeparator()); diff --git a/src/org/labkey/test/tests/FileAttachmentColumnTest.java b/src/org/labkey/test/tests/FileAttachmentColumnTest.java index 9c05dc255c..2d86c8c135 100644 --- a/src/org/labkey/test/tests/FileAttachmentColumnTest.java +++ b/src/org/labkey/test/tests/FileAttachmentColumnTest.java @@ -550,9 +550,9 @@ private void validateSampleData(String sampleType, String folderPath, List { // verify fie download behavior File downloadedFile = doAndWaitForDownload(() -> optionalFileLink.get().click()); - checker().wrapAssertion(() -> Assertions.assertThat(TestFileUtils.getFileContents(downloadedFile)) + checker().wrapAssertion(() -> Assertions.assertThat(TestFileUtils.getMD5Hash(downloadedFile.toPath())) .as("expect the downloaded file to be the expected file") - .isEqualTo(TestFileUtils.getFileContents(file))); // guard against renames like file2.xyz + .isEqualTo(TestFileUtils.getMD5Hash(file.toPath()))); // guard against renames like file2.xyz } } } @@ -576,9 +576,9 @@ private void validateAssayRun(String assayName, String folderPath, String runNam if (optionalFileLink.isPresent()) { var file = doAndWaitForDownload(()-> optionalFileLink.get().click()); - checker().wrapAssertion(()-> Assertions.assertThat(TestFileUtils.getFileContents(file)) + checker().wrapAssertion(()-> Assertions.assertThat(TestFileUtils.getMD5Hash(file.toPath())) .as("expect the downloaded file to have equivalent content") - .isEqualTo(TestFileUtils.getFileContents(runFile))); + .isEqualTo(TestFileUtils.getMD5Hash(runFile.toPath()))); } var resultsPage = runsPage.clickAssayIdLink(runName); @@ -644,9 +644,9 @@ private void validateDatasetData(String datasetName, String folderPath, List optionalFileLink.get().click()); - checker().wrapAssertion(() -> Assertions.assertThat(TestFileUtils.getFileContents(downloadedFile)) + checker().wrapAssertion(() -> Assertions.assertThat(TestFileUtils.getMD5Hash(downloadedFile.toPath())) .as("expect the downloaded file to be the expected file") - .isEqualTo(TestFileUtils.getFileContents(file))); // guard against renames like file2.xyz + .isEqualTo(TestFileUtils.getMD5Hash(file.toPath()))); // guard against renames like file2.xyz } } } From efbfd7b26ce589ff74fb335e80725cab6894d2ff Mon Sep 17 00:00:00 2001 From: Trey Chadick Date: Wed, 9 Jul 2025 16:18:15 -0700 Subject: [PATCH 3/3] Allow `ScriptReportPage.saveReport` to return `null` (#2546) --- .../test/pages/reports/ScriptReportPage.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/org/labkey/test/pages/reports/ScriptReportPage.java b/src/org/labkey/test/pages/reports/ScriptReportPage.java index 31b0db491e..a037747028 100644 --- a/src/org/labkey/test/pages/reports/ScriptReportPage.java +++ b/src/org/labkey/test/pages/reports/ScriptReportPage.java @@ -17,8 +17,9 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.Map; -import java.util.Objects; import java.util.Optional; import static org.labkey.test.components.ext4.Checkbox.Ext4Checkbox; @@ -89,12 +90,25 @@ public String saveReport(String name, boolean isSaveAs, int wait) { saveReportWithName(name, isSaveAs); } - return Objects.requireNonNullElse(getReportId(), reportIdBeforeSave); + String reportIdAfterSave = getReportId(); + return reportIdAfterSave == null ? reportIdBeforeSave : reportIdAfterSave; } public String getReportId() { - return getUrlParam("reportId", true); + String paramName = "reportId"; + + Map params = WebTestHelper.parseUrlQuery(getURL()); + String paramValue = params.get(paramName); + + if (paramValue == null) + { + paramValue = params.entrySet().stream() + .filter(entry -> entry.getKey().endsWith("." + paramName)) + .map(Map.Entry::getValue).findFirst().orElse(null); + } + + return paramValue == null ? null : URLDecoder.decode(paramValue, StandardCharsets.UTF_8); } /**