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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/org/labkey/test/components/bootstrap/ModalDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.labkey.test.WebDriverWrapper.WAIT_FOR_JAVASCRIPT;

Expand Down Expand Up @@ -84,6 +86,25 @@ public String getBodyText()
return elementCache().body.getText();
}

public Integer getCountFromTitle()
{
Pattern pattern = Pattern.compile("(\\d+)");
Matcher matcher = pattern.matcher(getTitle());
if (matcher.find())
{
try
{
return Integer.parseInt(matcher.group(1).trim());
}
catch (NumberFormatException e)
{
// If we can't parse the number, return null
return null;
}
}
return null;
}

public void close()
{
elementCache().closeButton.click();
Expand Down
40 changes: 39 additions & 1 deletion src/org/labkey/test/components/ui/DeleteConfirmationDialog.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
package org.labkey.test.components.ui;

import org.jetbrains.annotations.NotNull;
import org.labkey.remoteapi.CommandException;
import org.labkey.test.BootstrapLocators;
import org.labkey.test.Locator;
import org.labkey.test.TestProperties;
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.WebTestHelper;
import org.labkey.test.components.UpdatingComponent;
import org.labkey.test.components.bootstrap.ModalDialog;
import org.labkey.test.components.html.Input;
import org.labkey.test.util.AuditLogHelper;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.io.IOException;
import java.util.function.Function;
import java.util.function.Supplier;

public class DeleteConfirmationDialog<ConfirmPage extends WebDriverWrapper> extends ModalDialog
{
private final Function<Runnable, ConfirmPage> _confirmationSynchronizationFunction;
private boolean skipAuditEventCheck = false;

public DeleteConfirmationDialog(@NotNull WebDriverWrapper sourcePage, Supplier<ConfirmPage> confirmPageSupplier)
{
Expand Down Expand Up @@ -68,6 +74,12 @@ protected void waitForReady()
"The delete confirmation dialog did not become ready.", 1_000);
}

public DeleteConfirmationDialog<ConfirmPage> setSkipAuditEventCheck(boolean skipAuditEventCheck)
{
this.skipAuditEventCheck = skipAuditEventCheck;
return this;
}

public void cancelDelete()
{
this.dismiss("Cancel");
Expand All @@ -80,7 +92,33 @@ public ConfirmPage confirmDelete()

public ConfirmPage confirmDelete(Integer waitSeconds)
{
return _confirmationSynchronizationFunction.apply(() -> this.dismiss("Yes, Delete", waitSeconds));
Integer count = getCountFromTitle();
AuditLogHelper.AuditEvent auditEventName = getAuditEvent();

var confirmPage = _confirmationSynchronizationFunction.apply(() -> this.dismiss("Yes, Delete", waitSeconds));

if (!skipAuditEventCheck && count != null && auditEventName != null && !TestProperties.isTrialServer())
verifyAuditEvents(getWrapper(), getWrapper().getCurrentProject(), auditEventName, count);

return confirmPage;
}

public AuditLogHelper.AuditEvent getAuditEvent()
{
return new AuditLogHelper(getWrapper()).getAuditEventNameFromURL();
}

public static void verifyAuditEvents(WebDriverWrapper wrapper, String containerPath, AuditLogHelper.AuditEvent auditEventName, int entityCount)
{
try
{
AuditLogHelper auditLogHelper = new AuditLogHelper(wrapper, () -> WebTestHelper.getRemoteApiConnection(false));
auditLogHelper.checkAuditEventDiffCountForLastTransaction(containerPath, auditEventName, 0, entityCount);
}
catch (CommandException | IOException e)
{
throw new RuntimeException(e);
}
}

public Boolean isDeleteEnabled()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,25 +350,6 @@ public EntityBulkUpdateDialog clearActionComment()
return this;
}

public Integer getCountFromTitle()
{
// expecting title to be like "Update N items"
String title = getTitle();
String[] parts = title.split(" ");
if (parts.length > 1)
{
try
{
return Integer.parseInt(parts[1]);
}
catch (NumberFormatException nfe)
{
return null;
}
}
return null;
}

// dismiss the dialog

public String clickUpdateExpectingError()
Expand All @@ -395,7 +376,7 @@ public void clickUpdate(boolean skipAuditEventCheck)

// check for the expected number of Data Changes in the latest audit event records
AuditLogHelper auditLogHelper = new AuditLogHelper(getWrapper(), () -> WebTestHelper.getRemoteApiConnection(false));
String auditEventName = auditLogHelper.getAuditEventNameFromURL();
AuditLogHelper.AuditEvent auditEventName = auditLogHelper.getAuditEventNameFromURL();
if (!skipAuditEventCheck && auditEventName != null && !TestProperties.isTrialServer())
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ public DetailDataPanel clickSave(boolean skipAuditEventCheck)

// check for the expected number of Data Changes in the latest audit event records
AuditLogHelper auditLogHelper = new AuditLogHelper(getWrapper(), () -> WebTestHelper.getRemoteApiConnection(false));
String auditEventName = auditLogHelper.getAuditEventNameFromURL();
AuditLogHelper.AuditEvent auditEventName = auditLogHelper.getAuditEventNameFromURL();
if (!skipAuditEventCheck && auditEventName != null && !TestProperties.isTrialServer())
{
try
Expand Down
44 changes: 33 additions & 11 deletions src/org/labkey/test/util/AuditLogHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ public AuditLogHelper(WebDriverWrapper wrapper)
this(wrapper, wrapper::createDefaultConnection);
}

public enum AuditEvent
{
SAMPLE_TIMELINE_EVENT("SampleTimelineEvent"),
SOURCES_AUDIT_EVENT("SourcesAuditEvent"),
INVENTORY_AUDIT_EVENT("InventoryAuditEvent"),
LIST_AUDIT_EVENT("ListAuditEvent"),
EXPERIMENT_AUDIT_EVENT("ExperimentAuditEvent"),
SAMPLE_WORKFLOW_AUDIT_EVENT("SamplesWorkflowAuditEvent");

private final String _name;

AuditEvent(String name)
{
_name = name;
}

public String getName()
{
return _name;
}
}

public Integer getLatestAuditRowId(String auditTable) throws IOException, CommandException
{
String rowId = "rowId";
Expand Down Expand Up @@ -101,10 +123,10 @@ public DataRegionTable goToAuditEventView(String eventType)
* @throws IOException Can be thrown by the SelectRowsCommand.
* @throws CommandException Can be thrown by the SelectRowsCommand.
*/
public SelectRowsResponse getAuditLogsFromLKS(String containerPath, String auditEventName, List<String> columnNames,
public SelectRowsResponse getAuditLogsFromLKS(String containerPath, AuditEvent auditEventName, List<String> columnNames,
List<Filter> filters, @Nullable Integer maxRows, @Nullable ContainerFilter containerFilter) throws IOException, CommandException
{
SelectRowsCommand cmd = new SelectRowsCommand("auditLog", auditEventName);
SelectRowsCommand cmd = new SelectRowsCommand("auditLog", auditEventName.getName());
cmd.setColumns(columnNames);
cmd.addFilter("ProjectId/Name", _wrapper.getCurrentProject(), Filter.Operator.EQUAL);
filters.forEach(cmd::addFilter);
Expand All @@ -115,14 +137,14 @@ public SelectRowsResponse getAuditLogsFromLKS(String containerPath, String audit
return cmd.execute(_connectionSupplier.get(), containerPath);
}

public List<Map<String, Object>> getAuditLogsForTransactionId(String containerPath, String auditEventName, List<String> columnNames,
public List<Map<String, Object>> getAuditLogsForTransactionId(String containerPath, AuditEvent auditEventName, List<String> columnNames,
Integer transactionId, @Nullable ContainerFilter containerFilter) throws IOException, CommandException
{
List<Filter> transactionFilter = List.of(new Filter("TransactionId", transactionId, Filter.Operator.EQUAL));
return getAuditLogsFromLKS(containerPath, auditEventName, columnNames, transactionFilter, null, containerFilter).getRows();
}

public void checkAuditEventValuesForTransactionId(String containerPath, String auditEventName, Integer transactionId, int rowCount, Map<String, Object> expectedValues) throws IOException, CommandException
public void checkAuditEventValuesForTransactionId(String containerPath, AuditEvent auditEventName, Integer transactionId, int rowCount, Map<String, Object> expectedValues) throws IOException, CommandException
{
List<String> columnNames = expectedValues.keySet().stream().map(Object::toString).toList();
List<Map<String, Object>> events = getAuditLogsForTransactionId(containerPath, auditEventName, columnNames, transactionId, ContainerFilter.CurrentAndSubfolders);
Expand All @@ -143,11 +165,11 @@ public void checkTimelineAuditEventDiffCount(String containerPath, List<Integer>
{
checkAuditEventDiffCount(containerPath, getAuditEventNameFromURL(), expectedDiffCounts);
}
public void checkAuditEventDiffCount(String containerPath, String auditEventName, List<Integer> expectedDiffCounts) throws IOException, CommandException
public void checkAuditEventDiffCount(String containerPath, AuditEvent auditEventName, List<Integer> expectedDiffCounts) throws IOException, CommandException
{
checkAuditEventDiffCount(containerPath, auditEventName, Collections.emptyList(), expectedDiffCounts);
}
public void checkAuditEventDiffCount(String containerPath, String auditEventName, List<Filter> filters, List<Integer> expectedDiffCounts) throws IOException, CommandException
public void checkAuditEventDiffCount(String containerPath, AuditEvent auditEventName, List<Filter> filters, List<Integer> expectedDiffCounts) throws IOException, CommandException
{
Integer maxRows = expectedDiffCounts.size();
List<Map<String, Object>> events = getAuditLogsFromLKS(containerPath, auditEventName, List.of("InventoryUpdateType", "NewRecordMap"), filters, maxRows, ContainerFilter.CurrentAndSubfolders).getRows();
Expand All @@ -171,7 +193,7 @@ public void checkAuditEventDiffCount(String containerPath, String auditEventName
}
}

public Integer getLastTransactionId(String containerPath, String auditEventName) throws IOException, CommandException
public Integer getLastTransactionId(String containerPath, AuditEvent auditEventName) throws IOException, CommandException
{
List<Map<String, Object>> events = getAuditLogsFromLKS(containerPath, auditEventName, List.of("TransactionId"), Collections.emptyList(), 1, ContainerFilter.CurrentAndSubfolders).getRows();
return events.size() == 1 ? (Integer) events.get(0).get("TransactionId") : null;
Expand All @@ -182,7 +204,7 @@ public Integer getLastTransactionId(String containerPath, String auditEventName)
* If an expectedEventCount is also provided, it will check that the number of events for that transactionId matches the expectedEventCount.
* @return transactionId
*/
public Integer checkAuditEventDiffCountForLastTransaction(String containerPath, String auditEventName, int expectedDiffCount,
public Integer checkAuditEventDiffCountForLastTransaction(String containerPath, AuditEvent auditEventName, int expectedDiffCount,
@Nullable Integer expectedEventCount) throws IOException, CommandException
{
Integer transactionId = getLastTransactionId(containerPath, auditEventName);
Expand All @@ -195,12 +217,12 @@ public Integer checkAuditEventDiffCountForLastTransaction(String containerPath,
return transactionId;
}

public String getAuditEventNameFromURL()
public AuditEvent getAuditEventNameFromURL()
{
if (isSamplesRoute())
return "SampleTimelineEvent";
return AuditEvent.SAMPLE_TIMELINE_EVENT;
else if (isDataClassRoute())
return "SourcesAuditEvent";
return AuditEvent.SOURCES_AUDIT_EVENT;
return null;
}

Expand Down