From d4f70985cd9d0f9df4900f80ef03f44cc66b41b1 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Wed, 3 Sep 2025 12:19:17 -0700 Subject: [PATCH] FileBrowserHelper.getFileDetailInfo: Support more refined filtering --- src/org/labkey/test/AssayAPITest.java | 6 +- src/org/labkey/test/tests/SampleTypeTest.java | 10 +- .../labkey/test/util/FileBrowserHelper.java | 95 ++++++++++++++----- 3 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/org/labkey/test/AssayAPITest.java b/src/org/labkey/test/AssayAPITest.java index 1ccaa3fcd5..201db65e20 100644 --- a/src/org/labkey/test/AssayAPITest.java +++ b/src/org/labkey/test/AssayAPITest.java @@ -311,8 +311,8 @@ public void testImportRun_dataRows() throws Exception assayHelper.importAssay(assayId, runName, dataRowsInvalidResultFileDirectory, getProjectName(), Collections.singletonMap("RunFileField", CREST_FILE.getName()), Collections.emptyMap(), "DataFileField: Invalid file path: ../"); // valid run file and valid result file - FileBrowserHelper.FileDetailInfo runFileInfo = _fileBrowserHelper.getFileDetailInfo(getProjectName(), CREST_FILE.getName()); - FileBrowserHelper.FileDetailInfo resultFileInfo = _fileBrowserHelper.getFileDetailInfo(getProjectName(), SCREENSHOT_FILE.getName()); + FileBrowserHelper.FileDetailInfo runFileInfo = FileBrowserHelper.getFileDetailInfo(getProjectName(), CREST_FILE.getName()); + FileBrowserHelper.FileDetailInfo resultFileInfo = FileBrowserHelper.getFileDetailInfo(getProjectName(), SCREENSHOT_FILE.getName()); List> scenarios = List.of(new Pair<>(CREST_FILE.getName(), SCREENSHOT_FILE.getName()), new Pair<>(runFileInfo.absoluteFilePath(), resultFileInfo.absoluteFilePath()), new Pair<>(runFileInfo.webDavUrl(), resultFileInfo.webDavUrl()), @@ -388,7 +388,7 @@ public void testGpatSaveBatch() throws Exception goToModule("FileContent"); _fileBrowserHelper.uploadFile(HELP_ICON_FILE); goToManageAssays(); - FileBrowserHelper.FileDetailInfo runFileInfo = _fileBrowserHelper.getFileDetailInfo(getProjectName(), "help.jpg"); + FileBrowserHelper.FileDetailInfo runFileInfo = FileBrowserHelper.getFileDetailInfo(getProjectName(), "help.jpg"); ((APIAssayHelper) _assayHelper).saveBatch(assayName, "Valid absolute path", Collections.singletonMap("RunFileField", runFileInfo.absoluteFilePath()), resultRows, getProjectName(), null); ((APIAssayHelper) _assayHelper).saveBatch(assayName, "Valid webdav full path", Collections.singletonMap("RunFileField", runFileInfo.webDavUrl()), resultRows, getProjectName(), null); ((APIAssayHelper) _assayHelper).saveBatch(assayName, "Valid webdav relative path", Collections.singletonMap("RunFileField", runFileInfo.webDavUrlRelative()), resultRows, getProjectName(), null); diff --git a/src/org/labkey/test/tests/SampleTypeTest.java b/src/org/labkey/test/tests/SampleTypeTest.java index 4962306eb9..a48eb18528 100644 --- a/src/org/labkey/test/tests/SampleTypeTest.java +++ b/src/org/labkey/test/tests/SampleTypeTest.java @@ -1608,9 +1608,9 @@ public void testFilePathOnBulkImport() _fileBrowserHelper.uploadFile(TestFileUtils.getSampleData(testFileHomeName)); _fileBrowserHelper.uploadFile(TestFileUtils.getSampleData(testFileHomeNameB)); _fileBrowserHelper.createFolder(homeFileDirectory); - FileBrowserHelper.FileDetailInfo homeFileInfo = _fileBrowserHelper.getFileDetailInfo(PROJECT_NAME, testFileHomeName); - FileBrowserHelper.FileDetailInfo homeFileBInfo = _fileBrowserHelper.getFileDetailInfo(PROJECT_NAME, testFileHomeNameB); - FileBrowserHelper.FileDetailInfo homeDirInfo = _fileBrowserHelper.getFileDetailInfo(PROJECT_NAME, homeFileDirectory); + FileBrowserHelper.FileDetailInfo homeFileInfo = FileBrowserHelper.getFileDetailInfo(PROJECT_NAME, testFileHomeName); + FileBrowserHelper.FileDetailInfo homeFileBInfo = FileBrowserHelper.getFileDetailInfo(PROJECT_NAME, testFileHomeNameB); + FileBrowserHelper.FileDetailInfo homeDirInfo = FileBrowserHelper.getFileDetailInfo(PROJECT_NAME, homeFileDirectory); String folderContainerPath = PROJECT_NAME + "/" + FOLDER_NAME; String testFileSubName = "sampleType.tsv"; @@ -1619,8 +1619,8 @@ public void testFilePathOnBulkImport() goToModule("FileContent"); _fileBrowserHelper.uploadFile(TestFileUtils.getSampleData(testFileSubName)); _fileBrowserHelper.createFolder(subFileDirectory); - FileBrowserHelper.FileDetailInfo subFileInfo = _fileBrowserHelper.getFileDetailInfo(folderContainerPath, testFileSubName); - FileBrowserHelper.FileDetailInfo subDirInfo = _fileBrowserHelper.getFileDetailInfo(folderContainerPath, subFileDirectory); + FileBrowserHelper.FileDetailInfo subFileInfo = FileBrowserHelper.getFileDetailInfo(folderContainerPath, testFileSubName); + FileBrowserHelper.FileDetailInfo subDirInfo = FileBrowserHelper.getFileDetailInfo(folderContainerPath, subFileDirectory); goToProjectHome(); clickAndWait(Locator.linkWithText(sampleTypeNameHome)); diff --git a/src/org/labkey/test/util/FileBrowserHelper.java b/src/org/labkey/test/util/FileBrowserHelper.java index b4ac3b149e..f4fee662d8 100644 --- a/src/org/labkey/test/util/FileBrowserHelper.java +++ b/src/org/labkey/test/util/FileBrowserHelper.java @@ -18,13 +18,12 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.Mutable; import org.apache.commons.lang3.mutable.MutableObject; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.junit.Assert; import org.labkey.remoteapi.CommandException; -import org.labkey.remoteapi.Connection; import org.labkey.remoteapi.query.Filter; import org.labkey.remoteapi.query.SelectRowsCommand; -import org.labkey.remoteapi.query.SelectRowsResponse; import org.labkey.test.BaseWebDriverTest; import org.labkey.test.Locator; import org.labkey.test.SortDirection; @@ -51,9 +50,11 @@ import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; +import static java.util.Collections.emptyList; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -880,56 +881,100 @@ public void openFolderTree() } } - private String stringOrNull(Object value) + private static String stringOrNull(Object value) { if (value == null) return null; return (String) value; } - public record FileDetailInfo(String fileName, String absoluteFilePath, String dataFileUrl, String webDavUrl, String webDavUrlRelative) + public record FileDetailInfo(String fileName, String absoluteFilePath, String dataFileUrl, String relativeFolder, String webDavUrl, String webDavUrlRelative) { } - public FileDetailInfo getFileDetailInfo(String containerPath, String fileName) + /** + * Queries the "exp"."files" table to gather metadata about a specific file. + * + * @param containerPath The container path in which to make the request. + * @param fileName The name of the file to find. + */ + public static @Nullable FileDetailInfo getFileDetailInfo(String containerPath, String fileName) + { + return getFileDetailInfo(containerPath, fileName, null); + } + + /** + * Queries the "exp"."files" table to gather metadata about a specific file. Optionally, a relativeFolder can be + * supplied to match against the "RelativeFolder" column. This is useful when looking for files in a specific + * subdirectory. + * + * @param containerPath The container path in which to make the request. + * @param fileName The name of the file to find. + * @param relativeFolder The expected value of the "RelativeFolder" column. If null, the column is not checked. + */ + public static @Nullable FileDetailInfo getFileDetailInfo(String containerPath, String fileName, @Nullable String relativeFolder) + { + var fileInfos = getFileDetailInfos(containerPath, List.of(new Filter("Name", fileName))); + + // "RelativeFolder" is not a filterable column on the query table + if (relativeFolder != null) + fileInfos = fileInfos.stream().filter(f -> relativeFolder.equals(f.relativeFolder)).toList(); + + if (fileInfos.size() > 1) + { + String message = String.format("%d files found with name \"%s\"", fileInfos.size(), fileName); + if (relativeFolder != null) + message += String.format(" in relative folder \"%s\"", relativeFolder); + message += ". Expected 0 or 1 files with that name."; + + throw new AssertionError(message); + } + + return fileInfos.isEmpty() ? null : fileInfos.get(0); + } + + private static @NotNull List getFileDetailInfos(String containerPath, @Nullable Collection filters) { - List filePathColumns = List.of("AbsoluteFilePath", "FileExists", "DataFileUrl", "WebDavUrl", "WebDavUrlRelative"); try { - Connection cn = WebTestHelper.getRemoteApiConnection(); - SelectRowsCommand cmd = new SelectRowsCommand("exp", "files"); - cmd.addFilter("Name", fileName, Filter.Operator.EQUAL); - cmd.setColumns(filePathColumns); - SelectRowsResponse response = cmd.execute(cn, "/" + containerPath); + var cmd = new SelectRowsCommand("exp", "files"); + cmd.setColumns(List.of("AbsoluteFilePath", "DataFileUrl", "FileExists", "Name", "RelativeFolder", "WebDavUrl", "WebDavUrlRelative")); + + if (filters != null) + { + for (var filter : filters) + cmd.addFilter(filter); + } + + var response = cmd.execute(WebTestHelper.getRemoteApiConnection(), "/" + containerPath); - for (Map row: response.getRows()) + var files = new ArrayList(); + for (var row : response.getRows()) { if (!(Boolean) row.get("FileExists")) continue; - Object absoluteFilePath = row.get("AbsoluteFilePath"); - Object dataFileUrl = row.get("DataFileUrl"); - Object webDavUrl = row.get("WebDavUrl"); - Object webDavUrlRelative = row.get("WebDavUrlRelative"); - return new FileDetailInfo(fileName, stringOrNull(absoluteFilePath), stringOrNull(dataFileUrl), stringOrNull(webDavUrl), stringOrNull(webDavUrlRelative)); + String fileName = stringOrNull(row.get("Name")); + String absoluteFilePath = stringOrNull(row.get("AbsoluteFilePath")); + String dataFileUrl = stringOrNull(row.get("DataFileUrl")); + String relativeFolder = stringOrNull(row.get("RelativeFolder")); + String webDavUrl = stringOrNull(row.get("WebDavUrl")); + String webDavUrlRelative = stringOrNull(row.get("WebDavUrlRelative")); + files.add(new FileDetailInfo(fileName, absoluteFilePath, dataFileUrl, relativeFolder, webDavUrl, webDavUrlRelative)); } + + return files; } catch (CommandException ce) { - if (ce.getStatusCode() == 404) - { - return null; - } - else - { + if (ce.getStatusCode() != 404) throw new RuntimeException(ce); - } } catch (IOException ioe) { throw new RuntimeException(ioe); } - return null; + return emptyList(); } // See PageFlowUtil.encodeURIComponent()