From 3f09f83298d68253d393a58a74238adcce390781 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Wed, 29 Apr 2026 14:52:55 -0700 Subject: [PATCH 1/3] ListMoveRowsTest: use ContainerInfo and FieldInfo --- .../test/tests/list/ListMoveRowsTest.java | 91 ++++++++++--------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/src/org/labkey/test/tests/list/ListMoveRowsTest.java b/src/org/labkey/test/tests/list/ListMoveRowsTest.java index b96b6f9a66..efd886b0de 100644 --- a/src/org/labkey/test/tests/list/ListMoveRowsTest.java +++ b/src/org/labkey/test/tests/list/ListMoveRowsTest.java @@ -19,12 +19,13 @@ import org.labkey.test.categories.Daily; import org.labkey.test.categories.Data; import org.labkey.test.categories.Hosting; +import org.labkey.test.params.ContainerInfo; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldInfo; import org.labkey.test.params.list.IntListDefinition; import org.labkey.test.params.list.ListDefinition; import org.labkey.test.params.list.VarListDefinition; import org.labkey.test.util.AuditLogHelper; -import org.labkey.test.util.DomainUtils; import org.labkey.test.util.TestDataGenerator; import org.labkey.test.util.TestUser; import org.labkey.test.util.query.MoveRowsResponse; @@ -38,6 +39,8 @@ import java.util.Map; import static org.labkey.test.util.AuditLogHelper.AuditEvent.LIST_AUDIT_EVENT; +import static org.labkey.test.util.DomainUtils.DomainKind.IntList; +import static org.labkey.test.util.DomainUtils.DomainKind.VarList; import static org.labkey.test.util.PermissionsHelper.AUTHOR_ROLE; import static org.labkey.test.util.PermissionsHelper.EDITOR_ROLE; import static org.labkey.test.util.PermissionsHelper.READER_ROLE; @@ -45,30 +48,30 @@ @Category({Daily.class, Data.class, Hosting.class}) // Matches ListTest for now public class ListMoveRowsTest extends BaseWebDriverTest { - private static final String PROJECT_NAME = "ListMoveRowsTest"; - private static final String PROJECT_PATH = "/" + PROJECT_NAME; - private static final String SUBFOLDER_A_NAME = "SubfolderA"; - private static final String SUBFOLDER_A_PATH = "/" + PROJECT_NAME + "/" + SUBFOLDER_A_NAME; - private static final String SUBFOLDER_MINOR_A_NAME = "MinorA"; - private static final String SUBFOLDER_MINOR_A_PATH = SUBFOLDER_A_PATH + "/" + SUBFOLDER_MINOR_A_NAME; - private static final String SUBFOLDER_B_NAME = "SubfolderB"; - private static final String SUBFOLDER_B_PATH = "/" + PROJECT_NAME + "/" + SUBFOLDER_B_NAME; + private static final ContainerInfo PROJECT = ContainerInfo.project("ListMoveRowsTest"); + private static final String PROJECT_PATH = PROJECT.getContainerPath(); + private static final ContainerInfo SUBFOLDER_A = ContainerInfo.folder("SubfolderA", PROJECT); + private static final String SUBFOLDER_A_PATH = SUBFOLDER_A.getContainerPath(); + private static final ContainerInfo SUBFOLDER_MINOR_A = ContainerInfo.folder("MinorA", SUBFOLDER_A); + private static final String SUBFOLDER_MINOR_A_PATH = SUBFOLDER_MINOR_A.getContainerPath(); + private static final ContainerInfo SUBFOLDER_B = ContainerInfo.folder("SubfolderB", PROJECT); + private static final String SUBFOLDER_B_PATH = SUBFOLDER_B.getContainerPath(); private static final String LIST_SCHEMA = "lists"; private static final TestUser AUTHOR_USER = new TestUser("author@listmoverows.test"); private static final TestUser READER_USER = new TestUser("reader@listmoverows.test"); private static final TestUser SUBFOLDER_EDITOR_USER = new TestUser("sub.editor@listmoverows.test"); - private static final String attachmentFieldName = TestDataGenerator.randomFieldName("Attachment", null, DomainUtils.DomainKind.IntList); - private static final String booleanFieldName = TestDataGenerator.randomFieldName("Boolean", null, DomainUtils.DomainKind.IntList); - private static final String dateFieldName = TestDataGenerator.randomFieldName("Date", null, DomainUtils.DomainKind.IntList); - private static final String dateTimeFieldName = TestDataGenerator.randomFieldName("DateTime", null, DomainUtils.DomainKind.IntList); - private static final String decimalFieldName = TestDataGenerator.randomFieldName("Decimal", null, DomainUtils.DomainKind.IntList); - private static final String integerFieldName = TestDataGenerator.randomFieldName("Integer", null, DomainUtils.DomainKind.IntList); + private static final FieldInfo attachmentField = IntList.randomField("Attachment", FieldDefinition.ColumnType.Attachment); + private static final FieldInfo booleanField = IntList.randomField("Boolean", FieldDefinition.ColumnType.Boolean); + private static final FieldInfo dateField = IntList.randomField("Date", FieldDefinition.ColumnType.Date); + private static final FieldInfo dateTimeField = IntList.randomField("DateTime", FieldDefinition.ColumnType.DateAndTime); + private static final FieldInfo decimalField = IntList.randomField("Decimal", FieldDefinition.ColumnType.Decimal); + private static final FieldInfo integerField = IntList.randomField("Integer", FieldDefinition.ColumnType.Integer); - private static final String autoIncrementKeyFieldName = TestDataGenerator.randomFieldName("AutoIncrementKey", null, DomainUtils.DomainKind.IntList); - private static final String integerKeyFieldName = TestDataGenerator.randomFieldName("IntegerKey", null, DomainUtils.DomainKind.IntList); - private static final String stringKeyFieldName = TestDataGenerator.randomFieldName("StringKey", null, DomainUtils.DomainKind.VarList); + private static final FieldInfo autoIncrementKeyField = IntList.randomField("AutoIncrementKey", FieldDefinition.ColumnType.Integer); + private static final FieldInfo integerKeyField = IntList.randomField("IntegerKey", FieldDefinition.ColumnType.Integer); + private static final FieldInfo stringKeyField = VarList.randomField("StringKey", FieldDefinition.ColumnType.String); private static final File SAMPLE_DATA_FILE = TestFileUtils.getSampleData("lists/ListImportFields.txt"); @@ -93,9 +96,9 @@ private void doSetup() throws Exception // Create folders { _containerHelper.createProject(getProjectName(), null); - _containerHelper.createSubfolder(getProjectName(), SUBFOLDER_A_NAME); - _containerHelper.createSubfolder(getProjectName(), SUBFOLDER_B_NAME); - _containerHelper.createSubfolder(SUBFOLDER_A_PATH, SUBFOLDER_MINOR_A_NAME); + SUBFOLDER_A.create(_containerHelper); + SUBFOLDER_B.create(_containerHelper); + SUBFOLDER_MINOR_A.create(_containerHelper); } // Configure users @@ -123,18 +126,18 @@ private void doSetup() throws Exception var fields = getFields(); // List keyed by auto-increment - var autoKeyListName = DomainUtils.DomainKind.IntList.randomName("AUTO"); - AUTO_INCREMENT_LIST = (IntListDefinition) new IntListDefinition(autoKeyListName, autoIncrementKeyFieldName) + var autoKeyListName = IntList.randomName("AUTO"); + AUTO_INCREMENT_LIST = (IntListDefinition) new IntListDefinition(autoKeyListName, autoIncrementKeyField.getName()) .setFields(fields); AUTO_INCREMENT_LIST.getCreateCommand().execute(conn, PROJECT_PATH); AUTO_INCREMENT_LIST.setListId(resolveListId(conn, autoKeyListName, PROJECT_PATH)); // List keyed by integer (not auto-increment) - var intKeyField = new FieldDefinition(integerKeyFieldName, FieldDefinition.ColumnType.Integer); + var intKeyField = integerKeyField.getFieldDefinition(); var intListFields = new ArrayList(); intListFields.add(intKeyField); intListFields.addAll(fields); - var intKeyListName = DomainUtils.DomainKind.IntList.randomName("INT"); + var intKeyListName = IntList.randomName("INT"); INTEGER_KEY_LIST = (IntListDefinition) new IntListDefinition(intKeyListName) .setKeyName(intKeyField.getName()) .setFields(intListFields); @@ -142,11 +145,11 @@ private void doSetup() throws Exception INTEGER_KEY_LIST.setListId(resolveListId(conn, intKeyListName, PROJECT_PATH)); // List keyed by string - var stringKeyField = new FieldDefinition(stringKeyFieldName); + var stringKeyField = ListMoveRowsTest.stringKeyField.getFieldDefinition(); var varListFields = new ArrayList(); varListFields.add(stringKeyField); varListFields.addAll(fields); - var stringKeyListName = DomainUtils.DomainKind.VarList.randomName("STR"); + var stringKeyListName = VarList.randomName("STR"); STRING_KEY_LIST = (VarListDefinition) new VarListDefinition(stringKeyListName) .setFields(varListFields) .setKeyName(stringKeyField.getName()); @@ -266,8 +269,8 @@ public void testPermissions() throws Exception public void testListInSubfolder() throws Exception { // Create a list domain in a subfolder - var subfolderListName = DomainUtils.DomainKind.IntList.randomName("SUBFOLDER"); - var subfolderList = (IntListDefinition) new IntListDefinition(subfolderListName, autoIncrementKeyFieldName) + var subfolderListName = IntList.randomName("SUBFOLDER"); + var subfolderList = new IntListDefinition(subfolderListName, autoIncrementKeyField.getName()) .setFields(getFields()); var conn = createDefaultConnection(); subfolderList.getCreateCommand().execute(conn, SUBFOLDER_A_PATH); @@ -276,11 +279,11 @@ public void testListInSubfolder() throws Exception var subARows = addRows(subfolderList, SUBFOLDER_A_PATH, 10, 0); // Cannot move rows from a list defined in a subfolder to the project - String expectedError = String.format("List '%s' is not accessible from folder %s.", subfolderList.getName(), PROJECT_PATH); + String expectedError = String.format("List '%s' is not accessible from folder %s.", subfolderList.getName(), "/" + PROJECT_PATH); moveRowsExpectingError(subfolderList, SUBFOLDER_A_PATH, PROJECT_PATH, subARows.getRows(), expectedError); // Cannot move rows from a list defined in a subfolder to a folder further down the hierarchy - expectedError = String.format("List '%s' is not accessible from folder %s.", subfolderList.getName(), SUBFOLDER_MINOR_A_PATH); + expectedError = String.format("List '%s' is not accessible from folder %s.", subfolderList.getName(), "/" + SUBFOLDER_MINOR_A_PATH); moveRowsExpectingError(subfolderList, SUBFOLDER_A_PATH, SUBFOLDER_MINOR_A_PATH, subARows.getRows(), expectedError); } @@ -312,7 +315,7 @@ public void testInvalidArguments() throws Exception { truncateList(AUTO_INCREMENT_LIST); var response = addRows(AUTO_INCREMENT_LIST, getProjectName(), 1, 0); - var validId = response.getRows().get(0).get(autoIncrementKeyFieldName); + var validId = response.getRows().getFirst().get(autoIncrementKeyField.getName()); moveRowsExpectingError(AUTO_INCREMENT_LIST, getProjectName(), SUBFOLDER_B_PATH, List.of(), "No 'rows' array supplied."); moveRowsExpectingError(AUTO_INCREMENT_LIST, getProjectName(), SUBFOLDER_B_PATH, List.of(Map.of("InvalidKey", validId)), "Key field value required for moving list rows."); @@ -376,7 +379,7 @@ private void successfullyMoveRows(ListDefinition list, List> private int attachmentCount(List> rows) { - return (int) rows.stream().filter(row -> row.get(attachmentFieldName) != null).count(); + return (int) rows.stream().filter(row -> row.get(attachmentField.getName()) != null).count(); } private void verifySuccessfulMove( @@ -505,8 +508,8 @@ private SelectRowsResponse addRows(ListDefinition list, String containerPath, in // adds an initial set of rows without attachment values, then adds a second set of rows with attachment values. // Each row with attachment values is entered manually through the UI form. var dataGenerator = list.getTestDataGenerator(containerPath) - .addDataSupplier(stringKeyFieldName, () -> TestDataGenerator.randomString(TestDataGenerator.randomInt(21, 57))) - .addDataSupplier(attachmentFieldName, () -> null); + .addDataSupplier(stringKeyField.getName(), () -> TestDataGenerator.randomString(TestDataGenerator.randomInt(21, 57))) + .addDataSupplier(attachmentField.getName(), () -> null); dataGenerator.withGeneratedRows(numRows - numRowsWithAttachmentValue) .insertRows(); @@ -519,7 +522,7 @@ private SelectRowsResponse addRows(ListDefinition list, String containerPath, in { var newRow = new CaseInsensitiveHashMap<>(); newRow.putAll(row); - newRow.put(attachmentFieldName, SAMPLE_DATA_FILE); + newRow.put(attachmentField.getName(), SAMPLE_DATA_FILE); _listHelper.insertNewRow(newRow, false); } @@ -530,12 +533,12 @@ private SelectRowsResponse addRows(ListDefinition list, String containerPath, in private List getFields() { return List.of( - new FieldDefinition(attachmentFieldName, FieldDefinition.ColumnType.Attachment), - new FieldDefinition(booleanFieldName, FieldDefinition.ColumnType.Boolean), - new FieldDefinition(dateFieldName, FieldDefinition.ColumnType.Date), - new FieldDefinition(dateTimeFieldName, FieldDefinition.ColumnType.DateAndTime), - new FieldDefinition(decimalFieldName, FieldDefinition.ColumnType.DateAndTime), - new FieldDefinition(integerFieldName, FieldDefinition.ColumnType.Integer) + attachmentField.getFieldDefinition(), + booleanField.getFieldDefinition(), + dateField.getFieldDefinition(), + dateTimeField.getFieldDefinition(), + decimalField.getFieldDefinition(), + integerField.getFieldDefinition() ); } @@ -546,7 +549,7 @@ private Integer resolveListId(Connection conn, String listName, String container cmd.setColumns(List.of("ListId")); var response = cmd.execute(conn, containerPath); - return (Integer) response.getRows().get(0).get("ListId"); + return (Integer) response.getRows().getFirst().get("ListId"); } private void truncateList(ListDefinition list) throws IOException, CommandException @@ -564,7 +567,7 @@ private void truncateList(ListDefinition list) throws IOException, CommandExcept @Override protected String getProjectName() { - return PROJECT_NAME; + return PROJECT.getName(); } @Override From 8bb1357fe14264812ad81c71671767583785c76a Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Wed, 29 Apr 2026 15:45:02 -0700 Subject: [PATCH 2/3] ListLookupTest: use ContainerInfo and FieldInfo --- .../test/tests/list/ListLookupTest.java | 128 +++++++++--------- 1 file changed, 63 insertions(+), 65 deletions(-) diff --git a/src/org/labkey/test/tests/list/ListLookupTest.java b/src/org/labkey/test/tests/list/ListLookupTest.java index 9513d8677c..559deb827d 100644 --- a/src/org/labkey/test/tests/list/ListLookupTest.java +++ b/src/org/labkey/test/tests/list/ListLookupTest.java @@ -1,6 +1,7 @@ package org.labkey.test.tests.list; import org.jetbrains.annotations.Nullable; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -12,7 +13,9 @@ import org.labkey.test.components.CustomizeView; import org.labkey.test.pages.ImportDataPage; import org.labkey.test.pages.list.EditListDefinitionPage; +import org.labkey.test.params.ContainerInfo; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldInfo; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.DomainUtils; import org.labkey.test.util.EscapeUtil; @@ -21,13 +24,12 @@ import org.labkey.test.util.query.QueryApiHelper; import java.io.IOException; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import static org.junit.Assert.assertEquals; import static org.labkey.test.params.FieldDefinition.labelFromName; +import static org.labkey.test.util.DomainUtils.DomainKind.IntList; import static org.labkey.test.util.TextUtils.normalizeSpace; import static org.labkey.test.util.TestDataGenerator.ALL_CHARS_PLACEHOLDER; import static org.labkey.test.util.TestDataGenerator.REPEAT_PLACEHOLDER; @@ -36,16 +38,20 @@ @Category({Daily.class, Data.class, Hosting.class}) public class ListLookupTest extends BaseWebDriverTest { - private static final String lookToListName = TestDataGenerator.randomDomainName("lookToList", DomainUtils.DomainKind.IntList); + private static final ContainerInfo PROJECT = ContainerInfo.project("ListLookupTest"); + + private static final String lookToListName = IntList.randomName("lookToList"); private static final String lookToKeyFieldName = TestDataGenerator.randomFieldName("lookToKeyField", 5, 5, "" + REPEAT_PLACEHOLDER + ALL_CHARS_PLACEHOLDER, DomainUtils.DomainKind.IntList); - private static final String lookToFieldName = TestDataGenerator.randomFieldName("lookToField", null, DomainUtils.DomainKind.IntList); + private static final String lookToKeyFieldKey = EscapeUtil.fieldKeyEncodePart(lookToKeyFieldName); + private static final FieldInfo lookToField = IntList.randomField("lookToField", FieldDefinition.ColumnType.String); + private static final String lookToFieldFieldKey = EscapeUtil.fieldKeyEncodePart(lookToField.getName()); private static List> lookToListValues; private static String lookupKeyAsNameNumber; private static String lookupKeyAsNameFieldValue; - private static final String lookFromListName = TestDataGenerator.randomDomainName("lookFromList", DomainUtils.DomainKind.IntList); + private static final String lookFromListName = IntList.randomName("lookFromList"); private static final String lookFromKeyFieldName = TestDataGenerator.randomFieldName("Look From Key Field", 5, 5, "" + REPEAT_PLACEHOLDER + ALL_CHARS_PLACEHOLDER, DomainUtils.DomainKind.IntList); - private static final String lookFromLookupFieldName = TestDataGenerator.randomFieldName("Look From Lookup Field", null, DomainUtils.DomainKind.IntList); - private static final String lookFromLookupFieldKey = EscapeUtil.fieldKeyEncodePart(lookFromLookupFieldName); + private static final FieldInfo lookFromLookupField = IntList.randomField("Look From Lookup Field", new FieldDefinition.IntLookup("lists", lookToListName)); + private static final String lookFromLookupFieldKey = EscapeUtil.fieldKeyEncodePart(lookFromLookupField.getName()); @BeforeClass public static void setupProject() @@ -54,16 +60,21 @@ public static void setupProject() init.doSetup(); } + @Before + public void beforeTest() throws Exception + { + resetList(); + } + private void doSetup() { log("Setup project and list module"); _containerHelper.createProject(getProjectName(), null); log("Create a list to use as a lookup table with some number-like names."); - _listHelper.createList(getProjectName(), lookToListName, lookToKeyFieldName, - new FieldDefinition(lookToFieldName, FieldDefinition.ColumnType.String)); + _listHelper.createList(getProjectName(), lookToListName, lookToKeyFieldName, lookToField.getFieldDefinition()); String bulkData = tsvFromColumn(List.of( - lookToFieldName, + lookToField.getName(), "1E2", "102", "Lookup", @@ -73,81 +84,75 @@ private void doSetup() DataRegionTable dataRegionTable = new DataRegionTable("query", getDriver()); CustomizeView customizer = dataRegionTable.openCustomizeGrid(); customizer.showHiddenItems(); - customizer.addColumn(EscapeUtil.fieldKeyEncodePart(lookToKeyFieldName)); + customizer.addColumn(lookToKeyFieldKey); customizer.clickViewGrid(); lookToListValues = dataRegionTable.getTableData(); - lookupKeyAsNameNumber = lookToListValues.get(0).get(EscapeUtil.fieldKeyEncodePart(lookToKeyFieldName)); - lookupKeyAsNameFieldValue = lookToListValues.get(0).get(EscapeUtil.fieldKeyEncodePart(lookToFieldName)); - _listHelper.insertNewRow(Map.of(lookToFieldName, lookupKeyAsNameNumber)); + lookupKeyAsNameNumber = lookToListValues.getFirst().get(lookToKeyFieldKey); + lookupKeyAsNameFieldValue = lookToListValues.getFirst().get(lookToFieldFieldKey); + _listHelper.insertNewRow(Map.of(lookToField.getName(), lookupKeyAsNameNumber)); log("Create a second list that looks up to the first list."); _listHelper.createList(getProjectName(), lookFromListName, lookFromKeyFieldName); EditListDefinitionPage listDefinitionPage = _listHelper.goToEditDesign(lookFromListName); listDefinitionPage.getFieldsPanel() - .addField(lookFromLookupFieldName) - .setLookup(new FieldDefinition.IntLookup("lists", lookToListName)); + .addField(lookFromLookupField.getFieldDefinition()); listDefinitionPage.clickSave(); } - @Test public void testWithoutValidatorOrAlternateKeys() throws IOException, CommandException { goToProjectHome(); setLookupValidatorEnabled(false); - resetList(); log("Import data into the second list without alternate keys."); - String bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, lookupKeyAsNameNumber)); + String bulkData = tsvFromColumn(List.of(lookFromLookupField.getName(), lookupKeyAsNameNumber)); _listHelper.clickImportData() .setText(bulkData) .submit(); + log("Verify the import succeeds and resolves by primary key when not expecting alternate keys."); - List> expectedData = List.of( - Map.of(lookFromLookupFieldKey, lookupKeyAsNameFieldValue) - ); + List> expectedData = List.of(Map.of(lookFromLookupFieldKey, lookupKeyAsNameFieldValue)); validateListValues(expectedData); log("Clean out list before next import."); resetList(); + log("Import data into second list without alternate keys supplying invalid primary key"); - bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, "1000")); + bulkData = tsvFromColumn(List.of(lookFromLookupField.getName(), "1000")); _listHelper.clickImportData() .setText(bulkData) .submit(); + log("Verify the import succeeds but invalid primary key is left unresolved."); - expectedData = List.of( - Map.of(lookFromLookupFieldKey, "<1000>") - ); + expectedData = List.of(Map.of(lookFromLookupFieldKey, "<1000>")); validateListValues(expectedData); log("Check for error if not using alternate key and type does not match"); - bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, "noneSuch")); - ImportDataPage importDataPage = _listHelper.clickImportData(); - String error = importDataPage + bulkData = tsvFromColumn(List.of(lookFromLookupField.getName(), "noneSuch")); + String error = _listHelper.clickImportData() .setText(bulkData) .submitExpectingError(); checker().withScreenshot().verifyEquals("Error message for invalid primary key not as expected", - "Could not convert value 'noneSuch' (String) for Integer field '" + normalizeSpace(lookFromLookupFieldName) + "'", error); + "Could not convert value 'noneSuch' (String) for Integer field '" + normalizeSpace(lookFromLookupField.getName()) + "'", error); } @Test - public void testWithoutValidatorWithAlternateKeys() throws IOException, CommandException + public void testWithoutValidatorWithAlternateKeys() { goToProjectHome(); setLookupValidatorEnabled(false); - log("Clean out list before next import."); - resetList(); + log("Import data into the second list using number-like lookup values expecting alternate keys but also accepting primary keys."); String bulkData = tsvFromColumn(List.of( - lookFromLookupFieldName, + lookFromLookupField.getName(), "1E2", // valid alternate key looking like a number lookupKeyAsNameNumber, // valid alternate key same value as a primary key ".123", // valid alternate key looking like a float "Lookup", // valid alternate key that is a string lookupKeyAsNameNumber, // another copy "102", // valid number-like alternate key - lookToListValues.get(1).get(EscapeUtil.fieldKeyEncodePart(lookToKeyFieldName)), // primary key value not matching an alternate key + lookToListValues.get(1).get(lookToKeyFieldKey), // primary key value not matching an alternate key "1000" // primary key-type value that doesn't match )); _listHelper.clickImportData() @@ -162,33 +167,31 @@ public void testWithoutValidatorWithAlternateKeys() throws IOException, CommandE Map.of(lookFromLookupFieldKey, "Lookup"), Map.of(lookFromLookupFieldKey, lookupKeyAsNameNumber), Map.of(lookFromLookupFieldKey, "102"), - Map.of(lookFromLookupFieldKey, lookToListValues.get(1).get(EscapeUtil.fieldKeyEncodePart(lookToFieldName))), + Map.of(lookFromLookupFieldKey, lookToListValues.get(1).get(lookToFieldFieldKey)), Map.of(lookFromLookupFieldKey, "<1000>") ); validateListValues(expectedData); log("Check for error if providing non-matching string value that is not a number"); - bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, "NotAValue")); + bulkData = tsvFromColumn(List.of(lookFromLookupField.getName(), "NotAValue")); ImportDataPage importDataPage = _listHelper.clickImportData(); String error = importDataPage .setText(bulkData) .setImportLookupByAlternateKey(true) .submitExpectingError(); checker().withScreenshot().verifyEquals("Error message after supplying invalid alternate key not as expected", - "Value 'NotAValue' not found for field " + normalizeSpace(lookFromLookupFieldName) + " in the current context.", error); + "Value 'NotAValue' not found for field " + normalizeSpace(lookFromLookupField.getName()) + " in the current context.", error); } @Test - public void testWithLookupValidatorWithoutAlternateKeys() throws IOException, CommandException + public void testWithLookupValidatorWithoutAlternateKeys() { goToProjectHome(); setLookupValidatorEnabled(true); - log("Clean out list before next import."); - resetList(); // without alternate keys log("With lookup validation on, import data into the second list without alternate keys."); - String bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, lookupKeyAsNameNumber)); + String bulkData = tsvFromColumn(List.of(lookFromLookupField.getName(), lookupKeyAsNameNumber)); _listHelper.clickImportData() .setText(bulkData) .submit(); @@ -201,38 +204,36 @@ public void testWithLookupValidatorWithoutAlternateKeys() throws IOException, Co log("With lookup validation on, import data and provide an invalid primary key."); ImportDataPage importDataPage = _listHelper.clickImportData(); String error = importDataPage - .setText(tsvFromColumn(List.of(lookFromLookupFieldName, "1000"))) + .setText(tsvFromColumn(List.of(lookFromLookupField.getName(), "1000"))) .submitExpectingError(); checker().withScreenshot().verifyEquals("Error message for invalid primary key value not as expected", "Value '1000' was not present in lookup target 'lists." + normalizeSpace(lookToListName) - + "' for field '" + normalizeSpace(labelFromName(lookFromLookupFieldName)) + "'", error); + + "' for field '" + normalizeSpace(labelFromName(lookFromLookupField.getName())) + "'", error); log("With lookup validation on, import data and provide an invalid primary key of type string."); error = importDataPage - .setText(tsvFromColumn(List.of(lookFromLookupFieldName, "Look"))) + .setText(tsvFromColumn(List.of(lookFromLookupField.getName(), "Look"))) .submitExpectingError(); checker().withScreenshot().verifyEquals("Error message for invalid primary key type not as expected", - "Could not convert value 'Look' (String) for Integer field '" + normalizeSpace(lookFromLookupFieldName) + "'", error); + "Could not convert value 'Look' (String) for Integer field '" + normalizeSpace(lookFromLookupField.getName()) + "'", error); } @Test - public void testWithLookupValidatorAndAlternateKeys() throws IOException, CommandException + public void testWithLookupValidatorAndAlternateKeys() { goToProjectHome(); setLookupValidatorEnabled(true); - log("Clean out list before next import."); - resetList(); log("With lookup validation on, import data into the second list using number-like lookup values expecting alternate keys but also accepting primary keys."); String bulkData = tsvFromColumn(List.of( - lookFromLookupFieldName, + lookFromLookupField.getName(), "1E2", // valid alternate key looking like a number lookupKeyAsNameNumber, // valid alternate key same value as a primary key ".123", // valid alternate key looking like a float "Lookup", // valid alternate key that is a string lookupKeyAsNameNumber, // another copy "102", // valid number-like alternate key - lookToListValues.get(1).get(EscapeUtil.fieldKeyEncodePart(lookToKeyFieldName)) // primary key value not matching an alternate key + lookToListValues.get(1).get(lookToKeyFieldKey) // primary key value not matching an alternate key )); _listHelper.clickImportData() .setText(bulkData) @@ -246,28 +247,27 @@ public void testWithLookupValidatorAndAlternateKeys() throws IOException, Comman Map.of(lookFromLookupFieldKey, "Lookup"), Map.of(lookFromLookupFieldKey, lookupKeyAsNameNumber), Map.of(lookFromLookupFieldKey, "102"), - Map.of(lookFromLookupFieldKey, lookToListValues.get(1).get(EscapeUtil.fieldKeyEncodePart(lookToFieldName))) + Map.of(lookFromLookupFieldKey, lookToListValues.get(1).get(lookToFieldFieldKey)) ); validateListValues(expectedData); - bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, "Invalid")); + bulkData = tsvFromColumn(List.of(lookFromLookupField.getName(), "Invalid")); ImportDataPage importDataPage = _listHelper.clickImportData(); String error = importDataPage .setText(bulkData) .setImportLookupByAlternateKey(true) .submitExpectingError(); checker().withScreenshot().verifyEquals("Error message for invalid string alternate key not as expected", - "Value 'Invalid' not found for field " + normalizeSpace(lookFromLookupFieldName) + " in the current context.", error); + "Value 'Invalid' not found for field " + normalizeSpace(lookFromLookupField.getName()) + " in the current context.", error); - bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, "1234")); + bulkData = tsvFromColumn(List.of(lookFromLookupField.getName(), "1234")); error = importDataPage .setText(bulkData) .setImportLookupByAlternateKey(true) .submitExpectingError(); checker().withScreenshot().verifyEquals("Error message for invalid number-like alternate key not as expected", "Value '1234' was not present in lookup target 'lists." + normalizeSpace(lookToListName) - + "' for field '" + normalizeSpace(labelFromName(lookFromLookupFieldName)) + "'", error); - + + "' for field '" + normalizeSpace(labelFromName(lookFromLookupField.getName())) + "'", error); } private void setLookupValidatorEnabled(boolean enabled) @@ -275,7 +275,7 @@ private void setLookupValidatorEnabled(boolean enabled) log("Setting lookup validator to " + enabled + " on list " + lookFromListName); EditListDefinitionPage listDefinitionPage = _listHelper.goToEditDesign(lookFromListName); listDefinitionPage.getFieldsPanel() - .getField(lookFromLookupFieldName) + .getField(lookFromLookupField.getName()) .expand() .setLookupValidatorEnabled(enabled); listDefinitionPage.clickSave(); @@ -288,11 +288,10 @@ private void resetList() throws IOException, CommandException private void validateListValues(List> expectedValue) { - DataRegionTable dataRegionTable = new DataRegionTable("query", getDriver()); - List> actualValue = dataRegionTable.getTableData(); + List> actualValue = new DataRegionTable("query", getDriver()) + .getTableData(); - assertEquals("List data not as expected after action.", - expectedValue, actualValue); + checker().withScreenshot().verifyEquals("List data not as expected after action.", expectedValue, actualValue); } private String tsvFromColumn(List column) @@ -304,13 +303,12 @@ private String tsvFromColumn(List column) @Override protected @Nullable String getProjectName() { - return "List Lookup Test"; + return PROJECT.getName(); } @Override public List getAssociatedModules() { - return Arrays.asList("list"); + return List.of("list"); } - } From 56a42bc96b9c5cafdf8f0d7a32d45a5e855bd8f3 Mon Sep 17 00:00:00 2001 From: labkey-nicka Date: Thu, 30 Apr 2026 12:14:14 -0700 Subject: [PATCH 3/3] Code review feedback --- .../test/tests/list/ListLookupTest.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/org/labkey/test/tests/list/ListLookupTest.java b/src/org/labkey/test/tests/list/ListLookupTest.java index 559deb827d..779299f3d2 100644 --- a/src/org/labkey/test/tests/list/ListLookupTest.java +++ b/src/org/labkey/test/tests/list/ListLookupTest.java @@ -14,12 +14,9 @@ import org.labkey.test.pages.ImportDataPage; import org.labkey.test.pages.list.EditListDefinitionPage; import org.labkey.test.params.ContainerInfo; -import org.labkey.test.params.FieldDefinition; import org.labkey.test.params.FieldInfo; import org.labkey.test.util.DataRegionTable; -import org.labkey.test.util.DomainUtils; -import org.labkey.test.util.EscapeUtil; -import org.labkey.test.util.TestDataGenerator; +import org.labkey.test.util.ListHelper; import org.labkey.test.util.data.TestDataUtils; import org.labkey.test.util.query.QueryApiHelper; @@ -28,11 +25,11 @@ import java.util.List; import java.util.Map; +import static org.labkey.test.params.FieldDefinition.ColumnType; +import static org.labkey.test.params.FieldDefinition.IntLookup; import static org.labkey.test.params.FieldDefinition.labelFromName; import static org.labkey.test.util.DomainUtils.DomainKind.IntList; import static org.labkey.test.util.TextUtils.normalizeSpace; -import static org.labkey.test.util.TestDataGenerator.ALL_CHARS_PLACEHOLDER; -import static org.labkey.test.util.TestDataGenerator.REPEAT_PLACEHOLDER; // Issue 52098, Issue 49422 @Category({Daily.class, Data.class, Hosting.class}) @@ -41,17 +38,17 @@ public class ListLookupTest extends BaseWebDriverTest private static final ContainerInfo PROJECT = ContainerInfo.project("ListLookupTest"); private static final String lookToListName = IntList.randomName("lookToList"); - private static final String lookToKeyFieldName = TestDataGenerator.randomFieldName("lookToKeyField", 5, 5, "" + REPEAT_PLACEHOLDER + ALL_CHARS_PLACEHOLDER, DomainUtils.DomainKind.IntList); - private static final String lookToKeyFieldKey = EscapeUtil.fieldKeyEncodePart(lookToKeyFieldName); - private static final FieldInfo lookToField = IntList.randomField("lookToField", FieldDefinition.ColumnType.String); - private static final String lookToFieldFieldKey = EscapeUtil.fieldKeyEncodePart(lookToField.getName()); + private static final FieldInfo lookToKeyField = IntList.randomField("lookToKeyField", ColumnType.Integer); + private static final String lookToKeyFieldKey = lookToKeyField.toString(); + private static final FieldInfo lookToField = IntList.randomField("lookToField", ColumnType.String); + private static final String lookToFieldFieldKey = lookToField.toString(); private static List> lookToListValues; private static String lookupKeyAsNameNumber; private static String lookupKeyAsNameFieldValue; private static final String lookFromListName = IntList.randomName("lookFromList"); - private static final String lookFromKeyFieldName = TestDataGenerator.randomFieldName("Look From Key Field", 5, 5, "" + REPEAT_PLACEHOLDER + ALL_CHARS_PLACEHOLDER, DomainUtils.DomainKind.IntList); - private static final FieldInfo lookFromLookupField = IntList.randomField("Look From Lookup Field", new FieldDefinition.IntLookup("lists", lookToListName)); - private static final String lookFromLookupFieldKey = EscapeUtil.fieldKeyEncodePart(lookFromLookupField.getName()); + private static final FieldInfo lookFromKeyField = IntList.randomField("Look From Key Field", ColumnType.Integer); + private static final FieldInfo lookFromLookupField = IntList.randomField("Look From Lookup Field", new IntLookup(ListHelper.LIST_SCHEMA, lookToListName)); + private static final String lookFromLookupFieldKey = lookFromLookupField.toString(); @BeforeClass public static void setupProject() @@ -72,7 +69,7 @@ private void doSetup() _containerHelper.createProject(getProjectName(), null); log("Create a list to use as a lookup table with some number-like names."); - _listHelper.createList(getProjectName(), lookToListName, lookToKeyFieldName, lookToField.getFieldDefinition()); + _listHelper.createList(getProjectName(), lookToListName, lookToKeyField.getName(), lookToField.getFieldDefinition()); String bulkData = tsvFromColumn(List.of( lookToField.getName(), "1E2", @@ -92,7 +89,7 @@ private void doSetup() _listHelper.insertNewRow(Map.of(lookToField.getName(), lookupKeyAsNameNumber)); log("Create a second list that looks up to the first list."); - _listHelper.createList(getProjectName(), lookFromListName, lookFromKeyFieldName); + _listHelper.createList(getProjectName(), lookFromListName, lookFromKeyField.getName()); EditListDefinitionPage listDefinitionPage = _listHelper.goToEditDesign(lookFromListName); listDefinitionPage.getFieldsPanel() .addField(lookFromLookupField.getFieldDefinition()); @@ -283,7 +280,7 @@ private void setLookupValidatorEnabled(boolean enabled) private void resetList() throws IOException, CommandException { - new QueryApiHelper(createDefaultConnection(), getProjectName(), "lists", lookFromListName).truncateTable(); + new QueryApiHelper(createDefaultConnection(), getProjectName(), ListHelper.LIST_SCHEMA, lookFromListName).truncateTable(); } private void validateListValues(List> expectedValue)