From d5bf0ab0427bbd466039afd03a18256fcde4678f Mon Sep 17 00:00:00 2001 From: XingY Date: Mon, 27 Apr 2026 21:46:15 -0700 Subject: [PATCH 1/3] Selenium test for list with mvtc folder export/import --- ...ChoiceImportExportAndOtherDomainsTest.java | 80 ++++++++++++++++--- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java b/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java index bf4d4d376d..7ba0f3fefa 100644 --- a/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java +++ b/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java @@ -18,6 +18,7 @@ import org.labkey.test.params.FieldDefinition; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.IssuesHelper; +import org.labkey.test.util.OptionalFeatureHelper; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.SampleTypeHelper; @@ -39,8 +40,11 @@ public class TextChoiceImportExportAndOtherDomainsTest extends TextChoiceTest private static final String LIST_NAME = "Simple_TC_List"; private static final String LIST_TC_FIELD = "LTC_Field"; private static final String LIST_TEXT_FIELD = "Str"; + private static final String LIST_MVTC_FIELD = "LMVTC_Field"; private static final List LIST_VALUES = Arrays.asList("L1", "L2|withPipes|", "L3", "L4"); + private static final List LIST_MVTC_VALUES = Arrays.asList("M1", "M2", "M3"); private static final List> listData = new ArrayList<>(); + private static final List> listMvtcData = new ArrayList<>(); // Issue names, etc... private static final String ISSUE_DESIGN_NAME = "Simple_TC_Issue"; @@ -97,13 +101,16 @@ private void doSetup() *

* This test will: *

    - *
  • Create a list design with a TextChoice field.
  • + *
  • Create a list design with a TextChoice field and optionally a MultiValueTextChoice field.
  • *
  • Import list data in bulk.
  • *
  • Add a new list item using the UI.
  • *
*

