diff --git a/modules/ETLtest/resources/ETLs/SourceToTarget2BulkLoad.xml b/modules/ETLtest/resources/ETLs/SourceToTarget2BulkLoad.xml
new file mode 100644
index 0000000000..6b906aec7b
--- /dev/null
+++ b/modules/ETLtest/resources/ETLs/SourceToTarget2BulkLoad.xml
@@ -0,0 +1,15 @@
+
+
+ Source to target2 bulk load
+ append rows from source to target, skip detailed auditing
+
+
+ Copy to target2
+
+
+
+
+
+
+
+
diff --git a/modules/ETLtest/resources/ETLs/SourceToTarget2NoBulkLoad.xml b/modules/ETLtest/resources/ETLs/SourceToTarget2NoBulkLoad.xml
new file mode 100644
index 0000000000..78a3118667
--- /dev/null
+++ b/modules/ETLtest/resources/ETLs/SourceToTarget2NoBulkLoad.xml
@@ -0,0 +1,15 @@
+
+
+ Source to target2 no bulk load
+ append rows from source to target, with detailed auditing
+
+
+ Copy to target2 no bulkLoad
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/ETLtest/resources/schemas/etltest.xml b/modules/ETLtest/resources/schemas/etltest.xml
index a8326e4947..1abc4f056e 100644
--- a/modules/ETLtest/resources/schemas/etltest.xml
+++ b/modules/ETLtest/resources/schemas/etltest.xml
@@ -27,6 +27,7 @@
+ DETAILED
diff --git a/src/org/labkey/remoteapi/query/ImportExperimentDataCommand.java b/src/org/labkey/remoteapi/query/ImportExperimentDataCommand.java
new file mode 100644
index 0000000000..9b5ac8b915
--- /dev/null
+++ b/src/org/labkey/remoteapi/query/ImportExperimentDataCommand.java
@@ -0,0 +1,78 @@
+package org.labkey.remoteapi.query;
+
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.labkey.test.WebTestHelper;
+import org.labkey.test.util.AuditLogHelper;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ImportExperimentDataCommand extends ImportDataCommand
+{
+ private AuditLogHelper.AuditBehaviorType _auditBehavior;
+ private Boolean _crossTypeImport;
+ private Boolean _crossFolderImport;
+ private String _containerPath;
+
+ public ImportExperimentDataCommand(String schemaName, String queryName, String containerPath)
+ {
+ super(schemaName, queryName);
+ _containerPath = containerPath;
+ }
+
+ public AuditLogHelper.AuditBehaviorType getAuditBehavior()
+ {
+ return _auditBehavior;
+ }
+
+ public void setAuditBehavior(AuditLogHelper.AuditBehaviorType auditBehavior)
+ {
+ _auditBehavior = auditBehavior;
+ }
+
+ public Boolean getCrossTypeImport()
+ {
+ return _crossTypeImport;
+ }
+
+ public void setCrossTypeImport(Boolean crossTypeImport)
+ {
+ _crossTypeImport = crossTypeImport;
+ }
+
+ public Boolean getCrossFolderImport()
+ {
+ return _crossFolderImport;
+ }
+
+ public void setCrossFolderImport(Boolean crossFolderImport)
+ {
+ _crossFolderImport = crossFolderImport;
+ }
+
+ @Override
+ protected HttpPost createRequest(URI uri) {
+ HttpPost post = super.createRequest(uri);
+ String action = "samples".equalsIgnoreCase(getSchemaName()) ? "importSamples" : "importData";
+ Map params = new HashMap<>();
+ if (_auditBehavior != null)
+ params.put("auditBehavior", _auditBehavior.name());
+ if (_crossTypeImport)
+ params.put("crossTypeImport", "true");
+ if (_crossFolderImport)
+ params.put("crossFolderImport", "true");
+ String url = WebTestHelper.buildURL("experiment", _containerPath, action, params);
+ try
+ {
+ post.setUri(new URI(url));
+ }
+ catch (URISyntaxException e)
+ {
+ throw new RuntimeException(e);
+ }
+ return post;
+ }
+
+}
diff --git a/src/org/labkey/test/BaseWebDriverTest.java b/src/org/labkey/test/BaseWebDriverTest.java
index 6b34832353..ca319c26c4 100644
--- a/src/org/labkey/test/BaseWebDriverTest.java
+++ b/src/org/labkey/test/BaseWebDriverTest.java
@@ -75,6 +75,7 @@
import org.labkey.test.util.AbstractContainerHelper;
import org.labkey.test.util.ApiPermissionsHelper;
import org.labkey.test.util.ArtifactCollector;
+import org.labkey.test.util.AuditLogHelper;
import org.labkey.test.util.ComponentQuery;
import org.labkey.test.util.Crawler;
import org.labkey.test.util.CspLogUtil;
@@ -2743,14 +2744,35 @@ public void dismissReleaseBanner(String productName, boolean dismiss)
}
protected void verifyQueryAPI(String schema, String dataType, Map row, boolean isInsert, String... errorMsg)
+ {
+ verifyQueryAPI(schema, dataType, null, row, isInsert, errorMsg);
+ }
+
+ protected void verifyQueryAPI(String schema, String dataType, @Nullable AuditLogHelper.AuditBehaviorType auditBehavior, Map row, boolean isInsert, String... errorMsg)
{
String action = isInsert ? "insertRows" : "updateRows";
String updateScript = "LABKEY.Query." + action + "({ schemaName: \"" + schema + "\", "+
"queryName: " + EscapeUtil.toJSONStr(dataType) + ", " +
+ (auditBehavior == null ? "" : ("auditBehavior: " + EscapeUtil.toJSONStr(auditBehavior.name())) + ", ") +
"success: callback," +
"failure: callback," +
"rows: [" + EscapeUtil.toJSONRow(row) + "]" +
"})";
+ log(updateScript);
+ executeAndVerifyScript(updateScript, errorMsg);
+ }
+
+ protected void verifyQueryAPI(String schema, String dataType, @Nullable AuditLogHelper.AuditBehaviorType auditBehavior, List