From fca3716ecbeccf56a4cff64d211169760bcc8ef9 Mon Sep 17 00:00:00 2001 From: XingY Date: Mon, 12 May 2025 23:38:32 -0700 Subject: [PATCH 01/13] fix regex/validator, add selenium tests --- src/org/labkey/test/tests/AuditLogTest.java | 235 ++---------------- .../labkey/test/tests/DomainDesignerTest.java | 38 ++- .../test/tests/TextChoiceSampleTypeTest.java | 41 ++- src/org/labkey/test/util/AuditLogHelper.java | 207 +++++++++++++++ 4 files changed, 300 insertions(+), 221 deletions(-) diff --git a/src/org/labkey/test/tests/AuditLogTest.java b/src/org/labkey/test/tests/AuditLogTest.java index f2407751d0..d4013337b8 100644 --- a/src/org/labkey/test/tests/AuditLogTest.java +++ b/src/org/labkey/test/tests/AuditLogTest.java @@ -97,6 +97,7 @@ public class AuditLogTest extends BaseWebDriverTest public static final String COMMENT_COLUMN = "Comment"; private final ApiPermissionsHelper permissionsHelper = new ApiPermissionsHelper(this); + private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); @Override public List getAssociatedModules() @@ -601,10 +602,10 @@ public void testDomainPropertyEvents() createList(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, null, listColumns); - List> domainPropertyEventRows = getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, null); + List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, null); // Add the list of the event ids to an ignore list so future tests don't look at them again. - List ignoreIds = new ArrayList<>(getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + List ignoreIds = new ArrayList<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); if(domainPropertyEventRows.size() != 3) { @@ -618,11 +619,11 @@ public void testDomainPropertyEvents() log("Validate that the expected rows are there."); Map field01ExpectedColumns = Maps.of("action", "Created"); Map field01ExpectedComment = Maps.of("Name", FIELD01_NAME,"Label", FIELD01_LABEL,"Type", "String","Description", FIELD01_DESCRIPTION); - boolean pass = validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD01_NAME, field01ExpectedColumns, field01ExpectedComment); + boolean pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD01_NAME, field01ExpectedColumns, field01ExpectedComment); Map field02ExpectedColumns = Maps.of("action", "Created"); Map field02ExpectedComment = Maps.of("Name", FIELD02_NAME,"Label", FIELD02_LABEL,"Type", FIELD02_TYPE.getLabel(),"Description", FIELD02_DESCRIPTION); - pass = validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD02_NAME, field02ExpectedColumns, field02ExpectedComment) && pass; + pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD02_NAME, field02ExpectedColumns, field02ExpectedComment) && pass; // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -654,10 +655,10 @@ public void testDomainPropertyEvents() listDefinitionPage.clickSave(); log("Get a list of ids from the Domain Events Audit Log again but this time remove from the list the ids from the created events."); - domainPropertyEventRows = getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); + domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); // Add the list of the event ids to an ignore list so future tests don't look at them again. - ignoreIds.addAll(getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); if(domainPropertyEventRows.size() != 2) { @@ -672,12 +673,12 @@ public void testDomainPropertyEvents() "Description", FIELD01_DESCRIPTION + " -> " + FIELD01_UPDATED_DESCRIPTION, "PHI", "Not PHI -> Restricted PHI", "Required", "false -> true"); - pass = validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD01_NAME, field01ExpectedColumns, field01ExpectedComment); + pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD01_NAME, field01ExpectedColumns, field01ExpectedComment); field02ExpectedColumns = Maps.of("action", "Modified"); - field02ExpectedComment = Maps.of("ConditionalFormats", "old: , new: 1", + field02ExpectedComment = Maps.of("ConditionalFormats", "old: , new: format.column~eq=5: ", "DefaultScale", "Linear -> Log"); - pass = validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD02_NAME, field02ExpectedColumns, field02ExpectedComment) && pass; + pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD02_NAME, field02ExpectedColumns, field02ExpectedComment) && pass; // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -696,10 +697,10 @@ public void testDomainPropertyEvents() listDefinitionPage.clickSave(); log("Validate that a 'Create' event was logged for the new filed."); - domainPropertyEventRows = getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); + domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); // Add the list of the event ids to an ignore list so future tests don't look at them again. - ignoreIds.addAll(getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); if(domainPropertyEventRows.size() != 1) { @@ -714,7 +715,7 @@ public void testDomainPropertyEvents() "Label", FIELD03_LABEL, "Type", FIELD03_TYPE.getLabel(), "Lookup", "[Schema: lists, Query: " + LOOK_UP_LIST01 + "]"); - pass = validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, field03ExpectedComment); + pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, field03ExpectedComment); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -738,12 +739,12 @@ public void testDomainPropertyEvents() field03ExpectedComment = Maps.of("Lookup", "[Query: old: " + LOOK_UP_LIST01 + ", new: " + LOOK_UP_LIST02 + "]"); log("Get a list of ids from the Domain Events Audit Log again but remove from the list the ids from all of the previous events."); - domainPropertyEventRows = getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); + domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); // Add the list of the event ids to an ignore list so future tests don't look at them again. - ignoreIds.addAll(getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); - pass = validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, field03ExpectedComment); + pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, field03ExpectedComment); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -762,9 +763,9 @@ public void testDomainPropertyEvents() field03ExpectedColumns = Maps.of("action", "Deleted"); log("Get a list of ids from the Domain Events Audit Log again but remove from the list the ids from all of the previous events."); - domainPropertyEventRows = getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); + domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); - pass = validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, null); + pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, null); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -775,204 +776,4 @@ public void testDomainPropertyEvents() log("Ok, it looks like everything was logged as expected. Yipeee!"); } - private boolean validateExpectedRowInDomainPropertyAuditLog(List> domainPropertyEventRows, String propertyName, Map expectedColumns, @Nullable Map expectedComment) - { - boolean pass = true; - - for(Map row : domainPropertyEventRows) - { - - if(getLogColumnValue(row, "propertyname").equals(propertyName)) - { - log("Validate the columns for property '" + propertyName + "'."); - for(String fieldName : expectedColumns.keySet()) - { - if(!getLogColumnValue(row, fieldName).equals(expectedColumns.get(fieldName))) - { - pass = false; - log("************** For field '" + fieldName + "' expected value '" + expectedColumns.get(fieldName) + "' found '" + row.get(fieldName) + "' **************"); - } - } - - if(null != expectedComment) - { - log("Validate that the Comment field is as expected."); - Map commentFieldValues = getDomainPropertyEventComment(row); - pass = validateCommentHasExpectedValues(commentFieldValues, expectedComment) && pass; - } - } - - } - - return pass; - } - - private boolean validateCommentHasExpectedValues(Map comment, Map expected) - { - boolean pass = true; - - for(String key : expected.keySet()) - { - if(!expected.get(key).equals(comment.get(key))) - { - log("************** Comment value does not contain expected value for field '" + key + "'. Expected '" + expected.get(key) + "' found '" + comment.get(key) + "'. **************"); - pass = false; - } - } - - return pass; - } - - private List> getDomainPropertyEventsFromDomainEvents(String projectName, String domainName, @Nullable List ignoreIds) - { - List domainEventIds = getDomainEventIds(projectName, domainName); - - if(null != ignoreIds) - { - log("Removing the ignore ids from the list."); - domainEventIds.removeAll(ignoreIds); - } - - log("Get all of the Domain Property Events for '" + domainName + "' that are linked to the domain events."); - List> domainPropertyEventRows = getDomainPropertyEventLog(domainName, domainEventIds); - log("Number of 'Domain Property Event' log entries: " + domainPropertyEventRows.size()); - - return domainPropertyEventRows; - } - - private List getDomainEventIds(String projectName, String domainName) - { - log("Get a list of the Domain Events for project '" + projectName + "'. "); - List> domainAuditEventAllRows = getDomainEventLog(projectName); - log("Number of 'Domain Event' log entries for '" + projectName + "': " + domainAuditEventAllRows.size()); - - log("Filter the list to look only at '" + domainName + "'."); - List> domainAuditEventRows = new ArrayList<>(); - - for(Map row : domainAuditEventAllRows) - { - if(getLogColumnValue(row, "domainname").toLowerCase().trim().equals(domainName.toLowerCase().trim())) - domainAuditEventRows.add(row); - } - - List domainEventIds = new ArrayList<>(); - domainAuditEventRows.forEach((event)->domainEventIds.add(getLogColumnValue(event, "rowid"))); - - log("Number of 'Domain Event' log entries for '" + domainName + "': " + domainEventIds.size()); - - return domainEventIds; - } - - private List getDomainEventIdsFromPropertyEvents(List> domainPropertyEventRows) - { - List domainEventIds = new ArrayList<>(); - - for(Map row : domainPropertyEventRows) - { - domainEventIds.add(getLogColumnValue(row, "domaineventid")); - } - - return domainEventIds; - } - - private List> getDomainEventLog(String projectName) - { - Connection cn = WebTestHelper.getRemoteApiConnection(); - SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainAuditEvent"); - cmd.setRequiredVersion(9.1); - cmd.setColumns(Arrays.asList("rowid", "created", "createdby", "impersonatedby", "projectid", "domainuri", "domainname", "comment")); - cmd.addFilter("projectid/DisplayName", projectName, Filter.Operator.EQUAL); - cmd.setContainerFilter(ContainerFilter.AllFolders); - - return executeSelectCommand(cn, cmd); - } - - private List> getDomainPropertyEventLog(String domainName, @Nullable List eventIds) - { - Connection cn = WebTestHelper.getRemoteApiConnection(); - SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainPropertyAuditEvent"); - cmd.setRequiredVersion(9.1); - cmd.setColumns(Arrays.asList("Created", "CreatedBy", "ImpersonatedBy", "propertyname", "action", "domainname", "domaineventid", "Comment")); - cmd.addFilter("domainname", domainName, Filter.Operator.EQUAL); - - if(null != eventIds) - { - StringBuilder stringBuilder = new StringBuilder(); - eventIds.forEach((id)->{ - if(!stringBuilder.isEmpty()) - stringBuilder.append(";"); - stringBuilder.append(id); - }); - cmd.addFilter("domaineventid/rowid", stringBuilder, Filter.Operator.IN); - } - - cmd.setContainerFilter(ContainerFilter.AllFolders); - - return executeSelectCommand(cn, cmd); - } - - private List> executeSelectCommand(Connection cn, SelectRowsCommand cmd) - { - List> rowsReturned = new ArrayList<>(); - try - { - SelectRowsResponse response = cmd.execute(cn, "/"); - log("Number of rows: " + response.getRowCount()); - rowsReturned.addAll(response.getRows()); - } - catch(IOException | CommandException ex) - { - // Just fail here, don't toss the exception up the stack. - fail("There was a command exception when getting the log: " + ex); - } - - return rowsReturned; - } - - private Map getDomainPropertyEventComment(Map row) - { - String comment = getLogColumnValue(row, "Comment"); - - String[] commentAsArray = comment.split(";"); - - Map fieldComments = new HashMap<>(); - - for (String s : commentAsArray) - { - String[] fieldValue = s.split(":"); - - // If the split on the ':' produced more than two entries in the array it most likely means that the - // comment for that property had a : in it. So treat the first entry as the field name and then concat the - // other fields together. - // For example the ConditionalFormats field will log the following during an update: - // ConditionalFormats: old: , new: 1; - // And a create of a Lookup will log as: - // Lookup: [Schema: lists, Query: LookUp01]; - StringBuilder sb = new StringBuilder(); - sb.append(fieldValue[1].trim()); - - for (int j = 2; j < fieldValue.length; j++) - { - sb.append(":"); - sb.append(fieldValue[j]); - } - - fieldComments.put(fieldValue[0].trim(), sb.toString()); - } - - return fieldComments; - } - - private String getLogColumnValue(Map rowEntry, String columnName) - { - try - { - return ((Map) rowEntry.get(columnName)).get("value").toString(); - } - catch(JSONException je) - { - // Just fail here, don't toss the exception up the stack. - throw new IllegalArgumentException(je); - } - } } diff --git a/src/org/labkey/test/tests/DomainDesignerTest.java b/src/org/labkey/test/tests/DomainDesignerTest.java index 757a332d9b..c3858d6a1d 100644 --- a/src/org/labkey/test/tests/DomainDesignerTest.java +++ b/src/org/labkey/test/tests/DomainDesignerTest.java @@ -40,7 +40,9 @@ import org.labkey.test.pages.experiment.CreateSampleTypePage; import org.labkey.test.pages.list.EditListDefinitionPage; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; +import org.labkey.test.util.Maps; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.TestDataGenerator; import org.openqa.selenium.WebElement; @@ -71,6 +73,9 @@ @Category({BVT.class}) public class DomainDesignerTest extends BaseWebDriverTest { + private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); + final String DOMAIN_PROPERTY_LOG_NAME = "Domain property events"; + @Override protected void doCleanup(boolean afterTest) throws TestTimeoutException { @@ -1335,18 +1340,23 @@ public void testConditionalFormat() throws Exception public void testRegexValidator() throws Exception { String listName = "regexValidatorList"; - + String fieldNameWithReg = "favoriteSnack"; FieldDefinition.LookupInfo lookupInfo = new FieldDefinition.LookupInfo(getProjectName(), "lists", listName); TestDataGenerator dgen = new TestDataGenerator(lookupInfo) .withColumns(List.of( new FieldDefinition("name", FieldDefinition.ColumnType.String), new FieldDefinition("favoriteIceCream", FieldDefinition.ColumnType.String), - new FieldDefinition("favoriteSnack", FieldDefinition.ColumnType.String), + new FieldDefinition(fieldNameWithReg, FieldDefinition.ColumnType.String), new FieldDefinition("size", FieldDefinition.ColumnType.Integer))); DomainResponse createResponse = dgen.createDomain(createDefaultConnection(), "IntList", Map.of("keyName", "Key")); + + List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), listName, null); + // Add the list of the event ids to an ignore list so future tests don't look at them again. + List ignoreIds = new ArrayList<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + DomainDesignerPage domainDesignerPage = DomainDesignerPage.beginAt(this, getProjectName(), "lists", listName); DomainFormPanel domainFormPanel = domainDesignerPage.fieldsPanel(); - DomainFieldRow favoriteSnack = domainFormPanel.getField("favoriteSnack"); + DomainFieldRow favoriteSnack = domainFormPanel.getField(fieldNameWithReg); RegexValidatorDialog validatorDialog = favoriteSnack.clickRegexButton(); RegexValidatorPanel panel = validatorDialog.getValidationPanel(); @@ -1371,6 +1381,28 @@ public void testRegexValidator() throws Exception assertEquals("expected error message should be on the field", "favorite snack cannot be twizzlers, yo", specialCharsValidator.get("errorMessage")); + // check audit log + log("Get a list of ids from the Domain Events Audit Log again but this time remove from the list the ids from the created events."); + domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), listName, ignoreIds); + ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + + if(domainPropertyEventRows.size() != 1) + { + // We are going to fail, so navigate to the Domain Property Events Audit Log. + _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); + Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, domainPropertyEventRows.size()); + } + + log("Validate that the expected rows after the update are in the log."); + Map fieldExpectedColumns = Maps.of("action", "Modified"); + Map fieldExpectedComment = Maps.of("Validators", "old: , new: neverTwizzlers, twizzler, failOnMatch=true, favorite snack cannot be twizzlers, yo, twizzler is not a snack, Regular Expression"); + boolean pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, fieldNameWithReg, fieldExpectedColumns, fieldExpectedComment); + + if(!pass) + _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); + + Assert.assertTrue("The values logged for the updating domain field regex event were not as expected. See log for details.", pass); + // this test does not verify that attempts to insert values that match will get an error } diff --git a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java index c44a54e052..ba392edb25 100644 --- a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java +++ b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java @@ -1,5 +1,6 @@ package org.labkey.test.tests; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -16,7 +17,9 @@ import org.labkey.test.params.FieldDefinition; import org.labkey.test.params.FieldDefinition.ColumnType; import org.labkey.test.params.experiment.SampleTypeDefinition; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; +import org.labkey.test.util.Maps; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.SampleTypeHelper; import org.labkey.test.util.TestDataGenerator; @@ -35,6 +38,8 @@ @Category({Daily.class}) public class TextChoiceSampleTypeTest extends BaseWebDriverTest { + private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); + final String DOMAIN_PROPERTY_LOG_NAME = "Domain property events"; @Override public BrowserType bestBrowser() @@ -326,6 +331,10 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm TestDataGenerator dataGenerator = createSampleType(sampleTypeName, namePrefix, textChoiceFieldName, expectedUnLockedValues); + List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), sampleTypeName, null); + // Add the list of the event ids to an ignore list so future tests don't look at them again. + List ignoreIds = new ArrayList<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + log("Create some samples that have TextChoice values set."); // Only assign a few of the values to samples (i.e. lock them). @@ -447,6 +456,8 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm updatePage.clickSave(); + verifyDomainFieldAuditDetail(ignoreIds, "old: Text Choice Validator, \u00C5\\|\u00C5|BB|CC|DD|E E E|\u0083\u0083|GG|H, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); + // Construct a list of samples that have TextChoice set and what they are expected to be. List> expectedSamples = new ArrayList<>(); @@ -496,7 +507,7 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm log("Click save, there should be no errors."); updatePage.clickSave(); - log("Finally update a value and click the save button for the sample type without clicking 'Apply'."); + log("Next update a value and click the save button for the sample type without clicking 'Apply'."); waitAndClickAndWait(Locator.lkButton("Edit Type")); updatePage = new UpdateSampleTypePage(getDriver()); @@ -525,6 +536,34 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm checker().verifyTrue(String.format("Expected value '%s' is not in the list of values.", valueToUpdate), actualValues.contains(valueToUpdate)); + log("Finally update a value and click the save button for the sample type and clicking 'Apply'."); + fieldRow.updateTextChoiceValue(valueToUpdate, updatedValue); + updatePage.clickSave(); + + verifyDomainFieldAuditDetail(ignoreIds, "old: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H no change|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); + + } + + private void verifyDomainFieldAuditDetail(List ignoreIds, String auditDetail) + { + final String sampleTypeName = "TC_Value_Updates"; + final String textChoiceFieldName = "TextChoice_Field_1"; + + List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), sampleTypeName, ignoreIds); + ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + if(domainPropertyEventRows.size() != 1) + { + _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); + Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, domainPropertyEventRows.size()); + } + log("Validate that the expected rows after the update are in the log."); + Map fieldExpectedColumns = Maps.of("action", "Modified"); + Map fieldExpectedComment = Maps.of("Validators", auditDetail); + boolean pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, textChoiceFieldName, fieldExpectedColumns, fieldExpectedComment); + if(!pass) + _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); + Assert.assertTrue("The values logged for the updating domain field regex event were not as expected. See log for details.", pass); + } /** diff --git a/src/org/labkey/test/util/AuditLogHelper.java b/src/org/labkey/test/util/AuditLogHelper.java index 4064181740..73a663a77d 100644 --- a/src/org/labkey/test/util/AuditLogHelper.java +++ b/src/org/labkey/test/util/AuditLogHelper.java @@ -1,6 +1,7 @@ package org.labkey.test.util; import org.jetbrains.annotations.Nullable; +import org.json.JSONException; import org.labkey.remoteapi.CommandException; import org.labkey.remoteapi.Connection; import org.labkey.remoteapi.query.ContainerFilter; @@ -10,18 +11,23 @@ import org.labkey.remoteapi.query.Sort; import org.labkey.test.Locator; import org.labkey.test.WebDriverWrapper; +import org.labkey.test.WebTestHelper; import org.labkey.test.pages.core.admin.ShowAdminPage; import org.labkey.test.pages.core.admin.ShowAuditLogPage; import java.io.IOException; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Stream; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class AuditLogHelper { @@ -188,4 +194,205 @@ public interface ConnectionSupplier { Connection get() throws IOException, CommandException; } + + public boolean validateExpectedRowInDomainPropertyAuditLog(List> domainPropertyEventRows, String propertyName, Map expectedColumns, @Nullable Map expectedComment) + { + boolean pass = true; + + for(Map row : domainPropertyEventRows) + { + + if(getLogColumnValue(row, "propertyname").equals(propertyName)) + { + TestLogger.log("Validate the columns for property '" + propertyName + "'."); + for(String fieldName : expectedColumns.keySet()) + { + if(!getLogColumnValue(row, fieldName).equals(expectedColumns.get(fieldName))) + { + pass = false; + TestLogger.log("************** For field '" + fieldName + "' expected value '" + expectedColumns.get(fieldName) + "' found '" + row.get(fieldName) + "' **************"); + } + } + + if(null != expectedComment) + { + TestLogger.log("Validate that the Comment field is as expected."); + Map commentFieldValues = getDomainPropertyEventComment(row); + pass = validateCommentHasExpectedValues(commentFieldValues, expectedComment) && pass; + } + } + + } + + return pass; + } + + private boolean validateCommentHasExpectedValues(Map comment, Map expected) + { + boolean pass = true; + + for(String key : expected.keySet()) + { + if(!expected.get(key).equals(comment.get(key))) + { + TestLogger.log("************** Comment value does not contain expected value for field '" + key + "'. Expected '" + expected.get(key) + "' found '" + comment.get(key) + "'. **************"); + pass = false; + } + } + + return pass; + } + + public List> getDomainPropertyEventsFromDomainEvents(String projectName, String domainName, @Nullable List ignoreIds) + { + List domainEventIds = getDomainEventIds(projectName, domainName); + + if(null != ignoreIds) + { + TestLogger.log("Removing the ignore ids from the list."); + domainEventIds.removeAll(ignoreIds); + } + + TestLogger.log("Get all of the Domain Property Events for '" + domainName + "' that are linked to the domain events."); + List> domainPropertyEventRows = getDomainPropertyEventLog(domainName, domainEventIds); + TestLogger.log("Number of 'Domain Property Event' log entries: " + domainPropertyEventRows.size()); + + return domainPropertyEventRows; + } + + private List getDomainEventIds(String projectName, String domainName) + { + TestLogger.log("Get a list of the Domain Events for project '" + projectName + "'. "); + List> domainAuditEventAllRows = getDomainEventLog(projectName); + TestLogger.log("Number of 'Domain Event' log entries for '" + projectName + "': " + domainAuditEventAllRows.size()); + + TestLogger.log("Filter the list to look only at '" + domainName + "'."); + List> domainAuditEventRows = new ArrayList<>(); + + for(Map row : domainAuditEventAllRows) + { + if(getLogColumnValue(row, "domainname").toLowerCase().trim().equals(domainName.toLowerCase().trim())) + domainAuditEventRows.add(row); + } + + List domainEventIds = new ArrayList<>(); + domainAuditEventRows.forEach((event)->domainEventIds.add(getLogColumnValue(event, "rowid"))); + + TestLogger.log("Number of 'Domain Event' log entries for '" + domainName + "': " + domainEventIds.size()); + + return domainEventIds; + } + + public List getDomainEventIdsFromPropertyEvents(List> domainPropertyEventRows) + { + List domainEventIds = new ArrayList<>(); + + for(Map row : domainPropertyEventRows) + { + domainEventIds.add(getLogColumnValue(row, "domaineventid")); + } + + return domainEventIds; + } + + private List> getDomainEventLog(String projectName) + { + Connection cn = WebTestHelper.getRemoteApiConnection(); + SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainAuditEvent"); + cmd.setRequiredVersion(9.1); + cmd.setColumns(Arrays.asList("rowid", "created", "createdby", "impersonatedby", "projectid", "domainuri", "domainname", "comment")); + cmd.addFilter("projectid/DisplayName", projectName, Filter.Operator.EQUAL); + cmd.setContainerFilter(ContainerFilter.AllFolders); + + return executeSelectCommand(cn, cmd); + } + + private List> getDomainPropertyEventLog(String domainName, @Nullable List eventIds) + { + Connection cn = WebTestHelper.getRemoteApiConnection(); + SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainPropertyAuditEvent"); + cmd.setRequiredVersion(9.1); + cmd.setColumns(Arrays.asList("Created", "CreatedBy", "ImpersonatedBy", "propertyname", "action", "domainname", "domaineventid", "Comment")); + cmd.addFilter("domainname", domainName, Filter.Operator.EQUAL); + + if(null != eventIds) + { + StringBuilder stringBuilder = new StringBuilder(); + eventIds.forEach((id)->{ + if(!stringBuilder.isEmpty()) + stringBuilder.append(";"); + stringBuilder.append(id); + }); + cmd.addFilter("domaineventid/rowid", stringBuilder, Filter.Operator.IN); + } + + cmd.setContainerFilter(ContainerFilter.AllFolders); + + return executeSelectCommand(cn, cmd); + } + + private List> executeSelectCommand(Connection cn, SelectRowsCommand cmd) + { + List> rowsReturned = new ArrayList<>(); + try + { + SelectRowsResponse response = cmd.execute(cn, "/"); + TestLogger.log("Number of rows: " + response.getRowCount()); + rowsReturned.addAll(response.getRows()); + } + catch(IOException | CommandException ex) + { + // Just fail here, don't toss the exception up the stack. + fail("There was a command exception when getting the log: " + ex); + } + + return rowsReturned; + } + + private Map getDomainPropertyEventComment(Map row) + { + String comment = getLogColumnValue(row, "Comment"); + + String[] commentAsArray = comment.split(";"); + + Map fieldComments = new HashMap<>(); + + for (String s : commentAsArray) + { + String[] fieldValue = s.split(":"); + + // If the split on the ':' produced more than two entries in the array it most likely means that the + // comment for that property had a : in it. So treat the first entry as the field name and then concat the + // other fields together. + // For example the ConditionalFormats field will log the following during an update: + // ConditionalFormats: old: , new: 1; + // And a create of a Lookup will log as: + // Lookup: [Schema: lists, Query: LookUp01]; + StringBuilder sb = new StringBuilder(); + sb.append(fieldValue[1].trim()); + + for (int j = 2; j < fieldValue.length; j++) + { + sb.append(":"); + sb.append(fieldValue[j]); + } + + fieldComments.put(fieldValue[0].trim(), sb.toString()); + } + + return fieldComments; + } + + private String getLogColumnValue(Map rowEntry, String columnName) + { + try + { + return ((Map) rowEntry.get(columnName)).get("value").toString(); + } + catch(JSONException je) + { + // Just fail here, don't toss the exception up the stack. + throw new IllegalArgumentException(je); + } + } } From 65d4f41d283261e21cbf17bf4f545db4c736ed57 Mon Sep 17 00:00:00 2001 From: XingY Date: Tue, 13 May 2025 14:46:59 -0700 Subject: [PATCH 02/13] update tests --- src/org/labkey/test/tests/AuditLogTest.java | 4 +- .../labkey/test/tests/DomainDesignerTest.java | 4 +- .../test/tests/TextChoiceSampleTypeTest.java | 30 ++++-- src/org/labkey/test/util/AuditLogHelper.java | 91 +++++++++++++------ 4 files changed, 91 insertions(+), 38 deletions(-) diff --git a/src/org/labkey/test/tests/AuditLogTest.java b/src/org/labkey/test/tests/AuditLogTest.java index d4013337b8..d1e4bec71d 100644 --- a/src/org/labkey/test/tests/AuditLogTest.java +++ b/src/org/labkey/test/tests/AuditLogTest.java @@ -61,8 +61,10 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -605,7 +607,7 @@ public void testDomainPropertyEvents() List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, null); // Add the list of the event ids to an ignore list so future tests don't look at them again. - List ignoreIds = new ArrayList<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + Set ignoreIds = new HashSet<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); if(domainPropertyEventRows.size() != 3) { diff --git a/src/org/labkey/test/tests/DomainDesignerTest.java b/src/org/labkey/test/tests/DomainDesignerTest.java index c3858d6a1d..0b12af77dd 100644 --- a/src/org/labkey/test/tests/DomainDesignerTest.java +++ b/src/org/labkey/test/tests/DomainDesignerTest.java @@ -55,8 +55,10 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import static org.hamcrest.CoreMatchers.containsString; @@ -1352,7 +1354,7 @@ public void testRegexValidator() throws Exception List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), listName, null); // Add the list of the event ids to an ignore list so future tests don't look at them again. - List ignoreIds = new ArrayList<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + Set ignoreIds = new HashSet<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); DomainDesignerPage domainDesignerPage = DomainDesignerPage.beginAt(this, getProjectName(), "lists", listName); DomainFormPanel domainFormPanel = domainDesignerPage.fieldsPanel(); diff --git a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java index ba392edb25..68d2b80dba 100644 --- a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java +++ b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java @@ -1,5 +1,6 @@ package org.labkey.test.tests; +import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -31,8 +32,10 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; @Category({Daily.class}) @@ -40,6 +43,7 @@ public class TextChoiceSampleTypeTest extends BaseWebDriverTest { private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); final String DOMAIN_PROPERTY_LOG_NAME = "Domain property events"; + final String DOMAIN_LOG_NAME = "Domain events"; @Override public BrowserType bestBrowser() @@ -331,9 +335,9 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm TestDataGenerator dataGenerator = createSampleType(sampleTypeName, namePrefix, textChoiceFieldName, expectedUnLockedValues); - List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), sampleTypeName, null); // Add the list of the event ids to an ignore list so future tests don't look at them again. - List ignoreIds = new ArrayList<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + Set ignoreIds = new HashSet<>(); + ignoreIds.addAll(_auditLogHelper.getDomainEventIds(getProjectName(), sampleTypeName, null)); log("Create some samples that have TextChoice values set."); @@ -456,7 +460,7 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm updatePage.clickSave(); - verifyDomainFieldAuditDetail(ignoreIds, "old: Text Choice Validator, \u00C5\\|\u00C5|BB|CC|DD|E E E|\u0083\u0083|GG|H, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); + verifyDomainFieldAuditDetail(ignoreIds, "AliquotNameExpression: -> ${${AliquotedFrom}-:withCounter}; The column(s) of domain TC_Value_Updates were modified", "old: Text Choice Validator, \u00C5\\|\u00C5|BB|CC|DD|E E E|\u0083\u0083|GG|H, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); // Construct a list of samples that have TextChoice set and what they are expected to be. List> expectedSamples = new ArrayList<>(); @@ -540,21 +544,20 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm fieldRow.updateTextChoiceValue(valueToUpdate, updatedValue); updatePage.clickSave(); - verifyDomainFieldAuditDetail(ignoreIds, "old: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H no change|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); + verifyDomainFieldAuditDetail(ignoreIds, "The column(s) of domain TC_Value_Updates were modified", "old: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H no change|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); } - private void verifyDomainFieldAuditDetail(List ignoreIds, String auditDetail) + private void verifyDomainFieldAuditDetail(Set ignoreIds, String auditComment, String auditDetail) { final String sampleTypeName = "TC_Value_Updates"; final String textChoiceFieldName = "TextChoice_Field_1"; List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), sampleTypeName, ignoreIds); - ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); if(domainPropertyEventRows.size() != 1) { _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); - Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, domainPropertyEventRows.size()); + Assert.assertEquals("The number of entries in the domain property audit log were not as expected.", 1, domainPropertyEventRows.size()); } log("Validate that the expected rows after the update are in the log."); Map fieldExpectedColumns = Maps.of("action", "Modified"); @@ -564,6 +567,19 @@ private void verifyDomainFieldAuditDetail(List ignoreIds, String auditDe _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); Assert.assertTrue("The values logged for the updating domain field regex event were not as expected. See log for details.", pass); + List auditComments = _auditLogHelper.getDomainEventComments(getProjectName(), sampleTypeName, ignoreIds); + if(auditComments.size() != 1) + { + _auditLogHelper.goToAuditEventView(DOMAIN_LOG_NAME); + Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, domainPropertyEventRows.size()); + } + + pass = auditComments.get(0).equals(auditComment); + if(!pass) + _auditLogHelper.goToAuditEventView(DOMAIN_LOG_NAME); + Assert.assertEquals("The comment logged for the updating domain was not as expected. See log for details.", auditComment, auditComments.get(0)); + + ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); } /** diff --git a/src/org/labkey/test/util/AuditLogHelper.java b/src/org/labkey/test/util/AuditLogHelper.java index 73a663a77d..ccd1eed86e 100644 --- a/src/org/labkey/test/util/AuditLogHelper.java +++ b/src/org/labkey/test/util/AuditLogHelper.java @@ -19,13 +19,17 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.stream.Stream; +import static java.lang.Integer.parseInt; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -243,15 +247,9 @@ private boolean validateCommentHasExpectedValues(Map comment, Ma return pass; } - public List> getDomainPropertyEventsFromDomainEvents(String projectName, String domainName, @Nullable List ignoreIds) + public List> getDomainPropertyEventsFromDomainEvents(String projectName, String domainName, @Nullable Set ignoreIds) { - List domainEventIds = getDomainEventIds(projectName, domainName); - - if(null != ignoreIds) - { - TestLogger.log("Removing the ignore ids from the list."); - domainEventIds.removeAll(ignoreIds); - } + List domainEventIds = getDomainEventIds(projectName, domainName, ignoreIds); TestLogger.log("Get all of the Domain Property Events for '" + domainName + "' that are linked to the domain events."); List> domainPropertyEventRows = getDomainPropertyEventLog(domainName, domainEventIds); @@ -260,54 +258,76 @@ public List> getDomainPropertyEventsFromDomainEvents(String return domainPropertyEventRows; } - private List getDomainEventIds(String projectName, String domainName) + public List getDomainEventIds(String projectName, String domainName, @Nullable Collection ignoreIds) { - TestLogger.log("Get a list of the Domain Events for project '" + projectName + "'. "); - List> domainAuditEventAllRows = getDomainEventLog(projectName); - TestLogger.log("Number of 'Domain Event' log entries for '" + projectName + "': " + domainAuditEventAllRows.size()); - - TestLogger.log("Filter the list to look only at '" + domainName + "'."); - List> domainAuditEventRows = new ArrayList<>(); - - for(Map row : domainAuditEventAllRows) - { - if(getLogColumnValue(row, "domainname").toLowerCase().trim().equals(domainName.toLowerCase().trim())) - domainAuditEventRows.add(row); - } + List> domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); - List domainEventIds = new ArrayList<>(); - domainAuditEventRows.forEach((event)->domainEventIds.add(getLogColumnValue(event, "rowid"))); + List domainEventIds = new ArrayList<>(); + domainAuditEventAllRows.forEach((event)->domainEventIds.add(getLogColumnIntValue(event, "rowid"))); TestLogger.log("Number of 'Domain Event' log entries for '" + domainName + "': " + domainEventIds.size()); return domainEventIds; } - public List getDomainEventIdsFromPropertyEvents(List> domainPropertyEventRows) + public List getDomainEventComments(String projectName, String domainName, @Nullable Collection ignoreIds) { - List domainEventIds = new ArrayList<>(); + List> domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); + + List domainEventComments = new ArrayList<>(); + domainAuditEventAllRows.forEach((event)->domainEventComments.add(getLogColumnValue(event, "comment"))); + return domainEventComments; + } + + public Set getDomainEventIdsFromPropertyEvents(List> domainPropertyEventRows) + { + Set domainEventIds = new HashSet<>(); for(Map row : domainPropertyEventRows) { - domainEventIds.add(getLogColumnValue(row, "domaineventid")); + domainEventIds.add(getLogColumnIntValue(row, "domaineventid")); } return domainEventIds; } - private List> getDomainEventLog(String projectName) + private List> getDomainEventLog(String projectName, String domainName, @Nullable Collection ignoreIds) { + TestLogger.log("Get a list of the Domain Events for project '" + projectName + "'. "); + Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainAuditEvent"); cmd.setRequiredVersion(9.1); cmd.setColumns(Arrays.asList("rowid", "created", "createdby", "impersonatedby", "projectid", "domainuri", "domainname", "comment")); cmd.addFilter("projectid/DisplayName", projectName, Filter.Operator.EQUAL); + if(null != ignoreIds) + { + StringBuilder stringBuilder = new StringBuilder(); + ignoreIds.forEach((id)->{ + if(!stringBuilder.isEmpty()) + stringBuilder.append(";"); + stringBuilder.append(id); + }); + cmd.addFilter("rowId", stringBuilder, Filter.Operator.NOT_IN); + } cmd.setContainerFilter(ContainerFilter.AllFolders); - return executeSelectCommand(cn, cmd); + List> domainAuditEventAllRows = executeSelectCommand(cn, cmd); + TestLogger.log("Number of 'Domain Event' log entries for '" + projectName + "': " + domainAuditEventAllRows.size()); + + TestLogger.log("Filter the list to look only at '" + domainName + "'."); + List> domainAuditEventRows = new ArrayList<>(); + + for(Map row : domainAuditEventAllRows) + { + if(getLogColumnValue(row, "domainname").toLowerCase().trim().equals(domainName.toLowerCase().trim())) + domainAuditEventRows.add(row); + } + + return domainAuditEventRows; } - private List> getDomainPropertyEventLog(String domainName, @Nullable List eventIds) + private List> getDomainPropertyEventLog(String domainName, @Nullable List eventIds) { Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainPropertyAuditEvent"); @@ -395,4 +415,17 @@ private String getLogColumnValue(Map rowEntry, String columnName throw new IllegalArgumentException(je); } } + + private Integer getLogColumnIntValue(Map rowEntry, String columnName) + { + try + { + return parseInt(getLogColumnValue(rowEntry, columnName)); + } + catch(JSONException je) + { + // Just fail here, don't toss the exception up the stack. + throw new IllegalArgumentException(je); + } + } } From f3fdd2777a17d498fcdbe82d0468a8f88fb7f3a6 Mon Sep 17 00:00:00 2001 From: XingY Date: Tue, 13 May 2025 23:38:32 -0700 Subject: [PATCH 03/13] selenium tests --- .../labkey/test/tests/DomainDesignerTest.java | 6 ++++ .../labkey/test/tests/LinkedSchemaTest.java | 13 ++++++-- .../tests/SampleTypeParentColumnTest.java | 10 +++++++ src/org/labkey/test/tests/StudyBaseTest.java | 3 ++ .../test/tests/TextChoiceSampleTypeTest.java | 2 +- .../test/tests/list/ListDateAndTimeTest.java | 9 ++++++ src/org/labkey/test/tests/list/ListTest.java | 20 +++++++++++++ src/org/labkey/test/util/AuditLogHelper.java | 30 +++++++++++++++++++ 8 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/org/labkey/test/tests/DomainDesignerTest.java b/src/org/labkey/test/tests/DomainDesignerTest.java index 0b12af77dd..d897f5279f 100644 --- a/src/org/labkey/test/tests/DomainDesignerTest.java +++ b/src/org/labkey/test/tests/DomainDesignerTest.java @@ -288,6 +288,12 @@ public void testInvalidLookupDomainField() throws IOException, CommandException EditListDefinitionPage editListDefinitionPage = new EditListDefinitionPage(getDriver()); editListDefinitionPage.setName(editedListName) .clickSave(); + checker().verifyEquals("The comment logged for the list update was not as expected.", + "The name of the list domain 'InvalidLookUpNameList' was changed to 'InvalidLookUpNameList_edited'. " + + "Name: InvalidLookUpNameList -> InvalidLookUpNameList_edited; " + + "The descriptor of domain InvalidLookUpNameList_edited was updated", + _auditLogHelper.getLastDomainEventComment(getProjectName(), editedListName)); + domainDesignerPage = DomainDesignerPage.beginAt(this, getProjectName(), "exp.materials", sampleType); assertEquals("Look up should be updated after list renaming", "Current Folder > lists > " + editedListName, domainDesignerPage.fieldsPanel().getField("lookUpField").detailsMessage()); diff --git a/src/org/labkey/test/tests/LinkedSchemaTest.java b/src/org/labkey/test/tests/LinkedSchemaTest.java index d8494d75f9..e08977b326 100644 --- a/src/org/labkey/test/tests/LinkedSchemaTest.java +++ b/src/org/labkey/test/tests/LinkedSchemaTest.java @@ -36,6 +36,7 @@ import org.labkey.test.params.list.ListDefinition; import org.labkey.test.params.list.VarListDefinition; import org.labkey.test.util.ApiPermissionsHelper; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.LogMethod; import org.labkey.test.util.SchemaHelper; @@ -109,6 +110,7 @@ public class LinkedSchemaTest extends BaseWebDriverTest private static final String STUDY_FOLDER = "StudyFolder"; // Folder used to validate fix for issues 32454 & 32456 private static final String MOTHER = "Mother"; private static final String READER_USER = "reader@linkedschema.test"; + private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); public static final String LIST_NAME = "LinkedSchemaTestPeople"; public static final String LIST_DATA = "Name\tAge\tCrazy\tP\tQ\tR\tS\tT\tU\tV\tW\tX\tY\tZ\n" + @@ -445,7 +447,8 @@ public void lookupTest() //Change the Mother column lookup to point to the other folder, then ensure that the mother lookup is no longer propagating changelistLookup(SOURCE_FOLDER, "NIMHDemographics", MOTHER, new FieldDefinition.LookupInfo("/" + PROJECT_NAME + "/" + OTHER_FOLDER, "lists", "NIMHDemographics") - .setTableType(FieldDefinition.ColumnType.Integer)); + .setTableType(FieldDefinition.ColumnType.Integer), + "Lookup: [Container: old: null, new: OtherFolder, ];"); assertLookupsWorking(TARGET_FOLDER, "BasicLinkedSchema", "NIMHDemographics", true, "Father"); assertLookupsWorking(TARGET_FOLDER, "BasicLinkedSchema", "NIMHDemographics", false, "Mother"); @@ -460,7 +463,8 @@ public void lookupTest() //Change the Mother column lookup to point to the query, and then make sure that the table has lookups appropriately. changelistLookup(SOURCE_FOLDER, "NIMHDemographics", MOTHER, new FieldDefinition.LookupInfo("/" + PROJECT_NAME + "/" + SOURCE_FOLDER, "lists", "QueryOverLookup") - .setTableType(FieldDefinition.ColumnType.Integer)); + .setTableType(FieldDefinition.ColumnType.Integer), + "Lookup: [Container: old: OtherFolder, new: SourceFolder, Query: old: NIMHDemographics, new: QueryOverLookup];"); assertLookupsWorking(TARGET_FOLDER, "QueryLinkedSchema", "NIMHDemographics", true, "Mother", "Father"); } @@ -991,7 +995,7 @@ protected void assertLookupsWorking(String sourceFolder, String schemaName, Stri } } - protected void changelistLookup(String sourceFolder, String tableName, String fieldName, FieldDefinition.LookupInfo info) + protected void changelistLookup(String sourceFolder, String tableName, String fieldName, FieldDefinition.LookupInfo info, String changeLog) { clickFolder(sourceFolder); @@ -1001,6 +1005,9 @@ protected void changelistLookup(String sourceFolder, String tableName, String fi listDefinitionPage.getFieldsPanel() .getField(fieldName).setLookup(info); listDefinitionPage.clickSave(); + + checker().verifyEquals("Domain audit comment not as expected after changing lookup", "The column(s) of domain " + tableName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), tableName)); + checker().verifyEquals("Domain field audit comment not as expected", List.of(changeLog), _auditLogHelper.getLastDomainPropertyComment(getProjectName(), tableName)); } protected void createLinkedSchemaQuery(String sourceFolder, String schemaName, String queryName, String tableName) diff --git a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java index c3da61d38a..140f932608 100644 --- a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java +++ b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java @@ -18,6 +18,7 @@ import org.labkey.test.pages.experiment.UpdateSampleTypePage; import org.labkey.test.params.FieldDefinition; import org.labkey.test.params.experiment.SampleTypeDefinition; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.ExcelHelper; import org.labkey.test.util.PortalHelper; @@ -65,6 +66,8 @@ public class SampleTypeParentColumnTest extends BaseWebDriverTest COL_DESCRIPTION_CAPTION, COL_DESCRIPTION_NAME, COL_NAME_CAPTION, COL_NAME_NAME); + private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); + @Override public List getAssociatedModules() { @@ -605,6 +608,10 @@ public void testUseThenRemoveAnAliasParentColumn() updatePage.removeParentAlias(PARENT_COLUMN); updatePage.clickSave(); + checker().verifyEquals("The comment logged for the updating domain was not as expected.", + "AliquotNameExpression: -> ${${AliquotedFrom}-:withCounter};ImportAlias: P7(materialInputs/" + SAMPLE_TYPE_NAME + ",required=false) -> ; The descriptor of domain " + SAMPLE_TYPE_NAME + " was updated", + _auditLogHelper.getLastDomainEventComment(getProjectName(), SAMPLE_TYPE_NAME)); + log("Import some more samples using the alias column and make sure it doesn't work."); sampleText = "Name\t" + PARENT_COLUMN + "\n" + "SG_03\tSG_01\n"; @@ -702,6 +709,9 @@ public void testAliasNameConflictsWithFieldName() updatePage.addParentAlias(GOOD_PARENT_NAME, SampleTypeDesigner.CURRENT_SAMPLE_TYPE); updatePage.clickSave(); + checker().verifyEquals("The comment logged for the updating domain was not as expected.", "ImportAlias: -> P8(materialInputs/" + SAMPLE_TYPE_NAME + ",required=false); The descriptor of domain " + SAMPLE_TYPE_NAME + " was updated", + _auditLogHelper.getLastDomainEventComment(getProjectName(), SAMPLE_TYPE_NAME)); + clickFolder(SUB_FOLDER_NAME); updatePage = sampleHelper.goToEditSampleType(SAMPLE_TYPE_NAME); Assert.assertEquals("Expected parent alias name not found.", GOOD_PARENT_NAME, updatePage.getParentAlias(0)); diff --git a/src/org/labkey/test/tests/StudyBaseTest.java b/src/org/labkey/test/tests/StudyBaseTest.java index c248fb8fba..db50748835 100644 --- a/src/org/labkey/test/tests/StudyBaseTest.java +++ b/src/org/labkey/test/tests/StudyBaseTest.java @@ -31,6 +31,7 @@ import org.labkey.test.params.FieldDefinition.PhiSelectType; import org.labkey.test.util.APITestHelper; import org.labkey.test.util.ApiPermissionsHelper; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.LogMethod; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.StudyHelper; @@ -73,6 +74,8 @@ protected void setupRequestStatuses() new SpecimenHelper(this).setupRequestStatuses(); } + protected final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); + @Override public List getAssociatedModules() { diff --git a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java index 68d2b80dba..76e3f8499c 100644 --- a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java +++ b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java @@ -571,7 +571,7 @@ private void verifyDomainFieldAuditDetail(Set ignoreIds, String auditCo if(auditComments.size() != 1) { _auditLogHelper.goToAuditEventView(DOMAIN_LOG_NAME); - Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, domainPropertyEventRows.size()); + Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, auditComments.size()); } pass = auditComments.get(0).equals(auditComment); diff --git a/src/org/labkey/test/tests/list/ListDateAndTimeTest.java b/src/org/labkey/test/tests/list/ListDateAndTimeTest.java index 140542c360..9361e8eadc 100644 --- a/src/org/labkey/test/tests/list/ListDateAndTimeTest.java +++ b/src/org/labkey/test/tests/list/ListDateAndTimeTest.java @@ -27,6 +27,7 @@ import org.labkey.test.pages.core.admin.LookAndFeelSettingsPage; import org.labkey.test.pages.list.EditListDefinitionPage; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionExportHelper; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.ExcelHelper; @@ -50,6 +51,8 @@ public class ListDateAndTimeTest extends BaseWebDriverTest private static SimpleDateFormat _defaultTimeFormat = null; private static SimpleDateFormat _defaultDateTimeFormat = null; + private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); + @Override public List getAssociatedModules() { @@ -1222,6 +1225,9 @@ public void testDateAndTimeFormat() listDefinitionPage.clickSave(); + checker().verifyEquals("Domain audit comment not as expected after changing datetime format", "The column(s) of domain " + listName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + checker().verifyEqualsSorted("Domain field audit comment not as expected", List.of("Format: yyyy-MM-dd -> ddMMMyy;", "Format: hh:mm a -> HH:mm:ss;", "Format: yyyy-MM-dd hh:mm a -> dd-MMM-yyyy HH:mm:ss;"), _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + expectedData = new ArrayList<>(); for(Date date : dates) @@ -1350,6 +1356,9 @@ public void testConvertDateTimeField() throws IOException, CommandException listDefinitionPage.clickSave(); + checker().verifyEquals("Domain audit comment not as expected after changing data type", "The column(s) of domain Convert DateTime Field List were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + checker().verifyEqualsSorted("Domain field audit comment not as expected", List.of("Type: DateTime -> Date;", "Type: DateTime -> Time;"), _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + // Update default format after changing the types. DATE_FORMAT dateFormat = DATE_FORMAT.Default; TIME_FORMAT timeFormat = TIME_FORMAT.Default; diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index c00b99fba4..8e8c5044c7 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -56,6 +56,7 @@ import org.labkey.test.params.FieldDefinition.StringLookup; import org.labkey.test.tests.AuditLogTest; import org.labkey.test.util.AbstractDataRegionExportOrSignHelper.ColumnHeaderType; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionExportHelper; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.EscapeUtil; @@ -192,6 +193,8 @@ public class ListTest extends BaseWebDriverTest private final File TSV_SAMPLE_FILE = TestFileUtils.getSampleData("fileTypes/tsv_sample.tsv"); private final String TSV_LIST_NAME = "Fruits from TSV"; + private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); + @Override public List getAssociatedModules() { @@ -1227,6 +1230,12 @@ private void customFormattingTest() listDefinitionPage.clickSave(); + checker().verifyEquals("Domain audit comment not as expected after changing conditional format", "The column(s) of domain " + TSV_LIST_NAME + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), TSV_LIST_NAME)); + checker().verifyEqualsSorted("Domain field audit comment not as expected", + List.of("ConditionalFormats: old: , new: format.column~gt=7: text-decoration: line-through;, format.column~gt=5: font-weight: bold;;", + "ConditionalFormats: old: , new: format.column~eq=true: text-decoration: line-through;font-weight: bold;font-style: italic;color: #68ccca;background-color: #d33115 !important;;"), + _auditLogHelper.getLastDomainPropertyComment(getProjectName(), TSV_LIST_NAME)); + // Verify conditional format of boolean column // look for cells that do not match the assertTextPresent(TSV_LIST_NAME); @@ -1294,6 +1303,11 @@ public void doRenameFieldsTest() .setLabel(newFieldName); listDefinitionPage.clickSave(); + checker().verifyEquals("Domain audit comment not as expected after renaming a field", "The column(s) of domain " + listName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + checker().verifyEqualsSorted("Domain field audit comment not as expected", + List.of("Name: "+ origFieldName + " -> " + newFieldName + "; Label: " + origFieldName + " -> " + newFieldName + ";"), + _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + assertTextPresent(newFieldName); assertTextNotPresent(origFieldName); @@ -1331,6 +1345,11 @@ public void exportPhiFileColumn() throws Exception listDefinitionPage.setColumnPhiLevel("RestrictedPhiColumn", FieldDefinition.PhiSelectType.Restricted); listDefinitionPage.clickSave(); + checker().verifyEquals("Domain audit comment not as expected after changing PHI setting for a field", "The column(s) of domain " + listName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + checker().verifyEqualsSorted("Domain field audit comment not as expected", + List.of("PHI: Not PHI -> Limited PHI;", "PHI: Not PHI -> Full PHI;", "PHI: Not PHI -> Restricted PHI;"), + _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + goToProjectHome(); clickAndWait(Locator.linkWithText(listName)); @@ -1502,6 +1521,7 @@ public void testFieldUniqueConstraint() .getField(fieldName2).expand().clickAdvancedSettings().setUniqueConstraint(true) .apply(); listDefinitionPage.clickSave(); + // TODO, domain audit not implemented for unique constraint changes viewRawTableMetadata(listName); verifyTableIndices("unique_constraint_list_", List.of("field_name1", "fieldname_2")); assertTextNotPresent("unique_constraint_list_fieldname_3"); diff --git a/src/org/labkey/test/util/AuditLogHelper.java b/src/org/labkey/test/util/AuditLogHelper.java index ccd1eed86e..55a29b554e 100644 --- a/src/org/labkey/test/util/AuditLogHelper.java +++ b/src/org/labkey/test/util/AuditLogHelper.java @@ -270,6 +270,35 @@ public List getDomainEventIds(String projectName, String domainName, @N return domainEventIds; } + public Map getLastDomainEvent(String projectName, String domainName) + { + return getDomainEventLog(projectName, domainName, null).get(0); + } + + public Integer getLastDomainEventId(String projectName, String domainName) + { + return getLogColumnIntValue(getLastDomainEvent(projectName, domainName), "rowid"); + } + + public String getLastDomainEventComment(String projectName, String domainName) + { + return getLogColumnValue(getLastDomainEvent(projectName, domainName), "comment"); + } + + public List getLastDomainPropertyValues(String projectName, String domainName, String columnName) + { + Integer lastDomainEventId = getLastDomainEventId(projectName, domainName); + List> allRows = getDomainPropertyEventLog(domainName, Collections.singletonList(lastDomainEventId)); + List domainPropEventComments = new ArrayList<>(); + allRows.forEach((event)->domainPropEventComments.add(getLogColumnValue(event, columnName))); + return domainPropEventComments; + } + + public List getLastDomainPropertyComment(String projectName, String domainName) + { + return getLastDomainPropertyValues(projectName, domainName, "comment"); + } + public List getDomainEventComments(String projectName, String domainName, @Nullable Collection ignoreIds) { List> domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); @@ -311,6 +340,7 @@ private List> getDomainEventLog(String projectName, String d cmd.addFilter("rowId", stringBuilder, Filter.Operator.NOT_IN); } cmd.setContainerFilter(ContainerFilter.AllFolders); + cmd.setSorts(Arrays.asList(new Sort("RowId", Sort.Direction.DESCENDING))); List> domainAuditEventAllRows = executeSelectCommand(cn, cmd); TestLogger.log("Number of 'Domain Event' log entries for '" + projectName + "': " + domainAuditEventAllRows.size()); From 250bc6d602fde42514fc26d75666e7e1c7b59923 Mon Sep 17 00:00:00 2001 From: XingY Date: Wed, 14 May 2025 13:56:03 -0700 Subject: [PATCH 04/13] audit unique indices update --- src/org/labkey/test/tests/list/ListTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index 8e8c5044c7..5080541cdf 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -1521,7 +1521,11 @@ public void testFieldUniqueConstraint() .getField(fieldName2).expand().clickAdvancedSettings().setUniqueConstraint(true) .apply(); listDefinitionPage.clickSave(); - // TODO, domain audit not implemented for unique constraint changes + + checker().verifyEquals("Domain audit comment not as expected after updating field unique constraint", + "Index: -> [field Name1, unique: true, fieldName_2, unique: true]; The descriptor of domain " + listName + " was updated", + _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + viewRawTableMetadata(listName); verifyTableIndices("unique_constraint_list_", List.of("field_name1", "fieldname_2")); assertTextNotPresent("unique_constraint_list_fieldname_3"); @@ -1535,6 +1539,11 @@ public void testFieldUniqueConstraint() .getField(fieldName3).expand().clickAdvancedSettings().setUniqueConstraint(true) .apply(); listDefinitionPage.clickSave(); + + checker().verifyEquals("Domain audit comment not as expected after updating field unique constraint", + "Index: field name1, unique: true, fieldname_2, unique: true -> FieldName@3, unique: true, field Name1, unique: true; The descriptor of domain " + listName + " was updated", + _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + viewRawTableMetadata(listName); verifyTableIndices("unique_constraint_list_", List.of("field_name1", "fieldname_3")); assertTextNotPresent("unique_constraint_list_fieldname_2"); From fc71a509165e75217c8627dd73d4f919bedf5d21 Mon Sep 17 00:00:00 2001 From: XingY Date: Mon, 19 May 2025 00:17:19 -0700 Subject: [PATCH 05/13] fixes and update tests --- src/org/labkey/test/tests/AuditLogTest.java | 143 ++++++--------- .../labkey/test/tests/DomainDesignerTest.java | 36 ++-- .../test/tests/TextChoiceSampleTypeTest.java | 63 +++---- src/org/labkey/test/util/AuditLogHelper.java | 166 ++++++++++++------ 4 files changed, 201 insertions(+), 207 deletions(-) diff --git a/src/org/labkey/test/tests/AuditLogTest.java b/src/org/labkey/test/tests/AuditLogTest.java index d1e4bec71d..b44e84ebaa 100644 --- a/src/org/labkey/test/tests/AuditLogTest.java +++ b/src/org/labkey/test/tests/AuditLogTest.java @@ -18,18 +18,13 @@ import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; -import org.json.JSONException; import org.junit.Assert; import org.junit.Test; import org.junit.experimental.categories.Category; import org.labkey.remoteapi.CommandException; import org.labkey.remoteapi.Connection; -import org.labkey.remoteapi.query.ContainerFilter; -import org.labkey.remoteapi.query.Filter; import org.labkey.remoteapi.query.InsertRowsCommand; import org.labkey.remoteapi.query.SaveRowsResponse; -import org.labkey.remoteapi.query.SelectRowsCommand; -import org.labkey.remoteapi.query.SelectRowsResponse; import org.labkey.test.BaseWebDriverTest; import org.labkey.test.Locator; import org.labkey.test.TestFileUtils; @@ -48,7 +43,6 @@ import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.Log4jUtils; -import org.labkey.test.util.Maps; import org.labkey.test.util.PermissionsHelper; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.UIUserHelper; @@ -61,10 +55,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -579,7 +571,6 @@ public void testDomainPropertyEvents() final String FIELD03_NAME = "Field03"; final String FIELD03_LABEL = "Field 03 Lookup"; - final ColumnType FIELD03_TYPE = ColumnType.Integer; final String DOMAIN_PROPERTY_LOG_NAME = "Domain property events"; @@ -604,28 +595,30 @@ public void testDomainPropertyEvents() createList(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, null, listColumns); - List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, null); - - // Add the list of the event ids to an ignore list so future tests don't look at them again. - Set ignoreIds = new HashSet<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); - - if(domainPropertyEventRows.size() != 3) - { - // We are going to fail, so navigate to the Domain Property Events Audit Log so the screen shot shows the log. - // I do the navigation because the log validation is happening by the API, so if there is a failure in the log - // we may be on a page that will add no value to the screen shot artifact. - goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); - Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 3, domainPropertyEventRows.size()); - } - log("Validate that the expected rows are there."); - Map field01ExpectedColumns = Maps.of("action", "Created"); - Map field01ExpectedComment = Maps.of("Name", FIELD01_NAME,"Label", FIELD01_LABEL,"Type", "String","Description", FIELD01_DESCRIPTION); - boolean pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD01_NAME, field01ExpectedColumns, field01ExpectedComment); - Map field02ExpectedColumns = Maps.of("action", "Created"); - Map field02ExpectedComment = Maps.of("Name", FIELD02_NAME,"Label", FIELD02_LABEL,"Type", FIELD02_TYPE.getLabel(),"Description", FIELD02_DESCRIPTION); - pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD02_NAME, field02ExpectedColumns, field02ExpectedComment) && pass; + String eventInitValue = "Name=ChangeMyColumns&AllowDelete=true&AllowUpload=true&AllowExport=true&DiscussionSetting=0" + + "&EntireListIndexSetting=0&EntireListBodySetting=0&EachItemBodySetting=0&EntireListIndex=false&EachItemIndex=false&FileAttachmentIndex=false"; + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, LIST_CHECK_LOG, null, + "The domain " + LIST_CHECK_LOG + " was created. The column(s) of domain " + LIST_CHECK_LOG + " were modified.", + null, null, eventInitValue); + String field1InitValue = "Name=Field01&Label=This%20is%20Field%2001&Type=String&Scale=4000&Description=Simple%20String%20field." + + "&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false&Dimension=false" + + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false" + + "&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default"; + AuditLogHelper.DetailedAuditEventRow field1ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD01_NAME, "Created", + null, null, null, field1InitValue); + + String field2InitValue = "Name=Field02&Label=This%20is%20Field%2002&Type=Integer&Description=Simple%20Integer%20field." + + "&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=true&Dimension=false" + + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false" + + "&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default"; + AuditLogHelper.DetailedAuditEventRow field2ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD02_NAME, "Created", + null, null, null, field2InitValue); + + AuditLogHelper.DetailedAuditEventRow keyFieldExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, "Key", "Created", + null, null, null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of("Key", keyFieldExpectedEvent, FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -656,31 +649,23 @@ public void testDomainPropertyEvents() listDefinitionPage.clickSave(); - log("Get a list of ids from the Domain Events Audit Log again but this time remove from the list the ids from the created events."); - domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); - - // Add the list of the event ids to an ignore list so future tests don't look at them again. - ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); - - if(domainPropertyEventRows.size() != 2) - { - // We are going to fail, so navigate to the Domain Property Events Audit Log. - goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); - Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 2, domainPropertyEventRows.size()); - } + expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, LIST_CHECK_LOG, null, + "The column(s) of domain " + LIST_CHECK_LOG + " were modified.", + "", eventInitValue, eventInitValue); + + String field1UpdateValue = "Name=Field01&Label=This%20is%20Update%20Label%20for%20Field%2001&Type=String&Scale=4000&Description=This%20should%20be%20a%20new%20description%20for%20the%20field." + + "&PHI=Restricted%20PHI&DefaultScale=Linear&Required=true&Hidden=false&MvEnabled=false&Measure=false&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true" + + "&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default"; + field1ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD01_NAME, "Modified", + "The following properties were updated: Label, Description, PHI, Required", "", field1InitValue, field1UpdateValue); + String field2UpdateValue = "Name=Field02&Label=This%20is%20Field%2002&Type=Integer&Description=Simple%20Integer%20field.&Format=%23!&PHI=Not%20PHI" + + "&DefaultScale=Log&Required=false&Hidden=false&MvEnabled=false&Measure=true&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true" + + "&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default&ConditionalFormat=format.column~eq%3D5%3A%20"; + field2ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD02_NAME, "Modified", + "The following properties were updated: DefaultScale, Format, ConditionalFormat", "", field2InitValue, field2UpdateValue); log("Validate that the expected rows after the update are in the log."); - field01ExpectedColumns = Maps.of("action", "Modified"); - field01ExpectedComment = Maps.of("Label", FIELD01_LABEL + " -> " + FIELD01_UPDATED_LABEL, - "Description", FIELD01_DESCRIPTION + " -> " + FIELD01_UPDATED_DESCRIPTION, - "PHI", "Not PHI -> Restricted PHI", - "Required", "false -> true"); - pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD01_NAME, field01ExpectedColumns, field01ExpectedComment); - - field02ExpectedColumns = Maps.of("action", "Modified"); - field02ExpectedComment = Maps.of("ConditionalFormats", "old: , new: format.column~eq=5: ", - "DefaultScale", "Linear -> Log"); - pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD02_NAME, field02ExpectedColumns, field02ExpectedComment) && pass; + pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -698,26 +683,15 @@ public void testDomainPropertyEvents() .setLabel(FIELD03_LABEL)); listDefinitionPage.clickSave(); - log("Validate that a 'Create' event was logged for the new filed."); - domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); - - // Add the list of the event ids to an ignore list so future tests don't look at them again. - ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + String field3CreateValue = "Name=Field03&Label=Field%2003%20Lookup&Type=Integer&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false" + + "&Measure=false&Dimension=true&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false" + + "&DefaultValueType=Editable%20default&Lookup=%7B%22queryName%22%3A%22LookUp01%22%2C%22schemaName%22%3A%22lists%22%7D"; + AuditLogHelper.DetailedAuditEventRow field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Created", + null, "", null, field3CreateValue); - if(domainPropertyEventRows.size() != 1) - { - // We are going to fail, so navigate to the Domain Property Events Audit Log. - goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); - Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, domainPropertyEventRows.size()); - } + log("Validate that the expected rows after the update are in the log."); + pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); - log("Validate that the expected row is there for the newly created field."); - Map field03ExpectedColumns = Maps.of("action", "Created"); - Map field03ExpectedComment = Maps.of("Name", FIELD03_NAME, - "Label", FIELD03_LABEL, - "Type", FIELD03_TYPE.getLabel(), - "Lookup", "[Schema: lists, Query: " + LOOK_UP_LIST01 + "]"); - pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, field03ExpectedComment); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -736,17 +710,14 @@ public void testDomainPropertyEvents() .setLookup(new FieldDefinition.IntLookup(null, "lists", LOOK_UP_LIST02)); listDefinitionPage.clickSave(); - log("Validate that the expected row is there for the after modifying the Lookup field."); - field03ExpectedColumns = Maps.of("action", "Modified"); - field03ExpectedComment = Maps.of("Lookup", "[Query: old: " + LOOK_UP_LIST01 + ", new: " + LOOK_UP_LIST02 + "]"); - - log("Get a list of ids from the Domain Events Audit Log again but remove from the list the ids from all of the previous events."); - domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); - - // Add the list of the event ids to an ignore list so future tests don't look at them again. - ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); + log("Validate that the expected rows after the update are in the log."); + String field3UpdateValue = "Name=Field03&Label=Field%2003%20Lookup&Type=Integer&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false" + + "&Measure=false&Dimension=true&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false" + + "&Scannable=false&DefaultValueType=Editable%20default&Lookup=%7B%22queryName%22%3A%22LookUp02%22%2C%22schemaName%22%3A%22lists%22%7D"; + field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Modified", + "The following property was updated: Lookup", "", field3CreateValue, field3UpdateValue); + pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); - pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, field03ExpectedComment); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -761,15 +732,9 @@ public void testDomainPropertyEvents() listDefinitionPage.getFieldsPanel().getField(3).clickRemoveField(true); listDefinitionPage.clickSave(); - log("Validate that the expected row is there after deleting the Lookup field."); - field03ExpectedColumns = Maps.of("action", "Deleted"); - - log("Get a list of ids from the Domain Events Audit Log again but remove from the list the ids from all of the previous events."); - domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(AUDIT_PROPERTY_EVENTS_PROJECT, LIST_CHECK_LOG, ignoreIds); - - pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, FIELD03_NAME, field03ExpectedColumns, null); - - // We are going to fail, so navigate to the Domain Property Events Audit Log. + field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Deleted", + "", "", null, null); + pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); if(!pass) goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); diff --git a/src/org/labkey/test/tests/DomainDesignerTest.java b/src/org/labkey/test/tests/DomainDesignerTest.java index d897f5279f..4ad8881160 100644 --- a/src/org/labkey/test/tests/DomainDesignerTest.java +++ b/src/org/labkey/test/tests/DomainDesignerTest.java @@ -42,7 +42,6 @@ import org.labkey.test.params.FieldDefinition; import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; -import org.labkey.test.util.Maps; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.TestDataGenerator; import org.openqa.selenium.WebElement; @@ -55,10 +54,8 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import static org.hamcrest.CoreMatchers.containsString; @@ -289,9 +286,7 @@ public void testInvalidLookupDomainField() throws IOException, CommandException editListDefinitionPage.setName(editedListName) .clickSave(); checker().verifyEquals("The comment logged for the list update was not as expected.", - "The name of the list domain 'InvalidLookUpNameList' was changed to 'InvalidLookUpNameList_edited'. " + - "Name: InvalidLookUpNameList -> InvalidLookUpNameList_edited; " + - "The descriptor of domain InvalidLookUpNameList_edited was updated", + "The name of the list domain 'InvalidLookUpNameList' was changed to 'InvalidLookUpNameList_edited'. The descriptor of domain InvalidLookUpNameList_edited was updated", _auditLogHelper.getLastDomainEventComment(getProjectName(), editedListName)); domainDesignerPage = DomainDesignerPage.beginAt(this, getProjectName(), "exp.materials", sampleType); @@ -1358,10 +1353,6 @@ public void testRegexValidator() throws Exception new FieldDefinition("size", FieldDefinition.ColumnType.Integer))); DomainResponse createResponse = dgen.createDomain(createDefaultConnection(), "IntList", Map.of("keyName", "Key")); - List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), listName, null); - // Add the list of the event ids to an ignore list so future tests don't look at them again. - Set ignoreIds = new HashSet<>(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); - DomainDesignerPage domainDesignerPage = DomainDesignerPage.beginAt(this, getProjectName(), "lists", listName); DomainFormPanel domainFormPanel = domainDesignerPage.fieldsPanel(); DomainFieldRow favoriteSnack = domainFormPanel.getField(fieldNameWithReg); @@ -1389,22 +1380,17 @@ public void testRegexValidator() throws Exception assertEquals("expected error message should be on the field", "favorite snack cannot be twizzlers, yo", specialCharsValidator.get("errorMessage")); - // check audit log - log("Get a list of ids from the Domain Events Audit Log again but this time remove from the list the ids from the created events."); - domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), listName, ignoreIds); - ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); - - if(domainPropertyEventRows.size() != 1) - { - // We are going to fail, so navigate to the Domain Property Events Audit Log. - _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); - Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, domainPropertyEventRows.size()); - } - log("Validate that the expected rows after the update are in the log."); - Map fieldExpectedColumns = Maps.of("action", "Modified"); - Map fieldExpectedComment = Maps.of("Validators", "old: , new: neverTwizzlers, twizzler, failOnMatch=true, favorite snack cannot be twizzlers, yo, twizzler is not a snack, Regular Expression"); - boolean pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, fieldNameWithReg, fieldExpectedColumns, fieldExpectedComment); + String fieldOldValues = "Name=favoriteSnack&Type=String&Scale=4000&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false" + + "&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false" + + "&Scannable=false&DefaultValueType=Editable%20default"; + String fieldNewValues = fieldOldValues + "&Validator=neverTwizzlers%2C%20twizzler%20is%20not%20a%20snack%2C%20twizzler%2C%20failOnMatch%3Dtrue%2C%20favorite%20snack%20cannot%20be%20twizzlers%2C%20yo%2C%20Regular%20Expression"; + AuditLogHelper.DetailedAuditEventRow fieldEvent = new AuditLogHelper.DetailedAuditEventRow(null, fieldNameWithReg, "Modified", + "The following property was updated: Validator", "", fieldOldValues, fieldNewValues); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The column(s) of domain " + listName + " were modified.", + "", null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Map.of(fieldNameWithReg, fieldEvent)); if(!pass) _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); diff --git a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java index 76e3f8499c..f1b341d3c9 100644 --- a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java +++ b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java @@ -1,7 +1,5 @@ package org.labkey.test.tests; -import org.apache.commons.lang3.StringUtils; -import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -20,7 +18,6 @@ import org.labkey.test.params.experiment.SampleTypeDefinition; import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; -import org.labkey.test.util.Maps; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.SampleTypeHelper; import org.labkey.test.util.TestDataGenerator; @@ -42,8 +39,6 @@ public class TextChoiceSampleTypeTest extends BaseWebDriverTest { private final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); - final String DOMAIN_PROPERTY_LOG_NAME = "Domain property events"; - final String DOMAIN_LOG_NAME = "Domain events"; @Override public BrowserType bestBrowser() @@ -460,7 +455,21 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm updatePage.clickSave(); - verifyDomainFieldAuditDetail(ignoreIds, "AliquotNameExpression: -> ${${AliquotedFrom}-:withCounter}; The column(s) of domain TC_Value_Updates were modified", "old: Text Choice Validator, \u00C5\\|\u00C5|BB|CC|DD|E E E|\u0083\u0083|GG|H, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); + log("Validate that the expected rows after the update are in the log."); + String fieldOldValues = "Name=TextChoice_Field_1&Type=String&Scale=4000&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false&Dimension=false" + + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false" + + "&DefaultValueType=Editable%20default&Validator=Text%20Choice%20Validator%2C%20%C3%85%5C%7C%C3%85%7CBB%7CCC%7CDD%7CE%20E%20E%7C%C2%83%C2%83%7CGG%7CH%2C%20Text%20Choice%20Validator"; + String fieldUpdateValues = "Name=TextChoice_Field_1&Type=String&Scale=4000&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false&Dimension=false" + + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false" + + "&DefaultValueType=Editable%20default&Validator=Text%20Choice%20Validator%2C%20BB%7CCC%20and%20here%20is%20an%20update%7CE%20E%20E%7CGG%7CH%7C%C2%83%C2%83%20updated%7C%C3%85%5C%7C%C3%85%2C%20Text%20Choice%20Validator"; + AuditLogHelper.DetailedAuditEventRow fieldEvent = new AuditLogHelper.DetailedAuditEventRow(null, textChoiceFieldName, "Modified", + "The following property was updated: Validator", "", fieldOldValues, fieldUpdateValues); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, sampleTypeName, null, + "The column(s) of domain " + sampleTypeName + " were modified.", + "", null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(sampleTypeName, getProjectName(), expectedDomainEvent, Map.of(textChoiceFieldName, fieldEvent)); + checker().verifyTrue("Audit event is not as expected", pass); + // Construct a list of samples that have TextChoice set and what they are expected to be. List> expectedSamples = new ArrayList<>(); @@ -544,44 +553,18 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm fieldRow.updateTextChoiceValue(valueToUpdate, updatedValue); updatePage.clickSave(); - verifyDomainFieldAuditDetail(ignoreIds, "The column(s) of domain TC_Value_Updates were modified", "old: Text Choice Validator, BB|CC and here is an update|E E E|GG|H|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator, new: Text Choice Validator, BB|CC and here is an update|E E E|GG|H no change|\u0083\u0083 updated|\u00C5\\|\u00C5, null, null, null, Text Choice Validator"); - - } - - private void verifyDomainFieldAuditDetail(Set ignoreIds, String auditComment, String auditDetail) - { - final String sampleTypeName = "TC_Value_Updates"; - final String textChoiceFieldName = "TextChoice_Field_1"; - - List> domainPropertyEventRows = _auditLogHelper.getDomainPropertyEventsFromDomainEvents(getProjectName(), sampleTypeName, ignoreIds); - if(domainPropertyEventRows.size() != 1) - { - _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); - Assert.assertEquals("The number of entries in the domain property audit log were not as expected.", 1, domainPropertyEventRows.size()); - } log("Validate that the expected rows after the update are in the log."); - Map fieldExpectedColumns = Maps.of("action", "Modified"); - Map fieldExpectedComment = Maps.of("Validators", auditDetail); - boolean pass = _auditLogHelper.validateExpectedRowInDomainPropertyAuditLog(domainPropertyEventRows, textChoiceFieldName, fieldExpectedColumns, fieldExpectedComment); - if(!pass) - _auditLogHelper.goToAuditEventView(DOMAIN_PROPERTY_LOG_NAME); - Assert.assertTrue("The values logged for the updating domain field regex event were not as expected. See log for details.", pass); - - List auditComments = _auditLogHelper.getDomainEventComments(getProjectName(), sampleTypeName, ignoreIds); - if(auditComments.size() != 1) - { - _auditLogHelper.goToAuditEventView(DOMAIN_LOG_NAME); - Assert.assertEquals("The number of entries in the domain audit log were not as expected.", 1, auditComments.size()); - } - - pass = auditComments.get(0).equals(auditComment); - if(!pass) - _auditLogHelper.goToAuditEventView(DOMAIN_LOG_NAME); - Assert.assertEquals("The comment logged for the updating domain was not as expected. See log for details.", auditComment, auditComments.get(0)); + String fieldUpdateValues2 = "Name=TextChoice_Field_1&Type=String&Scale=4000&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false" + + "&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false" + + "&Scannable=false&DefaultValueType=Editable%20default&Validator=Text%20Choice%20Validator%2C%20BB%7CCC%20and%20here%20is%20an%20update%7CE%20E%20E%7CGG%7CH%20no%20change%7C%C2%83%C2%83%20updated%7C%C3%85%5C%7C%C3%85%2C%20Text%20Choice%20Validator"; + fieldEvent = new AuditLogHelper.DetailedAuditEventRow(null, textChoiceFieldName, "Modified", + "The following property was updated: Validator", "", fieldUpdateValues, fieldUpdateValues2); + pass = _auditLogHelper.validateLastDomainAuditEvents(sampleTypeName, getProjectName(), expectedDomainEvent, Map.of(textChoiceFieldName, fieldEvent)); + checker().verifyTrue("Audit event is not as expected", pass); - ignoreIds.addAll(_auditLogHelper.getDomainEventIdsFromPropertyEvents(domainPropertyEventRows)); } + /** *

