Skip to content
Open
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
19 changes: 14 additions & 5 deletions src/org/labkey/test/LabKeySiteWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -321,22 +321,31 @@ protected void bypassSecondaryAuthentication()
}
}

protected void acceptTermsOfUse(String termsText, boolean clickAgree)
protected boolean acceptTermsOfUse(String termsText, boolean clickAgree)
{
boolean signed = false;
Optional<WebElement> optionalCheckbox = Locators.termsOfUseCheckbox().findOptionalElement(getDriver());
optionalCheckbox.ifPresent(termsCheckbox ->

if (optionalCheckbox.isPresent())
{
if (termsCheckbox.isDisplayed())

if (optionalCheckbox.get().isDisplayed())
{
checkCheckbox(termsCheckbox);
checkCheckbox(optionalCheckbox.get());
if (null != termsText)
{
assertTextPresent(termsText);
}
if (clickAgree)
{
clickButton("Agree");
signed = true;
}
}
});
}

return signed;

}

@LogMethod
Expand Down
57 changes: 55 additions & 2 deletions src/org/labkey/test/tests/BaseTermsOfUseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,25 @@
package org.labkey.test.tests;

import org.junit.BeforeClass;
import org.labkey.remoteapi.CommandException;
import org.labkey.remoteapi.query.Filter;
import org.labkey.test.BaseWebDriverTest;
import org.labkey.test.Locator;
import org.labkey.test.TestTimeoutException;
import org.labkey.test.WebTestHelper;
import org.labkey.test.util.ApiPermissionsHelper;
import org.labkey.test.util.AuditLogHelper;
import org.labkey.test.util.PortalHelper;
import org.labkey.test.util.WikiHelper;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.labkey.api.security.UserManager.USER_AUDIT_EVENT;
import static org.labkey.test.util.PermissionsHelper.EDITOR_ROLE;
import static org.labkey.test.util.PermissionsHelper.READER_ROLE;

Expand All @@ -43,6 +50,7 @@ public class BaseTermsOfUseTest extends BaseWebDriverTest
protected final PortalHelper _portalHelper = new PortalHelper(this);
protected WikiHelper _wikiHelper = new WikiHelper(this);
protected final ApiPermissionsHelper _permissionsHelper = new ApiPermissionsHelper(this);
protected final AuditLogHelper _auditLogHelper = new AuditLogHelper(this);

protected static final String WIKI_TERMS_TITLE = "Terms of Use";
protected static final String PROJECT_TERMS_SNIPPET = "fight club";
Expand Down Expand Up @@ -112,8 +120,10 @@ protected void createProjectWithTermsOfUse(String name, String termsText, boolea
}
}

protected void createTermsOfUsePage(String projectName, String body)
protected boolean createTermsOfUsePage(String projectName, String body)
{
boolean signed = false;

String message;
if (null != projectName)
{
Expand All @@ -134,8 +144,51 @@ protected void createTermsOfUsePage(String projectName, String body)
setFormElement(Locator.name("title"), WIKI_TERMS_TITLE);
setFormElement(Locator.name("body"), body);
_wikiHelper.saveWikiPage();
acceptTermsOfUse(null, true);
signed = acceptTermsOfUse(null, true);
}

return signed;
}

protected void validateAuditLogEntries(String path, int minRowId, List<Map<String, Object>> expected) throws IOException, CommandException
{
log(String.format("Validating %s user events in the audit log for path / project '%s' and above row id of %d",
USER_AUDIT_EVENT, path, minRowId));

List<Map<String, Object>> actualLog = getAuditLogEntries(path, minRowId);

checker().verifyEquals("Number of audit log entries not as expected.",
expected.size(), actualLog.size());

List<Map<String, Object>> unmatched = expected.stream()
.filter(expectedRow -> {
Set<String> keysOfInterest = expectedRow.keySet();
return actualLog.stream().noneMatch(actualRow -> {
Map<String, Object> actualFiltered = actualRow.entrySet().stream()
.filter(e -> keysOfInterest.contains(e.getKey()))
.collect(HashMap::new,
(m, e) -> m.put(e.getKey(), e.getValue()),
HashMap::putAll);
return actualFiltered.equals(expectedRow);
});
})
.toList();

checker().verifyTrue("Expected rows with no match in actual: " + unmatched, unmatched.isEmpty());

}

