Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 70 additions & 75 deletions src/org/labkey/test/tests/list/ListLookupTest.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -12,40 +13,42 @@
import org.labkey.test.components.CustomizeView;
import org.labkey.test.pages.ImportDataPage;
import org.labkey.test.pages.list.EditListDefinitionPage;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.params.ContainerInfo;
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;

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.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})
public class ListLookupTest extends BaseWebDriverTest
{
private static final String lookToListName = TestDataGenerator.randomDomainName("lookToList", DomainUtils.DomainKind.IntList);
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 ContainerInfo PROJECT = ContainerInfo.project("ListLookupTest");

private static final String lookToListName = IntList.randomName("lookToList");
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<Map<String, String>> lookToListValues;
private static String lookupKeyAsNameNumber;
private static String lookupKeyAsNameFieldValue;
private static final String lookFromListName = TestDataGenerator.randomDomainName("lookFromList", DomainUtils.DomainKind.IntList);
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 String lookFromListName = IntList.randomName("lookFromList");
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()
Expand All @@ -54,16 +57,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, lookToKeyField.getName(), lookToField.getFieldDefinition());
String bulkData = tsvFromColumn(List.of(
lookToFieldName,
lookToField.getName(),
"1E2",
"102",
"Lookup",
Expand All @@ -73,81 +81,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);
_listHelper.createList(getProjectName(), lookFromListName, lookFromKeyField.getName());
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<Map<String, String>> expectedData = List.of(
Map.of(lookFromLookupFieldKey, lookupKeyAsNameFieldValue)
);
List<Map<String, String>> 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()
Expand All @@ -162,33 +164,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();
Expand All @@ -201,38 +201,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)
Expand All @@ -246,53 +244,51 @@ 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)
{
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();
}

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<Map<String, String>> expectedValue)
{
DataRegionTable dataRegionTable = new DataRegionTable("query", getDriver());
List<Map<String, String>> actualValue = dataRegionTable.getTableData();
List<Map<String, String>> 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<String> column)
Expand All @@ -304,13 +300,12 @@ private String tsvFromColumn(List<String> column)
@Override
protected @Nullable String getProjectName()
{
return "List Lookup Test";
return PROJECT.getName();
}

@Override
public List<String> getAssociatedModules()
{
return Arrays.asList("list");
return List.of("list");
}

}
Loading
Loading