Merge branch 'main' into 15768-multi-select-operations Arvados-DCO-1.1-Signed-off...
[arvados-workbench2.git] / cypress / support / commands.js
index 199b5c13c570932b2ce5d5a2c0bc068da8a0577f..46d77fe8b19721a5b87a63fab7900a20802cb7f9 100644 (file)
 // -- This will overwrite an existing command --
 // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
 
+import { extractFilesData } from "services/collection-service/collection-service-files-response";
+
 const controllerURL = Cypress.env("controller_url");
 const systemToken = Cypress.env("system_token");
 let createdResources = [];
 
-// Clean up on a 'before' hook to allow post-mortem analysis on individual tests.
-beforeEach(function () {
+const containerLogFolderPrefix = "log for container ";
+
+// Clean up anything that was created.  You can temporarily add
+// 'return' to the top if you need the resources to hang around to
+// debug a specific test.
+afterEach(function () {
     if (createdResources.length === 0) {
         return;
     }
-    cy.log(`Cleaning ${createdResources.length} previously created resource(s)`);
+    cy.log(`Cleaning ${createdResources.length} previously created resource(s).`);
     createdResources.forEach(function ({ suffix, uuid }) {
         // Don't fail when a resource isn't already there, some objects may have
         // been removed, directly or indirectly, from the test that created them.
@@ -140,88 +146,72 @@ Cypress.Commands.add("createLink", (token, data) => {
     });
 });
 
-Cypress.Commands.add("createGroup", (token, data) => {
-    return cy.createResource(token, "groups", {
-        group: JSON.stringify(data),
-        ensure_unique_name: true,
-    });
-});
-
-Cypress.Commands.add("trashGroup", (token, uuid) => {
-    return cy.deleteResource(token, "groups", uuid);
-});
-
-Cypress.Commands.add("createWorkflow", (token, data) => {
-    return cy.createResource(token, "workflows", {
-        workflow: JSON.stringify(data),
-        ensure_unique_name: true,
-    });
-});
-
-Cypress.Commands.add("getCollection", (token, uuid) => {
-    return cy.getResource(token, "collections", uuid);
-});
-
-Cypress.Commands.add("createCollection", (token, data) => {
-    return cy.createResource(token, "collections", {
-        collection: JSON.stringify(data),
-        ensure_unique_name: true,
-    });
-});
-
-Cypress.Commands.add("updateCollection", (token, uuid, data) => {
-    return cy.updateResource(token, "collections", uuid, {
-        collection: JSON.stringify(data),
-    });
-});
-
-Cypress.Commands.add("getContainer", (token, uuid) => {
-    return cy.getResource(token, "containers", uuid);
-});
-
-Cypress.Commands.add("updateContainer", (token, uuid, data) => {
-    return cy.updateResource(token, "containers", uuid, {
-        container: JSON.stringify(data),
-    });
-});
-
-Cypress.Commands.add("createContainerRequest", (token, data) => {
-    return cy.createResource(token, "container_requests", {
-        container_request: JSON.stringify(data),
-        ensure_unique_name: true,
-    });
-});
-
-Cypress.Commands.add("updateContainerRequest", (token, uuid, data) => {
-    return cy.updateResource(token, "container_requests", uuid, {
-        container_request: JSON.stringify(data),
-    });
-});
-
-Cypress.Commands.add("createLog", (token, data) => {
-    return cy.createResource(token, "logs", {
-        log: JSON.stringify(data),
-    });
-});
+Cypress.Commands.add(
+    "doWebDAVRequest",
+    (method = "GET", path = "", data = null, qs = null, token = systemToken, auth = false, followRedirect = true, failOnStatusCode = true) => {
+        return cy.doRequest("GET", "/arvados/v1/config", null, null).then(({ body: config }) => {
+            return cy.request({
+                method: method,
+                url: `${config.Services.WebDAVDownload.ExternalURL.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`,
+                body: data,
+                qs: auth ? qs : Object.assign({ api_token: token }, qs),
+                auth: auth ? { bearer: `${token}` } : undefined,
+                followRedirect: followRedirect,
+                failOnStatusCode: failOnStatusCode,
+            });
+        });
+    }
+);
 
-Cypress.Commands.add("logsForContainer", (token, uuid, logType, logTextArray = []) => {
-    let logs = [];
-    for (const logText of logTextArray) {
-        logs.push(
-            cy
-                .createLog(token, {
-                    object_uuid: uuid,
-                    event_type: logType,
-                    properties: {
-                        text: logText,
-                    },
+Cypress.Commands.add("getUser", (username, first_name = "", last_name = "", is_admin = false, is_active = true) => {
+    // Create user if not already created
+    return (
+        cy
+            .doRequest(
+                "POST",
+                "/auth/controller/callback",
+                {
+                    auth_info: JSON.stringify({
+                        email: `${username}@example.local`,
+                        username: username,
+                        first_name: first_name,
+                        last_name: last_name,
+                        alternate_emails: [],
+                    }),
+                    return_to: ",https://example.local",
+                },
+                null,
+                systemToken,
+                true,
+                false
+            ) // Don't follow redirects so we can catch the token
+            .its("headers.location")
+            .as("location")
+            // Get its token and set the account up as admin and/or active
+            .then(
+                function () {
+                    this.userToken = this.location.split("=")[1];
+                    assert.isString(this.userToken);
+                    return cy
+                        .doRequest("GET", "/arvados/v1/users", null, {
+                            filters: `[["username", "=", "${username}"]]`,
+                        })
+                        .its("body.items.0")
+                        .as("aUser")
+                        .then(function () {
+                            cy.doRequest("PUT", `/arvados/v1/users/${this.aUser.uuid}`, {
+                                user: {
+                                    is_admin: is_admin,
+                                    is_active: is_active,
+                                },
+                            }).as("lastLogRecord");
+                        });
+                },
+                cy.getAll("@lastLogRecord").then(function () {
+                    return logs;
                 })
-                .as("lastLogRecord")
-        );
-    }
-    cy.getAll("@lastLogRecord").then(function () {
-        return logs;
-    });
+            )
+    );
 });
 
 Cypress.Commands.add("createVirtualMachine", (token, data) => {
@@ -268,45 +258,131 @@ Cypress.Commands.add("updateResource", (token, suffix, uuid, data) => {
         });
 });
 
-Cypress.Commands.add("loginAs", user => {
-    cy.clearCookies();
-    cy.clearLocalStorage();
-    cy.visit(`/token/?api_token=${user.token}`);
-    cy.url({ timeout: 10000 }).should("contain", "/projects/");
-    cy.get("div#root").should("contain", "Arvados Workbench (zzzzz)");
-    cy.get("div#root").should("not.contain", "Your account is inactive");
+Cypress.Commands.add("createCollection", (token, data) => {
+    return cy.createResource(token, "collections", {
+        collection: JSON.stringify(data),
+        ensure_unique_name: true,
+    });
 });
 
-Cypress.Commands.add("testEditProjectOrCollection", (container, oldName, newName, newDescription, isProject = true) => {
-    cy.get(container).contains(oldName).rightclick();
-    cy.get("[data-cy=context-menu]")
-        .contains(isProject ? "Edit project" : "Edit collection")
-        .click();
-    cy.get("[data-cy=form-dialog]").within(() => {
-        cy.get("input[name=name]").clear().type(newName);
-        cy.get(isProject ? "div[contenteditable=true]" : "input[name=description]")
-            .clear()
-            .type(newDescription);
-        cy.get("[data-cy=form-submit-btn]").click();
+Cypress.Commands.add("getCollection", (token, uuid) => {
+    return cy.getResource(token, "collections", uuid);
+});
+
+Cypress.Commands.add("updateCollection", (token, uuid, data) => {
+    return cy.updateResource(token, "collections", uuid, {
+        collection: JSON.stringify(data),
     });
+});
 
-    cy.get(container).contains(newName).rightclick();
-    cy.get("[data-cy=context-menu]")
-        .contains(isProject ? "Edit project" : "Edit collection")
-        .click();
-    cy.get("[data-cy=form-dialog]").within(() => {
-        cy.get("input[name=name]").should("have.value", newName);
+Cypress.Commands.add("collectionReplaceFiles", (token, uuid, data) => {
+    return cy.updateResource(token, "collections", uuid, {
+        collection: {
+            preserve_version: true,
+        },
+        replace_files: JSON.stringify(data),
+    });
+});
 
-        if (isProject) {
-            cy.get("span[data-text=true]").contains(newDescription);
-        } else {
-            cy.get("input[name=description]").should("have.value", newDescription);
-        }
+Cypress.Commands.add("getContainer", (token, uuid) => {
+    return cy.getResource(token, "containers", uuid);
+});
+
+Cypress.Commands.add("updateContainer", (token, uuid, data) => {
+    return cy.updateResource(token, "containers", uuid, {
+        container: JSON.stringify(data),
+    });
+});
+
+Cypress.Commands.add("getContainerRequest", (token, uuid) => {
+    return cy.getResource(token, "container_requests", uuid);
+});
+
+Cypress.Commands.add("createContainerRequest", (token, data) => {
+    return cy.createResource(token, "container_requests", {
+        container_request: JSON.stringify(data),
+        ensure_unique_name: true,
+    });
+});
 
-        cy.get("[data-cy=form-cancel-btn]").click();
+Cypress.Commands.add("updateContainerRequest", (token, uuid, data) => {
+    return cy.updateResource(token, "container_requests", uuid, {
+        container_request: JSON.stringify(data),
     });
 });
 
+/**
+ * Requires an admin token for log_uuid modification to succeed
+ */
+Cypress.Commands.add("appendLog", (token, crUuid, fileName, lines = []) =>
+    cy.getContainerRequest(token, crUuid).then(containerRequest => {
+        if (containerRequest.log_uuid) {
+            cy.listContainerRequestLogs(token, crUuid).then(logFiles => {
+                const filePath = `${containerRequest.log_uuid}/${containerLogFolderPrefix}${containerRequest.container_uuid}/${fileName}`;
+                if (logFiles.find(file => file.name === fileName)) {
+                    // File exists, fetch and append
+                    return cy
+                        .doWebDAVRequest("GET", `c=${filePath}`, null, null, token)
+                        .then(({ body: contents }) =>
+                            cy.doWebDAVRequest("PUT", `c=${filePath}`, contents.split("\n").concat(lines).join("\n"), null, token)
+                        );
+                } else {
+                    // File not exists, put new file
+                    cy.doWebDAVRequest("PUT", `c=${filePath}`, lines.join("\n"), null, token);
+                }
+            });
+        } else {
+            // Create log collection
+            return cy
+                .createCollection(token, {
+                    name: `Test log collection ${Math.floor(Math.random() * 999999)}`,
+                    owner_uuid: containerRequest.owner_uuid,
+                    manifest_text: "",
+                })
+                .then(collection => {
+                    // Update CR log_uuid to fake log collection
+                    cy.updateContainerRequest(token, containerRequest.uuid, {
+                        log_uuid: collection.uuid,
+                    }).then(() =>
+                        // Create empty directory for container uuid
+                        cy
+                            .collectionReplaceFiles(token, collection.uuid, {
+                                [`/${containerLogFolderPrefix}${containerRequest.container_uuid}`]: "d41d8cd98f00b204e9800998ecf8427e+0",
+                            })
+                            .then(() =>
+                                // Put new log file with contents into fake log collection
+                                cy.doWebDAVRequest(
+                                    "PUT",
+                                    `c=${collection.uuid}/${containerLogFolderPrefix}${containerRequest.container_uuid}/${fileName}`,
+                                    lines.join("\n"),
+                                    null,
+                                    token
+                                )
+                            )
+                    );
+                });
+        }
+    })
+);
+
+Cypress.Commands.add("listContainerRequestLogs", (token, crUuid) =>
+    cy.getContainerRequest(token, crUuid).then(containerRequest =>
+        cy
+            .doWebDAVRequest(
+                "PROPFIND",
+                `c=${containerRequest.log_uuid}/${containerLogFolderPrefix}${containerRequest.container_uuid}`,
+                null,
+                null,
+                token
+            )
+            .then(({ body: data }) => {
+                return extractFilesData(new DOMParser().parseFromString(data, "text/xml"));
+            })
+    )
+);
+
+cy.get("[data-cy=form-cancel-btn]").click();
+
 Cypress.Commands.add("doSearch", searchTerm => {
     cy.get("[data-cy=searchbar-input-field]").type(`{selectall}${searchTerm}{enter}`);
     cy.get("[data-cy=searchbar-parent-form]").submit();