private List<Map<String, Object>> getAuditLogEntries(String path, int minRowId) throws IOException, CommandException
{
log(String.format("Get %s audit log entries for path '%s' where RowId is greater than %d.",
USER_AUDIT_EVENT, path, minRowId));

List<Filter> filters = List.of(
new Filter("Comment", "Agreed to terms of use", Filter.Operator.EQUAL),
new Filter("RowId", minRowId, Filter.Operator.getOperator("GREATER_THAN")));

return _auditLogHelper.getAuditLogsFromLKS(path, null, AuditLogHelper.AuditEvent.USER_AUDIT_EVENT,
List.of("RowId", "Date", "CreatedBy", "ImpersonatedBy", "User", "Comment"), filters, null, null).getRows();
}

@Override
Expand Down
37 changes: 36 additions & 1 deletion src/org/labkey/test/tests/ProjectTermsOfUseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,23 @@

import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.labkey.remoteapi.CommandException;
import org.labkey.test.BaseWebDriverTest;
import org.labkey.test.Locator;
import org.labkey.test.Locators;
import org.labkey.test.WebTestHelper;
import org.labkey.test.categories.Daily;
import org.labkey.test.util.Maps;
import org.labkey.test.util.PasswordUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.labkey.api.security.UserManager.USER_AUDIT_EVENT;

@Category({Daily.class})
@BaseWebDriverTest.ClassTimeout(minutes = 6)
Expand All @@ -40,8 +49,11 @@ protected void doSetup()
}

@Test
public void projectTermsOfUseTest()
public void projectTermsOfUseTest() throws IOException, CommandException
{
// RowId is a single sequence across every container, so one baseline covers every path checked below.
int initialRowId = _auditLogHelper.getLatestAuditRowId(USER_AUDIT_EVENT);

log("Terms don't come into play until you log out");
clickProject(NON_PUBLIC_TERMS_PROJECT2_NAME);
assertTextNotPresent("fight club");
Expand Down Expand Up @@ -121,6 +133,28 @@ public void projectTermsOfUseTest()
clickAndWait(Locator.linkWithText("Edit"));
deleteWikiPage();
assertTextNotPresent(WIKI_TERMS_TITLE);

log("Validate the audit logs show 'agreement to terms' entry.");

// No terms for this project.
validateAuditLogEntries("/" + PUBLIC_NO_TERMS_PROJECT_NAME, initialRowId, new ArrayList<>());

// The remaining three projects should have the same audit log entries.
int defaultUserId = _userHelper.getUserId(PasswordUtil.getUsername());
int impersonatedUserId = _userHelper.getUserId(USER);
List<Map<String, Object>> expected = new ArrayList<>();
expected.add(Map.of("CreatedBy", impersonatedUserId,
"User", impersonatedUserId,
"ImpersonatedBy", defaultUserId));
Map<String, Object> row = new HashMap<>();
row.put("CreatedBy", defaultUserId);
row.put("User", defaultUserId);
row.put("ImpersonatedBy", null);
expected.add(row);

validateAuditLogEntries("/" + PUBLIC_TERMS_PROJECT_NAME, initialRowId, expected);
validateAuditLogEntries("/" + NON_PUBLIC_TERMS_PROJECT2_NAME, initialRowId, expected);
validateAuditLogEntries("/" + NON_PUBLIC_TERMS_PROJECT_NAME, initialRowId, expected);
}

protected void deleteWikiPage()
Expand All @@ -129,5 +163,6 @@ protected void deleteWikiPage()
clickButton("Delete Page");
clickButton("Delete");
}

}

32 changes: 27 additions & 5 deletions src/org/labkey/test/tests/SiteWideTermsOfUseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@
import org.openqa.selenium.WebElement;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.labkey.api.security.UserManager.USER_AUDIT_EVENT;