* Validate the TextChoice values when editing/create a sample. diff --git a/src/org/labkey/test/util/AuditLogHelper.java b/src/org/labkey/test/util/AuditLogHelper.java index 55a29b554e..1ccf324e71 100644 --- a/src/org/labkey/test/util/AuditLogHelper.java +++ b/src/org/labkey/test/util/AuditLogHelper.java @@ -1,5 +1,6 @@ package org.labkey.test.util; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; import org.json.JSONException; import org.labkey.remoteapi.CommandException; @@ -199,99 +200,137 @@ public interface ConnectionSupplier Connection get() throws IOException, CommandException; } - public boolean validateExpectedRowInDomainPropertyAuditLog(List> domainPropertyEventRows, String propertyName, Map expectedColumns, @Nullable Map expectedComment) + public boolean validateDetailAuditLog(DetailedAuditEventRow expectedAuditDetail, DetailedAuditEventRow actualAuditDetail) { boolean pass = true; - - for(Map row : domainPropertyEventRows) + for (String prop : propertyAuditColumns) { - - if(getLogColumnValue(row, "propertyname").equals(propertyName)) + if (expectedAuditDetail.getColumn(prop) != null) { - TestLogger.log("Validate the columns for property '" + propertyName + "'."); - for(String fieldName : expectedColumns.keySet()) - { - if(!getLogColumnValue(row, fieldName).equals(expectedColumns.get(fieldName))) - { - pass = false; - TestLogger.log("************** For field '" + fieldName + "' expected value '" + expectedColumns.get(fieldName) + "' found '" + row.get(fieldName) + "' **************"); - } - } + if (StringUtils.isEmpty(expectedAuditDetail.getColumn(prop)) && actualAuditDetail.getColumn(prop) == null) + continue; - if(null != expectedComment) + if (!expectedAuditDetail.getColumn(prop).equals(actualAuditDetail.getColumn(prop))) { - TestLogger.log("Validate that the Comment field is as expected."); - Map commentFieldValues = getDomainPropertyEventComment(row); - pass = validateCommentHasExpectedValues(commentFieldValues, expectedComment) && pass; + pass = false; + TestLogger.log(prop + " is not as expected. Expected: " + expectedAuditDetail.getColumn(prop) + ", Actual: " + actualAuditDetail.getColumn(prop)); } } - } - return pass; } - private boolean validateCommentHasExpectedValues(Map comment, Map expected) + public boolean validateDomainPropertiesAuditLog(String domainName, Integer domainEventId, Map expectedAuditDetails) { + Map actualAuditDetails = getDomainPropertyEvents(domainName, domainEventId); boolean pass = true; - - for(String key : expected.keySet()) + if (expectedAuditDetails.keySet().size() != actualAuditDetails.keySet().size()) + { + pass = false; + TestLogger.log("Number of DomainPropertyAuditEvent events not as expected."); + } + for (String key : expectedAuditDetails.keySet()) { - if(!expected.get(key).equals(comment.get(key))) + DetailedAuditEventRow expectedAuditDetail = expectedAuditDetails.get(key); + DetailedAuditEventRow actualAuditDetail = actualAuditDetails.get(key); + if (actualAuditDetail == null) { - TestLogger.log("************** Comment value does not contain expected value for field '" + key + "'. Expected '" + expected.get(key) + "' found '" + comment.get(key) + "'. **************"); pass = false; + TestLogger.log("Field " + key + " is missing DomainPropertyAuditEvent."); } + else + pass = pass && validateDetailAuditLog(expectedAuditDetail, actualAuditDetail); } return pass; } - public List> getDomainPropertyEventsFromDomainEvents(String projectName, String domainName, @Nullable Set ignoreIds) + public boolean validateLastDomainAuditEvents(String domainName, String projectName, DetailedAuditEventRow expectedDomainEvent, Map expectedDomainPropertyEvents) { - List domainEventIds = getDomainEventIds(projectName, domainName, ignoreIds); - - TestLogger.log("Get all of the Domain Property Events for '" + domainName + "' that are linked to the domain events."); - List> domainPropertyEventRows = getDomainPropertyEventLog(domainName, domainEventIds); - TestLogger.log("Number of 'Domain Property Event' log entries: " + domainPropertyEventRows.size()); - - return domainPropertyEventRows; + DetailedAuditEventRow latestDomainEvent = getLastDomainEvent(projectName, domainName); + boolean pass = validateDetailAuditLog(expectedDomainEvent, latestDomainEvent); + return pass && validateDomainPropertiesAuditLog(domainName, latestDomainEvent.rowId, expectedDomainPropertyEvents); } public List getDomainEventIds(String projectName, String domainName, @Nullable Collection ignoreIds) { - List> domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); + List domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); List domainEventIds = new ArrayList<>(); - domainAuditEventAllRows.forEach((event)->domainEventIds.add(getLogColumnIntValue(event, "rowid"))); + domainAuditEventAllRows.forEach((event)->domainEventIds.add(event.rowId)); TestLogger.log("Number of 'Domain Event' log entries for '" + domainName + "': " + domainEventIds.size()); return domainEventIds; } - public Map getLastDomainEvent(String projectName, String domainName) + public DetailedAuditEventRow getLastDomainEvent(String projectName, String domainName) { return getDomainEventLog(projectName, domainName, null).get(0); } public Integer getLastDomainEventId(String projectName, String domainName) { - return getLogColumnIntValue(getLastDomainEvent(projectName, domainName), "rowid"); + return getLastDomainEvent(projectName, domainName).rowId; } public String getLastDomainEventComment(String projectName, String domainName) { - return getLogColumnValue(getLastDomainEvent(projectName, domainName), "comment"); + return getLastDomainEvent(projectName, domainName).comment; } - public List getLastDomainPropertyValues(String projectName, String domainName, String columnName) + public static List propertyAuditColumns = List.of("type", "comment", "usercomment", "oldvalues", "newvalues"); + public record DetailedAuditEventRow(Integer rowId, String keyValue, String type, String comment, String userComment, String oldValues, String newValues) { - Integer lastDomainEventId = getLastDomainEventId(projectName, domainName); - List> allRows = getDomainPropertyEventLog(domainName, Collections.singletonList(lastDomainEventId)); - List domainPropEventComments = new ArrayList<>(); - allRows.forEach((event)->domainPropEventComments.add(getLogColumnValue(event, columnName))); + public String getColumn(String columnName) + { + String columnname = columnName.toLowerCase(); + return switch (columnname) + { + case "keyvalue" -> keyValue; + case "rowid" -> rowId + ""; + case "type" -> type; + case "comment" -> comment; + case "usercomment" -> userComment; + case "oldvalues" -> oldValues; + case "newvalues" -> newValues; + default -> null; + }; + } + + public String getLogString() + { + return "Comment: " + comment + "\nOldValue:" + oldValues + "\nNewValue:" + newValues; + } + } + + public Map getDomainPropertyEvents(String domainName, Integer domainEventId) + { + List> allRows = getDomainPropertyEventLog(domainName, Collections.singletonList(domainEventId)); + Map domainPropEventComments = new HashMap<>(); + allRows.forEach((event)->{ + Integer rowId = getLogColumnIntValue(event, "RowId"); + String propertyName = getLogColumnValue(event, "PropertyName"); + String action = getLogColumnValue(event, "Action"); + String comment = getLogColumnValue(event, "Comment"); + String userComment = getLogColumnValue(event, "UserComment"); + String oldValue = getLogColumnValue(event, "oldValues"); + String newValue = getLogColumnValue(event, "newValues"); + domainPropEventComments.put(propertyName, new DetailedAuditEventRow(rowId, propertyName, action, comment, userComment, oldValue, newValue)); + }); return domainPropEventComments; + + } + + public Map getLastDomainPropertyEvents(String projectName, String domainName) + { + Integer lastDomainEventId = getLastDomainEventId(projectName, domainName); + return getDomainPropertyEvents(domainName, lastDomainEventId); + } + + public List getLastDomainPropertyValues(String projectName, String domainName, String columnName) + { + return getLastDomainPropertyEvents(projectName, domainName).values().stream().map(values -> values.getColumn(columnName)).toList(); } public List getLastDomainPropertyComment(String projectName, String domainName) @@ -301,10 +340,10 @@ public List getLastDomainPropertyComment(String projectName, String doma public List getDomainEventComments(String projectName, String domainName, @Nullable Collection ignoreIds) { - List> domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); + List domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); List domainEventComments = new ArrayList<>(); - domainAuditEventAllRows.forEach((event)->domainEventComments.add(getLogColumnValue(event, "comment"))); + domainAuditEventAllRows.forEach((event)->domainEventComments.add(event.comment)); return domainEventComments; } @@ -320,14 +359,14 @@ public Set getDomainEventIdsFromPropertyEvents(List return domainEventIds; } - private List> getDomainEventLog(String projectName, String domainName, @Nullable Collection ignoreIds) + private List getDomainEventLog(String projectName, String domainName, @Nullable Collection ignoreIds) { TestLogger.log("Get a list of the Domain Events for project '" + projectName + "'. "); Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainAuditEvent"); cmd.setRequiredVersion(9.1); - cmd.setColumns(Arrays.asList("rowid", "created", "createdby", "impersonatedby", "projectid", "domainuri", "domainname", "comment")); + cmd.setColumns(Arrays.asList("rowid", "domainuri", "domainname", "comment", "usercomment", "oldvalues", "newvalues")); cmd.addFilter("projectid/DisplayName", projectName, Filter.Operator.EQUAL); if(null != ignoreIds) { @@ -346,12 +385,22 @@ private List> getDomainEventLog(String projectName, String d TestLogger.log("Number of 'Domain Event' log entries for '" + projectName + "': " + domainAuditEventAllRows.size()); TestLogger.log("Filter the list to look only at '" + domainName + "'."); - List> domainAuditEventRows = new ArrayList<>(); + List domainAuditEventRows = new ArrayList<>(); for(Map row : domainAuditEventAllRows) { - if(getLogColumnValue(row, "domainname").toLowerCase().trim().equals(domainName.toLowerCase().trim())) - domainAuditEventRows.add(row); + String domainName_ = getLogColumnValue(row, "domainname"); + + if(domainName_.trim().equalsIgnoreCase(domainName.trim())) + { + Integer rowId = getLogColumnIntValue(row, "rowid"); + String comment = getLogColumnValue(row, "comment"); + String userComment = getLogColumnValue(row, "usercomment"); + String oldValue = getLogColumnValue(row, "oldvalues"); + String newValue = getLogColumnValue(row, "newvalues"); + + domainAuditEventRows.add(new DetailedAuditEventRow(rowId, domainName, null, comment, userComment, oldValue, newValue)); + } } return domainAuditEventRows; @@ -362,7 +411,7 @@ private List> getDomainPropertyEventLog(String domainName, @ Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainPropertyAuditEvent"); cmd.setRequiredVersion(9.1); - cmd.setColumns(Arrays.asList("Created", "CreatedBy", "ImpersonatedBy", "propertyname", "action", "domainname", "domaineventid", "Comment")); + cmd.setColumns(Arrays.asList("Created", "CreatedBy", "ImpersonatedBy", "propertyname", "action", "domainname", "domaineventid", "Comment", "UserComment", "oldvalues", "newvalues")); cmd.addFilter("domainname", domainName, Filter.Operator.EQUAL); if(null != eventIds) @@ -402,6 +451,8 @@ private List> executeSelectCommand(Connection cn, SelectRows private Map getDomainPropertyEventComment(Map row) { String comment = getLogColumnValue(row, "Comment"); + if (comment != null) + return null; String[] commentAsArray = comment.split(";"); @@ -437,7 +488,13 @@ private String getLogColumnValue(Map rowEntry, String columnName { try { - return ((Map) rowEntry.get(columnName)).get("value").toString(); + Map val = ((Map) rowEntry.get(columnName)); + if (val == null) + return null; + Object value = val.get("value"); + if (value == null) + return null; + return value.toString(); } catch(JSONException je) { @@ -450,7 +507,10 @@ private Integer getLogColumnIntValue(Map rowEntry, String column { try { - return parseInt(getLogColumnValue(rowEntry, columnName)); + String strVal = getLogColumnValue(rowEntry, columnName); + if (strVal == null) + return null; + return parseInt(strVal); } catch(JSONException je) { From 6719cf5e4d8abb1f70c721a5f368d354c70dcb87 Mon Sep 17 00:00:00 2001 From: XingY Date: Mon, 19 May 2025 23:39:27 -0700 Subject: [PATCH 06/13] update tests --- src/org/labkey/test/tests/AuditLogTest.java | 20 +++---- .../labkey/test/tests/DomainDesignerTest.java | 14 +++-- .../labkey/test/tests/LinkedSchemaTest.java | 45 ++++++++++++---- .../tests/SampleTypeParentColumnTest.java | 22 ++++++-- .../test/tests/TextChoiceSampleTypeTest.java | 6 +-- .../test/tests/list/ListDateAndTimeTest.java | 21 ++++++-- src/org/labkey/test/tests/list/ListTest.java | 52 ++++++++++++------- src/org/labkey/test/util/AuditLogHelper.java | 45 +++++++++++----- 8 files changed, 154 insertions(+), 71 deletions(-) diff --git a/src/org/labkey/test/tests/AuditLogTest.java b/src/org/labkey/test/tests/AuditLogTest.java index b44e84ebaa..eb58eeae80 100644 --- a/src/org/labkey/test/tests/AuditLogTest.java +++ b/src/org/labkey/test/tests/AuditLogTest.java @@ -601,23 +601,23 @@ public void testDomainPropertyEvents() "&EntireListIndexSetting=0&EntireListBodySetting=0&EachItemBodySetting=0&EntireListIndex=false&EachItemIndex=false&FileAttachmentIndex=false"; AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, LIST_CHECK_LOG, null, "The domain " + LIST_CHECK_LOG + " was created. The column(s) of domain " + LIST_CHECK_LOG + " were modified.", - null, null, eventInitValue); + null, null, eventInitValue, null); String field1InitValue = "Name=Field01&Label=This%20is%20Field%2001&Type=String&Scale=4000&Description=Simple%20String%20field." + "&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false&Dimension=false" + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false" + "&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default"; AuditLogHelper.DetailedAuditEventRow field1ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD01_NAME, "Created", - null, null, null, field1InitValue); + null, null, null, field1InitValue, null); String field2InitValue = "Name=Field02&Label=This%20is%20Field%2002&Type=Integer&Description=Simple%20Integer%20field." + "&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=true&Dimension=false" + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false" + "&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default"; AuditLogHelper.DetailedAuditEventRow field2ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD02_NAME, "Created", - null, null, null, field2InitValue); + null, null, null, field2InitValue, null); AuditLogHelper.DetailedAuditEventRow keyFieldExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, "Key", "Created", - null, null, null, null); + null, null, null, null, null); boolean pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of("Key", keyFieldExpectedEvent, FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); // We are going to fail, so navigate to the Domain Property Events Audit Log. @@ -651,18 +651,18 @@ public void testDomainPropertyEvents() expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, LIST_CHECK_LOG, null, "The column(s) of domain " + LIST_CHECK_LOG + " were modified.", - "", eventInitValue, eventInitValue); + "", eventInitValue, eventInitValue, null); String field1UpdateValue = "Name=Field01&Label=This%20is%20Update%20Label%20for%20Field%2001&Type=String&Scale=4000&Description=This%20should%20be%20a%20new%20description%20for%20the%20field." + "&PHI=Restricted%20PHI&DefaultScale=Linear&Required=true&Hidden=false&MvEnabled=false&Measure=false&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true" + "&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default"; field1ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD01_NAME, "Modified", - "The following properties were updated: Label, Description, PHI, Required", "", field1InitValue, field1UpdateValue); + "The following properties were updated: Label, Description, PHI, Required", "", field1InitValue, field1UpdateValue, null); String field2UpdateValue = "Name=Field02&Label=This%20is%20Field%2002&Type=Integer&Description=Simple%20Integer%20field.&Format=%23!&PHI=Not%20PHI" + "&DefaultScale=Log&Required=false&Hidden=false&MvEnabled=false&Measure=true&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true" + "&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default&ConditionalFormat=format.column~eq%3D5%3A%20"; field2ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD02_NAME, "Modified", - "The following properties were updated: DefaultScale, Format, ConditionalFormat", "", field2InitValue, field2UpdateValue); + "The following properties were updated: DefaultScale, Format, ConditionalFormat", "", field2InitValue, field2UpdateValue, null); log("Validate that the expected rows after the update are in the log."); pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); @@ -687,7 +687,7 @@ public void testDomainPropertyEvents() "&Measure=false&Dimension=true&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false" + "&DefaultValueType=Editable%20default&Lookup=%7B%22queryName%22%3A%22LookUp01%22%2C%22schemaName%22%3A%22lists%22%7D"; AuditLogHelper.DetailedAuditEventRow field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Created", - null, "", null, field3CreateValue); + null, "", null, field3CreateValue, null); log("Validate that the expected rows after the update are in the log."); pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); @@ -715,7 +715,7 @@ public void testDomainPropertyEvents() "&Measure=false&Dimension=true&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false" + "&Scannable=false&DefaultValueType=Editable%20default&Lookup=%7B%22queryName%22%3A%22LookUp02%22%2C%22schemaName%22%3A%22lists%22%7D"; field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Modified", - "The following property was updated: Lookup", "", field3CreateValue, field3UpdateValue); + "The following property was updated: Lookup", "", field3CreateValue, field3UpdateValue, null); pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); @@ -733,7 +733,7 @@ public void testDomainPropertyEvents() listDefinitionPage.clickSave(); field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Deleted", - "", "", null, null); + "", "", null, null, null); pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); if(!pass) goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); diff --git a/src/org/labkey/test/tests/DomainDesignerTest.java b/src/org/labkey/test/tests/DomainDesignerTest.java index 4ad8881160..75b7b98886 100644 --- a/src/org/labkey/test/tests/DomainDesignerTest.java +++ b/src/org/labkey/test/tests/DomainDesignerTest.java @@ -54,6 +54,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -285,9 +286,12 @@ public void testInvalidLookupDomainField() throws IOException, CommandException EditListDefinitionPage editListDefinitionPage = new EditListDefinitionPage(getDriver()); editListDefinitionPage.setName(editedListName) .clickSave(); - checker().verifyEquals("The comment logged for the list update was not as expected.", - "The name of the list domain 'InvalidLookUpNameList' was changed to 'InvalidLookUpNameList_edited'. The descriptor of domain InvalidLookUpNameList_edited was updated", - _auditLogHelper.getLastDomainEventComment(getProjectName(), editedListName)); + + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The name of the list domain 'InvalidLookUpNameList' was changed to 'InvalidLookUpNameList_edited'. The descriptor of domain InvalidLookUpNameList_edited was updated.", + "", null, null, "Name: " + listName + " > " + editedListName); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Collections.emptyMap()); + checker().verifyTrue("The comment logged for the list renaming was not as expected", pass); domainDesignerPage = DomainDesignerPage.beginAt(this, getProjectName(), "exp.materials", sampleType); assertEquals("Look up should be updated after list renaming", "Current Folder > lists > " + editedListName, domainDesignerPage.fieldsPanel().getField("lookUpField").detailsMessage()); @@ -1386,10 +1390,10 @@ public void testRegexValidator() throws Exception "&Scannable=false&DefaultValueType=Editable%20default"; String fieldNewValues = fieldOldValues + "&Validator=neverTwizzlers%2C%20twizzler%20is%20not%20a%20snack%2C%20twizzler%2C%20failOnMatch%3Dtrue%2C%20favorite%20snack%20cannot%20be%20twizzlers%2C%20yo%2C%20Regular%20Expression"; AuditLogHelper.DetailedAuditEventRow fieldEvent = new AuditLogHelper.DetailedAuditEventRow(null, fieldNameWithReg, "Modified", - "The following property was updated: Validator", "", fieldOldValues, fieldNewValues); + "The following property was updated: Validator", "", fieldOldValues, fieldNewValues, null); AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, "The column(s) of domain " + listName + " were modified.", - "", null, null); + "", null, null, null); boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Map.of(fieldNameWithReg, fieldEvent)); if(!pass) diff --git a/src/org/labkey/test/tests/LinkedSchemaTest.java b/src/org/labkey/test/tests/LinkedSchemaTest.java index 28fe3c0052..8dde69b219 100644 --- a/src/org/labkey/test/tests/LinkedSchemaTest.java +++ b/src/org/labkey/test/tests/LinkedSchemaTest.java @@ -35,6 +35,7 @@ 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.APIContainerHelper; import org.labkey.test.util.ApiPermissionsHelper; import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; @@ -46,6 +47,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import static org.junit.Assert.assertEquals; @@ -428,7 +430,7 @@ void deleteLinkedSchema() } @Test - public void lookupTest() + public void lookupTest() throws CommandException { String sourceContainerPath = "/" + getProjectName() + "/" + SOURCE_FOLDER; _schemaHelper.createLinkedSchema(getProjectName() + "/" + TARGET_FOLDER, "BasicLinkedSchema", sourceContainerPath, null, "lists", "NIMHDemographics,NIMHPortions", null); @@ -443,12 +445,23 @@ public void lookupTest() //Make sure that the lookup columns propagated properly into the linked schema assertLookupsWorking(TARGET_FOLDER, "BasicLinkedSchema", "NIMHDemographics", true, "Mother", "Father"); + String sourceFolderId = ((APIContainerHelper) _containerHelper).getContainerId(getProjectName() + "/" + SOURCE_FOLDER); + String otherFolderId = ((APIContainerHelper) _containerHelper).getContainerId(getProjectName() + "/" + OTHER_FOLDER); + // Linked schemas disallow lookups to other folders outside of the current folder. //Change the Mother column lookup to point to the other folder, then ensure that the mother lookup is no longer propagating - changelistLookup(SOURCE_FOLDER, "NIMHDemographics", MOTHER, + String fieldOldValues = "Name=Mother&Label=Mother&Type=Integer&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false&Dimension=false" + + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false" + + "&Lookup=%7B%22queryName%22%3A%22NIMHDemographics%22%2C%22schemaName%22%3A%22lists%22%7D"; + String fieldUpdateValues = "Name=Mother&Label=Mother&Type=Integer&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false&Dimension=false" + + "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false" + + "&Lookup=%7B%22queryName%22%3A%22NIMHDemographics%22%2C%22schemaName%22%3A%22lists%22%2C%22containerId%22%3A%22" + + otherFolderId + "%22%7D"; + + changelistLookup( new FieldDefinition.LookupInfo("/" + PROJECT_NAME + "/" + OTHER_FOLDER, "lists", "NIMHDemographics") .setTableType(FieldDefinition.ColumnType.Integer), - "Lookup: [Container: old: null, new: OtherFolder, ];"); + fieldOldValues, fieldUpdateValues); assertLookupsWorking(TARGET_FOLDER, "BasicLinkedSchema", "NIMHDemographics", true, "Father"); assertLookupsWorking(TARGET_FOLDER, "BasicLinkedSchema", "NIMHDemographics", false, "Mother"); @@ -460,11 +473,14 @@ public void lookupTest() assertLookupsWorking(TARGET_FOLDER, "QueryLinkedSchema", "QueryOverLookup", true, "Father"); assertLookupsWorking(TARGET_FOLDER, "QueryLinkedSchema", "QueryOverLookup", false, "Mother"); + String fieldUpdateValues2 = "Name=Mother&Label=Mother&Type=Integer&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false&Measure=false&Dimension=false&ShownInInsert=true" + + "&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false&Lookup=%7B%22queryName%22%3A%22QueryOverLookup%22%2C%22schemaName%22%3A%22lists%22%2C%22containerId%22%3A%22" + + sourceFolderId + "%22%7D"; //Change the Mother column lookup to point to the query, and then make sure that the table has lookups appropriately. - changelistLookup(SOURCE_FOLDER, "NIMHDemographics", MOTHER, + changelistLookup( new FieldDefinition.LookupInfo("/" + PROJECT_NAME + "/" + SOURCE_FOLDER, "lists", "QueryOverLookup") .setTableType(FieldDefinition.ColumnType.Integer), - "Lookup: [Container: old: OtherFolder, new: SourceFolder, Query: old: NIMHDemographics, new: QueryOverLookup];"); + fieldUpdateValues, fieldUpdateValues2); assertLookupsWorking(TARGET_FOLDER, "QueryLinkedSchema", "NIMHDemographics", true, "Mother", "Father"); } @@ -995,19 +1011,26 @@ protected void assertLookupsWorking(String sourceFolder, String schemaName, Stri } } - protected void changelistLookup(String sourceFolder, String tableName, String fieldName, FieldDefinition.LookupInfo info, String changeLog) + protected void changelistLookup(FieldDefinition.LookupInfo info, String fieldOldValues, String fieldUpdateValues) { - clickFolder(sourceFolder); + clickFolder(LinkedSchemaTest.SOURCE_FOLDER); goToManageLists(); - EditListDefinitionPage listDefinitionPage = _listHelper.goToEditDesign(tableName); + EditListDefinitionPage listDefinitionPage = _listHelper.goToEditDesign("NIMHDemographics"); listDefinitionPage.getFieldsPanel() - .getField(fieldName).setLookup(info); + .getField(LinkedSchemaTest.MOTHER).setLookup(info); listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after changing lookup", "The column(s) of domain " + tableName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), tableName)); - checker().verifyEquals("Domain field audit comment not as expected", List.of(changeLog), _auditLogHelper.getLastDomainPropertyComment(getProjectName(), tableName)); + + log("Validate domain and domain property audit log."); + AuditLogHelper.DetailedAuditEventRow fieldEvent = new AuditLogHelper.DetailedAuditEventRow(null, LinkedSchemaTest.MOTHER, "Modified", + "The following property was updated: Lookup", "", fieldOldValues, fieldUpdateValues, null); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, "NIMHDemographics", null, + "The column(s) of domain " + "NIMHDemographics" + " were modified.", + "", null, null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents("NIMHDemographics", getProjectName(), expectedDomainEvent, Map.of(LinkedSchemaTest.MOTHER, fieldEvent)); + checker().verifyTrue("Domain audit long not as expected after changing lookup expected", pass); } protected void createLinkedSchemaQuery(String sourceFolder, String schemaName, String queryName, String tableName) diff --git a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java index 140f932608..004b52037d 100644 --- a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java +++ b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -608,9 +609,14 @@ public void testUseThenRemoveAnAliasParentColumn() updatePage.removeParentAlias(PARENT_COLUMN); updatePage.clickSave(); - checker().verifyEquals("The comment logged for the updating domain was not as expected.", - "AliquotNameExpression: -> ${${AliquotedFrom}-:withCounter};ImportAlias: P7(materialInputs/" + SAMPLE_TYPE_NAME + ",required=false) -> ; The descriptor of domain " + SAMPLE_TYPE_NAME + " was updated", - _auditLogHelper.getLastDomainEventComment(getProjectName(), SAMPLE_TYPE_NAME)); + log("Validate domain audit log."); + String oldValues = "Name=SimpleSampleType07&ImportAlias=P7(materialInputs%2FSimpleSampleType07%2Crequired%3Dfalse)"; + String newValues = "Name=SimpleSampleType07&AliquotNameExpression=%24%7B%24%7BAliquotedFrom%7D-%3AwithCounter%7D"; + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, SAMPLE_TYPE_NAME, null, + "The descriptor of domain " + SAMPLE_TYPE_NAME + " was updated.", + "", oldValues, newValues, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(SAMPLE_TYPE_NAME, PROJECT_NAME, expectedDomainEvent, Collections.emptyMap()); + checker().verifyTrue("Domain audit long not as expected after removing the parent alias column", pass); log("Import some more samples using the alias column and make sure it doesn't work."); sampleText = "Name\t" + PARENT_COLUMN + "\n" + @@ -709,8 +715,14 @@ public void testAliasNameConflictsWithFieldName() updatePage.addParentAlias(GOOD_PARENT_NAME, SampleTypeDesigner.CURRENT_SAMPLE_TYPE); updatePage.clickSave(); - checker().verifyEquals("The comment logged for the updating domain was not as expected.", "ImportAlias: -> P8(materialInputs/" + SAMPLE_TYPE_NAME + ",required=false); The descriptor of domain " + SAMPLE_TYPE_NAME + " was updated", - _auditLogHelper.getLastDomainEventComment(getProjectName(), SAMPLE_TYPE_NAME)); + log("Validate domain audit log."); + String oldValues = "Name=SimpleSampleType08&AliquotNameExpression=%24%7B%24%7BAliquotedFrom%7D-%3AwithCounter%7D"; + String newValues = "Name=SimpleSampleType08&AliquotNameExpression=%24%7B%24%7BAliquotedFrom%7D-%3AwithCounter%7D&ImportAlias=P8(materialInputs%2FSimpleSampleType08%2Crequired%3Dfalse)"; + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, SAMPLE_TYPE_NAME, null, + "The descriptor of domain " + SAMPLE_TYPE_NAME + " was updated.", + "", oldValues, newValues, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(SAMPLE_TYPE_NAME, PROJECT_NAME, expectedDomainEvent, Collections.emptyMap()); + checker().verifyTrue("Domain audit long not as expected after adding a parent alias column", pass); clickFolder(SUB_FOLDER_NAME); updatePage = sampleHelper.goToEditSampleType(SAMPLE_TYPE_NAME); diff --git a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java index f1b341d3c9..f6485402a9 100644 --- a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java +++ b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java @@ -463,10 +463,10 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm "&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false&Scannable=false" + "&DefaultValueType=Editable%20default&Validator=Text%20Choice%20Validator%2C%20BB%7CCC%20and%20here%20is%20an%20update%7CE%20E%20E%7CGG%7CH%7C%C2%83%C2%83%20updated%7C%C3%85%5C%7C%C3%85%2C%20Text%20Choice%20Validator"; AuditLogHelper.DetailedAuditEventRow fieldEvent = new AuditLogHelper.DetailedAuditEventRow(null, textChoiceFieldName, "Modified", - "The following property was updated: Validator", "", fieldOldValues, fieldUpdateValues); + "The following property was updated: Validator", "", fieldOldValues, fieldUpdateValues, null); AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, sampleTypeName, null, "The column(s) of domain " + sampleTypeName + " were modified.", - "", null, null); + "", null, null, null); boolean pass = _auditLogHelper.validateLastDomainAuditEvents(sampleTypeName, getProjectName(), expectedDomainEvent, Map.of(textChoiceFieldName, fieldEvent)); checker().verifyTrue("Audit event is not as expected", pass); @@ -558,7 +558,7 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm "&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false&ExcludedFromShifting=false" + "&Scannable=false&DefaultValueType=Editable%20default&Validator=Text%20Choice%20Validator%2C%20BB%7CCC%20and%20here%20is%20an%20update%7CE%20E%20E%7CGG%7CH%20no%20change%7C%C2%83%C2%83%20updated%7C%C3%85%5C%7C%C3%85%2C%20Text%20Choice%20Validator"; fieldEvent = new AuditLogHelper.DetailedAuditEventRow(null, textChoiceFieldName, "Modified", - "The following property was updated: Validator", "", fieldUpdateValues, fieldUpdateValues2); + "The following property was updated: Validator", "", fieldUpdateValues, fieldUpdateValues2, null); pass = _auditLogHelper.validateLastDomainAuditEvents(sampleTypeName, getProjectName(), expectedDomainEvent, Map.of(textChoiceFieldName, fieldEvent)); checker().verifyTrue("Audit event is not as expected", pass); diff --git a/src/org/labkey/test/tests/list/ListDateAndTimeTest.java b/src/org/labkey/test/tests/list/ListDateAndTimeTest.java index 9361e8eadc..3406f513a8 100644 --- a/src/org/labkey/test/tests/list/ListDateAndTimeTest.java +++ b/src/org/labkey/test/tests/list/ListDateAndTimeTest.java @@ -1225,8 +1225,15 @@ public void testDateAndTimeFormat() listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after changing datetime format", "The column(s) of domain " + listName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); - checker().verifyEqualsSorted("Domain field audit comment not as expected", List.of("Format: yyyy-MM-dd -> ddMMMyy;", "Format: hh:mm a -> HH:mm:ss;", "Format: yyyy-MM-dd hh:mm a -> dd-MMM-yyyy HH:mm:ss;"), _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The column(s) of domain " + listName + " were modified.", + "", null, null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, PROJECT_NAME, expectedDomainEvent, + Map.of(timeCol, new AuditLogHelper.DetailedAuditEventRow(null, timeCol, "Modified","The following property was updated: Format",null, null, null, "Format: hh:mm a > HH:mm:ss"), + dateCol, new AuditLogHelper.DetailedAuditEventRow(null, dateCol, "Modified","The following property was updated: Format",null, null, null, "Format: yyyy-MM-dd > ddMMMyy"), + dateTimeCol, new AuditLogHelper.DetailedAuditEventRow(null, dateTimeCol, "Modified","The following property was updated: Format",null, null, null, "Format: yyyy-MM-dd hh:mm a > dd-MMM-yyyy HH:mm:ss")) + ); + checker().verifyTrue("Domain audit log not as expected after adding a parent alias column", pass); expectedData = new ArrayList<>(); @@ -1356,8 +1363,14 @@ public void testConvertDateTimeField() throws IOException, CommandException listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after changing data type", "The column(s) of domain Convert DateTime Field List were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); - checker().verifyEqualsSorted("Domain field audit comment not as expected", List.of("Type: DateTime -> Date;", "Type: DateTime -> Time;"), _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The column(s) of domain " + listName + " were modified.", + "", null, null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, PROJECT_NAME, expectedDomainEvent, + Map.of(dateTimeToDateCol, new AuditLogHelper.DetailedAuditEventRow(null, dateTimeToDateCol, "Modified","The following properties were updated: Type, Format",null, null, null, "Type: DateTime > Date\nFormat: MMMM dd yyyy HH:mm > "), + dateTimeToTimeCol, new AuditLogHelper.DetailedAuditEventRow(null, dateTimeToTimeCol, "Modified","The following properties were updated: Type, Format",null, null, null, "Type: DateTime > Time\nFormat: yyyy-MMM-dd HH:mm:ss > ")) + ); + checker().verifyTrue("Domain audit log not as expected after changing data type", pass); // Update default format after changing the types. DATE_FORMAT dateFormat = DATE_FORMAT.Default; diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index 5080541cdf..e256f79b3d 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -1230,11 +1230,14 @@ private void customFormattingTest() listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after changing conditional format", "The column(s) of domain " + TSV_LIST_NAME + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), TSV_LIST_NAME)); - checker().verifyEqualsSorted("Domain field audit comment not as expected", - List.of("ConditionalFormats: old: , new: format.column~gt=7: text-decoration: line-through;, format.column~gt=5: font-weight: bold;;", - "ConditionalFormats: old: , new: format.column~eq=true: text-decoration: line-through;font-weight: bold;font-style: italic;color: #68ccca;background-color: #d33115 !important;;"), - _auditLogHelper.getLastDomainPropertyComment(getProjectName(), TSV_LIST_NAME)); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, TSV_LIST_NAME, null, + "The column(s) of domain " + TSV_LIST_NAME + " were modified.", + "", null, null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(TSV_LIST_NAME, getProjectName(), expectedDomainEvent, + Map.of("IntCol", new AuditLogHelper.DetailedAuditEventRow(null, "IntCol", "Modified","The following properties were updated: Type, ConditionalFormat",null, null, null, "ConditionalFormat: » format.column~gt=7: text-decoration: line-through;, format.column~gt=5: font-weight: bold;"), + "BoolCol", new AuditLogHelper.DetailedAuditEventRow(null, "BoolCol", "Modified","The following properties were updated: ConditionalFormat",null, null, null, "ConditionalFormat: » format.column~eq=true: text-decoration: line-through;font-weight: bold;font-style: italic;color: #68ccca;background-color: #d33115 !important;")) + ); + checker().verifyTrue("Domain audit comment not as expected after changing conditional format", pass); // Verify conditional format of boolean column // look for cells that do not match the @@ -1303,10 +1306,12 @@ public void doRenameFieldsTest() .setLabel(newFieldName); listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after renaming a field", "The column(s) of domain " + listName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); - checker().verifyEqualsSorted("Domain field audit comment not as expected", - List.of("Name: "+ origFieldName + " -> " + newFieldName + "; Label: " + origFieldName + " -> " + newFieldName + ";"), - _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The column(s) of domain " + listName + " were modified.", + "", null, null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, + Map.of(newFieldName, new AuditLogHelper.DetailedAuditEventRow(null, newFieldName, "Modified","The following properties were updated: Name, Label",null, null, null, "Name: "+ origFieldName + " > " + newFieldName + "\nLabel: " + origFieldName + " > " + newFieldName))); + checker().verifyTrue("Domain audit comment not as expected after renaming a field", pass); assertTextPresent(newFieldName); assertTextNotPresent(origFieldName); @@ -1345,10 +1350,15 @@ public void exportPhiFileColumn() throws Exception listDefinitionPage.setColumnPhiLevel("RestrictedPhiColumn", FieldDefinition.PhiSelectType.Restricted); listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after changing PHI setting for a field", "The column(s) of domain " + listName + " were modified", _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); - checker().verifyEqualsSorted("Domain field audit comment not as expected", - List.of("PHI: Not PHI -> Limited PHI;", "PHI: Not PHI -> Full PHI;", "PHI: Not PHI -> Restricted PHI;"), - _auditLogHelper.getLastDomainPropertyComment(getProjectName(), listName)); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, TSV_LIST_NAME, null, + "The column(s) of domain " + TSV_LIST_NAME + " were modified.", + "", null, null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(TSV_LIST_NAME, getProjectName(), expectedDomainEvent, + Map.of("LimitedPhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "LimitedPhiColumn", "Modified","The following properties were updated: PHI",null, null, null, "PHI: Not PHI > Limited PHI"), + "PhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "PhiColumn", "Modified","The following properties were updated: PHI",null, null, null, "PHI: Not PHI > Full PHI"), + "RestrictedPhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "RestrictedPhiColumn", "Modified","The following properties were updated: PHI",null, null, null, "PHI: Not PHI > Restricted PHI")) + ); + checker().verifyTrue("Domain audit comment not as expected after changing conditional format", pass); goToProjectHome(); clickAndWait(Locator.linkWithText(listName)); @@ -1522,9 +1532,11 @@ public void testFieldUniqueConstraint() .apply(); listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after updating field unique constraint", - "Index: -> [field Name1, unique: true, fieldName_2, unique: true]; The descriptor of domain " + listName + " was updated", - _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The descriptor of domain " + listName + " was updated", + "", null, null, "Index: > [field Name1, unique: true, fieldName_2, unique: true]"); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Collections.emptyMap()); + checker().verifyTrue("Domain audit comment not as expected after updating field unique constraint", pass); viewRawTableMetadata(listName); verifyTableIndices("unique_constraint_list_", List.of("field_name1", "fieldname_2")); @@ -1540,9 +1552,11 @@ public void testFieldUniqueConstraint() .apply(); listDefinitionPage.clickSave(); - checker().verifyEquals("Domain audit comment not as expected after updating field unique constraint", - "Index: field name1, unique: true, fieldname_2, unique: true -> FieldName@3, unique: true, field Name1, unique: true; The descriptor of domain " + listName + " was updated", - _auditLogHelper.getLastDomainEventComment(getProjectName(), listName)); + expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The descriptor of domain " + listName + " was updated", + "", null, null, "Index: field name1, unique: true, fieldname_2, unique: true > FieldName@3, unique: true, field Name1, unique"); + pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Collections.emptyMap()); + checker().verifyTrue("Domain audit comment not as expected after updating field unique constraint", pass); viewRawTableMetadata(listName); verifyTableIndices("unique_constraint_list_", List.of("field_name1", "fieldname_3")); diff --git a/src/org/labkey/test/util/AuditLogHelper.java b/src/org/labkey/test/util/AuditLogHelper.java index 1ccf324e71..62f7440a04 100644 --- a/src/org/labkey/test/util/AuditLogHelper.java +++ b/src/org/labkey/test/util/AuditLogHelper.java @@ -205,15 +205,18 @@ public boolean validateDetailAuditLog(DetailedAuditEventRow expectedAuditDetail, boolean pass = true; for (String prop : propertyAuditColumns) { - if (expectedAuditDetail.getColumn(prop) != null) + String expectedValue = expectedAuditDetail.getColumn(prop); + if (expectedValue != null) { - if (StringUtils.isEmpty(expectedAuditDetail.getColumn(prop)) && actualAuditDetail.getColumn(prop) == null) + String actualValue = actualAuditDetail.getColumn(prop); + + if (StringUtils.isEmpty(expectedValue) && actualValue == null) continue; - if (!expectedAuditDetail.getColumn(prop).equals(actualAuditDetail.getColumn(prop))) + if (!expectedValue.equals(actualValue)) { pass = false; - TestLogger.log(prop + " is not as expected. Expected: " + expectedAuditDetail.getColumn(prop) + ", Actual: " + actualAuditDetail.getColumn(prop)); + TestLogger.log(prop + " is not as expected. Expected: " + expectedValue + ", Actual: " + actualValue); } } } @@ -222,6 +225,8 @@ public boolean validateDetailAuditLog(DetailedAuditEventRow expectedAuditDetail, public boolean validateDomainPropertiesAuditLog(String domainName, Integer domainEventId, Map expectedAuditDetails) { + if (expectedAuditDetails == null) + return true; Map actualAuditDetails = getDomainPropertyEvents(domainName, domainEventId); boolean pass = true; if (expectedAuditDetails.keySet().size() != actualAuditDetails.keySet().size()) @@ -274,13 +279,13 @@ public Integer getLastDomainEventId(String projectName, String domainName) return getLastDomainEvent(projectName, domainName).rowId; } - public String getLastDomainEventComment(String projectName, String domainName) + public String getLastDomainEventComment(String projectName, String domainName) // TODO delete { return getLastDomainEvent(projectName, domainName).comment; } - public static List propertyAuditColumns = List.of("type", "comment", "usercomment", "oldvalues", "newvalues"); - public record DetailedAuditEventRow(Integer rowId, String keyValue, String type, String comment, String userComment, String oldValues, String newValues) + public static List propertyAuditColumns = List.of("type", "comment", "usercomment", "oldvalues", "newvalues", "datachanges"); + public record DetailedAuditEventRow(Integer rowId, String keyValue, String type, String comment, String userComment, String oldValues, String newValues, String dataChanges) { public String getColumn(String columnName) { @@ -294,6 +299,7 @@ public String getColumn(String columnName) case "usercomment" -> userComment; case "oldvalues" -> oldValues; case "newvalues" -> newValues; + case "datachanges" -> dataChanges; default -> null; }; } @@ -316,7 +322,8 @@ public Map getDomainPropertyEvents(String domainN String userComment = getLogColumnValue(event, "UserComment"); String oldValue = getLogColumnValue(event, "oldValues"); String newValue = getLogColumnValue(event, "newValues"); - domainPropEventComments.put(propertyName, new DetailedAuditEventRow(rowId, propertyName, action, comment, userComment, oldValue, newValue)); + String dataChanges = getLogColumnDisplayValue(event, "dataChanges"); + domainPropEventComments.put(propertyName, new DetailedAuditEventRow(rowId, propertyName, action, comment, userComment, oldValue, newValue, dataChanges)); }); return domainPropEventComments; @@ -366,7 +373,7 @@ private List getDomainEventLog(String projectName, String Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainAuditEvent"); cmd.setRequiredVersion(9.1); - cmd.setColumns(Arrays.asList("rowid", "domainuri", "domainname", "comment", "usercomment", "oldvalues", "newvalues")); + cmd.setColumns(Arrays.asList("rowid", "domainuri", "domainname", "comment", "usercomment", "oldvalues", "newvalues", "datachanges")); cmd.addFilter("projectid/DisplayName", projectName, Filter.Operator.EQUAL); if(null != ignoreIds) { @@ -398,8 +405,8 @@ private List getDomainEventLog(String projectName, String String userComment = getLogColumnValue(row, "usercomment"); String oldValue = getLogColumnValue(row, "oldvalues"); String newValue = getLogColumnValue(row, "newvalues"); - - domainAuditEventRows.add(new DetailedAuditEventRow(rowId, domainName, null, comment, userComment, oldValue, newValue)); + String dataChanges = getLogColumnDisplayValue(row, "dataChanges"); + domainAuditEventRows.add(new DetailedAuditEventRow(rowId, domainName, null, comment, userComment, oldValue, newValue, dataChanges)); } } @@ -411,7 +418,7 @@ private List> getDomainPropertyEventLog(String domainName, @ Connection cn = WebTestHelper.getRemoteApiConnection(); SelectRowsCommand cmd = new SelectRowsCommand("auditLog", "DomainPropertyAuditEvent"); cmd.setRequiredVersion(9.1); - cmd.setColumns(Arrays.asList("Created", "CreatedBy", "ImpersonatedBy", "propertyname", "action", "domainname", "domaineventid", "Comment", "UserComment", "oldvalues", "newvalues")); + cmd.setColumns(Arrays.asList("Created", "CreatedBy", "ImpersonatedBy", "propertyname", "action", "domainname", "domaineventid", "Comment", "UserComment", "oldvalues", "newvalues", "datachanges")); cmd.addFilter("domainname", domainName, Filter.Operator.EQUAL); if(null != eventIds) @@ -484,14 +491,14 @@ private Map getDomainPropertyEventComment(Map ro return fieldComments; } - private String getLogColumnValue(Map rowEntry, String columnName) + private String getLogColumnValue(Map rowEntry, String columnName, String valueType) { try { Map val = ((Map) rowEntry.get(columnName)); if (val == null) return null; - Object value = val.get("value"); + Object value = val.get(valueType); if (value == null) return null; return value.toString(); @@ -503,6 +510,16 @@ private String getLogColumnValue(Map rowEntry, String columnName } } + private String getLogColumnValue(Map rowEntry, String columnName) + { + return getLogColumnValue(rowEntry, columnName, "value"); + } + + private String getLogColumnDisplayValue(Map rowEntry, String columnName) + { + return getLogColumnValue(rowEntry, columnName, "displayValue"); + } + private Integer getLogColumnIntValue(Map rowEntry, String columnName) { try From 26d2bd6f13d1ad8c60af8b19f77b013afe2a899f Mon Sep 17 00:00:00 2001 From: XingY Date: Wed, 21 May 2025 00:10:44 -0700 Subject: [PATCH 07/13] support calculated field audit changes, genId update audit, update/add tests --- .../domainproperties/EntityTypeDesigner.java | 18 ++++++++++++++ .../labkey/test/tests/LinkedSchemaTest.java | 2 +- src/org/labkey/test/tests/list/ListTest.java | 24 +++++++++---------- src/org/labkey/test/util/AuditLogHelper.java | 10 -------- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java b/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java index c92abe4c4e..6e037894e6 100644 --- a/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java +++ b/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java @@ -255,6 +255,21 @@ public Optional optionalWarningAlert() return elementCache().optionalWarningAlert(); } + public void setActionComment(String comment) + { + elementCache().commentInput.sendKeys(comment); + } + + public void clearActionComment() + { + elementCache().commentInput.clear(); + } + + public boolean isCommentInputPresent() + { + return elementCache().commentInputLocator.findOptionalElement(getDriver()).isPresent(); + } + /** * Dialog that allows the user to set the genId value. @@ -419,6 +434,9 @@ public final WebElement helpTarget(String divLabelText) final Locator uniqueIdMsgLoc = Locator.tagWithClass("div", "uniqueid-msg"); + public Locator.XPathLocator commentInputLocator = Locator.tagWithId("textarea", "actionComments"); + public WebElement commentInput = commentInputLocator.refindWhenNeeded(getDriver()); + public List parentAliases() { return Input.Input(Locator.name("alias"), getDriver()).findAll(propertiesPanel); diff --git a/src/org/labkey/test/tests/LinkedSchemaTest.java b/src/org/labkey/test/tests/LinkedSchemaTest.java index 8dde69b219..4a3bcce5f7 100644 --- a/src/org/labkey/test/tests/LinkedSchemaTest.java +++ b/src/org/labkey/test/tests/LinkedSchemaTest.java @@ -943,7 +943,7 @@ public void testAuditTableLinkedSchema() goToSchemaBrowser(); table = viewQueryData(linkedSchemaName, "DomainAuditEvent"); - checker().verifyEquals("Incorrect number of rows in DomainAuditEvent", 33, table.getDataRowCount()); + checker().verifyEquals("Incorrect number of rows in DomainAuditEvent", 23, table.getDataRowCount()); } protected void goToSchemaBrowserTable(String schemaName, String tableName) diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index e256f79b3d..bdf78185e4 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -1234,8 +1234,8 @@ private void customFormattingTest() "The column(s) of domain " + TSV_LIST_NAME + " were modified.", "", null, null, null); boolean pass = _auditLogHelper.validateLastDomainAuditEvents(TSV_LIST_NAME, getProjectName(), expectedDomainEvent, - Map.of("IntCol", new AuditLogHelper.DetailedAuditEventRow(null, "IntCol", "Modified","The following properties were updated: Type, ConditionalFormat",null, null, null, "ConditionalFormat: » format.column~gt=7: text-decoration: line-through;, format.column~gt=5: font-weight: bold;"), - "BoolCol", new AuditLogHelper.DetailedAuditEventRow(null, "BoolCol", "Modified","The following properties were updated: ConditionalFormat",null, null, null, "ConditionalFormat: » format.column~eq=true: text-decoration: line-through;font-weight: bold;font-style: italic;color: #68ccca;background-color: #d33115 !important;")) + Map.of("IntCol", new AuditLogHelper.DetailedAuditEventRow(null, "IntCol", "Modified","The following property was updated: ConditionalFormat",null, null, null, "ConditionalFormat: > format.column~gt=7: text-decoration: line-through;, format.column~gt=5: font-weight: bold;"), + "BoolCol", new AuditLogHelper.DetailedAuditEventRow(null, "BoolCol", "Modified","The following property was updated: ConditionalFormat",null, null, null, "ConditionalFormat: > format.column~eq=true: text-decoration: line-through;font-weight: bold;font-style: italic;color: #68ccca;background-color: #d33115 !important;")) ); checker().verifyTrue("Domain audit comment not as expected after changing conditional format", pass); @@ -1350,13 +1350,13 @@ public void exportPhiFileColumn() throws Exception listDefinitionPage.setColumnPhiLevel("RestrictedPhiColumn", FieldDefinition.PhiSelectType.Restricted); listDefinitionPage.clickSave(); - AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, TSV_LIST_NAME, null, - "The column(s) of domain " + TSV_LIST_NAME + " were modified.", + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, + "The column(s) of domain " + listName + " were modified.", "", null, null, null); - boolean pass = _auditLogHelper.validateLastDomainAuditEvents(TSV_LIST_NAME, getProjectName(), expectedDomainEvent, - Map.of("LimitedPhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "LimitedPhiColumn", "Modified","The following properties were updated: PHI",null, null, null, "PHI: Not PHI > Limited PHI"), - "PhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "PhiColumn", "Modified","The following properties were updated: PHI",null, null, null, "PHI: Not PHI > Full PHI"), - "RestrictedPhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "RestrictedPhiColumn", "Modified","The following properties were updated: PHI",null, null, null, "PHI: Not PHI > Restricted PHI")) + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, + Map.of("LimitedPhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "LimitedPhiColumn", "Modified","The following property was updated: PHI",null, null, null, "PHI: Not PHI > Limited PHI"), + "PhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "PhiColumn", "Modified","The following property was updated: PHI",null, null, null, "PHI: Not PHI > Full PHI"), + "RestrictedPhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "RestrictedPhiColumn", "Modified","The following property was updated: PHI",null, null, null, "PHI: Not PHI > Restricted PHI")) ); checker().verifyTrue("Domain audit comment not as expected after changing conditional format", pass); @@ -1533,8 +1533,8 @@ public void testFieldUniqueConstraint() listDefinitionPage.clickSave(); AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, - "The descriptor of domain " + listName + " was updated", - "", null, null, "Index: > [field Name1, unique: true, fieldName_2, unique: true]"); + "The descriptor of domain " + listName + " was updated.", + "", null, null, "Indices: > [field Name1, unique: true, fieldName_2, unique: true]"); boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Collections.emptyMap()); checker().verifyTrue("Domain audit comment not as expected after updating field unique constraint", pass); @@ -1553,8 +1553,8 @@ public void testFieldUniqueConstraint() listDefinitionPage.clickSave(); expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, - "The descriptor of domain " + listName + " was updated", - "", null, null, "Index: field name1, unique: true, fieldname_2, unique: true > FieldName@3, unique: true, field Name1, unique"); + "The descriptor of domain " + listName + " was updated.", + "", null, null, "Indices: [field name1, unique: true, fieldname_2, unique: true] > [FieldName@3, unique: true, field Name1, unique: true]"); pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Collections.emptyMap()); checker().verifyTrue("Domain audit comment not as expected after updating field unique constraint", pass); diff --git a/src/org/labkey/test/util/AuditLogHelper.java b/src/org/labkey/test/util/AuditLogHelper.java index 62f7440a04..685f3fd789 100644 --- a/src/org/labkey/test/util/AuditLogHelper.java +++ b/src/org/labkey/test/util/AuditLogHelper.java @@ -279,11 +279,6 @@ public Integer getLastDomainEventId(String projectName, String domainName) return getLastDomainEvent(projectName, domainName).rowId; } - public String getLastDomainEventComment(String projectName, String domainName) // TODO delete - { - return getLastDomainEvent(projectName, domainName).comment; - } - public static List propertyAuditColumns = List.of("type", "comment", "usercomment", "oldvalues", "newvalues", "datachanges"); public record DetailedAuditEventRow(Integer rowId, String keyValue, String type, String comment, String userComment, String oldValues, String newValues, String dataChanges) { @@ -340,11 +335,6 @@ public List getLastDomainPropertyValues(String projectName, String domai return getLastDomainPropertyEvents(projectName, domainName).values().stream().map(values -> values.getColumn(columnName)).toList(); } - public List getLastDomainPropertyComment(String projectName, String domainName) - { - return getLastDomainPropertyValues(projectName, domainName, "comment"); - } - public List getDomainEventComments(String projectName, String domainName, @Nullable Collection ignoreIds) { List domainAuditEventAllRows = getDomainEventLog(projectName, domainName, ignoreIds); From 836d4bd39372dbe1499220a7a8f910c86b70c0a0 Mon Sep 17 00:00:00 2001 From: XingY Date: Wed, 21 May 2025 11:38:14 -0700 Subject: [PATCH 08/13] add test for genId events --- .../tests/SampleTypeNameExpressionTest.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/org/labkey/test/tests/SampleTypeNameExpressionTest.java b/src/org/labkey/test/tests/SampleTypeNameExpressionTest.java index 71d21e438e..39dac35804 100644 --- a/src/org/labkey/test/tests/SampleTypeNameExpressionTest.java +++ b/src/org/labkey/test/tests/SampleTypeNameExpressionTest.java @@ -33,6 +33,7 @@ import org.labkey.test.pages.experiment.UpdateSampleTypePage; import org.labkey.test.params.FieldDefinition; import org.labkey.test.params.experiment.SampleTypeDefinition; +import org.labkey.test.util.AuditLogHelper; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.EscapeUtil; import org.labkey.test.util.PortalHelper; @@ -82,6 +83,8 @@ public class SampleTypeNameExpressionTest extends BaseWebDriverTest private static final File PARENT_EXCEL = TestFileUtils.getSampleData("samples/ParentSamples.xlsx"); + protected final AuditLogHelper _auditLogHelper = new AuditLogHelper(this); + @Override public List getAssociatedModules() { @@ -1283,6 +1286,13 @@ public void testSetAndResetOfGenId() idDialog.setGenId(Integer.toString(nextGenId)); idDialog.dismiss("Update"); + // check audit log + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, sampleType, null, + "The genId for domain Test_Set_GenId has been updated to " + (nextGenId - 1) + ".", null, null, + null, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(sampleType, getProjectName(), expectedDomainEvent, null); + checker().verifyTrue("Result Domain event not as expected after updating genId", pass); + log("Validate that the banner has been updated."); checker() @@ -1335,17 +1345,17 @@ public void testSetAndResetOfGenId() waitFor(updatePage::isResetGenIdVisible, "The 'Reset GenId' button should now be visible if the sample type is empty. Fatal error.", 500); - ModalDialog deleteDialog = updatePage.clickResetGenId(); + ModalDialog genIdDialog = updatePage.clickResetGenId(); String expectedMsg = String.format("The current genId is at %d. Resetting will reset genId back to 1 and cannot be undone.", nextGenId); checker() .withScreenshot("Reset_GenId_Dialog_Error") .verifyEquals("Message in the reset confirm dialog is not as expected.", - expectedMsg, deleteDialog.getBodyText()); + expectedMsg, genIdDialog.getBodyText()); log("Click 'Cancel' and verify banner/genId does not change."); - deleteDialog.dismiss("Cancel"); + genIdDialog.dismiss("Cancel"); checker() .withScreenshot("Reset_GenId_Cancel_Error") @@ -1354,8 +1364,15 @@ public void testSetAndResetOfGenId() log("Click 'Rest GenId' again and this time reset the genId."); - deleteDialog = updatePage.clickResetGenId(); - deleteDialog.dismiss("Reset"); + genIdDialog = updatePage.clickResetGenId(); + genIdDialog.dismiss("Reset"); + + expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, sampleType, null, + "The genId for domain " + sampleType + " has been updated to 0.", null, null, + null, null); + pass = _auditLogHelper.validateLastDomainAuditEvents(sampleType, getProjectName(), expectedDomainEvent, null); + checker().verifyTrue("Result Domain event not as expected after resetting genId", pass); + nextGenId = 1; checker() From 3655b802124a844bcdf0449ccecd4f348609c40b Mon Sep 17 00:00:00 2001 From: XingY Date: Wed, 21 May 2025 23:23:16 -0700 Subject: [PATCH 09/13] add more tests --- src/org/labkey/test/tests/AuditLogTest.java | 45 +++++++------------ .../test/tests/TextChoiceSampleTypeTest.java | 17 +++++++ .../test/tests/list/ListDateAndTimeTest.java | 2 +- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/org/labkey/test/tests/AuditLogTest.java b/src/org/labkey/test/tests/AuditLogTest.java index eb58eeae80..31a2da9680 100644 --- a/src/org/labkey/test/tests/AuditLogTest.java +++ b/src/org/labkey/test/tests/AuditLogTest.java @@ -88,6 +88,8 @@ public class AuditLogTest extends BaseWebDriverTest private static final String AUDIT_TEST_SUBFOLDER = "AuditVerifyTest_Subfolder"; private static final String AUDIT_PROPERTY_EVENTS_PROJECT = "AuditDomainPropertyEvents"; + final String DOMAIN_PROPERTY_LOG_NAME = "Domain property events"; + public static final String COMMENT_COLUMN = "Comment"; private final ApiPermissionsHelper permissionsHelper = new ApiPermissionsHelper(this); @@ -572,8 +574,6 @@ public void testDomainPropertyEvents() final String FIELD03_NAME = "Field03"; final String FIELD03_LABEL = "Field 03 Lookup"; - final String DOMAIN_PROPERTY_LOG_NAME = "Domain property events"; - _containerHelper.createProject(AUDIT_PROPERTY_EVENTS_PROJECT, null); PortalHelper portalHelper = new PortalHelper(getDriver()); @@ -618,13 +618,7 @@ public void testDomainPropertyEvents() AuditLogHelper.DetailedAuditEventRow keyFieldExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, "Key", "Created", null, null, null, null, null); - boolean pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of("Key", keyFieldExpectedEvent, FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); - - // We are going to fail, so navigate to the Domain Property Events Audit Log. - if(!pass) - goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); - - Assert.assertTrue("The values logged for the 'Created' events were not as expected. See log for details.", pass); + validateLastDomainAuditEvents(LIST_CHECK_LOG, "The values logged for the 'Created' events were not as expected.", expectedDomainEvent, Map.of("Key", keyFieldExpectedEvent, FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); log("Looks like the created events were as expected. Now modify some column/field attributes."); goToProjectHome(AUDIT_PROPERTY_EVENTS_PROJECT); @@ -665,13 +659,7 @@ public void testDomainPropertyEvents() "The following properties were updated: DefaultScale, Format, ConditionalFormat", "", field2InitValue, field2UpdateValue, null); log("Validate that the expected rows after the update are in the log."); - pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); - - // We are going to fail, so navigate to the Domain Property Events Audit Log. - if(!pass) - goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); - - Assert.assertTrue("The values logged for the 'Modified' events were not as expected. See log for details.", pass); + validateLastDomainAuditEvents(LIST_CHECK_LOG, "The values logged for the 'Modified' events were not as expected.", expectedDomainEvent, Map.of(FIELD01_NAME, field1ExpectedEvent, FIELD02_NAME, field2ExpectedEvent)); log("The modified events were logged as expected. Now add a lookup field."); goToProjectHome(AUDIT_PROPERTY_EVENTS_PROJECT); @@ -690,14 +678,7 @@ public void testDomainPropertyEvents() null, "", null, field3CreateValue, null); log("Validate that the expected rows after the update are in the log."); - pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); - - - // We are going to fail, so navigate to the Domain Property Events Audit Log. - if(!pass) - goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); - - Assert.assertTrue("The values logged for the 'Created' event for the lookup field were not as expected. See log for details.", pass); + validateLastDomainAuditEvents(LIST_CHECK_LOG, "The values logged for the 'Created' event for the lookup field were not as expected.", expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); log("The 'Created' event was logged as expected. Now modify the field to point to a new list in the lookup field."); goToProjectHome(AUDIT_PROPERTY_EVENTS_PROJECT); @@ -716,8 +697,7 @@ public void testDomainPropertyEvents() "&Scannable=false&DefaultValueType=Editable%20default&Lookup=%7B%22queryName%22%3A%22LookUp02%22%2C%22schemaName%22%3A%22lists%22%7D"; field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Modified", "The following property was updated: Lookup", "", field3CreateValue, field3UpdateValue, null); - pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); - + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); // We are going to fail, so navigate to the Domain Property Events Audit Log. if(!pass) @@ -734,13 +714,18 @@ public void testDomainPropertyEvents() field3ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, FIELD03_NAME, "Deleted", "", "", null, null, null); - pass = _auditLogHelper.validateLastDomainAuditEvents(LIST_CHECK_LOG, AUDIT_PROPERTY_EVENTS_PROJECT, expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); + validateLastDomainAuditEvents(LIST_CHECK_LOG, "The values logged for the 'Deleted' events for the lookup field were not as expected.", expectedDomainEvent, Map.of(FIELD03_NAME, field3ExpectedEvent)); + + log("Ok, it looks like everything was logged as expected. Yipeee!"); + } + + private void validateLastDomainAuditEvents(String domainName, String failComment, AuditLogHelper.DetailedAuditEventRow domainEvent, Map propertyEvents) + { + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(domainName, AUDIT_PROPERTY_EVENTS_PROJECT, domainEvent, propertyEvents); if(!pass) goToAuditEventView(this, DOMAIN_PROPERTY_LOG_NAME); - Assert.assertTrue("The values logged for the 'Deleted' events for the lookup field were not as expected. See log for details.", pass); - - log("Ok, it looks like everything was logged as expected. Yipeee!"); + Assert.assertTrue(failComment + " See log for details.", pass); } } diff --git a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java index f6485402a9..d4ca85dce3 100644 --- a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java +++ b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java @@ -1,5 +1,6 @@ package org.labkey.test.tests; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -598,6 +599,22 @@ public void testSetTextChoiceValueForSample() throws IOException, CommandExcepti TestDataGenerator dataGenerator = createSampleType(sampleTypeName, namePrefix, textChoiceFieldName, tcValues); + // audit log for creating new sample type + String fieldValueMap = "Name=TextChoice_Field&Type=String&Scale=4000&PHI=Not%20PHI&DefaultScale=Linear&Required=false&Hidden=false&MvEnabled=false" + + "&Measure=false&Dimension=false&ShownInInsert=true&ShownInDetails=true&ShownInUpdate=true&ShownInLookupView=false&RecommendedVariable=false" + + "&ExcludedFromShifting=false&Scannable=false&DefaultValueType=Editable%20default" + + "&Validator=Text%20Choice%20Validator%2C%20%C3%86%5C%7C%5C%7C%C3%86%7CBB%7CC%5C%7C%5C%7CC%2C%20Text%20Choice%20Validator"; + AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, sampleTypeName, null, + "The domain " + sampleTypeName + " was created. The column(s) of domain " + sampleTypeName + " were modified.", + null, null, "NameExpression=TCSM_%24%7BgenId%7D", null); + AuditLogHelper.DetailedAuditEventRow field1ExpectedEvent = new AuditLogHelper.DetailedAuditEventRow(null, textChoiceFieldName, "Created", + null, null, null, fieldValueMap, null); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(sampleTypeName, getProjectName(), expectedDomainEvent, + Map.of(textChoiceFieldName, field1ExpectedEvent, + "Str", new AuditLogHelper.DetailedAuditEventRow(null, "Str", "Created", + null, null, null, null, null))); + checker().verifyTrue("Audit log not as expected for creating a new sample type with text choice field.", pass); + log("Create some samples int the sample type. None of the samples will have a TextChoice value."); List availableSamples = new ArrayList<>(); diff --git a/src/org/labkey/test/tests/list/ListDateAndTimeTest.java b/src/org/labkey/test/tests/list/ListDateAndTimeTest.java index 3406f513a8..211181d651 100644 --- a/src/org/labkey/test/tests/list/ListDateAndTimeTest.java +++ b/src/org/labkey/test/tests/list/ListDateAndTimeTest.java @@ -1233,7 +1233,7 @@ public void testDateAndTimeFormat() dateCol, new AuditLogHelper.DetailedAuditEventRow(null, dateCol, "Modified","The following property was updated: Format",null, null, null, "Format: yyyy-MM-dd > ddMMMyy"), dateTimeCol, new AuditLogHelper.DetailedAuditEventRow(null, dateTimeCol, "Modified","The following property was updated: Format",null, null, null, "Format: yyyy-MM-dd hh:mm a > dd-MMM-yyyy HH:mm:ss")) ); - checker().verifyTrue("Domain audit log not as expected after adding a parent alias column", pass); + checker().verifyTrue("Domain audit log not as expected after updating formats", pass); expectedData = new ArrayList<>(); From d4a31eaec9af0bec56389ac978b3cf3e41de0abc Mon Sep 17 00:00:00 2001 From: XingY Date: Thu, 22 May 2025 09:11:01 -0700 Subject: [PATCH 10/13] fix test --- src/org/labkey/test/tests/DomainDesignerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/labkey/test/tests/DomainDesignerTest.java b/src/org/labkey/test/tests/DomainDesignerTest.java index 75b7b98886..fcc76afee7 100644 --- a/src/org/labkey/test/tests/DomainDesignerTest.java +++ b/src/org/labkey/test/tests/DomainDesignerTest.java @@ -290,7 +290,7 @@ public void testInvalidLookupDomainField() throws IOException, CommandException AuditLogHelper.DetailedAuditEventRow expectedDomainEvent = new AuditLogHelper.DetailedAuditEventRow(null, listName, null, "The name of the list domain 'InvalidLookUpNameList' was changed to 'InvalidLookUpNameList_edited'. The descriptor of domain InvalidLookUpNameList_edited was updated.", "", null, null, "Name: " + listName + " > " + editedListName); - boolean pass = _auditLogHelper.validateLastDomainAuditEvents(listName, getProjectName(), expectedDomainEvent, Collections.emptyMap()); + boolean pass = _auditLogHelper.validateLastDomainAuditEvents(editedListName, getProjectName(), expectedDomainEvent, Collections.emptyMap()); checker().verifyTrue("The comment logged for the list renaming was not as expected", pass); domainDesignerPage = DomainDesignerPage.beginAt(this, getProjectName(), "exp.materials", sampleType); From ccd9a85dfda8f16c6029ba2fccbcae50050a9023 Mon Sep 17 00:00:00 2001 From: XingY Date: Thu, 22 May 2025 13:49:11 -0700 Subject: [PATCH 11/13] fix more tests --- src/org/labkey/test/tests/list/ListTest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index bdf78185e4..266f6ae0eb 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -638,14 +638,17 @@ public void testCustomViews() clickAndWait(Locator.linkWithText("view history")); checker().wrapAssertion(()->assertTextPresent(":History")); checker().wrapAssertion(()->assertTextPresent("record was modified", 2)); // An existing list record was modified - checker().wrapAssertion(()->assertTextPresent("were modified", 8)); // The column(s) of LIST_NAME_COLORS domain were modified + + checker().wrapAssertion(()->assertTextPresent(" was created. The column(s) of domain ", 1));// Create domain and update columns combined into a single event + checker().wrapAssertion(()->assertTextPresent(" were modified.", 7)); // The column(s) of LIST_NAME_COLORS domain were modified + checker().wrapAssertion(()->assertTextPresent("The descriptor of domain.", 1)); // The description LIST_NAME_COLORS domain were modified checker().wrapAssertion(()->assertTextPresent("Bulk inserted", 2)); checker().wrapAssertion(()->assertTextPresent("A new list record was inserted", 1)); checker().wrapAssertion(()->assertTextPresent("was created", 2)); // Once for the list, once for the domain // List insert/update events should each have a link to the list item that was modified, but the other events won't have a link - checker().wrapAssertion(()->assertEquals("details Links", 6, DataRegionTable.detailsLinkLocator().findElements(getDriver()).size())); - checker().wrapAssertion(()->assertEquals("Project Links", 18, DataRegionTable.Locators.table().append(Locator.linkWithText(PROJECT_VERIFY)).findElements(getDriver()).size())); - checker().wrapAssertion(()->assertEquals("List Links", 18, DataRegionTable.Locators.table().append(Locator.linkWithText(LIST_NAME_COLORS)).findElements(getDriver()).size())); + checker().wrapAssertion(()->assertEquals("details Links", 6/*List Events*/ + 8/*Domain Audit*/, DataRegionTable.detailsLinkLocator().findElements(getDriver()).size())); + checker().wrapAssertion(()->assertEquals("Project Links", 17, DataRegionTable.Locators.table().append(Locator.linkWithText(PROJECT_VERIFY)).findElements(getDriver()).size())); + checker().wrapAssertion(()->assertEquals("List Links", 17, DataRegionTable.Locators.table().append(Locator.linkWithText(LIST_NAME_COLORS)).findElements(getDriver()).size())); DataRegionTable dataRegionTable = new DataRegionTable("query", getDriver()); dataRegionTable.clickRowDetails(0); checker().wrapAssertion(()->assertTextPresent("List Item Details")); From bd745220b80630d44dd7a9e9febcdf9e63d589a2 Mon Sep 17 00:00:00 2001 From: XingY Date: Thu, 22 May 2025 19:53:47 -0700 Subject: [PATCH 12/13] clean --- src/org/labkey/test/tests/TextChoiceSampleTypeTest.java | 2 +- src/org/labkey/test/tests/list/ListTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java index d4ca85dce3..ca6fd7aafe 100644 --- a/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java +++ b/src/org/labkey/test/tests/TextChoiceSampleTypeTest.java @@ -469,7 +469,7 @@ public void testUpdatingAndDeletingValuesInSampleType() throws IOException, Comm "The column(s) of domain " + sampleTypeName + " were modified.", "", null, null, null); boolean pass = _auditLogHelper.validateLastDomainAuditEvents(sampleTypeName, getProjectName(), expectedDomainEvent, Map.of(textChoiceFieldName, fieldEvent)); - checker().verifyTrue("Audit event is not as expected", pass); + checker().verifyTrue("Audit event is not as expected after text choice after", pass); // Construct a list of samples that have TextChoice set and what they are expected to be. diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index 266f6ae0eb..93604f43c9 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -1361,7 +1361,7 @@ public void exportPhiFileColumn() throws Exception "PhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "PhiColumn", "Modified","The following property was updated: PHI",null, null, null, "PHI: Not PHI > Full PHI"), "RestrictedPhiColumn", new AuditLogHelper.DetailedAuditEventRow(null, "RestrictedPhiColumn", "Modified","The following property was updated: PHI",null, null, null, "PHI: Not PHI > Restricted PHI")) ); - checker().verifyTrue("Domain audit comment not as expected after changing conditional format", pass); + checker().verifyTrue("Domain audit comment not as expected after changing PHI setting", pass); goToProjectHome(); clickAndWait(Locator.linkWithText(listName)); From c950bf1d53b706eb365b61c60895db3ab62aefc7 Mon Sep 17 00:00:00 2001 From: XingY Date: Fri, 23 May 2025 09:11:09 -0700 Subject: [PATCH 13/13] fix test --- src/org/labkey/test/tests/list/ListTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index 93604f43c9..a5b62e0ec1 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -641,7 +641,7 @@ public void testCustomViews() checker().wrapAssertion(()->assertTextPresent(" was created. The column(s) of domain ", 1));// Create domain and update columns combined into a single event checker().wrapAssertion(()->assertTextPresent(" were modified.", 7)); // The column(s) of LIST_NAME_COLORS domain were modified - checker().wrapAssertion(()->assertTextPresent("The descriptor of domain.", 1)); // The description LIST_NAME_COLORS domain were modified + checker().wrapAssertion(()->assertTextPresent("The descriptor of domain", 1)); // The description LIST_NAME_COLORS domain were modified checker().wrapAssertion(()->assertTextPresent("Bulk inserted", 2)); checker().wrapAssertion(()->assertTextPresent("A new list record was inserted", 1)); checker().wrapAssertion(()->assertTextPresent("was created", 2)); // Once for the list, once for the domain