diff --git a/src/org/labkey/test/components/CustomizeView.java b/src/org/labkey/test/components/CustomizeView.java index 4e688abdc5..9d8fb0ff73 100644 --- a/src/org/labkey/test/components/CustomizeView.java +++ b/src/org/labkey/test/components/CustomizeView.java @@ -31,6 +31,7 @@ import org.labkey.test.params.FieldKey; import org.labkey.test.selenium.RefindingWebElement; import org.labkey.test.util.DataRegionTable; +import org.labkey.test.util.EscapeUtil; import org.labkey.test.util.Ext4Helper; import org.labkey.test.util.LogMethod; import org.labkey.test.util.LoggedParam; @@ -335,6 +336,20 @@ public enum ViewItemType Sort } + private String encodeFieldKeyPart(String fieldKeyPart) + { + String _fieldKeyPart = EscapeUtil.encodeUriPath(fieldKeyPart); + if (_fieldKeyPart != null) + { + // Jetty encodes # ? ; ' but we want to preserve these characters in paths + _fieldKeyPart = _fieldKeyPart.replaceAll("%23", "#"); + _fieldKeyPart = _fieldKeyPart.replaceAll("%3F", "?"); + _fieldKeyPart = _fieldKeyPart.replaceAll("%3B", ";"); + _fieldKeyPart = _fieldKeyPart.replaceAll("%27", "'"); + } + return _fieldKeyPart; + } + /** * expand customize view fields tree to expose the specified column * @return The row element for the specified column @@ -343,7 +358,7 @@ private WebElement expandPivots(CharSequence fieldKey) { Iterator fieldKeyIterator = Objects.requireNonNull(FieldKey.fromFieldKey(fieldKey), "Invalid fieldKey: " + fieldKey).getIterator(); FieldKey currentFieldKey = fieldKeyIterator.next(); - String dataRecordId = currentFieldKey.toString().toUpperCase(); + String dataRecordId = encodeFieldKeyPart(currentFieldKey.toString().toUpperCase()); while (fieldKeyIterator.hasNext()) { @@ -358,7 +373,7 @@ private WebElement expandPivots(CharSequence fieldKey) WebDriverWrapper.waitFor(() -> Locator.css("tr[data-recordid] + tr:not(.x4-grid-row)").findElements(getComponentElement()).isEmpty(), 2000); // Spacer row appears during expansion animation currentFieldKey = fieldKeyIterator.next(); - dataRecordId = currentFieldKey.toString().toUpperCase(); + dataRecordId = encodeFieldKeyPart(currentFieldKey.toString().toUpperCase()); } return Locator.tag("tr").withClass("x4-grid-data-row").withAttribute("data-recordid", dataRecordId).findElement(getComponentElement()); diff --git a/src/org/labkey/test/tests/component/GridPanelTest.java b/src/org/labkey/test/tests/component/GridPanelTest.java index d38641af9b..99711eba1f 100644 --- a/src/org/labkey/test/tests/component/GridPanelTest.java +++ b/src/org/labkey/test/tests/component/GridPanelTest.java @@ -23,6 +23,7 @@ import org.labkey.test.components.ui.search.FilterExpressionPanel; import org.labkey.test.components.ui.search.FilterFacetedPanel; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldInfo; import org.labkey.test.params.FieldKey; import org.labkey.test.params.experiment.SampleTypeDefinition; import org.labkey.test.util.DataRegionTable; @@ -64,11 +65,11 @@ public class GridPanelTest extends GridPanelBaseTest // Column names. private static final String FILTER_NAME_COL = "Name"; private static final String FILTER_EXPDATE_COL = "Expiration Date"; - private static final String FILTER_STRING_COL = "Str"; - private static final String FILTER_INT_COL = "Int"; - private static final String FILTER_EXTEND_CHAR_COL = "\u0106\u00D8\u0139"; - private static final String FILTER_BOOL_COL = "Bool"; - private static final String FILTER_DATE_COL = "Date"; + private static final FieldInfo FILTER_STRING_COL = new FieldInfo("Str\uD83D\uDC7E]|*안", FieldDefinition.ColumnType.String); + private static final FieldInfo FILTER_INT_COL = new FieldInfo("Int&`~_@", FieldDefinition.ColumnType.Integer); + private static final FieldInfo FILTER_EXTEND_CHAR_COL = new FieldInfo(TestDataGenerator.randomFieldName("\u0106\u00D8\u0139", 0, 5), FieldDefinition.ColumnType.String); + private static final FieldInfo FILTER_BOOL_COL = new FieldInfo(TestDataGenerator.randomFieldName("Bool", 0, 5), FieldDefinition.ColumnType.Boolean); + private static final FieldInfo FILTER_DATE_COL = new FieldInfo(TestDataGenerator.randomFieldName("Date", 0, 5), FieldDefinition.ColumnType.DateAndTime); private static final String FILTER_STORED_AMOUNT_COL = "Amount"; // Views and columns used in the views. The views are only applied to the small sample type (Small_SampleType). @@ -77,7 +78,6 @@ public class GridPanelTest extends GridPanelBaseTest private static final String VIEW_FILTERED_COLUMN = "Filtered_Column"; private static final List extraColumnsNames = Arrays.asList("IsAliquot", "genId"); // Special case for adding the columns to the view and calling getRows api. private static final List extraColumnsHeaders = Arrays.asList("Is Aliquot", "Gen Id"); // The column headers as they appear in the UI and exported file. - private static final List removedColumns = Arrays.asList(FILTER_BOOL_COL); // Various values used to populate Str field for records. Also used in filtering/searching. // Note: Small_SampleType is populated with random data and will have none of these values. @@ -143,10 +143,11 @@ private void doSetup() throws IOException, CommandException private void createSmallSampleType() throws IOException, CommandException { SampleTypeDefinition props = new SampleTypeDefinition(SMALL_SAMPLE_TYPE) - .setFields(Arrays.asList(new FieldDefinition(FILTER_INT_COL, FieldDefinition.ColumnType.Integer), - new FieldDefinition(FILTER_STRING_COL, FieldDefinition.ColumnType.String), - new FieldDefinition(FILTER_DATE_COL, FieldDefinition.ColumnType.DateAndTime), - new FieldDefinition(FILTER_BOOL_COL, FieldDefinition.ColumnType.Boolean))); + .setFields(Arrays.asList( + FILTER_INT_COL.getFieldDefinition(), + FILTER_STRING_COL.getFieldDefinition(), + FILTER_DATE_COL.getFieldDefinition(), + FILTER_BOOL_COL.getFieldDefinition())); TestDataGenerator sampleSetDataGenerator = SampleTypeAPIHelper.createEmptySampleType(getProjectName(), props); @@ -159,10 +160,10 @@ private void createSmallSampleType() throws IOException, CommandException sampleSetDataGenerator.addCustomRow( Map.of(FILTER_NAME_COL, String.format("%s%d", SMALL_SAMPLE_PREFIX, rowCount), - FILTER_INT_COL, TestDataGenerator.randomInt(1, INT_MAX), - FILTER_STRING_COL, stringSets.get(setIndex++), - FILTER_DATE_COL, sampleSetDataGenerator.randomDateString(DateUtils.addWeeks(new Date(), -25), new Date()), - FILTER_BOOL_COL, sampleSetDataGenerator.randomBoolean()) + FILTER_INT_COL.getName(), TestDataGenerator.randomInt(1, INT_MAX), + FILTER_STRING_COL.getName(), stringSets.get(setIndex++), + FILTER_DATE_COL.getName(), sampleSetDataGenerator.randomDateString(DateUtils.addWeeks(new Date(), -25), new Date()), + FILTER_BOOL_COL.getName(), sampleSetDataGenerator.randomBoolean()) ); } @@ -190,14 +191,14 @@ private void createSmallSampleType() throws IOException, CommandException log(String.format("Create the '%s' view for the '%s' sample type.", VIEW_FEWER_COLUMNS, SMALL_SAMPLE_TYPE)); cv = drtSamples.openCustomizeGrid(); - for(String columnName : removedColumns) + for(FieldInfo column : List.of(FILTER_BOOL_COL)) { - cv.removeColumn(columnName); + cv.removeColumn(column); } cv.saveCustomView(VIEW_FEWER_COLUMNS); log(String.format("Finally create a view named '%s' for '%s' that only has a filter.", VIEW_FILTERED_COLUMN, SMALL_SAMPLE_TYPE)); - drtSamples.setFilter(FieldKey.encodePart(FILTER_STRING_COL), "Contains One Of", String.format("%1$s\n%1$s%2$s", stringSetMembers.get(0), stringSetMembers.get(1))); + drtSamples.setFilter(FILTER_STRING_COL, "Contains One Of", String.format("%1$s\n%1$s%2$s", stringSetMembers.get(0), stringSetMembers.get(1))); cv = drtSamples.openCustomizeGrid(); cv.saveCustomView(VIEW_FILTERED_COLUMN); @@ -209,9 +210,9 @@ private void createSmallSampleType() throws IOException, CommandException private void createFilterSampleType() throws IOException, CommandException { List fields = new ArrayList<>(); - fields.add(new FieldDefinition(FILTER_STRING_COL, FieldDefinition.ColumnType.String)); - fields.add(new FieldDefinition(FILTER_INT_COL, FieldDefinition.ColumnType.Integer)); - fields.add(new FieldDefinition(FILTER_EXTEND_CHAR_COL, FieldDefinition.ColumnType.String)); + fields.add(FILTER_STRING_COL.getFieldDefinition()); + fields.add(FILTER_INT_COL.getFieldDefinition()); + fields.add(FILTER_EXTEND_CHAR_COL.getFieldDefinition()); SampleTypeDefinition sampleTypeDefinition = new SampleTypeDefinition(FILTER_SAMPLE_TYPE).setFields(fields); @@ -291,9 +292,9 @@ else if(sampleId % 7 == 0 && stringWithNumCount < NUMBER_STRING_COUNT) sampleSetDataGenerator.addCustomRow( Map.of(FILTER_NAME_COL, String.format("%s%d", FILTER_SAMPLE_PREFIX, sampleId++), - FILTER_INT_COL, intValue++, - FILTER_STRING_COL, filterColValue, - FILTER_EXTEND_CHAR_COL, extColValue)); + FILTER_INT_COL.getName(), intValue++, + FILTER_STRING_COL.getName(), filterColValue, + FILTER_EXTEND_CHAR_COL.getName(), extColValue)); } @@ -724,8 +725,8 @@ public void testMultipleFiltersOnOneColumn() throws IOException, CommandExceptio // Query the table to get the expected number of rows. List filters = List.of( - new Filter(FILTER_INT_COL, low, Filter.Operator.getOperator("GREATER_THAN")), - new Filter(FILTER_INT_COL, high, Filter.Operator.getOperator("LESS_THAN_OR_EQUAL"))); + new Filter(FILTER_INT_COL.toString(), low, Filter.Operator.getOperator("GREATER_THAN")), + new Filter(FILTER_INT_COL.toString(), high, Filter.Operator.getOperator("LESS_THAN_OR_EQUAL"))); int expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); checker().withScreenshot("Multiple_Filters_One_Column_Error") @@ -831,7 +832,7 @@ public void testFilterErrorAndFilterOnlyTab() log(String.format("Filter on the '%s' field. This should only provide a 'Filter' tab.", FILTER_INT_COL)); - filterDialog.selectField(FILTER_INT_COL); + filterDialog.selectField(FILTER_INT_COL.getLabel()); checker().verifyFalse(String.format("There should be no 'Choose Values' tab for the '%s' field.", FILTER_INT_COL), filterDialog.getTabText().contains("Choose Values")); @@ -847,7 +848,7 @@ public void testFilterErrorAndFilterOnlyTab() String errorMsg = filterDialog.confirmExpectingError(); checker().verifyEquals("Expected error message not present.", - String.format("Missing filter values for: %s.", FILTER_INT_COL), errorMsg); + String.format("Missing filter values for: %s.", FILTER_INT_COL.getLabel()), errorMsg); checker().screenShotIfNewError("Filter_Dialog_Error"); @@ -885,7 +886,7 @@ public void testInteractionBetweenDialogTabs() throws IOException, CommandExcept log(String.format("Select '%s' and get the list of values for the field before filtering.", FILTER_STRING_COL)); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); FilterFacetedPanel facetedPanel = filterDialog.selectFacetTab(); @@ -919,7 +920,7 @@ public void testInteractionBetweenDialogTabs() throws IOException, CommandExcept log(String.format("Open the dialog again and validate that the list of values to select from for '%s' is reduced.", FILTER_STRING_COL)); filterDialog = grid.getGridBar().openFilterDialog(); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); facetedPanel = filterDialog.selectFacetTab(); actualValues = facetedPanel.getAvailableValues(); @@ -943,7 +944,7 @@ public void testInteractionBetweenDialogTabs() throws IOException, CommandExcept log("Validate that applying a filter for a fields checks the values in the dialog."); filterDialog = grid.getGridBar().openFilterDialog(); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); String firstFilterValue = stringSets.get(0); @@ -996,7 +997,7 @@ public void testInteractionBetweenDialogTabs() throws IOException, CommandExcept // Query the table to get the expected number of rows to be returned. List filters = List.of( - new Filter(FILTER_STRING_COL, String.format("%s;%s", firstFilterValue, secondFilterValue), + new Filter(FILTER_STRING_COL.toString(), String.format("%s;%s", firstFilterValue, secondFilterValue), Filter.Operator.getOperator("IN"))); int expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); @@ -1029,15 +1030,15 @@ public void testSearchAndFilter() throws IOException, CommandException GridFilterModal filterDialog = grid.getGridBar().openFilterDialog(); - filterDialog.selectField(FILTER_INT_COL); + filterDialog.selectField(FILTER_INT_COL.getLabel()); - log(String.format("Filter '%s' for values between %d and %d.", FILTER_INT_COL, low, high)); + log(String.format("Filter '%s' for values between %d and %d.", FILTER_INT_COL.getLabel(), low, high)); FilterExpressionPanel expressionPanel = filterDialog.selectExpressionTab(); expressionPanel.setFilters(new FilterExpressionPanel.Expression(Filter.Operator.GT, low), new FilterExpressionPanel.Expression(Filter.Operator.LT, high)); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); filterDialog.selectFacetTab(); @@ -1055,9 +1056,9 @@ public void testSearchAndFilter() throws IOException, CommandException // Query the table to get the expected number of rows to be returned. Will modify this list later so make it mutable. List filters = new ArrayList<>(); - filters.add(new Filter(FILTER_STRING_COL, oneOfFilter, Filter.Operator.getOperator("CONTAINS_ONE_OF"))); - filters.add(new Filter(FILTER_INT_COL, low, Filter.Operator.getOperator("GREATER_THAN"))); - filters.add(new Filter(FILTER_INT_COL, high, Filter.Operator.getOperator("LESS_THAN"))); + filters.add(new Filter(FILTER_STRING_COL.toString(), oneOfFilter, Filter.Operator.getOperator("CONTAINS_ONE_OF"))); + filters.add(new Filter(FILTER_INT_COL.toString(), low, Filter.Operator.getOperator("GREATER_THAN"))); + filters.add(new Filter(FILTER_INT_COL.toString(), high, Filter.Operator.getOperator("LESS_THAN"))); int expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); checker().verifyEquals("Number of rows after filter applied not as expected.", @@ -1072,7 +1073,7 @@ public void testSearchAndFilter() throws IOException, CommandException grid.getGridBar().searchFor(searchString); // Because the search string is specific to the Str column a query can be used to get the expected count. - filters.add(new Filter(FILTER_STRING_COL, searchString, Filter.Operator.getOperator("CONTAINS"))); + filters.add(new Filter(FILTER_STRING_COL.toString(), searchString, Filter.Operator.getOperator("CONTAINS"))); expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); checker().withScreenshot("Filter_With_Search_Error") @@ -1088,7 +1089,7 @@ public void testSearchAndFilter() throws IOException, CommandException // Again can use a query to get the expected number of rows from the search. filters = new ArrayList<>(); - filters.add(new Filter(FILTER_STRING_COL, searchString, Filter.Operator.getOperator("CONTAINS"))); + filters.add(new Filter(FILTER_STRING_COL.toString(), searchString, Filter.Operator.getOperator("CONTAINS"))); expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); checker().verifyEquals("Number of rows after filter were cleared not as expected.", @@ -1122,15 +1123,15 @@ public void testFilterPills() throws IOException, CommandException GridFilterModal filterDialog = grid.getGridBar().openFilterDialog(); - filterDialog.selectField(FILTER_INT_COL); + filterDialog.selectField(FILTER_INT_COL.getLabel()); - log(String.format("Filter '%s' for values greater than %d and less than %d.", FILTER_INT_COL, low, high)); + log(String.format("Filter '%s' for values greater than %d and less than %d.", FILTER_INT_COL.getLabel(), low, high)); FilterExpressionPanel expressionPanel = filterDialog.selectExpressionTab(); expressionPanel.setFilters(new FilterExpressionPanel.Expression(Filter.Operator.GT, low), new FilterExpressionPanel.Expression(Filter.Operator.LT, high)); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); String oneOfFilter = String.format("%s\n%s\n%s", stringSetMembers.get(0), stringSetMembers.get(1), stringSetMembers.get(2)); @@ -1140,8 +1141,8 @@ public void testFilterPills() throws IOException, CommandException expressionPanel.setFilter(new FilterExpressionPanel.Expression(Filter.Operator.CONTAINS_ONE_OF, oneOfFilter)); List expectedValues = new ArrayList<>(); - expectedValues.add(FILTER_INT_COL); - expectedValues.add(FILTER_STRING_COL); + expectedValues.add(FILTER_INT_COL.getLabel()); + expectedValues.add(FILTER_STRING_COL.getLabel()); List actualValues = filterDialog.getFilteredFieldLabels(); @@ -1149,16 +1150,16 @@ public void testFilterPills() throws IOException, CommandException Collections.sort(actualValues); checker().withScreenshot("Filtered_Fields_Not_Marked") - .verifyEquals(String.format("The '%s' and '%s' fields are not marked as filtered.", FILTER_INT_COL, FILTER_STRING_COL), + .verifyEquals(String.format("The '%s' and '%s' fields are not marked as filtered.", FILTER_INT_COL.getLabel(), FILTER_STRING_COL), expectedValues, actualValues); filterDialog.confirm(); - String pillToRemove = String.format("%s < %d", FILTER_INT_COL, high); + String pillToRemove = String.format("%s < %d", FILTER_INT_COL.getLabel(), high); expectedValues = new ArrayList<>(); expectedValues.add(pillToRemove); - expectedValues.add(String.format("%s > %d", FILTER_INT_COL, low)); + expectedValues.add(String.format("%s > %d", FILTER_INT_COL.getLabel(), low)); expectedValues.add(String.format("%s Contains One Of %s", FILTER_STRING_COL, oneOfFilter.replace("\n", ", "))); List filterPills = grid.getFilterStatusValues(); @@ -1172,9 +1173,9 @@ public void testFilterPills() throws IOException, CommandException expectedValues, actualValues); List filters = List.of( - new Filter(FILTER_INT_COL, low, Filter.Operator.getOperator("GREATER_THAN")), - new Filter(FILTER_INT_COL, high, Filter.Operator.getOperator("LESS_THAN")), - new Filter(FILTER_STRING_COL, oneOfFilter, Filter.Operator.getOperator("CONTAINS_ONE_OF"))); + new Filter(FILTER_INT_COL.toString(), low, Filter.Operator.getOperator("GREATER_THAN")), + new Filter(FILTER_INT_COL.toString(), high, Filter.Operator.getOperator("LESS_THAN")), + new Filter(FILTER_STRING_COL.toString(), oneOfFilter, Filter.Operator.getOperator("CONTAINS_ONE_OF"))); int expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); checker().verifyEquals("Rows returned after filters applied not as expected.", @@ -1193,8 +1194,8 @@ public void testFilterPills() throws IOException, CommandException } filters = List.of( - new Filter(FILTER_INT_COL, low, Filter.Operator.getOperator("GREATER_THAN")), - new Filter(FILTER_STRING_COL, oneOfFilter, Filter.Operator.getOperator("CONTAINS_ONE_OF"))); + new Filter(FILTER_INT_COL.toString(), low, Filter.Operator.getOperator("GREATER_THAN")), + new Filter(FILTER_STRING_COL.toString(), oneOfFilter, Filter.Operator.getOperator("CONTAINS_ONE_OF"))); expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); checker().verifyEquals("Rows returned after filter pill removed not as expected.", @@ -1220,18 +1221,18 @@ public void testFilterPills() throws IOException, CommandException */ expectedValues = new ArrayList<>(); - expectedValues.add(FILTER_INT_COL); - expectedValues.add(FILTER_STRING_COL); + expectedValues.add(FILTER_INT_COL.getLabel()); + expectedValues.add(FILTER_STRING_COL.getLabel()); actualValues = filterDialog.getFilteredFieldLabels(); Collections.sort(expectedValues); Collections.sort(actualValues); - checker().verifyEquals(String.format("Both the '%s' and '%s' fields should be marked as filtered.", FILTER_INT_COL, FILTER_STRING_COL), + checker().verifyEquals(String.format("Both the '%s' and '%s' fields should be marked as filtered.", FILTER_INT_COL.getLabel(), FILTER_STRING_COL), expectedValues, actualValues); - filterDialog.selectField(FILTER_INT_COL); + filterDialog.selectField(FILTER_INT_COL.getLabel()); expressionPanel = filterDialog.selectExpressionTab(); @@ -1248,7 +1249,7 @@ public void testFilterPills() throws IOException, CommandException checker().screenShotIfNewError("Populated_Filter_Int_Field_Error"); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); expressionPanel = filterDialog.selectExpressionTab(); @@ -1270,13 +1271,13 @@ public void testFilterPills() throws IOException, CommandException private void createSemicolonSampleType() throws IOException, CommandException { SampleTypeDefinition props = new SampleTypeDefinition(SEMICOLON_SAMPLE_TYPE) - .setFields(Arrays.asList(new FieldDefinition(FILTER_STRING_COL, FieldDefinition.ColumnType.String))); + .setFields(Arrays.asList(FILTER_STRING_COL.getFieldDefinition())); TestDataGenerator sampleSetDataGenerator = SampleTypeAPIHelper.createEmptySampleType(getProjectName(), props); for (int i = 0; i < SEMICOLON_VALUES.length; i++) - sampleSetDataGenerator.addCustomRow(Map.of(FILTER_NAME_COL, "Semi_" + i, FILTER_STRING_COL, SEMICOLON_VALUES[i])); + sampleSetDataGenerator.addCustomRow(Map.of(FILTER_NAME_COL, "Semi_" + i, FILTER_STRING_COL.getName(), SEMICOLON_VALUES[i])); // add a second for one of the values to test with filtering behavior - sampleSetDataGenerator.addCustomRow(Map.of(FILTER_NAME_COL, "Semi_5", FILTER_STRING_COL, SEMICOLON_VALUES[4])); + sampleSetDataGenerator.addCustomRow(Map.of(FILTER_NAME_COL, "Semi_5", FILTER_STRING_COL.getName(), SEMICOLON_VALUES[4])); sampleSetDataGenerator.insertRows(); } @@ -1325,7 +1326,7 @@ public void testFilterValueWithSemicolon() throws IOException, CommandException log("Testing filtering for individual values using faceted filter tab"); for (String value : SEMICOLON_VALUES) { - GridFilterModal filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL); + GridFilterModal filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL.getLabel()); filterModal.selectFacetTab().selectValue(value); filterModal.confirm(); int expectedCount = value.equals(SEMICOLON_VALUES[4]) ? 2 : 1; @@ -1337,7 +1338,7 @@ public void testFilterValueWithSemicolon() throws IOException, CommandException log("Testing selected faceted value, switching tabs, and confirming Equals filter"); for (String value : SEMICOLON_VALUES) { - GridFilterModal filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL); + GridFilterModal filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL.getLabel()); filterModal.selectFacetTab().selectValue(value); FilterExpressionPanel expressionPanel = filterModal.selectExpressionTab(); checker().verifyTrue("Filter type not as expected", expressionPanel.hasFilterType(0, "Equals")); @@ -1350,7 +1351,7 @@ public void testFilterValueWithSemicolon() throws IOException, CommandException } log("Testing combination of selected faceted values, switching tabs, and confirming Equals One Of filter type/values"); - GridFilterModal filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL); + GridFilterModal filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL.getLabel()); FilterFacetedPanel facetedPanel = filterModal.selectFacetTab(); facetedPanel.selectValue(SEMICOLON_VALUES[0]); facetedPanel.checkValues(SEMICOLON_VALUES[4]); @@ -1359,7 +1360,7 @@ public void testFilterValueWithSemicolon() throws IOException, CommandException checker().verifyEquals("Filter value not as expected", expressionPanel.getFilterTextValue(0), SEMICOLON_VALUES[0] + "\n" + SEMICOLON_VALUES[4]); filterModal.confirm(); checker().verifyEquals("Number of records returned from filter not as expected.", 3, grid.getRecordCount()); - filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL); + filterModal = grid.getGridBar().openFilterDialog().selectField(FILTER_STRING_COL.getLabel()); facetedPanel = filterModal.selectFacetTab(); facetedPanel.selectValue(SEMICOLON_VALUES[0]); facetedPanel.checkValues(SEMICOLON_VALUES[4]); @@ -1390,7 +1391,7 @@ public void testSearchIsSameAsContainsFilter() throws IOException, CommandExcept // Identify how many rows should be returned. List filters = List.of( - new Filter(FILTER_STRING_COL, searchString, Filter.Operator.getOperator("CONTAINS"))); + new Filter(FILTER_STRING_COL.toString(), searchString, Filter.Operator.getOperator("CONTAINS"))); int expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); int actualCount = grid.getRecordCount(); @@ -1405,7 +1406,7 @@ public void testSearchIsSameAsContainsFilter() throws IOException, CommandExcept GridFilterModal filterDialog = grid.getGridBar().openFilterDialog(); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); FilterExpressionPanel expressionPanel = filterDialog.selectExpressionTab(); expressionPanel.setFilter(new FilterExpressionPanel.Expression(Filter.Operator.CONTAINS, searchString)); @@ -1457,9 +1458,9 @@ public void testSearchAcrossColumns() throws IOException, CommandException // Query the table to get a list of samples/rows that should not be in the result from the search. List filters = List.of(new Filter(FILTER_NAME_COL, searchString, Filter.Operator.getOperator("DOES_NOT_CONTAIN")), - new Filter(FILTER_STRING_COL, searchString, Filter.Operator.getOperator("DOES_NOT_CONTAIN")), - new Filter(FILTER_EXTEND_CHAR_COL, searchString, Filter.Operator.getOperator("DOES_NOT_CONTAIN")), - new Filter(FILTER_INT_COL, searchString, Filter.Operator.getOperator("EQUAL"))); + new Filter(FILTER_STRING_COL.toString(), searchString, Filter.Operator.getOperator("DOES_NOT_CONTAIN")), + new Filter(FILTER_EXTEND_CHAR_COL.toString(), searchString, Filter.Operator.getOperator("DOES_NOT_CONTAIN")), + new Filter(FILTER_INT_COL.toString(), searchString, Filter.Operator.getOperator("EQUAL"))); List> rows = getExpectedResults(FILTER_SAMPLE_TYPE, null, Arrays.asList(FILTER_NAME_COL), filters); boolean error = false; @@ -1499,23 +1500,23 @@ public void testFilteringAndSearchingForExtendedCharacters() throws IOException, grid.getGridBar().clearSearch(); - log(String.format("Filter the '%s' column for value '%s'.", FILTER_EXTEND_CHAR_COL, EXTEND_RECORD_STRING)); + log(String.format("Filter the '%s' column for value '%s'.", FILTER_EXTEND_CHAR_COL.getLabel(), EXTEND_RECORD_STRING)); GridFilterModal filterDialog = grid.getGridBar().openFilterDialog(); - filterDialog.selectField(FILTER_EXTEND_CHAR_COL); + filterDialog.selectField(FILTER_EXTEND_CHAR_COL.getLabel()); FilterExpressionPanel expressionPanel = filterDialog.selectExpressionTab(); expressionPanel.setFilter(new FilterExpressionPanel.Expression(Filter.Operator.CONTAINS, EXTEND_RECORD_STRING)); filterDialog.confirm(); List filters = List.of( - new Filter(FILTER_EXTEND_CHAR_COL, EXTEND_RECORD_STRING, Filter.Operator.getOperator("EQUAL"))); + new Filter(FILTER_EXTEND_CHAR_COL.toString(), EXTEND_RECORD_STRING, Filter.Operator.getOperator("EQUAL"))); int expectedCount = getExpectedResults(FILTER_SAMPLE_TYPE, null, null, filters).size(); checker().withScreenshot("Filter_Extended_Error") .verifyEquals(String.format("Number of records returned when filtering column '%s' for '%s' not as expected.", - FILTER_EXTEND_CHAR_COL, EXTEND_RECORD_STRING), + FILTER_EXTEND_CHAR_COL.getLabel(), EXTEND_RECORD_STRING), expectedCount, grid.getRecordCount()); } @@ -1534,10 +1535,11 @@ public void testExport() throws IOException, CommandException log("Filter the grid and validate only the filtered results are exported."); grid.filterColumn(FILTER_STRING_COL, Filter.Operator.EQUAL, MULTI_PAGE_STRING); - List columns = Arrays.asList(FILTER_NAME_COL, FILTER_STRING_COL, FILTER_INT_COL, FILTER_EXTEND_CHAR_COL); + List columns = Arrays.asList(new FieldInfo(FILTER_NAME_COL), FILTER_STRING_COL, FILTER_INT_COL, FILTER_EXTEND_CHAR_COL); + List columnsFKs = Arrays.asList(FILTER_NAME_COL, FILTER_STRING_COL.toString(), FILTER_INT_COL.toString(), FILTER_EXTEND_CHAR_COL.toString()); List filters = List.of( - new Filter(FILTER_STRING_COL, MULTI_PAGE_STRING, Filter.Operator.getOperator("EQUAL"))); - List> expectedValues = getExpectedResults(FILTER_SAMPLE_TYPE, null, columns, filters); + new Filter(FILTER_STRING_COL.toString(), MULTI_PAGE_STRING, Filter.Operator.getOperator("EQUAL"))); + List> expectedValues = getExpectedResults(FILTER_SAMPLE_TYPE, null, columnsFKs, filters); File exportedFile = grid.getGridBar().exportData(GridBar.ExportType.CSV); @@ -1553,8 +1555,8 @@ public void testExport() throws IOException, CommandException grid.clearFilters(); filters = List.of( - new Filter(FILTER_STRING_COL, ONE_PAGE_STRING, Filter.Operator.getOperator("EQUAL"))); - expectedValues = getExpectedResults(FILTER_SAMPLE_TYPE, null, columns, filters); + new Filter(FILTER_STRING_COL.toString(), ONE_PAGE_STRING, Filter.Operator.getOperator("EQUAL"))); + expectedValues = getExpectedResults(FILTER_SAMPLE_TYPE, null, columnsFKs, filters); exportedFile = grid.getGridBar().exportData(GridBar.ExportType.CSV); @@ -1570,25 +1572,25 @@ public void testExport() throws IOException, CommandException exportedFile = grid.getGridBar().exportData(GridBar.ExportType.CSV); // The extra column added have spaces in the name so the column header in the exported file, so use the header values. - columns = new ArrayList<>(extraColumnsHeaders); - columns.add(FILTER_DATE_COL); - columns.add(FILTER_NAME_COL); - columns.add(FILTER_BOOL_COL); - columns.add(FILTER_STRING_COL); - columns.add(FILTER_INT_COL); - validateExportedColumnHeader(exportedFile, columns, new ArrayList<>()); + List columnLabels = new ArrayList<>(extraColumnsHeaders); + columnLabels.add(FILTER_DATE_COL.getLabel()); + columnLabels.add(FILTER_NAME_COL); + columnLabels.add(FILTER_BOOL_COL.getLabel()); + columnLabels.add(FILTER_STRING_COL.getLabel()); + columnLabels.add(FILTER_INT_COL.getLabel()); + validateExportedColumnHeader(exportedFile, columnLabels, new ArrayList<>()); log(String.format("Now select the '%s' view.", VIEW_FEWER_COLUMNS)); grid.selectView(VIEW_FEWER_COLUMNS); exportedFile = grid.getGridBar().exportData(GridBar.ExportType.CSV); - columns = new ArrayList<>(); - columns.add(FILTER_DATE_COL); - columns.add(FILTER_NAME_COL); - columns.add(FILTER_STRING_COL); - columns.add(FILTER_INT_COL); - validateExportedColumnHeader(exportedFile, columns, removedColumns); + columnLabels = new ArrayList<>(); + columnLabels.add(FILTER_DATE_COL.getLabel()); + columnLabels.add(FILTER_NAME_COL); + columnLabels.add(FILTER_STRING_COL.getLabel()); + columnLabels.add(FILTER_INT_COL.getLabel()); + validateExportedColumnHeader(exportedFile, columnLabels, List.of(FILTER_BOOL_COL.getLabel())); // Test for Issue 46465 (Sample export do not respect filter when samples have been selected) grid = beginAtQueryGrid(FILTER_SAMPLE_TYPE); @@ -1617,13 +1619,13 @@ public void testExport() throws IOException, CommandException for(String colValue : intColData) { // All the rows will have the same value in the string column (FILTER_STRING_COL). - expectedData.add(Map.of(FILTER_STRING_COL, NUMBER_STRING, - FILTER_INT_COL, colValue)); + expectedData.add(Map.of(FILTER_STRING_COL.getName(), NUMBER_STRING, + FILTER_INT_COL.getName(), colValue)); } exportedFile = grid.getGridBar().exportData(GridBar.ExportType.CSV); - validateExportedData(exportedFile, expectedData, Arrays.asList(FILTER_STRING_COL, FILTER_INT_COL)); + validateExportedData(exportedFile, expectedData, List.of(FILTER_STRING_COL, FILTER_INT_COL)); } } @@ -1672,10 +1674,10 @@ public void testFilterDialogWithViews() throws IOException, CommandException List expectedList = new ArrayList<>(extraColumnsHeaders); expectedList.add(FILTER_NAME_COL); - expectedList.add(FILTER_STRING_COL); - expectedList.add(FILTER_INT_COL); - expectedList.add(FILTER_BOOL_COL); - expectedList.add(FILTER_DATE_COL); + expectedList.add(FILTER_STRING_COL.getLabel()); + expectedList.add(FILTER_INT_COL.getLabel()); + expectedList.add(FILTER_BOOL_COL.getLabel()); + expectedList.add(FILTER_DATE_COL.getLabel()); checker().withScreenshot("View_Extra_Field_Error") .verifyTrue(String.format("The fields listed in the dialog do not have expected values '%s'.", expectedList), @@ -1688,7 +1690,7 @@ public void testFilterDialogWithViews() throws IOException, CommandException grid.selectView(VIEW_FEWER_COLUMNS); expectedList.removeAll(extraColumnsHeaders); - expectedList.removeAll(removedColumns); + expectedList.remove(FILTER_BOOL_COL.getLabel()); filterDialog = grid.getGridBar().openFilterDialog(); actualList = filterDialog.getAvailableFieldLabels(); @@ -1696,9 +1698,9 @@ public void testFilterDialogWithViews() throws IOException, CommandException checker().verifyTrue(String.format("The fields listed in the dialog are not as expected. Expected '%s'.", expectedList), actualList.containsAll(expectedList)); - for(String removedColumn : removedColumns) + for(String removedColumn : List.of(FILTER_BOOL_COL.getLabel())) { - checker().verifyFalse(String.format("The field '%s' is listed in the dialog, it should not be.", removedColumn), + checker().fatal().verifyFalse(String.format("The field '%s' is listed in the dialog, it should not be.", removedColumn), actualList.contains(removedColumn)); } @@ -1716,7 +1718,7 @@ public void testFilterDialogWithViews() throws IOException, CommandException grid.selectView(VIEW_FEWER_COLUMNS); // Get the expected sample id. - List filters = List.of(new Filter(FILTER_BOOL_COL, true, Filter.Operator.getOperator("EQUAL"))); + List filters = List.of(new Filter(FILTER_BOOL_COL.toString(), true, Filter.Operator.getOperator("EQUAL"))); int expectedCount = getExpectedResults(SMALL_SAMPLE_TYPE, VIEW_FEWER_COLUMNS, null, filters).size(); checker().withScreenshot("View_Filtered_Removed_Column_Error") @@ -1735,9 +1737,9 @@ public void testFilterDialogWithViews() throws IOException, CommandException expectedList = new ArrayList<>(); expectedList.add(FILTER_NAME_COL); expectedList.add(FILTER_EXPDATE_COL); - expectedList.add(FILTER_INT_COL); - expectedList.add(FILTER_STRING_COL); - expectedList.add(FILTER_DATE_COL); + expectedList.add(FILTER_INT_COL.getLabel()); + expectedList.add(FILTER_STRING_COL.getLabel()); + expectedList.add(FILTER_DATE_COL.getLabel()); expectedList.add(FILTER_STORED_AMOUNT_COL); actualList = filterDialog.getAvailableFieldLabels(); @@ -1750,13 +1752,13 @@ public void testFilterDialogWithViews() throws IOException, CommandException // Build the list of expected values. // Get the expected sample id. - filters = List.of(new Filter(FILTER_BOOL_COL, true, Filter.Operator.getOperator("EQUAL"))); - List> strValues = getExpectedResults(SMALL_SAMPLE_TYPE, VIEW_FEWER_COLUMNS, List.of(FILTER_STRING_COL), filters); + filters = List.of(new Filter(FILTER_BOOL_COL.toString(), true, Filter.Operator.getOperator("EQUAL"))); + List> strValues = getExpectedResults(SMALL_SAMPLE_TYPE, VIEW_FEWER_COLUMNS, List.of(FILTER_STRING_COL.toString()), filters); expectedList = new ArrayList<>(); for(Map row : strValues) { - String value = row.get(FILTER_STRING_COL).toString(); + String value = row.get(FILTER_STRING_COL.getName()).toString(); if(!expectedList.contains(value)) { @@ -1766,7 +1768,7 @@ public void testFilterDialogWithViews() throws IOException, CommandException expectedList.add(ALL_OPTION); log(String.format("Validate that the list of values for the '%s' is as expected.", FILTER_STRING_COL)); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); actualList = filterDialog.selectFacetTab().getAvailableValues(); Collections.sort(expectedList); @@ -1784,7 +1786,7 @@ public void testFilterDialogWithViews() throws IOException, CommandException grid.selectView(VIEW_EXTRA_COLUMNS); List filterPills = grid.getFilterStatusValues(); - String expectedValue = String.format("%s = true", FILTER_BOOL_COL); + String expectedValue = String.format("%s = true", FILTER_BOOL_COL.getName()); checker().withScreenshot("View_Filter_Pill_Error").verifyTrue(String.format("Filter pills not as expected. There should only be one with value of '%s'", expectedValue), filterPills.size() == 1 && filterPills.get(0).getText().equals(expectedValue)); @@ -1793,10 +1795,10 @@ public void testFilterDialogWithViews() throws IOException, CommandException expectedList = new ArrayList<>(extraColumnsHeaders); expectedList.add(FILTER_NAME_COL); expectedList.add(FILTER_EXPDATE_COL); - expectedList.add(FILTER_STRING_COL); - expectedList.add(FILTER_INT_COL); - expectedList.add(FILTER_BOOL_COL); - expectedList.add(FILTER_DATE_COL); + expectedList.add(FILTER_STRING_COL.getLabel()); + expectedList.add(FILTER_INT_COL.getLabel()); + expectedList.add(FILTER_BOOL_COL.getLabel()); + expectedList.add(FILTER_DATE_COL.getLabel()); expectedList.add(FILTER_STORED_AMOUNT_COL); filterDialog = grid.getGridBar().openFilterDialog(); @@ -1809,7 +1811,7 @@ public void testFilterDialogWithViews() throws IOException, CommandException checker().verifyEquals("List of available fields not as expected.", expectedList, actualList); - expectedList = Arrays.asList(FILTER_BOOL_COL); + expectedList = Arrays.asList(FILTER_BOOL_COL.getLabel()); actualList = filterDialog.getFilteredFieldLabels(); checker().verifyEquals(String.format("List of filtered fields with view '%s' not as expected.", FILTER_BOOL_COL), @@ -1833,7 +1835,7 @@ public void testFilterDialogWithViews() throws IOException, CommandException actualList.isEmpty()); log("Make sure the values to filter for are as expected."); - filterDialog.selectField(FILTER_STRING_COL); + filterDialog.selectField(FILTER_STRING_COL.getLabel()); actualList = filterDialog.selectFacetTab().getAvailableValues(); // Going to hard code the expected values rather try and be clever and figure them out. @@ -1859,12 +1861,13 @@ public void testFilterDialogWithViews() throws IOException, CommandException * @param columns The columns to validate against. * @throws IOException Can be thrown by the file reader. */ - private void validateExportedData(File exportedFile, List> expectedValues, List columns) throws IOException + private void validateExportedData(File exportedFile, List> expectedValues, List columns) throws IOException { try (CSVReader reader = new CSVReader(Readers.getReader(exportedFile), GridBar.ExportType.CSV.getSeparator())) { - + List columnNames = columns.stream().map(FieldInfo::getName).toList(); + List columnLabels = columns.stream().map(FieldInfo::getLabel).toList(); List allRows = reader.readAll(); // Use headerRow, the column names, as keys for the map of actual data. @@ -1885,10 +1888,10 @@ private void validateExportedData(File exportedFile, List> e // Check the values from the identified columns (exported vs. expected). All exported values are stings // so need to convert the expected values. - for (String column : columns) + for (int colIndex = 0; colIndex < columnNames.size(); colIndex++) { - checker().verifyEquals(String.format("Value for column '%s' on row %d not as expected.", column, rowIndex + 1), - expectedRowData.get(column).toString(), actualRowData.get(column)); + checker().verifyEquals(String.format("Value for column '%s' on row %d not as expected.", columnNames.get(colIndex), rowIndex + 1), + expectedRowData.get(columnNames.get(colIndex)).toString(), actualRowData.get(columnLabels.get(colIndex))); } } diff --git a/src/org/labkey/test/util/TestDataGenerator.java b/src/org/labkey/test/util/TestDataGenerator.java index 9ef0d9a483..a35446b0fc 100644 --- a/src/org/labkey/test/util/TestDataGenerator.java +++ b/src/org/labkey/test/util/TestDataGenerator.java @@ -577,7 +577,7 @@ public static String randomFieldName(@NotNull String part, int numStartChars, in { // use the characters that we know are encoded in fieldKeys plus characters that we know clients are using // Issue 53197: Field name with double byte character can cause client side exception in Firefox when trying to customize grid view. - String chars = ALL_ILLEGAL_QUERY_KEY_CHARACTERS + " %()=+-[]_|*`'\":;<>?!@#^" + NON_LATIN_STRING;// + WIDE_PLACEHOLDER ; + String chars = ALL_ILLEGAL_QUERY_KEY_CHARACTERS + " %()=+-[]_|*`'\":;<>?!@#^" + NON_LATIN_STRING + WIDE_PLACEHOLDER ; String randomFieldName = randomName(part, numStartChars, numEndChars, chars, exclusion);