@Category({Daily.class})
@BaseWebDriverTest.ClassTimeout(minutes = 7)
Expand All @@ -45,13 +48,31 @@ public class SiteWideTermsOfUseTest extends BaseTermsOfUseTest
protected static final String NON_PUBLIC_NO_TERMS_PROJECT_NAME = "Non-public No Terms Project";

@Before
public void preTest()
public void preTest() throws IOException, CommandException
{
assureSiteWideTermsOfUsePage();

// Get the initial audit log row id, for sitewide terms. Use the row id as a filter when checking the log.
int logId = _auditLogHelper.getLatestAuditRowId(USER_AUDIT_EVENT);

int defaultUserId = _userHelper.getUserId(PasswordUtil.getUsername());
Map<String, Object> defaultUserAuditLogEntry = new HashMap<>();
defaultUserAuditLogEntry.put("CreatedBy", defaultUserId);
defaultUserAuditLogEntry.put("User", defaultUserId);
defaultUserAuditLogEntry.put("ImpersonatedBy", null);

if (assureSiteWideTermsOfUsePage())
{
validateAuditLogEntries("", logId, List.of(defaultUserAuditLogEntry));
}

if(!isElementPresent(Locator.linkWithText(getProjectName())))
{
goToHome();
acceptTermsOfUse(null, true);
if (acceptTermsOfUse(null, true))
{
validateAuditLogEntries("", logId, List.of(defaultUserAuditLogEntry));
}

}
}

Expand Down Expand Up @@ -94,10 +115,11 @@ public void editTermsAdminConsoleLinkTest()
Locators.bodyTitle().findElement(getDriver()).getText());
}

protected void assureSiteWideTermsOfUsePage()
protected boolean assureSiteWideTermsOfUsePage()
{
createTermsOfUsePage(null, SITE_WIDE_TERMS_TEXT);
boolean signed = createTermsOfUsePage(null, SITE_WIDE_TERMS_TEXT);
setFrequency(0);
return signed;
}

// Test that the site-wide terms appear when you log out, even if you've accepted the terms when logged in
Expand Down
12 changes: 9 additions & 3 deletions src/org/labkey/test/util/AuditLogHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ public enum AuditEvent
SAMPLE_TIMELINE_EVENT("SampleTimelineEvent"),
SAMPLE_WORKFLOW_AUDIT_EVENT("SamplesWorkflowAuditEvent"),
SOURCES_AUDIT_EVENT("SourcesAuditEvent"), // available with SampleManagement module
TRANSACTION_AUDIT_EVENT("TransactionAuditEvent");
TRANSACTION_AUDIT_EVENT("TransactionAuditEvent"),
USER_AUDIT_EVENT("UserAuditEvent");

private final String _name;

Expand Down Expand Up @@ -210,12 +211,17 @@ public SelectRowsResponse getAuditLogsFromLKS(String containerPath, AuditEvent a
return getAuditLogsFromLKS(containerPath, _wrapper.getCurrentProject(), auditEvent, columnNames, filters, maxRows, containerFilter);
}

public SelectRowsResponse getAuditLogsFromLKS(String containerPath, @NotNull String projectName, AuditEvent auditEvent, List<String> columnNames,
/**
* @param projectName Name of the project to filter to. If null or empty, no project filter is applied (e.g. for
* events logged against the root container, which don't belong to any project).
*/
public SelectRowsResponse getAuditLogsFromLKS(String containerPath, @Nullable String projectName, AuditEvent auditEvent, List<String> columnNames,
@Nullable List<Filter> filters, @Nullable Integer maxRows, @Nullable ContainerFilter containerFilter) throws IOException, CommandException
{
SelectRowsCommand cmd = new SelectRowsCommand("auditLog", auditEvent.getName());
cmd.setColumns(columnNames);
cmd.addFilter("ProjectId/Name", projectName, Filter.Operator.EQUAL);
if (StringUtils.isNotEmpty(projectName))
cmd.addFilter("ProjectId/Name", projectName, Filter.Operator.EQUAL);
if (filters != null)
filters.forEach(cmd::addFilter);
if (maxRows != null)
Expand Down