From d3b2bd362d00473765de82c40694223347774e48 Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Wed, 22 Dec 2021 10:06:52 -0800 Subject: [PATCH] E2e policy flow (#3322) --- changes/issue-3127-e2e-testing-policies | 1 + cypress/integration/all/app/hosts.spec.ts | 193 ++++++++-------- .../integration/all/app/policiesflow.spec.ts | 211 ++++++++++-------- cypress/integration/free/admin.spec.ts | 31 ++- cypress/integration/free/maintainer.spec.ts | 27 +++ cypress/integration/free/observer.spec.ts | 23 +- cypress/integration/premium/admin.spec.ts | 40 +++- .../integration/premium/maintainer.spec.ts | 43 +++- cypress/integration/premium/observer.spec.ts | 50 +++++ .../premium/team_maintainer_observer.spec.ts | 22 ++ cypress/support/commands.ts | 48 ++++ cypress/support/index.d.ts | 5 + 12 files changed, 483 insertions(+), 211 deletions(-) create mode 100644 changes/issue-3127-e2e-testing-policies diff --git a/changes/issue-3127-e2e-testing-policies b/changes/issue-3127-e2e-testing-policies new file mode 100644 index 0000000000..1ba773f399 --- /dev/null +++ b/changes/issue-3127-e2e-testing-policies @@ -0,0 +1 @@ +* e2e tests policies flow: Create, update, delete, and run policy as well as RBAC for policies page \ No newline at end of file diff --git a/cypress/integration/all/app/hosts.spec.ts b/cypress/integration/all/app/hosts.spec.ts index db3cf0d216..1e4a402a16 100644 --- a/cypress/integration/all/app/hosts.spec.ts +++ b/cypress/integration/all/app/hosts.spec.ts @@ -12,6 +12,7 @@ describe( cy.addDockerHost(); cy.clearDownloads(); cy.seedQueries(); + cy.seedPolicies(); }); afterEach(() => { @@ -19,19 +20,19 @@ describe( }); it( - "Can add new host from manage hosts page", + "Can add new host from manage hosts page, run policy on host, and delete a host", { retries: { runMode: 2, }, }, () => { + let hostname = ""; cy.visit("/hosts/manage"); + cy.get(".manage-hosts").should("contain", /hostname/i); // Ensures page load cy.contains("button", /generate installer/i).click(); - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(2000); - cy.findByText(/rpm/i).click(); + cy.findByText(/rpm/i).should("exist").click(); cy.contains("a", /download/i) .first() .click(); @@ -51,100 +52,104 @@ describe( cy.visit("/hosts/manage"); cy.location("pathname").should("match", /hosts\/manage/i); - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(1000); - cy.get('button[title="Online"]').click(); + cy.get(".manage-hosts").should("contain", /hostname/i); // Ensures page load + + cy.get("tbody").within(() => { + cy.get(".button--text-link").first().as("hostLink"); + }); + + cy.get("@hostLink") + // Set hostname variable for later assertions + .then((el) => { + console.log(el); + hostname = el.text(); + return el; + }) + .click(); // Go to host details page cy.location("pathname").should("match", /hosts\/[0-9]/i); - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(1000); - cy.get("span.status").contains(/online/i); + cy.get("span.status").should("contain", /online/i); + + // Run policy on host + let policyname = ""; + cy.contains("a", "Policies").click(); + + cy.getAttached("tbody").within(() => { + cy.get(".button--text-link").first().as("policyLink"); + }); + + cy.get("@policyLink") + // Set policyname variable for later assertions + .then((el) => { + console.log(el); + policyname = el.text(); + return el; + }); + + cy.findByText(/filevault/i) + .should("exist") + .click(); + + cy.findByText(/run/i).should("exist").click(); // Ensures page load + + cy.findByText(/all hosts/i) + .should("exist") + .click() + .then(() => { + cy.findByText(/run/i).click(); + cy.get(".data-table").within(() => { + cy.findByText(hostname).should("exist"); + }); + }); + + cy.visit("/hosts/manage"); + + cy.getAttached("tbody").within(() => { + cy.get(".button--text-link").first().as("hostLink"); + }); + + cy.get("@hostLink") + .click() + .then(() => { + cy.findByText(/about this host/i).should("exist"); + cy.findByText(hostname).should("exist"); + + // Open query host modal and select query + cy.get('img[alt="Query host icon"]').click(); + cy.get(".modal__modal_container") + .within(() => { + cy.findByText(/select a query/i).should("exist"); + cy.findByText(/detect presence/i).click(); + }) + .then(() => { + cy.findByText(/run query/i).click(); + cy.get(".data-table").within(() => { + cy.findByText(hostname).should("exist"); + }); + }); + }); + + cy.visit("/hosts/manage"); + + cy.getAttached("@hostLink") + .click() + .then(() => { + // Open delete host modal and delete host + cy.get('img[alt="Delete host icon"]').click(); + cy.get(".modal__modal_container") + .within(() => { + cy.findByText(/delete host/i).should("exist"); + cy.findByRole("button", { name: /delete/i }).click(); + }) + .then(() => { + cy.findByText(/add your devices to fleet/i).should("exist"); + cy.findByText(/generate installer/i).should("exist"); + cy.findByText(/about this host/i).should("not.exist"); + cy.findByText(hostname).should("not.exist"); + }); + }); } ); - - it("Can query a host and delete a host from host details page", () => { - let hostname = ""; - - cy.visit("/hosts/manage"); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(3000); - - cy.get("tbody").within(() => { - cy.get(".button--text-link").first().as("hostLink"); - }); - - cy.get("@hostLink") - // Set hostname variable for later assertions - .then((el) => { - console.log(el); - hostname = el.text(); - return el; - }) - .click() - .then(() => { - cy.findByText(/about this host/i).should("exist"); - cy.findByText(hostname).should("exist"); - - // Open query host modal and cancel - cy.get('img[alt="Query host icon"]').click(); - cy.get(".modal__modal_container").within(() => { - cy.findByText(/select a query/i).should("exist"); - cy.get(".modal__ex").click(); - }); - cy.findByText(/select a query/i).should("not.exist"); - - // Open query host modal and select query - cy.get('img[alt="Query host icon"]').click(); - cy.get(".modal__modal_container") - .within(() => { - cy.findByText(/select a query/i).should("exist"); - cy.findByText(/detect presence/i).click(); - }) - .then(() => { - cy.findByText(/run query/i).click(); - cy.get(".data-table").within(() => { - cy.findByText(hostname).should("exist"); - }); - }); - }); - - cy.visit("/hosts/manage"); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(3000); - cy.get("@hostLink") - // Set hostname variable for later assertions - .then((el) => { - console.log(el); - hostname = el.text(); - return el; - }) - .click() - .then(() => { - // Open delete host modal and cancel - cy.get('img[alt="Delete host icon"]').click(); - cy.get(".modal__modal_container").within(() => { - cy.findByText(/delete host/i).should("exist"); - cy.findByRole("button", { name: /cancel/i }).click(); - }); - cy.findByText(/delete host/i).should("not.exist"); - - // Open delete host modal and delete host - cy.get('img[alt="Delete host icon"]').click(); - cy.get(".modal__modal_container") - .within(() => { - cy.findByText(/delete host/i).should("exist"); - cy.findByRole("button", { name: /delete/i }).click(); - }) - .then(() => { - cy.findByText(/add your devices to fleet/i).should("exist"); - cy.findByText(/generate installer/i).should("exist"); - cy.findByText(/about this host/i).should("not.exist"); - cy.findByText(hostname).should("not.exist"); - }); - }); - }); } ); diff --git a/cypress/integration/all/app/policiesflow.spec.ts b/cypress/integration/all/app/policiesflow.spec.ts index 0e7dee5d37..b09055a33f 100644 --- a/cypress/integration/all/app/policiesflow.spec.ts +++ b/cypress/integration/all/app/policiesflow.spec.ts @@ -1,107 +1,120 @@ -// describe( -// "Policies flow", -// { -// defaultCommandTimeout: 20000, -// }, -// () => { -// beforeEach(() => { -// cy.setup(); -// cy.login(); -// cy.seedQueries(); -// }); -// it("Can create, check, and delete a policy successfully", () => { -// cy.intercept({ -// method: "GET", -// url: "/api/v1/fleet/global/policies", -// }).as("getPolicies"); -// cy.intercept({ -// method: "GET", -// url: "/api/v1/fleet/config", -// }).as("getConfig"); +describe( + "Policies flow", + { + defaultCommandTimeout: 20000, + }, + () => { + beforeEach(() => { + cy.setup(); + cy.login(); + }); + it("Can create, update, and delete a policy successfully", () => { + cy.visit("/policies/manage"); + cy.get(".manage-policies-page__description").should( + "contain", + /add policies/i + ); // Ensure page load -// cy.visit("/policies/manage"); + // Add a policy + cy.findByText(/add a policy/i).click(); + cy.findByText(/create your own policy/i).click(); -// // wait for state of policy table to settle otherwise re-renders cause elements to detach and tests will fail -// cy.wait("@getPolicies"); -// cy.wait("@getConfig"); + cy.get(".ace_scroller") + .click({ force: true }) + .type( + "{selectall}SELECT 1 FROM users WHERE username = 'backup' LIMIT 1;" + ); -// cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + cy.findByRole("button", { name: /save policy/i }).click(); -// // Add a policy -// cy.get(".no-policies__inner") -// .findByText(/add a policy/i) -// .should("exist") -// .click(); -// cy.get(".add-policy-modal").within(() => { -// cy.findByText(/select query/i) -// .should("exist") -// .click(); -// cy.findByText( -// /Detect Linux hosts with high severity vulnerable versions of OpenSSL/i -// ).click(); -// cy.findByRole("button", { name: /cancel/i }).should("exist"); -// cy.findByRole("button", { name: /add/i }).should("exist").click(); -// }); + // save modal + cy.get(".policy-form__policy-save-modal-name") + .click() + .type("Does the device have a user named 'backup'?"); -// // Confirm that policy was added successfully -// cy.findByText(/successfully added policy/i).should("exist"); -// cy.findByText(/select query/i).should("not.exist"); -// cy.get(".policies-list-wrapper").within(() => { -// cy.findByText(/1 query/i).should("exist"); -// cy.findByText(/yes/i).should("exist"); -// cy.findByText( -// /Detect Linux hosts with high severity vulnerable versions of OpenSSL/i -// ).should("exist"); + cy.get(".policy-form__policy-save-modal-description") + .click() + .type("Returns yes or no for having a user named 'backup'"); -// // Click on link in table and confirm that policies filter block diplays as expected on manage hosts page -// cy.get("tbody").within(() => { -// cy.get("tr") -// .first() -// .within(() => { -// cy.get("td").last().children().first().should("exist").click(); -// }); -// }); -// }); -// cy.get(".manage-hosts__policies-filter-block").within(() => { -// cy.findByText( -// /Detect Linux hosts with high severity vulnerable versions of OpenSSL/i -// ).should("exist"); -// cy.findByText(/yes/i).should("not.exist"); -// cy.findByText(/failing/i) -// .should("exist") -// .click(); -// cy.findByText(/yes/i).should("exist"); -// cy.get('img[alt="Remove policy filter"]').click(); -// cy.findByText( -// /Detect Linux hosts with high severity vulnerable versions of OpenSSL/i -// ).should("not.exist"); -// }); + cy.get(".policy-form__policy-save-modal-resolution") + .click() + .type("Create a user named 'backup'"); -// // Click on policies tab to return to manage policies page -// cy.get(".site-nav-container").within(() => { -// cy.findByText(/policies/i) -// .should("exist") -// .click(); -// }); + cy.findByRole("button", { name: /^Save$/ }).click(); -// // Delete policy -// cy.get("tbody").within(() => { -// cy.get("tr") -// .first() -// .within(() => { -// cy.get(".fleet-checkbox__input").check({ force: true }); -// }); -// }); -// cy.findByRole("button", { name: /remove/i }).click(); -// cy.get(".remove-policies-modal").within(() => { -// cy.findByRole("button", { name: /cancel/i }).should("exist"); -// cy.findByRole("button", { name: /remove/i }) -// .should("exist") -// .click(); -// }); -// cy.findByText( -// /Detect Linux hosts with high severity vulnerable versions of OpenSSL/i -// ).should("not.exist"); -// }); -// } -// ); + // Confirm that policy was added successfully + cy.findByText(/policy created/i).should("exist"); + + cy.visit("/policies/manage"); + cy.get(".manage-policies-page__description").should( + "contain", + /add policies/i + ); // Ensure page load + + // Add a default policy + cy.findByText(/add a policy/i).click(); + + cy.findByText(/gatekeeper enabled/i).click(); + cy.findByRole("button", { name: /save policy/i }).click(); + cy.findByRole("button", { name: /^Save$/ }).click(); + + // Confirm that policy was added successfully + cy.findByText(/policy created/i).should("exist"); + + cy.visit("/policies/manage"); + + // Click on link in table and confirm that policies filter block diplays as expected on manage hosts page + cy.getAttached(".failing_host_count__cell") + .first() + .within(() => { + cy.findByRole("button", { name: /0 hosts/i }).click(); + }); + + // confirm policy functionality on manage host page + cy.get(".manage-hosts__policies-filter-block").within(() => { + cy.findByText(/user named 'backup'/i).should("exist"); + cy.findByText(/no/i).should("exist").click(); + cy.findByText(/yes/i).should("exist"); + cy.get('img[alt="Remove policy filter"]').click(); + cy.findByText(/user named 'backup'/i).should("not.exist"); + }); + + // Click on policies tab to return to manage policies page + cy.get(".site-nav-container").within(() => { + cy.findByText(/policies/i).click(); + }); + + // Update policy + cy.findByText(/gatekeeper enabled/i).click(); + + cy.get(".ace_scroller") + .click({ force: true }) + .type( + "{selectall}SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;" + ); + + cy.findByRole("button", { name: /^Save$/ }).click(); + + // Confirm that policy was added successfully + cy.findByText(/policy updated/i).should("exist"); + + // Delete policy + cy.visit("/policies/manage"); + + cy.getAttached("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").check({ force: true }); + }); + }); + cy.findByRole("button", { name: /delete/i }).click(); + cy.get(".remove-policies-modal").within(() => { + cy.findByRole("button", { name: /cancel/i }).should("exist"); + cy.findByRole("button", { name: /delete/i }).click(); + }); + cy.findByText(/removed policy/i).should("exist"); + cy.findByText(/backup/i).should("not.exist"); + }); + } +); diff --git a/cypress/integration/free/admin.spec.ts b/cypress/integration/free/admin.spec.ts index d0198318e2..1ad40c87a1 100644 --- a/cypress/integration/free/admin.spec.ts +++ b/cypress/integration/free/admin.spec.ts @@ -10,6 +10,7 @@ describe( cy.setupSMTP(); cy.seedFree(); cy.seedQueries(); + cy.seedPolicies(); cy.addDockerHost(); cy.logout(); }); @@ -20,9 +21,7 @@ describe( it("Can perform the appropriate free-tier admin actions", () => { cy.login("anna@organization.com", "user123#"); cy.visit("/hosts/manage"); - - // Ensure page is loaded - cy.contains("All hosts"); + cy.get(".manage-hosts").should("contain", /hostname/i); // Ensures page load // On the hosts page, they should… @@ -113,6 +112,32 @@ describe( // On the Packs pages (manage, new, and edit), they should… // ^^General admin functionality for packs page is being tested in app/packflow.spec.ts + // On the policies manage page, they should… + cy.contains("a", "Policies").click(); + // See and select the "Add a policy", "delete", and "edit" policy + cy.findByRole("button", { name: /add a policy/i }).click(); + cy.get(".modal__ex").within(() => { + cy.findByRole("button").click(); + }); + + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").check({ force: true }); + }); + }); + cy.findByRole("button", { name: /delete/i }).click(); + cy.get(".remove-policies-modal").within(() => { + cy.findByRole("button", { name: /delete/i }).should("exist"); + cy.findByRole("button", { name: /cancel/i }).click(); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + + cy.findByRole("button", { name: /save/i }).should("exist"); + cy.findByRole("button", { name: /run/i }).should("exist"); + // On the Settings pages, they should… // See everything except for the “Teams” pages cy.visit("/settings/organization"); diff --git a/cypress/integration/free/maintainer.spec.ts b/cypress/integration/free/maintainer.spec.ts index 6ca16bc90c..a3f488b2e6 100644 --- a/cypress/integration/free/maintainer.spec.ts +++ b/cypress/integration/free/maintainer.spec.ts @@ -9,6 +9,7 @@ describe( cy.login(); cy.seedFree(); cy.seedQueries(); + cy.seedPolicies(); cy.addDockerHost(); cy.logout(); }); @@ -113,6 +114,32 @@ describe( // cy.findByText(/edit & run query/i).should("exist"); + // On the policies manage page, they should… + cy.contains("a", "Policies").click(); + // See and select the "Add a policy", "delete", and "edit" policy + cy.findByRole("button", { name: /add a policy/i }).click(); + cy.get(".modal__ex").within(() => { + cy.findByRole("button").click(); + }); + + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").check({ force: true }); + }); + }); + cy.findByRole("button", { name: /delete/i }).click(); + cy.get(".remove-policies-modal").within(() => { + cy.findByRole("button", { name: /delete/i }).should("exist"); + cy.findByRole("button", { name: /cancel/i }).click(); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + + cy.findByRole("button", { name: /save/i }).should("exist"); + cy.findByRole("button", { name: /run/i }).should("exist"); + // Packs pages: Can create, edit, delete a pack cy.visit("/packs/manage"); cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting diff --git a/cypress/integration/free/observer.spec.ts b/cypress/integration/free/observer.spec.ts index dbf065cf98..c7022b19f5 100644 --- a/cypress/integration/free/observer.spec.ts +++ b/cypress/integration/free/observer.spec.ts @@ -4,6 +4,7 @@ describe("Free tier - Observer user", () => { cy.login(); cy.seedFree(); cy.seedQueries(); + cy.seedPolicies(); cy.addDockerHost(); cy.logout(); }); @@ -74,11 +75,31 @@ describe("Free tier - Observer user", () => { cy.findByText(/show sql/i).click(); cy.findByRole("button", { name: /run query/i }).should("exist"); + // On the policies manage page, they should… + cy.contains("a", "Policies").click(); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + + // Not see the "Add a policy", "delete", "save", "run" policy + cy.findByRole("button", { name: /add a policy/i }).should("not.exist"); + + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").should("not.exist"); + }); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + + cy.findByRole("button", { name: /save/i }).should("not.exist"); + cy.findByRole("button", { name: /run/i }).should("not.exist"); + // On the Profile page, they should… // See Observer in Role section, and no Team section cy.visit("/profile"); - cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting cy.findByText(/teams/i).should("not.exist"); cy.findByText("Role") .next() diff --git a/cypress/integration/premium/admin.spec.ts b/cypress/integration/premium/admin.spec.ts index afbd28d6bc..55c52ed6d1 100644 --- a/cypress/integration/premium/admin.spec.ts +++ b/cypress/integration/premium/admin.spec.ts @@ -10,6 +10,7 @@ describe( cy.seedPremium(); cy.setupSMTP(); cy.seedQueries(); + cy.seedPolicies("apples"); cy.addDockerHost("apples"); cy.logout(); }); @@ -28,13 +29,10 @@ describe( cy.login("anna@organization.com", "user123#"); cy.visit("/hosts/manage"); - // Ensure the hosts page is loaded - cy.contains("All hosts"); - // On the hosts page, they should… // See the “Teams” column in the Hosts table - cy.get("thead").contains(/team/i).should("exist"); + cy.getAttached("thead").contains(/team/i).should("exist"); // See and select the “Generate installer” button cy.contains("button", /generate installer/i).click(); @@ -208,7 +206,39 @@ describe( cy.findByText(/successfully removed query/i).should("be.visible"); - cy.findByText(/query all/i).should("not.exist"); + // On the policies manage page, they should… + cy.contains("a", "Policies").click(); + + // See and select the "Add a policy", "delete", and "edit" policy + cy.findByRole("button", { name: /add a policy/i }) + .should("exist") + .click(); + cy.get(".modal__ex").within(() => { + cy.findByRole("button").click(); + }); + + // No global policies seeded, switch to team apples to create, delete, edit + cy.findByText(/ask yes or no questions/i).should("exist"); + cy.findByText(/all teams/i).click(); + cy.findByText(/apples/i).click(); + + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").check({ force: true }); + }); + }); + cy.findByRole("button", { name: /delete/i }).click(); + cy.get(".remove-policies-modal").within(() => { + cy.findByRole("button", { name: /delete/i }).should("exist"); + cy.findByRole("button", { name: /cancel/i }).click(); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + + cy.findByRole("button", { name: /save/i }).should("exist"); + cy.findByRole("button", { name: /run/i }).should("exist"); // On the Packs pages (manage, new, and edit), they should… // ^^General admin functionality for packs page is being tested in app/packflow.spec.ts diff --git a/cypress/integration/premium/maintainer.spec.ts b/cypress/integration/premium/maintainer.spec.ts index b86cc40c82..f81f67659c 100644 --- a/cypress/integration/premium/maintainer.spec.ts +++ b/cypress/integration/premium/maintainer.spec.ts @@ -9,7 +9,8 @@ describe( cy.login(); cy.seedPremium(); cy.seedQueries(); - cy.addDockerHost(); + cy.seedPolicies("apples"); + cy.addDockerHost("apples"); cy.logout(); }); @@ -20,14 +21,7 @@ describe( it("Can perform the appropriate basic global maintainer actions", () => { cy.login("mary@organization.com", "user123#"); cy.visit("/hosts/manage"); - - // Ensure page is loaded - cy.contains("All hosts"); - - // Host manage page: Teams column, select a team - cy.visit("/hosts/manage"); - - cy.wait(3000); // eslint-disable-line cypress/no-unnecessary-waiting + cy.get(".manage-hosts").should("contain", /hostname/i); // Ensures page load // See the "Manage" enroll secret” button. A modal appears after the user selects the button cy.contains("button", /manage enroll secret/i).click(); @@ -86,6 +80,37 @@ describe( // cy.findByText(/teams/i).should("exist"); // }); + // On the policies manage page, they should… + cy.contains("a", "Policies").click(); + // See and select the "Add a policy", "delete", and "edit" policy + cy.findByRole("button", { name: /add a policy/i }).click(); + cy.get(".modal__ex").within(() => { + cy.findByRole("button").click(); + }); + + // No global policies seeded, switch to team apples to create, delete, edit + cy.findByText(/ask yes or no questions/i).should("exist"); + cy.findByText(/all teams/i).click(); + cy.findByText(/apples/i).click(); + + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").check({ force: true }); + }); + }); + cy.findByRole("button", { name: /delete/i }).click(); + cy.get(".remove-policies-modal").within(() => { + cy.findByRole("button", { name: /delete/i }).should("exist"); + cy.findByRole("button", { name: /cancel/i }).click(); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + + cy.findByRole("button", { name: /save/i }).should("exist"); + cy.findByRole("button", { name: /run/i }).should("exist"); + // On the Packs pages (manage, new, and edit), they should… // On the Schedule pages (manage, new, and edit), they should… // ^^General maintainer functionality for packs page is being tested in free/maintainer.spec.ts diff --git a/cypress/integration/premium/observer.spec.ts b/cypress/integration/premium/observer.spec.ts index 4156ce1740..374fcd49bc 100644 --- a/cypress/integration/premium/observer.spec.ts +++ b/cypress/integration/premium/observer.spec.ts @@ -4,6 +4,7 @@ describe("Premium tier - Observer user", () => { cy.login(); cy.seedPremium(); cy.seedQueries(); + cy.seedPolicies("apples"); cy.addDockerHost("apples"); cy.logout(); }); @@ -56,6 +57,36 @@ describe("Premium tier - Observer user", () => { // cy.findByText(/Label name, host name, IP address, etc./i).click(); // cy.findByText(/teams/i).should("exist"); // }); + + // On the policies manage page, they should… + cy.visit("/policies/manage"); + cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting + + // Cannot see and select the "Add a policy", "delete", and "edit" policy + cy.findByRole("button", { name: /add a policy/i }).should("not.exist"); + + // No global policies seeded, switch to team apples to ensure cannot create, delete, edit + cy.findByText(/ask yes or no questions/i).should("exist"); + cy.findByText(/all teams/i).click(); + cy.findByText(/apples/i).click(); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + + // Not see the "Add a policy", "delete", "save", "run" policy + cy.findByRole("button", { name: /add a policy/i }).should("not.exist"); + + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").should("not.exist"); + }); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting + + cy.findByRole("button", { name: /save/i }).should("not.exist"); + // TODO: Uncomment out after bug fix #3364 + // cy.findByRole("button", { name: /run/i }).should("not.exist"); }); // Pseudo code for team observer only @@ -81,6 +112,25 @@ describe("Premium tier - Observer user", () => { cy.visit("/schedule/manage"); cy.findByText(/you do not have permissions/i).should("exist"); + // On the policies manage page, they should… + cy.visit("/policies/manage"); + cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting + + // Not see and select the "Add a policy", "delete", and "edit" policy + cy.findByRole("button", { name: /add a policy/i }).should("not.exist"); + cy.findByText(/all teams/i).should("not.exist"); + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").should("not.exist"); + }); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting + cy.findByRole("button", { name: /save/i }).should("not.exist"); + cy.findByRole("button", { name: /run/i }).should("not.exist"); + // On the Profile page, they should… // See Global in the Team section and Observer in the Role section cy.visit("/profile"); diff --git a/cypress/integration/premium/team_maintainer_observer.spec.ts b/cypress/integration/premium/team_maintainer_observer.spec.ts index a20cc2ec06..1958cdf6d0 100644 --- a/cypress/integration/premium/team_maintainer_observer.spec.ts +++ b/cypress/integration/premium/team_maintainer_observer.spec.ts @@ -9,6 +9,7 @@ describe( cy.login(); cy.seedPremium(); cy.seedQueries(); + cy.seedPolicies("apples"); cy.addDockerHost("apples"); cy.addDockerHost("oranges"); cy.logout(); @@ -47,6 +48,27 @@ describe( // NOT see and select "add label" cy.findByRole("button", { name: /new label/i }).should("not.exist"); + // On the Policies page, they should... + + // On observing team, not see the "Add a policy" button + cy.visit("/policies/manage"); + cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting + cy.findByText(/add a policy/i).should("not.exist"); + + cy.get("tbody").within(() => { + cy.get("tr") + .first() + .within(() => { + cy.get(".fleet-checkbox__input").should("not.exist"); + }); + }); + cy.findByText(/filevault enabled/i).click(); + cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting + cy.findByRole("button", { name: /save/i }).should("not.exist"); + + // TODO: Uncomment out after bug fix #3364, write test where save and run exists on team maintainer test + // cy.findByRole("button", { name: /run/i }).should("not.exist"); + // On the Host details page, they should… // See the “Team” information below the hostname diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 4239e3b501..04685c7e2c 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -99,6 +99,54 @@ Cypress.Commands.add("seedQueries", () => { }); }); +Cypress.Commands.add("seedPolicies", (team = "") => { + const policies = [ + { + name: "Is Filevault enabled on macOS devices?", + query: + "SELECT 1 FROM disk_encryption WHERE user_uuid IS NOT '' AND filevault_status = 'on' LIMIT 1", + description: + "Checks to make sure that the Filevault feature is enabled on macOS devices.", + resolution: + "Choose Apple menu > System Preferences, then click Security & Privacy. Click the FileVault tab. Click the Lock icon, then enter an administrator name and password. Click Turn On FileVault.", + }, + { + name: "Is Ubuntu, version 20.4.0 installed?", + query: + "SELECT 1 from os_version WHERE name = 'Ubuntu' AND major || '.' || minor || '.' || patch = '20.4.0';", + description: + "Returns yes or no for detecting operating system and version", + resolution: "Update OS if needed", + }, + ]; + + if (team === "apples") { + policies.forEach((policyForm) => { + const { name, query, description, resolution } = policyForm; + cy.request({ + url: "/api/v1/fleet/teams/1/policies", + method: "POST", + body: { name, query, description, resolution }, + auth: { + bearer: window.localStorage.getItem("FLEET::auth_token"), + }, + }); + }); + } else { + policies.forEach((policyForm) => { + const { name, query, description, resolution } = policyForm; + cy.request({ + url: "/api/v1/fleet/global/policies", + method: "POST", + body: { name, query, description, resolution }, + auth: { + bearer: window.localStorage.getItem("FLEET::auth_token"), + }, + }); + }); + } +}); + Cypress.Commands.add("setupSMTP", () => { const body = { smtp_settings: { diff --git a/cypress/support/index.d.ts b/cypress/support/index.d.ts index a6e3ddcc55..f8cd222708 100644 --- a/cypress/support/index.d.ts +++ b/cypress/support/index.d.ts @@ -23,6 +23,11 @@ declare namespace Cypress { */ seedQueries(): Chainable; + /** + * Custom command to add new queries by default. + */ + seedPolicies(): Chainable; + /** * Custom command to add a new user in Fleet (via fleetctl). */