+ * + * @param includeMvtc If true, include a {@link FieldDefinition.ColumnType#MultiValueTextChoice} field + * in the list and populate it. Only supported on PostgreSQL. */ - private void verifyTextChoiceInList() + private void verifyTextChoiceInList(boolean includeMvtc) { FieldDefinition tcField = new FieldDefinition(LIST_TC_FIELD, FieldDefinition.ColumnType.TextChoice); @@ -111,10 +118,24 @@ private void verifyTextChoiceInList() FieldDefinition txtField = new FieldDefinition(LIST_TEXT_FIELD, FieldDefinition.ColumnType.String); - log(String.format("Create a list named '%s' with a string field '%s' and a TextChoice field '%s'.", - LIST_NAME, LIST_TEXT_FIELD, LIST_TC_FIELD)); + final String allMVTCValues = "M1, M2, M3"; + if (includeMvtc) + { + FieldDefinition mvtcField = new FieldDefinition(LIST_MVTC_FIELD, FieldDefinition.ColumnType.MultiValueTextChoice); + mvtcField.setMultiChoiceValues(LIST_MVTC_VALUES); + + log(String.format("Create a list named '%s' with a string field '%s', a TextChoice field '%s', and a MultiValueTextChoice field '%s'.", + LIST_NAME, LIST_TEXT_FIELD, LIST_TC_FIELD, LIST_MVTC_FIELD)); - _listHelper.createList(getCurrentContainerPath(), LIST_NAME, "Key", tcField, txtField); + _listHelper.createList(getCurrentContainerPath(), LIST_NAME, "Key", tcField, txtField, mvtcField); + } + else + { + log(String.format("Create a list named '%s' with a string field '%s' and a TextChoice field '%s'.", + LIST_NAME, LIST_TEXT_FIELD, LIST_TC_FIELD)); + + _listHelper.createList(getCurrentContainerPath(), LIST_NAME, "Key", tcField, txtField); + } log("Bulk upload data into the list."); @@ -124,10 +145,23 @@ private void verifyTextChoiceInList() listData.add(Map.of(LIST_TC_FIELD, LIST_VALUES.get(2), LIST_TEXT_FIELD, "Is")); StringBuilder sb = new StringBuilder(); - sb.append(String.format("%s\t%s\n", LIST_TC_FIELD, LIST_TEXT_FIELD)); - for(Map row : listData) + if (includeMvtc) { - sb.append(String.format("%s\t%s\n", row.get(LIST_TC_FIELD), row.get(LIST_TEXT_FIELD))); + sb.append(String.format("%s\t%s\t%s\n", LIST_TC_FIELD, LIST_TEXT_FIELD, LIST_MVTC_FIELD)); + for (int i = 0; i < listData.size(); i++) + { + Map row = listData.get(i); + sb.append(String.format("%s\t%s\t%s\n", row.get(LIST_TC_FIELD), row.get(LIST_TEXT_FIELD), allMVTCValues)); + listMvtcData.add(LIST_MVTC_VALUES); + } + } + else + { + sb.append(String.format("%s\t%s\n", LIST_TC_FIELD, LIST_TEXT_FIELD)); + for (Map row : listData) + { + sb.append(String.format("%s\t%s\n", row.get(LIST_TC_FIELD), row.get(LIST_TEXT_FIELD))); + } } _listHelper.uploadData(sb.toString()); @@ -137,6 +171,9 @@ private void verifyTextChoiceInList() // Add the new row to the expected data. listData.add(newRow); + if (includeMvtc) + listMvtcData.add(List.of()); // No MVTC value for the UI-inserted row. + log("Add a new row to the list using the UI."); _listHelper.insertNewRow(newRow); @@ -208,6 +245,8 @@ private void verifyTextChoiceInIssueDesign() @Test public void testOtherDomainsExportAndImport() throws IOException, CommandException { + boolean isPg = WebTestHelper.getDatabaseType() == WebTestHelper.DatabaseType.PostgreSQL; + goToProjectHome(); log("Create a sample type, assay design and an assay run. These will be used to validate export/import."); @@ -219,8 +258,11 @@ public void testOtherDomainsExportAndImport() throws IOException, CommandExcepti Map assayResultRowData = createAssayRun(); + if (isPg) + OptionalFeatureHelper.enableOptionalFeature(createDefaultConnection(), "multiChoiceDataType"); + log("Create a list with a TextChoice field. The list will also be validated after import."); - verifyTextChoiceInList(); + verifyTextChoiceInList(isPg); log("Create an issue design with a TextChoice field and create an issue that uses it. Issue designs are not exported."); verifyTextChoiceInIssueDesign(); @@ -238,7 +280,7 @@ public void testOtherDomainsExportAndImport() throws IOException, CommandExcepti _containerHelper.createProject(IMPORTED_PROJ_NAME, null); - importFolderFromZip(exportFile); + importFolderFromZip(exportFile, false, 1); // Not sure if I need this either. Assert.assertEquals("Import caused server side errors.", 0, getServerErrorCount()); @@ -254,21 +296,37 @@ public void testOtherDomainsExportAndImport() throws IOException, CommandExcepti Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand cmd = new SelectRowsCommand("lists", LIST_NAME); - cmd.setColumns(Arrays.asList(LIST_TC_FIELD, LIST_TEXT_FIELD)); + List selectColumns = new ArrayList<>(Arrays.asList(LIST_TC_FIELD, LIST_TEXT_FIELD)); + if (isPg) + selectColumns.add(LIST_MVTC_FIELD); + cmd.setColumns(selectColumns); SelectRowsResponse response = cmd.execute(cn, getCurrentContainerPath()); List> importedListData = new ArrayList<>(); + List> importedListMvtcData = new ArrayList<>(); for (Map row : response.getRows()) { importedListData.add( Map.of(LIST_TC_FIELD, row.get(LIST_TC_FIELD).toString(), LIST_TEXT_FIELD, row.get(LIST_TEXT_FIELD).toString())); + + if (isPg) + { + Object mvtcRaw = row.get(LIST_MVTC_FIELD); + List mvtcValues = mvtcRaw instanceof List list + ? list.stream().map(Object::toString).toList() + : List.of(); + importedListMvtcData.add(mvtcValues); + } } checker().withScreenshot("Imported_List_Error") .verifyEquals("Imported data for the list not as expected.", listData, importedListData); + if (isPg) + checker().verifyEquals("Imported MultiValueTextChoice data for the list not as expected.", listMvtcData, importedListMvtcData); + log("Validate the assay data."); goToProjectHome(IMPORTED_PROJ_NAME); waitAndClickAndWait(Locator.linkWithText(ASSAY_NAME)); From 65dc91eb86306e50eb7052c2f2c2b26119f836c1 Mon Sep 17 00:00:00 2001 From: XingY Date: Tue, 28 Apr 2026 13:32:05 -0700 Subject: [PATCH 2/3] no longer need experimental flag --- .../test/tests/TextChoiceImportExportAndOtherDomainsTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java b/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java index 7ba0f3fefa..6d50b8998d 100644 --- a/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java +++ b/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java @@ -18,7 +18,6 @@ import org.labkey.test.params.FieldDefinition; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.IssuesHelper; -import org.labkey.test.util.OptionalFeatureHelper; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.SampleTypeHelper; @@ -258,9 +257,6 @@ public void testOtherDomainsExportAndImport() throws IOException, CommandExcepti Map assayResultRowData = createAssayRun(); - if (isPg) - OptionalFeatureHelper.enableOptionalFeature(createDefaultConnection(), "multiChoiceDataType"); - log("Create a list with a TextChoice field. The list will also be validated after import."); verifyTextChoiceInList(isPg); From 07a8d32929c24d7cac4b150de9a824b56b3b697a Mon Sep 17 00:00:00 2001 From: XingY Date: Wed, 29 Apr 2026 08:52:12 -0700 Subject: [PATCH 3/3] code review changes --- .../tests/TextChoiceImportExportAndOtherDomainsTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java b/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java index 6d50b8998d..65a9f1b6f5 100644 --- a/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java +++ b/src/org/labkey/test/tests/TextChoiceImportExportAndOtherDomainsTest.java @@ -1,5 +1,6 @@ package org.labkey.test.tests; +import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -41,7 +42,7 @@ public class TextChoiceImportExportAndOtherDomainsTest extends TextChoiceTest private static final String LIST_TEXT_FIELD = "Str"; private static final String LIST_MVTC_FIELD = "LMVTC_Field"; private static final List LIST_VALUES = Arrays.asList("L1", "L2|withPipes|", "L3", "L4"); - private static final List LIST_MVTC_VALUES = Arrays.asList("M1", "M2", "M3"); + private static final List LIST_MVTC_VALUES = Arrays.asList("M1&", "M2;b", "M3 %"); private static final List> listData = new ArrayList<>(); private static final List> listMvtcData = new ArrayList<>(); @@ -117,7 +118,7 @@ private void verifyTextChoiceInList(boolean includeMvtc) FieldDefinition txtField = new FieldDefinition(LIST_TEXT_FIELD, FieldDefinition.ColumnType.String); - final String allMVTCValues = "M1, M2, M3"; + final String allMVTCValues = StringUtils.join(LIST_MVTC_VALUES, ", "); if (includeMvtc) { FieldDefinition mvtcField = new FieldDefinition(LIST_MVTC_FIELD, FieldDefinition.ColumnType.MultiValueTextChoice);