diff --git a/src/org/labkey/test/LabKeySiteWrapper.java b/src/org/labkey/test/LabKeySiteWrapper.java index 2abd3f59fc..a118aece2c 100644 --- a/src/org/labkey/test/LabKeySiteWrapper.java +++ b/src/org/labkey/test/LabKeySiteWrapper.java @@ -1593,7 +1593,7 @@ public void waitForPipelineJobsToComplete(final int finishedJobsExpected, final * @param timeoutMilliseconds Maximum time to wait for pipeline jobs to finish (default 10 minutes) */ @LogMethod - public void waitForPipelineJobsToComplete(@LoggedParam final int finishedJobsExpected, @LoggedParam final String description, final boolean expectError, int timeoutMilliseconds) + public void waitForPipelineJobsToComplete(@LoggedParam final int finishedJobsExpected, @LoggedParam final String description, final boolean expectError, long timeoutMilliseconds) { final List statusValues = waitForPipelineJobsToFinish(finishedJobsExpected, Duration.ofMillis(timeoutMilliseconds)); diff --git a/src/org/labkey/test/TestCredentials.java b/src/org/labkey/test/TestCredentials.java index 5602121dba..342d9ba86e 100644 --- a/src/org/labkey/test/TestCredentials.java +++ b/src/org/labkey/test/TestCredentials.java @@ -46,7 +46,12 @@ public static File getCredentialsFile() { if (null == credentialsFile) { - setCredentialsFile(new File(System.getProperty("test.credentials.file", TestFileUtils.getTestRoot() + "/test.credentials.json"))); + String credentialsFileLocation = System.getProperty("test.credentials.file"); + if (credentialsFileLocation == null || credentialsFileLocation.isEmpty()) + { + credentialsFileLocation = TestFileUtils.getTestRoot() + "/test.credentials.json"; + } + setCredentialsFile(new File(credentialsFileLocation)); } return credentialsFile; } diff --git a/src/org/labkey/test/TestFileUtils.java b/src/org/labkey/test/TestFileUtils.java index 807a928b10..b72bc9a74c 100644 --- a/src/org/labkey/test/TestFileUtils.java +++ b/src/org/labkey/test/TestFileUtils.java @@ -38,6 +38,7 @@ import org.bouncycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder; import org.bouncycastle.util.io.Streams; import org.jetbrains.annotations.NotNull; +import org.labkey.api.util.FileUtil; import org.jetbrains.annotations.Nullable; import org.openqa.selenium.NotFoundException; @@ -97,7 +98,7 @@ public abstract class TestFileUtils public static String getFileContents(String rootRelativePath) { - return getFileContents(Paths.get(getLabKeyRoot(), rootRelativePath)); + return getFileContents(getLabKeyRoot().toPath().resolve(rootRelativePath)); } public static String getFileContents(final File file) @@ -137,7 +138,7 @@ public static String getStreamContentsAsString(InputStream is) throws IOExceptio return StringUtils.join(IOUtils.readLines(is, Charset.defaultCharset()).toArray(), System.lineSeparator()); } - public static String getLabKeyRoot() + public static File getLabKeyRoot() { if (_labkeyRoot == null) { @@ -151,7 +152,7 @@ public static String getLabKeyRoot() { throw new IllegalStateException("Specified LabKey root does not exist [" + _labkeyRoot + "]. Configure this by passing VM arg labkey.root={yourroot}"); } - if (!new File(_labkeyRoot, "server").exists()) + if (!FileUtil.appendName(_labkeyRoot, "server").exists()) { throw new IllegalStateException("Specified LabKey root exists [" + _labkeyRoot + "] but isn't the root of a LabKey enlistment. Configure this by passing VM arg labkey.root={yourroot}"); } @@ -167,25 +168,25 @@ public static String getLabKeyRoot() _labkeyRoot = _labkeyRoot.getParentFile().getParentFile(); // Working directory is in '{labkey.root}/server'; otherwise is in enlistment root else if (_labkeyRoot.getName().equals("server")) _labkeyRoot = _labkeyRoot.getParentFile(); // Working directory is in '{labkey.root}/server'; otherwise is in enlistment root - else if (!new File(_labkeyRoot, "server").exists()) + else if (!FileUtil.appendName(_labkeyRoot, "server").exists()) { throw new IllegalStateException("Unable to locate enlistment. Working directory [" + _labkeyRoot + "] isn't a recognized location. Configure manually with passing VM arg labkey.root={yourroot}"); } } } - return _labkeyRoot.toString(); + return _labkeyRoot; } public static File getServerLogDir() { - return new File(getDefaultDeployDir(), "embedded/logs"); + return FileUtil.appendName(FileUtil.appendName(getDefaultDeployDir(), "embedded"), "logs"); } public static File getTestRoot() { if (_testRoot == null) { - _testRoot = new File(getLabKeyRoot(), "server/testAutomation"); + _testRoot = FileUtil.appendName(FileUtil.appendName(getLabKeyRoot(), "server"), "testAutomation"); } return _testRoot; } @@ -199,7 +200,7 @@ public static File getTestBuildDir() { if (_buildDir == null) { - _buildDir = new File(getLabKeyRoot(), "build/modules/" + getTestProjectName()); // Gradle + _buildDir = FileUtil.appendPath(getLabKeyRoot(), org.labkey.api.util.Path.parse("build/modules/" + getTestProjectName())); // Gradle } return _buildDir; } @@ -207,12 +208,12 @@ public static File getTestBuildDir() public static File getBaseFileRoot() { // Files are a sibling of the modules directory - return new File(getModulesDir().getParentFile(), "files"); + return FileUtil.appendName(getModulesDir().getParentFile(), "files"); } public static File getGradleReportDir() { - return new File(getTestBuildDir(), "test/logs/reports"); + return FileUtil.appendPath(getTestBuildDir(), org.labkey.api.util.Path.parse("test/logs/reports")); } /** @@ -221,7 +222,7 @@ public static File getGradleReportDir() */ static File getDefaultDeployDir() { - return new File(getLabKeyRoot(), "build/deploy"); + return FileUtil.appendPath(getLabKeyRoot(), org.labkey.api.util.Path.parse("build/deploy")); } public static File getModulesDir() @@ -229,10 +230,10 @@ public static File getModulesDir() if (_modulesDir == null) { // Module root when deploying from embedded distribution - _modulesDir = new File(getDefaultDeployDir(), "embedded/modules"); + _modulesDir = FileUtil.appendPath(getDefaultDeployDir(), org.labkey.api.util.Path.parse("embedded/modules")); if (!_modulesDir.isDirectory()) { - _modulesDir = new File(getDefaultDeployDir(), "modules"); + _modulesDir = FileUtil.appendName(getDefaultDeployDir(), "modules"); } } return _modulesDir; @@ -240,16 +241,16 @@ public static File getModulesDir() public static File getDefaultFileRoot(String containerPath) { - return new File(getBaseFileRoot(), containerPath + "/@files"); + return FileUtil.appendPath(getBaseFileRoot(), org.labkey.api.util.Path.parse(containerPath + "/@files")); } public static String getDefaultWebAppRoot() { - File path = new File(getModulesDir().getParentFile(), "labkeyWebapp"); + File path = FileUtil.appendName(getModulesDir().getParentFile(), "labkeyWebapp"); if (!path.isDirectory()) { // Casing is different when deployed from an embedded distribution - path = new File(getModulesDir().getParentFile(), "labkeywebapp"); + path = FileUtil.appendName(getModulesDir().getParentFile(), "labkeywebapp"); } return path.toString(); } @@ -300,7 +301,7 @@ public static List getSampleDatas(String relativePath) for (File sampledataDir : sampledataDirs) { - File checkFile = new File(sampledataDir, relativePath); + File checkFile = FileUtil.appendPath(sampledataDir, org.labkey.api.util.Path.parse(relativePath)); if (checkFile.exists()) { foundFiles.add(checkFile); @@ -317,7 +318,7 @@ public static Set getSampleDataDirs() { _sampledataDirs = new TreeSet<>(); - File sampledataDirsFile = new File(getTestBuildDir(), "sampledata.dirs"); + File sampledataDirsFile = FileUtil.appendName(getTestBuildDir(), "sampledata.dirs"); if (sampledataDirsFile.exists()) { String path = getFileContents(sampledataDirsFile); @@ -325,8 +326,8 @@ public static Set getSampleDataDirs() } else { - _sampledataDirs.add(new File(getTestRoot(), "data")); - Path modulesDir = new File(getLabKeyRoot(), "server/modules").toPath(); + _sampledataDirs.add(FileUtil.appendName(getTestRoot(), "data")); + Path modulesDir = FileUtil.appendPath(getLabKeyRoot(), org.labkey.api.util.Path.parse("server/modules")).toPath(); try { // We know where the modules live; no reason to insist that sampledata.dirs exists. @@ -363,8 +364,8 @@ public static Set getSampleDataDirs() public static File getTestTempDir() { - File buildDir = new File(getLabKeyRoot(), "build"); - return new File(buildDir, "testTemp"); + File buildDir = FileUtil.appendName(getLabKeyRoot(), "build"); + return FileUtil.appendName(buildDir, "testTemp"); } /** @@ -378,7 +379,7 @@ public static File ensureTestTempDir(String... children) throws IOException File file = getTestTempDir(); for (String child : children) { - file = new File(file, child); + file = FileUtil.appendName(file, child); } FileUtils.forceMkdir(file); @@ -398,7 +399,7 @@ public static File ensureTestTempFile(String... children) throws IOException for (String child : children) { - file = new File(file, child); + file = FileUtil.appendName(file, child); } if (file.toString().length() == getTestTempDir().toString().length()) @@ -448,7 +449,7 @@ private static void checkFileLocation(File file) { try { - if (!FileUtils.directoryContains(new File(getLabKeyRoot()), file)) + if (!FileUtils.directoryContains(getLabKeyRoot(), file)) { // TODO: Consider throwing IllegalArgumentException LOG.info("DEBUG: Attempting to delete a file outside of test enlistment: " + getLabKeyRoot()); @@ -457,30 +458,6 @@ private static void checkFileLocation(File file) catch (IOException ignore) { } } - /** - * - * @param dir Location to create new file - * @param fileName Name of file to be created - * @param contents Text contents of file - * @return File object pointing to new file - * @deprecated Use {@link #writeFile(File, String)} or {@link #writeTempFile(String, String)} - */ - @Deprecated - public static File saveFile(File dir, String fileName, String contents) - { - File tsvFile = new File(dir, fileName); - - try - { - return writeFile(tsvFile, contents); - } - catch (IOException e) - { - e.printStackTrace(System.err); - return null; - } - } - /** * Write text to a file in the test temp directory. Temp directory will be created if it does not exist. * @param name Name of the file to be created. An existing file will be overwritten @@ -490,7 +467,7 @@ public static File saveFile(File dir, String fileName, String contents) */ public static File writeTempFile(String name, InputStream contents) throws IOException { - File file = new File(getTestTempDir(), name); + File file = FileUtil.appendPath(getTestTempDir(), org.labkey.api.util.Path.parse(name)); FileUtils.forceMkdirParent(file); FileUtils.copyInputStreamToFile(contents, file); @@ -506,7 +483,7 @@ public static File writeTempFile(String name, InputStream contents) throws IOExc */ public static File writeTempFile(String name, String contents) throws IOException { - File file = new File(getTestTempDir(), name); + File file = FileUtil.appendPath(getTestTempDir(), org.labkey.api.util.Path.parse(name)); FileUtils.forceMkdirParent(file); return writeFile(file, contents); @@ -587,7 +564,7 @@ public static List unzipToDirectory(File sourceZip, File unzipDir) throws while (null != (entry = zis.getNextEntry())) { - File destFile = new File(unzipDir, entry.getName()); + File destFile = FileUtil.appendName(unzipDir, entry.getName()); if (!destFile.getCanonicalPath().startsWith(unzipDir.getCanonicalPath() + File.separator)) { throw new IOException("Zip entry is outside of the target dir: " + entry.getName()); @@ -641,7 +618,7 @@ private static List unTar(final File inputFile, final File outputDir) thro while ((entry = inputStream.getNextEntry()) != null) { - final File outputFile = new File(outputDir, entry.getName()); + final File outputFile = FileUtil.appendPath(outputDir, org.labkey.api.util.Path.parse(entry.getName())); if (!outputFile.toPath().normalize().startsWith(normalizedOutputPath)) throw new IOException("Bad zip entry (" + entry.getName() + ") in " + inputFile.getAbsolutePath()); @@ -675,7 +652,7 @@ private static List unTar(final File inputFile, final File outputDir) thro */ private static File unGzip(final File inputFile, final File outputDir) throws IOException { - final File outputFile = new File(outputDir, inputFile.getName().substring(0, inputFile.getName().length() - 3)); + final File outputFile = FileUtil.appendName(outputDir, inputFile.getName().substring(0, inputFile.getName().length() - 3)); try (GZIPInputStream in = new GZIPInputStream(new FileInputStream(inputFile)); FileOutputStream out = new FileOutputStream(outputFile)) diff --git a/src/org/labkey/test/components/assay/AssayConstants.java b/src/org/labkey/test/components/assay/AssayConstants.java index 71ead8ea20..56db57c16a 100644 --- a/src/org/labkey/test/components/assay/AssayConstants.java +++ b/src/org/labkey/test/components/assay/AssayConstants.java @@ -12,5 +12,6 @@ public class AssayConstants public static final Locator COMMENTS_FIELD_LOCATOR = Locator.name("Comments"); public static final Locator TARGET_STUDY_FIELD_LOCATOR = Locator.name(TARGET_STUDY_FIELD_NAME); public static final Locator TEXT_AREA_DATA_PROVIDER_LOCATOR = Locator.xpath("//input[@value='textAreaDataProvider']"); - public static final Locator TEXT_AREA_DATA_COLLECTOR_LOCATOR = Locator.textarea("TextAreaDataCollector.textArea"); + public static final String TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME = "TextAreaDataCollector.textArea"; + public static final Locator TEXT_AREA_DATA_COLLECTOR_LOCATOR = Locator.textarea(TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME); } diff --git a/src/org/labkey/test/teamcity/TeamCityUtils.java b/src/org/labkey/test/teamcity/TeamCityUtils.java index a90f3d6070..07f67f67a9 100644 --- a/src/org/labkey/test/teamcity/TeamCityUtils.java +++ b/src/org/labkey/test/teamcity/TeamCityUtils.java @@ -117,7 +117,7 @@ public static void publishArtifact(File file, @Nullable String destination) { if (file != null && file.exists()) { - String labkeyRoot = new File(TestFileUtils.getLabKeyRoot()).getAbsolutePath(); + String labkeyRoot = TestFileUtils.getLabKeyRoot().getAbsolutePath(); String filePath = file.getAbsoluteFile().toPath().normalize().toString(); if (filePath.startsWith(labkeyRoot)) { diff --git a/src/org/labkey/test/testpicker/TestHelper.java b/src/org/labkey/test/testpicker/TestHelper.java index a117ea6ebd..7df41c79c8 100644 --- a/src/org/labkey/test/testpicker/TestHelper.java +++ b/src/org/labkey/test/testpicker/TestHelper.java @@ -55,7 +55,7 @@ public class TestHelper public static final String DEFAULT_PORT = WebTestHelper.getWebPort().toString(); public static final String DEFAULT_CONTEXT_PATH = WebTestHelper.getContextPath(); public static final String DEFAULT_SERVER = WebTestHelper.getTargetServer(); - public static final String DEFAULT_ROOT = TestFileUtils.getLabKeyRoot(); + public static final String DEFAULT_ROOT = TestFileUtils.getLabKeyRoot().toString(); private static Thread awtThread = null; private static final String _saveFileName = "savedConfigs.idx"; diff --git a/src/org/labkey/test/tests/FileBasedPipelineTest.java b/src/org/labkey/test/tests/FileBasedPipelineTest.java index 7791a439a4..131c0d7b07 100644 --- a/src/org/labkey/test/tests/FileBasedPipelineTest.java +++ b/src/org/labkey/test/tests/FileBasedPipelineTest.java @@ -130,7 +130,7 @@ public void testRCopyInlinePipeline() goToModule("FileContent"); _fileBrowserHelper.uploadFile(SAMPLE_FILE); - final String jobDescription = "@files/sample (InlineRCopy)"; + final String jobDescription = "sample (InlineRCopy)"; pipelineAnalysis.runPipelineAnalysis(importAction, targetFiles, protocolProperties, "Duplicate File(s)", true); pipelineAnalysis.verifyPipelineAnalysis(pipelineName, protocolName, jobDescription, null, fileRoot, outputFiles); @@ -239,7 +239,7 @@ public void testWithOutputLocation() goToModule("FileContent"); _fileBrowserHelper.uploadFile(SAMPLE_FILE); - final String jobDescription = "@files/sample (with_output_location)"; + final String jobDescription = "sample (with_output_location)"; pipelineAnalysis.runPipelineAnalysis(importAction, targetFiles, protocolProperties); pipelineAnalysis.verifyPipelineAnalysis(pipelineName, protocolName, null, jobDescription, fileRoot, outputFiles); diff --git a/src/org/labkey/test/tests/RlabkeyTest.java b/src/org/labkey/test/tests/RlabkeyTest.java index 716499192a..498c6da5ad 100644 --- a/src/org/labkey/test/tests/RlabkeyTest.java +++ b/src/org/labkey/test/tests/RlabkeyTest.java @@ -211,7 +211,7 @@ public void testRlabkeyPipelineApi() throws Exception // verify the expected pipeline jobs where run and completed goToProjectHome(); PipelineStatusTable pipelineStatusTable = goToDataPipeline(); - assertEquals("COMPLETE", pipelineStatusTable.getJobStatus("@files/sample (Rlabkey RCopy Test 1) (sample.txt)")); + assertEquals("COMPLETE", pipelineStatusTable.getJobStatus("sample (Rlabkey RCopy Test 1) (sample.txt)")); assertEquals("COMPLETE", pipelineStatusTable.getJobStatus("test pipe desc")); } diff --git a/src/org/labkey/test/tests/SampleTypeRemoteAPITest.java b/src/org/labkey/test/tests/SampleTypeRemoteAPITest.java index 1b146282f3..c90a58c629 100644 --- a/src/org/labkey/test/tests/SampleTypeRemoteAPITest.java +++ b/src/org/labkey/test/tests/SampleTypeRemoteAPITest.java @@ -37,6 +37,7 @@ import org.labkey.test.TestTimeoutException; import org.labkey.test.categories.Daily; import org.labkey.test.components.CustomizeView; +import org.labkey.test.components.assay.AssayConstants; import org.labkey.test.components.domain.DomainFormPanel; import org.labkey.test.pages.ReactAssayDesignerPage; import org.labkey.test.pages.assay.AssayImportPage; @@ -766,7 +767,7 @@ private void insertAssayData(String assayName, List dataGener for(TestDataGenerator dataGen : dataGenerators) { AssayImportPage page = new AssayImportPage(getDriver()) - .setNamedTextAreaValue("TextAreaDataCollector.textArea", + .setNamedTextAreaValue(AssayConstants.TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME, dataGen.getDataAsTsv()); imported++; diff --git a/src/org/labkey/test/tests/SimpleModuleTest.java b/src/org/labkey/test/tests/SimpleModuleTest.java index 42766be2a4..05eadd292e 100644 --- a/src/org/labkey/test/tests/SimpleModuleTest.java +++ b/src/org/labkey/test/tests/SimpleModuleTest.java @@ -132,8 +132,8 @@ public class SimpleModuleTest extends BaseWebDriverTest TestFileUtils.getSampleData("SimpleAndRestrictedModule/FolderWithRestricted.folder.zip"); private static final String THUMBNAIL_FOLDER = "thumbnails/"; - private static final String THUMBNAIL_FILENAME = "/Thumbnail.png"; - private static final String ICON_FILENAME = "/SmallThumbnail.png"; + private static final String THUMBNAIL_FILENAME = "Thumbnail.png"; + private static final String ICON_FILENAME = "SmallThumbnail.png"; private static final String KNITR_PEOPLE = "Knitr People"; private static final String SUPER_COOL_R_REPORT = "Super Cool R Report"; @@ -1204,7 +1204,7 @@ private void doTestReportIcon() throws IOException setFormElement(Locator.xpath("//table[contains(@class, 'dataset-search')]//input"), KNITR_PEOPLE); waitForElementToDisappear(Locator.tag("tr").withClass("x4-grid-row").containing(WANT_TO_BE_COOL).notHidden()); - File expectedIconFile = TestFileUtils.getSampleData(THUMBNAIL_FOLDER + KNITR_PEOPLE + ICON_FILENAME); + File expectedIconFile = TestFileUtils.getSampleData(THUMBNAIL_FOLDER + KNITR_PEOPLE + "/" + ICON_FILENAME); WebElement img = waitForElement(Locator.tag("img").withClass("dataview-icon").withoutClass("x4-tree-icon-parent").notHidden()); String backgroundImage = StringUtils.trimToEmpty(img.getCssValue("background-image")); @@ -1214,7 +1214,7 @@ private void doTestReportIcon() throws IOException Assert.fail("Module report icon style is not as expected: " + img.getDomAttribute("style")); } String iconUrl = matcher.group(1); - File downloadedIcon = new SimpleHttpRequest(iconUrl).getResponseAsFile(TestFileUtils.ensureTestTempFile(KNITR_PEOPLE + ICON_FILENAME)); + File downloadedIcon = new SimpleHttpRequest(iconUrl).getResponseAsFile(TestFileUtils.ensureTestTempFile(KNITR_PEOPLE, ICON_FILENAME)); Assertions.assertThat(downloadedIcon).as("Module report icon is not as expected") .hasSameBinaryContentAs(expectedIconFile); @@ -1232,13 +1232,13 @@ private void doTestReportCreatedDate() @LogMethod private void verifyReportThumbnail(@LoggedParam String reportTitle) throws IOException { - File expectedThumbnailFile = TestFileUtils.getSampleData(THUMBNAIL_FOLDER + reportTitle + THUMBNAIL_FILENAME); + File expectedThumbnailFile = TestFileUtils.getSampleData(THUMBNAIL_FOLDER + reportTitle + "/" + THUMBNAIL_FILENAME); WebElement reportLink = waitForElement(Locator.xpath("//a[text()='" + reportTitle + "']")); mouseOver(reportLink); WebElement thumbnail = waitForElement(Locator.xpath("//div[@class='thumbnail']/img").notHidden()); File downloadedThumbnail = new SimpleHttpRequest(thumbnail.getDomProperty("src")) - .getResponseAsFile(TestFileUtils.ensureTestTempFile(reportTitle + THUMBNAIL_FILENAME)); + .getResponseAsFile(TestFileUtils.ensureTestTempFile(reportTitle, THUMBNAIL_FILENAME)); Assertions.assertThat(downloadedThumbnail).as("Module report thumbnail is not as expected") .hasSameBinaryContentAs(expectedThumbnailFile); diff --git a/src/org/labkey/test/tests/assay/AbstractAssayTransformTest.java b/src/org/labkey/test/tests/assay/AbstractAssayTransformTest.java new file mode 100644 index 0000000000..3b9190a1da --- /dev/null +++ b/src/org/labkey/test/tests/assay/AbstractAssayTransformTest.java @@ -0,0 +1,46 @@ +package org.labkey.test.tests.assay; + +import org.junit.BeforeClass; +import org.labkey.test.BaseWebDriverTest; +import org.labkey.test.util.RReportHelper; + +import java.util.Collections; +import java.util.List; + +/** + * Shared setup/cleanup helpers for assay transform-related WebDriver tests. + * Consolidates common project creation, R configuration, and project cleanup. + */ +public abstract class AbstractAssayTransformTest extends BaseWebDriverTest +{ + @BeforeClass + public static void setupProject() + { + AbstractAssayTransformTest init = getCurrentTest(); + init.doSetup(); + } + + protected void doSetup() + { + new RReportHelper(this).ensureRConfig(); + _containerHelper.createProject(getProjectName(), "Assay"); + } + + @Override + protected void doCleanup(boolean afterTest) + { + _containerHelper.deleteProject(getProjectName(), afterTest); + } + + @Override + protected String getProjectName() + { + return getClass().getSimpleName() + " Project"; + } + + @Override + public List getAssociatedModules() + { + return Collections.emptyList(); + } +} diff --git a/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java b/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java index 974397525b..e8115ffa23 100644 --- a/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java +++ b/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java @@ -97,12 +97,12 @@ public void testAssayMV() setFormElement(AssayConstants.ASSAY_NAME_FIELD_LOCATOR, ASSAY_RUN_SINGLE_COLUMN); click(AssayConstants.TEXT_AREA_DATA_PROVIDER_LOCATOR); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), TEST_DATA_SINGLE_COLUMN_ASSAY_BAD); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, TEST_DATA_SINGLE_COLUMN_ASSAY_BAD); clickButton("Save and Finish"); assertLabKeyErrorPresent(); click(AssayConstants.TEXT_AREA_DATA_PROVIDER_LOCATOR); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), TEST_DATA_SINGLE_COLUMN_ASSAY); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, TEST_DATA_SINGLE_COLUMN_ASSAY); clickButton("Save and Finish"); assertNoLabKeyErrors(); clickAndWait(Locator.linkWithText(ASSAY_RUN_SINGLE_COLUMN)); diff --git a/src/org/labkey/test/tests/assay/AssayTransformImportUpdateTest.java b/src/org/labkey/test/tests/assay/AssayTransformImportUpdateTest.java index 15b9814577..366aaf8390 100644 --- a/src/org/labkey/test/tests/assay/AssayTransformImportUpdateTest.java +++ b/src/org/labkey/test/tests/assay/AssayTransformImportUpdateTest.java @@ -2,7 +2,6 @@ import org.assertj.core.api.Assertions; import org.junit.Assume; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; import org.labkey.test.BaseWebDriverTest; @@ -11,6 +10,7 @@ import org.labkey.test.WebTestHelper; import org.labkey.test.categories.Assays; import org.labkey.test.categories.Daily; +import org.labkey.test.components.assay.AssayConstants; import org.labkey.test.pages.ReactAssayDesignerPage; import org.labkey.test.pages.admin.UsageStatisticsPage; import org.labkey.test.pages.assay.AssayImportPage; @@ -19,13 +19,10 @@ import org.labkey.test.pages.pipeline.PipelineStatusDetailsPage; import org.labkey.test.params.FieldDefinition; import org.labkey.test.params.assay.GeneralAssayDesign; -import org.labkey.test.util.PipelineStatusTable; -import org.labkey.test.util.RReportHelper; import java.io.File; import java.time.Duration; import java.time.Instant; -import java.util.Arrays; import java.util.List; import static org.labkey.test.pages.ReactAssayDesignerPage.ScriptFileEvent.Edit; @@ -34,29 +31,8 @@ @Category({Assays.class, Daily.class}) @BaseWebDriverTest.ClassTimeout(minutes = 4) -public class AssayTransformImportUpdateTest extends BaseWebDriverTest +public class AssayTransformImportUpdateTest extends AbstractAssayTransformTest { - - @Override - protected void doCleanup(boolean afterTest) - { - _containerHelper.deleteProject(getProjectName(), afterTest); - } - - @BeforeClass - public static void setupProject() - { - AssayTransformImportUpdateTest init = getCurrentTest(); - - init.doSetup(); - } - - private void doSetup() - { - new RReportHelper(this).ensureRConfig(); - _containerHelper.createProject(getProjectName(), "Assay"); - } - @Test public void testEnableTransformForUpdate() throws Exception { @@ -89,6 +65,7 @@ public void testEnableTransformForUpdate() throws Exception var assayDesignerPage = ReactAssayDesignerPage.beginAt(this, getProjectName(), protocolResponse.getProtocolId(), "general", getURL().toString()); assayDesignerPage.addTransformScript(transformFile, true); + assayDesignerPage.goToBatchFields().removeAllFields(true); checker().verifyTrue("expect run on import to be enabled by default", assayDesignerPage.isScriptActionCheckboxEnabled(insertOrUpdateTransform, Import)); @@ -129,11 +106,10 @@ public void testEnableTransformForUpdate() throws Exception """; clickAndWait(Locator.linkWithText(insertOrUpdateTransformAssay)); - new AssayRunsPage(getDriver()).getTable().clickHeaderButton("Import Data"); - clickButton("Next"); + new AssayRunsPage(getDriver()).getTable().clickHeaderButtonAndWait("Import Data"); var importPage = new AssayImportPage(getDriver()); importPage.setNamedInputText("Name", "transformTestImport"); - importPage.setNamedTextAreaValue("TextAreaDataCollector.textArea", importData); + importPage.setNamedTextAreaValue(AssayConstants.TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME, importData); importPage.clickSaveAndFinish(); var assayDataPage = new AssayRunsPage(getDriver()).clickAssayIdLink("transformTestImport"); @@ -166,11 +142,10 @@ public void testEnableTransformForUpdate() throws Exception // now import some data to a new run called non_transform_import goToProjectHome(); clickAndWait(Locator.linkWithText(insertOrUpdateTransformAssay)); - new AssayRunsPage(getDriver()).getTable().clickHeaderButton("Import Data"); - clickButton("Next"); + new AssayRunsPage(getDriver()).getTable().clickHeaderButtonAndWait("Import Data"); importPage = new AssayImportPage(getDriver()); importPage.setNamedInputText("Name", "non_transform_import"); - importPage.setNamedTextAreaValue("TextAreaDataCollector.textArea", importData); + importPage.setNamedTextAreaValue(AssayConstants.TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME, importData); importPage.clickSaveAndFinish(); var assayDataPage2 = new AssayRunsPage(getDriver()).clickAssayIdLink("non_transform_import"); @@ -270,6 +245,7 @@ public void testCancelAsyncAssayTransformJob() throws Exception var assayDesignerPage = ReactAssayDesignerPage.beginAt(this, getProjectName(), protocolResponse.getProtocolId(), "general", getURL().toString()); assayDesignerPage.addTransformScript(transformFile, true); + assayDesignerPage.goToBatchFields().removeAllFields(true); assayDesignerPage.setBackgroundImport(true); assayDesignerPage.clickSave(); @@ -278,11 +254,10 @@ public void testCancelAsyncAssayTransformJob() throws Exception importDataBuilder.append(String.format("%d\t%d\tComment-%d\n", i, i, i)); clickAndWait(Locator.linkWithText(importCancelTransformAssay)); - new AssayRunsPage(getDriver()).getTable().clickHeaderButton("Import Data"); - clickButton("Next"); + new AssayRunsPage(getDriver()).getTable().clickHeaderButtonAndWait("Import Data"); var importPage = new AssayImportPage(getDriver()); importPage.setNamedInputText("Name", "cancelTransformTestImport"); - importPage.setNamedTextAreaValue("TextAreaDataCollector.textArea", importDataBuilder.toString()); + importPage.setNamedTextAreaValue(AssayConstants.TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME, importDataBuilder.toString()); Instant before = Instant.now(); importPage.clickSaveAndFinish(); @@ -311,16 +286,4 @@ public void testCancelAsyncAssayTransformJob() throws Exception resetErrors(); } - - @Override - protected String getProjectName() - { - return "AssayTransformImportUpdateTest Project"; - } - - @Override - public List getAssociatedModules() - { - return Arrays.asList(); - } } diff --git a/src/org/labkey/test/tests/assay/AssayTransformMissingParentDirTest.java b/src/org/labkey/test/tests/assay/AssayTransformMissingParentDirTest.java new file mode 100644 index 0000000000..69c8a94f29 --- /dev/null +++ b/src/org/labkey/test/tests/assay/AssayTransformMissingParentDirTest.java @@ -0,0 +1,90 @@ +package org.labkey.test.tests.assay; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.labkey.api.util.FileUtil; +import org.labkey.test.Locator; +import org.labkey.test.TestFileUtils; +import org.labkey.test.categories.Assays; +import org.labkey.test.categories.Daily; +import org.labkey.test.components.assay.AssayConstants; +import org.labkey.test.pages.ReactAssayDesignerPage; +import org.labkey.test.pages.assay.AssayImportPage; +import org.labkey.test.pages.assay.AssayRunsPage; +import org.labkey.test.params.assay.GeneralAssayDesign; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * Issue 54156: Regression test to ensure a reasonable error message is shown when an assay design references + * a transform script whose parent directory has since been deleted, and that the assay design can be fixed by removing the script. + */ +@Category({Assays.class, Daily.class}) +public class AssayTransformMissingParentDirTest extends AbstractAssayTransformTest +{ + @Test + public void testMissingParentDirectoryRegression() throws Exception + { + // Create a nested directory and an R transform script within it + String assayName = "missingParentDirAssay"; + Path parentDir = Files.createTempDirectory("assay-transform-parent-"); + Path nestedDir = FileUtil.createDirectories(parentDir.resolve("child"), false); + String scriptName = "transformMissingParent.R"; + String transformContent = "library(Rlabkey);"; + File transformFile = nestedDir.resolve(scriptName).toFile(); + TestFileUtils.writeFile(transformFile, transformContent); + + // Create a General assay and add the transform by absolute path (not upload) + var protocolResponse = new GeneralAssayDesign(assayName).createAssay(getProjectName(), createDefaultConnection()); + var assayDesignerPage = ReactAssayDesignerPage.beginAt(this, getProjectName(), protocolResponse.getProtocolId(), + "general", getURL().toString()); + assayDesignerPage.goToBatchFields().removeAllFields(true); + // add by path so the absolute path is stored; this allows reproducing the missing parent dir scenario + assayDesignerPage.addTransformScript(transformFile); + assayDesignerPage.clickSave(); + + // Now delete the parent dir to ensure we handle it reasonably + TestFileUtils.deleteDir(parentDir.toFile()); + + // Attempt to import data and verify a reasonable error message is shown + String importData = """ + VisitID\tParticipantID\tComment + 1\tP1\timport after parent deleted + """; + + clickAndWait(Locator.linkWithText(assayName)); + new AssayRunsPage(getDriver()).getTable().clickHeaderButtonAndWait("Import Data"); + var importPage = new AssayImportPage(getDriver()); + importPage.setNamedInputText("Name", "missingParentImport"); + importPage.setNamedTextAreaValue(AssayConstants.TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME, importData); + importPage.clickSaveAndFinish(); + + // Expect an error page/message indicating the transform script path cannot be used + // Be tolerant to platform-specific phrasing; assert any of these appear + String expectedPath = transformFile.getAbsolutePath(); + checker().withScreenshot("missing-parent-error") + .verifyTrue("Expect an error message about the transform script path not being found", + isTextPresent("transformMissingParent.R, configured for this assay does not exist.")); + + // Fix the assay design by removing the transform script + goToProjectHome(); + assayDesignerPage = ReactAssayDesignerPage.beginAt(this, getProjectName(), protocolResponse.getProtocolId(), + "general", getURL().toString()); + assayDesignerPage.removeTransformScript(scriptName); + assayDesignerPage.clickSave(); + + // Retry the import and verify it succeeds without the transform + clickAndWait(Locator.linkWithText(assayName)); + new AssayRunsPage(getDriver()).getTable().clickHeaderButtonAndWait("Import Data"); + importPage = new AssayImportPage(getDriver()); + importPage.setNamedInputText("Name", "fixedAssayImport"); + importPage.setNamedTextAreaValue(AssayConstants.TEXT_AREA_DATA_COLLECTOR_TEXT_AREA_NAME, importData); + importPage.clickSaveAndFinish(); + + // Verify we land on the run details page and can see the run name (no transform needed) + new AssayRunsPage(getDriver()).clickAssayIdLink("fixedAssayImport"); + } + +} diff --git a/src/org/labkey/test/tests/assay/AssayTransformWarningTest.java b/src/org/labkey/test/tests/assay/AssayTransformWarningTest.java index 949f22c58b..4320312e53 100644 --- a/src/org/labkey/test/tests/assay/AssayTransformWarningTest.java +++ b/src/org/labkey/test/tests/assay/AssayTransformWarningTest.java @@ -26,6 +26,7 @@ import org.labkey.test.TestTimeoutException; import org.labkey.test.categories.Assays; import org.labkey.test.categories.Daily; +import org.labkey.test.components.assay.AssayConstants; import org.labkey.test.pages.ReactAssayDesignerPage; import org.labkey.test.pages.files.WebDavPage; import org.labkey.test.params.FieldDefinition; @@ -113,7 +114,7 @@ public void testJavaTransformWarning() throws Exception clickButton("Import Data"); clickButton("Next"); setFormElement(ASSAY_NAME_FIELD_LOCATOR, runName); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), importData); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, importData); clickButton("Save and Finish"); assertElementPresent(Locators.labkeyError.containing("Inline warning from Java transform.")); @@ -156,7 +157,7 @@ public void testRTransformWarning() // Use this file as a sample upload file parameter setFormElement(Locator.name("myFile"), JAVA_TRANSFORM_SCRIPT); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), importData); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, importData); clickButton("Save and Finish"); assertElementPresent(Locators.labkeyError.containing("Inline warning from R transform.")); @@ -216,7 +217,7 @@ public void testRTransformUpdateWarning() throws Exception clickButton("Import Data"); clickButton("Next"); setFormElement(ASSAY_NAME_FIELD_LOCATOR, runName); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), importData); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, importData); clickButton("Save and Finish"); // edit the result, expect warning @@ -251,7 +252,7 @@ public void testRTransformError() clickButton("Next"); setFormElement(ASSAY_NAME_FIELD_LOCATOR, runName); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), importData); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, importData); clickButton("Save and Finish"); assertTextPresent("There are errors in the input file"); @@ -287,7 +288,7 @@ public void testTransformErrorOnUpdate() throws Exception clickButton("Import Data"); clickButton("Next"); setFormElement(ASSAY_NAME_FIELD_LOCATOR, runName); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), importData); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, importData); clickButton("Save and Finish"); diff --git a/src/org/labkey/test/tests/pipeline/PipelineProtocolArchiveTest.java b/src/org/labkey/test/tests/pipeline/PipelineProtocolArchiveTest.java index 15c836c84b..df367e5bc9 100644 --- a/src/org/labkey/test/tests/pipeline/PipelineProtocolArchiveTest.java +++ b/src/org/labkey/test/tests/pipeline/PipelineProtocolArchiveTest.java @@ -160,7 +160,7 @@ private void archiveSelected(DataRegionTable protocols) { doAndWaitForPageToLoad(()-> { - protocols.clickHeaderButtonByText("archive"); + protocols.clickHeaderButton("archive"); assertAlert("Are you sure you want to archive the selected protocol?"); }); } @@ -169,7 +169,7 @@ private void unarchiveSelected(DataRegionTable protocols) { doAndWaitForPageToLoad(()-> { - protocols.clickHeaderButtonByText("unarchive"); + protocols.clickHeaderButton("unarchive"); assertAlert("Are you sure you want to unarchive the selected protocol?"); }); } diff --git a/src/org/labkey/test/tests/study/StudyMissingValuesTest.java b/src/org/labkey/test/tests/study/StudyMissingValuesTest.java index 41fb42bb0b..13c708c3f9 100644 --- a/src/org/labkey/test/tests/study/StudyMissingValuesTest.java +++ b/src/org/labkey/test/tests/study/StudyMissingValuesTest.java @@ -207,7 +207,7 @@ public void testAssayLinkToStudyMV() clickButton("Next"); setFormElement(AssayConstants.ASSAY_NAME_FIELD_LOCATOR, ASSAY_RUN_SINGLE_COLUMN); click(AssayConstants.TEXT_AREA_DATA_PROVIDER_LOCATOR); - setFormElement(Locator.name("TextAreaDataCollector.textArea"), TEST_DATA_SINGLE_COLUMN_ASSAY); + setFormElement(AssayConstants.TEXT_AREA_DATA_COLLECTOR_LOCATOR, TEST_DATA_SINGLE_COLUMN_ASSAY); clickButton("Save and Finish"); assertNoLabKeyErrors(); diff --git a/src/org/labkey/test/util/DataRegion.java b/src/org/labkey/test/util/DataRegion.java index 83304f6299..4ff3baabaf 100644 --- a/src/org/labkey/test/util/DataRegion.java +++ b/src/org/labkey/test/util/DataRegion.java @@ -229,12 +229,6 @@ protected String replaceParameter(String param, String newValue) return url.getFile(); } - @Deprecated - public void clickHeaderButtonByText(String buttonText) - { - clickHeaderButton(buttonText); - } - public void clickHeaderButtonAndWait(String buttonText) { getWrapper().clickAndWait(elementCache().getHeaderButton(buttonText));