Cypress Testing: Modify default timeout (#1835)

- Change default timeout to 20 seconds on 8 more brittle e2e tests
This commit is contained in:
RachelElysia 2021-08-27 15:13:32 -07:00 committed by GitHub
parent 731fb599a1
commit 2c8d43f06b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 783 additions and 726 deletions

View file

@ -1,146 +1,155 @@
import * as path from "path";
describe("Hosts flow", () => {
beforeEach(() => {
cy.setup();
cy.login();
cy.addDockerHost();
});
describe(
"Hosts flow",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
cy.addDockerHost();
});
afterEach(() => {
cy.stopDockerHost();
});
afterEach(() => {
cy.stopDockerHost();
});
it(
"Can add new host from manage hosts page",
{
retries: {
runMode: 2,
},
},
() => {
cy.visit("/");
cy.contains("button", /add new host/i).click();
cy.get('a[href*="showSecret"]').click();
cy.contains("a", /download/i)
.first()
.click();
// Assert enroll secret downloaded matches the one displayed
// NOTE: This test often fails when the Cypress downloads folder was not cleared properly
// before each test run (seems to be related to issues with Cypress trashAssetsBeforeRun)
cy.readFile(path.join(Cypress.config("downloadsFolder"), "secret.txt"), {
timeout: 5000,
}).then((contents) => {
cy.get("input[disabled]").should("have.value", contents);
});
// Wait until the host becomes available (usually immediate in local
// testing, but may vary by environment).
cy.waitUntil(
() => {
cy.visit("/");
return Cypress.$('button[title="Online"]').length > 0;
it(
"Can add new host from manage hosts page",
{
retries: {
runMode: 2,
},
{ timeout: 30000, interval: 1000 }
);
},
() => {
cy.visit("/");
// Go to host details page
cy.get('button[title="Online"]').click();
cy.get("span.status").contains("online");
}
);
cy.contains("button", /add new host/i).click();
it("Can delete a host from host details page", () => {
let hostname = "";
cy.get('a[href*="showSecret"]').click();
cy.contains("a", /download/i)
.first()
.click();
cy.visit("/hosts/manage");
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 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();
// Assert enroll secret downloaded matches the one displayed
// NOTE: This test often fails when the Cypress downloads folder was not cleared properly
// before each test run (seems to be related to issues with Cypress trashAssetsBeforeRun)
cy.readFile(
path.join(Cypress.config("downloadsFolder"), "secret.txt"),
{
timeout: 5000,
}
).then((contents) => {
cy.get("input[disabled]").should("have.value", contents);
});
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(() => {
// Wait until the host becomes available (usually immediate in local
// testing, but may vary by environment).
cy.waitUntil(
() => {
cy.visit("/");
return Cypress.$('button[title="Online"]').length > 0;
},
{ timeout: 30000, interval: 1000 }
);
// Go to host details page
cy.get('button[title="Online"]').click();
cy.get("span.status").contains("online");
}
);
it("Can delete a host from host details page", () => {
let hostname = "";
cy.visit("/hosts/manage");
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 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: /delete/i }).click();
})
.then(() => {
cy.findByText(/successfully deleted/i).should("exist");
cy.findByText(/kinda empty in here/i).should("exist");
cy.findByText(/about this host/i).should("not.exist");
cy.findByText(hostname).should("not.exist");
cy.findByRole("button", { name: /cancel/i }).click();
});
});
});
cy.findByText(/delete host/i).should("not.exist");
it("Can query a host from host details page", () => {
cy.seedQueries();
let hostname = "";
cy.visit("/hosts/manage");
cy.get("tbody").within(() => {
cy.get(".button--text-link").first().as("hostLink");
// 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(/successfully deleted/i).should("exist");
cy.findByText(/kinda empty in here/i).should("exist");
cy.findByText(/about this host/i).should("not.exist");
cy.findByText(hostname).should("not.exist");
});
});
});
cy.get("@hostLink")
// Set hostname variable for later assertions
.then((el) => {
hostname = el.text();
return el;
})
.click()
.then(() => {
cy.findByText(/about this host/i).should("exist");
cy.findByText(hostname).should("exist");
it("Can query a host from host details page", () => {
cy.seedQueries();
// 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");
let hostname = "";
// 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(/edit & run query/i).should("exist");
cy.get(".target-select").within(() => {
cy.findByText(hostname).should("exist");
});
});
cy.visit("/hosts/manage");
cy.get("tbody").within(() => {
cy.get(".button--text-link").first().as("hostLink");
});
});
});
cy.get("@hostLink")
// Set hostname variable for later assertions
.then((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(/edit & run query/i).should("exist");
cy.get(".target-select").within(() => {
cy.findByText(hostname).should("exist");
});
});
});
});
}
);

View file

@ -1,63 +1,69 @@
describe("Label flow", () => {
beforeEach(() => {
cy.setup();
cy.login();
});
describe(
"Label flow",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
});
it("Create, edit, and delete a label successfully", () => {
cy.visit("/hosts/manage");
it("Create, edit, and delete a label successfully", () => {
cy.visit("/hosts/manage");
cy.findByRole("button", { name: /add label/i }).click();
cy.findByRole("button", { name: /add label/i }).click();
// Using class selector because third party element doesn't work with Cypress Testing Selector Library
cy.get(".ace_content")
.click()
.type("{selectall}{backspace}SELECT * FROM users;");
// Using class selector because third party element doesn't work with Cypress Testing Selector Library
cy.get(".ace_content")
.click()
.type("{selectall}{backspace}SELECT * FROM users;");
cy.findByLabelText(/name/i).click().type("Show all users");
cy.findByLabelText(/name/i).click().type("Show all users");
cy.findByLabelText(/description/i)
.click()
.type("Select all users across platforms.");
cy.findByLabelText(/description/i)
.click()
.type("Select all users across platforms.");
// Cannot call cy.select on div disguised as a dropdown
cy.findByText(/select one/i).click();
cy.findByText(/all platforms/i).click();
// Cannot call cy.select on div disguised as a dropdown
cy.findByText(/select one/i).click();
cy.findByText(/all platforms/i).click();
cy.findByRole("button", { name: /save label/i }).click();
cy.findByRole("button", { name: /save label/i }).click();
cy.findByText(/show all users/i).click();
cy.findByText(/show all users/i).click();
cy.get(".manage-hosts__label-block button").first().click();
cy.get(".manage-hosts__label-block button").first().click();
// Label SQL not editable to test
// Label SQL not editable to test
cy.findByLabelText(/name/i)
.click()
.type("{selectall}{backspace}Show all usernames");
cy.findByLabelText(/name/i)
.click()
.type("{selectall}{backspace}Show all usernames");
cy.findByLabelText(/description/i)
.click()
.type("{selectall}{backspace}Select all usernames on Mac.");
cy.findByLabelText(/description/i)
.click()
.type("{selectall}{backspace}Select all usernames on Mac.");
cy.findByText(/select one/i).should("not.exist");
cy.findByText(/select one/i).should("not.exist");
cy.findByText(/label platforms are immutable/i).should("exist");
cy.findByText(/label platforms are immutable/i).should("exist");
cy.findByRole("button", { name: /update label/i }).click();
cy.findByRole("button", { name: /update label/i }).click();
// TODO add test for flash message once issue with router is fixed
// Close success notification
// cy.get(".flash-message__remove").click();
// TODO add test for flash message once issue with router is fixed
// Close success notification
// cy.get(".flash-message__remove").click();
cy.get(".manage-hosts__label-block button").last().click();
cy.get(".manage-hosts__label-block button").last().click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".manage-hosts__modal-buttons > .button--alert")
.contains("button", /delete/i)
.click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".manage-hosts__modal-buttons > .button--alert")
.contains("button", /delete/i)
.click();
cy.findByText(/show all users/i).should("not.exist");
});
});
cy.findByText(/show all users/i).should("not.exist");
});
}
);

View file

@ -1,54 +1,60 @@
describe("Pack flow", () => {
beforeEach(() => {
cy.setup();
cy.login();
});
describe(
"Pack flow",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
});
it("Create, edit, and delete a pack successfully", () => {
cy.visit("/packs/manage");
it("Create, edit, and delete a pack successfully", () => {
cy.visit("/packs/manage");
cy.findByRole("button", { name: /create new pack/i }).click();
cy.findByRole("button", { name: /create new pack/i }).click();
cy.findByLabelText(/query pack title/i)
.click()
.type("Errors and crashes");
cy.findByLabelText(/query pack title/i)
.click()
.type("Errors and crashes");
cy.findByLabelText(/description/i)
.click()
.type("See all user errors and window crashes.");
cy.findByLabelText(/description/i)
.click()
.type("See all user errors and window crashes.");
cy.findByRole("button", { name: /save query pack/i }).click();
cy.findByRole("button", { name: /save query pack/i }).click();
cy.visit("/packs/manage");
cy.visit("/packs/manage");
cy.findByText(/errors and crashes/i).click();
cy.findByText(/errors and crashes/i).click();
cy.findByText(/edit pack/i).click();
cy.findByText(/edit pack/i).click();
cy.findByLabelText(/query pack title/i)
.click()
.type("{selectall}{backspace}Server errors");
cy.findByLabelText(/query pack title/i)
.click()
.type("{selectall}{backspace}Server errors");
cy.findByLabelText(/description/i)
.click()
.type("{selectall}{backspace}See all server errors.");
cy.findByLabelText(/description/i)
.click()
.type("{selectall}{backspace}See all server errors.");
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save/i }).click();
cy.visit("/packs/manage");
cy.visit("/packs/manage");
cy.get(".fleet-checkbox__input").check({ force: true });
cy.get(".fleet-checkbox__input").check({ force: true });
cy.findByRole("button", { name: /delete/i }).click();
cy.findByRole("button", { name: /delete/i }).click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".remove-pack-modal__btn-wrap > .button--alert")
.contains("button", /delete/i)
.click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".remove-pack-modal__btn-wrap > .button--alert")
.contains("button", /delete/i)
.click();
cy.findByText(/successfully deleted/i).should("be.visible");
cy.findByText(/successfully deleted/i).should("be.visible");
cy.findByText(/server errors/i).should("not.exist");
});
});
cy.findByText(/server errors/i).should("not.exist");
});
}
);

View file

@ -1,141 +1,147 @@
describe("Query flow", () => {
beforeEach(() => {
cy.setup();
cy.login();
});
describe(
"Query flow",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
});
it("Create, check, edit, and delete a query successfully and create, edit, and delete a global scheduled query successfully", () => {
cy.visit("/queries/manage");
it("Create, check, edit, and delete a query successfully and create, edit, and delete a global scheduled query successfully", () => {
cy.visit("/queries/manage");
cy.findByRole("button", { name: /create new query/i }).click();
cy.findByRole("button", { name: /create new query/i }).click();
cy.findByLabelText(/query name/i)
.click()
.type("Query all window crashes");
cy.findByLabelText(/query name/i)
.click()
.type("Query all window crashes");
// Using class selector because third party element doesn't work with Cypress Testing Selector Library
cy.get(".ace_scroller")
.click({ force: true })
.type("{selectall}{backspace}SELECT * FROM windows_crashes;");
// Using class selector because third party element doesn't work with Cypress Testing Selector Library
cy.get(".ace_scroller")
.click({ force: true })
.type("{selectall}{backspace}SELECT * FROM windows_crashes;");
cy.findByLabelText(/description/i)
.click()
.type("See all window crashes");
cy.findByLabelText(/description/i)
.click()
.type("See all window crashes");
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save as new/i }).click();
cy.findByRole("button", { name: /save as new/i }).click();
// Just refreshes to create new query, needs success alert to user that they created a query
// Just refreshes to create new query, needs success alert to user that they created a query
cy.visit("/queries/manage");
cy.visit("/queries/manage");
cy.findByText(/query all/i).click();
cy.findByText(/query all/i).click();
cy.findByText(/edit & run query/i).should("exist");
cy.findByText(/edit & run query/i).should("exist");
cy.get(".ace_scroller")
.click({ force: true })
.type(
"{selectall}{backspace}SELECT datetime, username FROM windows_crashes;"
);
cy.get(".ace_scroller")
.click({ force: true })
.type(
"{selectall}{backspace}SELECT datetime, username FROM windows_crashes;"
);
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save changes/i }).click();
cy.findByRole("button", { name: /save changes/i }).click();
cy.findByText(/query updated/i).should("be.visible");
cy.findByText(/query updated/i).should("be.visible");
// Test Schedules
cy.visit("/schedule/manage");
// Test Schedules
cy.visit("/schedule/manage");
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.findByRole("button", { name: /schedule a query/i }).click();
cy.findByRole("button", { name: /schedule a query/i }).click();
cy.findByText(/select query/i).click();
cy.findByText(/select query/i).click();
cy.findByText(/query all window crashes/i).click();
cy.findByText(/query all window crashes/i).click();
cy.get(
".schedule-editor-modal__form-field--frequency > .dropdown__select"
).click();
cy.get(
".schedule-editor-modal__form-field--frequency > .dropdown__select"
).click();
cy.findByText(/every week/i).click();
cy.findByText(/every week/i).click();
cy.findByText(/show advanced options/i).click();
cy.findByText(/show advanced options/i).click();
cy.get(
".schedule-editor-modal__form-field--logging > .dropdown__select"
).click();
cy.get(
".schedule-editor-modal__form-field--logging > .dropdown__select"
).click();
cy.findByText(/ignore removals/i).click();
cy.findByText(/ignore removals/i).click();
cy.get(".schedule-editor-modal__form-field--shard > .input-field")
.click()
.type("50");
cy.get(".schedule-editor-modal__form-field--shard > .input-field")
.click()
.type("50");
cy.get(".schedule-editor-modal__btn-wrap")
.contains("button", /schedule/i)
.click();
cy.get(".schedule-editor-modal__btn-wrap")
.contains("button", /schedule/i)
.click();
cy.visit("/schedule/manage");
cy.visit("/schedule/manage");
cy.findByText(/query all window crashes/i).should("exist");
cy.findByText(/query all window crashes/i).should("exist");
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.findByText(/actions/i).click();
cy.findByText(/edit/i).click();
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.findByText(/actions/i).click();
cy.findByText(/edit/i).click();
cy.get(
".schedule-editor-modal__form-field--frequency > .dropdown__select"
).click();
cy.get(
".schedule-editor-modal__form-field--frequency > .dropdown__select"
).click();
cy.findByText(/every 6 hours/i).click();
cy.findByText(/every 6 hours/i).click();
cy.findByText(/show advanced options/i).click();
cy.findByText(/show advanced options/i).click();
cy.findByText(/ignore removals/i).click();
cy.findByText(/snapshot/i).click();
cy.findByText(/ignore removals/i).click();
cy.findByText(/snapshot/i).click();
cy.get(".schedule-editor-modal__form-field--shard > .input-field")
.click()
.type("{selectall}{backspace}10");
cy.get(".schedule-editor-modal__form-field--shard > .input-field")
.click()
.type("{selectall}{backspace}10");
cy.get(".schedule-editor-modal__btn-wrap")
.contains("button", /schedule/i)
.click();
cy.get(".schedule-editor-modal__btn-wrap")
.contains("button", /schedule/i)
.click();
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.findByText(/actions/i).click();
cy.findByText(/remove/i).click();
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.findByText(/actions/i).click();
cy.findByText(/remove/i).click();
cy.get(".remove-scheduled-query-modal__btn-wrap")
.contains("button", /remove/i)
.click();
cy.get(".remove-scheduled-query-modal__btn-wrap")
.contains("button", /remove/i)
.click();
cy.findByText(/query all window crashes/i).should("not.exist");
// End Test Schedules
cy.findByText(/query all window crashes/i).should("not.exist");
// End Test Schedules
cy.visit("/queries/manage");
cy.visit("/queries/manage");
cy.findByText(/query all window crashes/i)
.parent()
.parent()
.within(() => {
cy.get(".fleet-checkbox__input").check({ force: true });
});
cy.findByText(/query all window crashes/i)
.parent()
.parent()
.within(() => {
cy.get(".fleet-checkbox__input").check({ force: true });
});
cy.findByRole("button", { name: /delete/i }).click();
cy.findByRole("button", { name: /delete/i }).click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".remove-query-modal")
.contains("button", /delete/i)
.click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".remove-query-modal")
.contains("button", /delete/i)
.click();
cy.findByText(/successfully removed query/i).should("be.visible");
cy.findByText(/successfully removed query/i).should("be.visible");
cy.findByText(/query all/i).should("not.exist");
});
});
cy.findByText(/query all/i).should("not.exist");
});
}
);

View file

@ -1,107 +1,115 @@
describe("Basic tier - Admin user", () => {
beforeEach(() => {
cy.setup();
cy.login();
cy.seedBasic();
cy.setupSMTP();
cy.seedQueries();
cy.addDockerHost("apples");
cy.logout();
});
afterEach(() => {
cy.stopDockerHost();
});
describe(
"Basic tier - Admin user",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
cy.seedBasic();
cy.setupSMTP();
cy.seedQueries();
cy.addDockerHost("apples");
cy.logout();
});
afterEach(() => {
cy.stopDockerHost();
});
it(
"Can perform the appropriate basic-tier admin actions",
{
retries: {
runMode: 2,
it(
"Can perform the appropriate basic-tier admin actions",
{
retries: {
runMode: 2,
},
},
},
() => {
cy.login("anna@organization.com", "user123#");
cy.visit("/");
() => {
cy.login("anna@organization.com", "user123#");
cy.visit("/");
// Ensure the hosts page is loaded
cy.contains("All hosts");
// Ensure the hosts page is loaded
cy.contains("All hosts");
// On the hosts page, they should…
// On the hosts page, they should…
// See the “Teams” column in the Hosts table
cy.get("thead").contains(/team/i).should("exist");
// See the “Teams” column in the Hosts table
cy.get("thead").contains(/team/i).should("exist");
// See and select the “Add new host” button
cy.contains("button", /add new host/i).click();
// See and select the “Add new host” button
cy.contains("button", /add new host/i).click();
// See the “Select a team for this new host” in the Add new host modal. This modal appears after the user selects the “Add new host” button
cy.get(".add-host-modal__team-dropdown-wrapper .Select-control").click();
// See the “Select a team for this new host” in the Add new host modal. This modal appears after the user selects the “Add new host” button
cy.get(
".add-host-modal__team-dropdown-wrapper .Select-control"
).click();
cy.get(".Select-menu-outer").within(() => {
cy.findByText(/no team/i).should("exist");
cy.get(".Select-menu-outer").within(() => {
cy.findByText(/no team/i).should("exist");
cy.findByText(/apples/i).should("exist");
cy.findByText(/oranges/i).should("exist");
});
cy.contains("button", /done/i).click();
// On the Host details page, they should…
// See the “Team” information below the hostname
// Be able to transfer Teams
cy.visit("/hosts/1");
cy.findByText(/team/i).next().contains("Apples");
cy.contains("button", /transfer/i).click();
cy.get(".Select-control").click();
cy.findByText(/create a team/i).should("exist");
cy.get(".Select-menu").within(() => {
cy.findByText(/no team/i).should("exist");
cy.findByText(/apples/i).should("exist");
cy.findByText(/oranges/i).click();
});
cy.get(".transfer-action-btn").click();
cy.findByText(/transferred to oranges/i).should("exist");
cy.findByText(/team/i).next().contains("Oranges");
// On the Queries - new / edit / run page, they should…
// See the “Teams” section in the Select target picker. This picker is summoned when the “Select targets” field is selected.
cy.visit("/queries/new");
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/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
// On the Schedule pages (manage, new, and edit), they should…
// ^^General admin functionality for packs page is being tested in app/queryflow.spec.ts
// On the Settings pages, they should…
// See the “Teams” navigation item and access the Settings - Teams page
cy.visit("/settings/organization");
cy.get(".react-tabs").within(() => {
cy.findByText(/teams/i).click();
});
// Access the Settings - Team details page
cy.findByText(/apples/i).click();
cy.findByText(/apples/i).should("exist");
cy.findByText(/oranges/i).should("exist");
});
cy.findByText(/manage users with global access here/i).should("exist");
cy.contains("button", /done/i).click();
// See the “Team” section in the create user modal. This modal is summoned when the “Create user” button is selected
cy.visit("/settings/organization");
cy.get(".react-tabs").within(() => {
cy.findByText(/users/i).click();
});
cy.findByRole("button", { name: /create user/i }).click();
cy.findByText(/assign teams/i).should("exist");
// On the Host details page, they should…
// See the “Team” information below the hostname
// Be able to transfer Teams
cy.visit("/hosts/1");
cy.findByText(/team/i).next().contains("Apples");
cy.contains("button", /transfer/i).click();
cy.get(".Select-control").click();
cy.findByText(/create a team/i).should("exist");
cy.get(".Select-menu").within(() => {
cy.findByText(/no team/i).should("exist");
cy.findByText(/apples/i).should("exist");
cy.findByText(/oranges/i).click();
});
cy.get(".transfer-action-btn").click();
cy.findByText(/transferred to oranges/i).should("exist");
cy.findByText(/team/i).next().contains("Oranges");
// On the Queries - new / edit / run page, they should…
// See the “Teams” section in the Select target picker. This picker is summoned when the “Select targets” field is selected.
cy.visit("/queries/new");
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/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
// On the Schedule pages (manage, new, and edit), they should…
// ^^General admin functionality for packs page is being tested in app/queryflow.spec.ts
// On the Settings pages, they should…
// See the “Teams” navigation item and access the Settings - Teams page
cy.visit("/settings/organization");
cy.get(".react-tabs").within(() => {
cy.findByText(/teams/i).click();
});
// Access the Settings - Team details page
cy.findByText(/apples/i).click();
cy.findByText(/apples/i).should("exist");
cy.findByText(/manage users with global access here/i).should("exist");
// See the “Team” section in the create user modal. This modal is summoned when the “Create user” button is selected
cy.visit("/settings/organization");
cy.get(".react-tabs").within(() => {
cy.findByText(/users/i).click();
});
cy.findByRole("button", { name: /create user/i }).click();
cy.findByText(/assign teams/i).should("exist");
// On the Profile page, they should…
// See Global in the Team section and Admin in the Role section
cy.visit("/profile");
cy.findByText(/team/i)
.next()
.contains(/global/i);
cy.findByText("Role").next().contains(/admin/i);
}
);
});
// On the Profile page, they should…
// See Global in the Team section and Admin in the Role section
cy.visit("/profile");
cy.findByText(/team/i)
.next()
.contains(/global/i);
cy.findByText("Role").next().contains(/admin/i);
}
);
}
);

View file

@ -1,91 +1,99 @@
describe("Basic tier - Maintainer user", () => {
beforeEach(() => {
cy.setup();
cy.login();
cy.seedBasic();
cy.seedQueries();
cy.addDockerHost();
cy.logout();
});
afterEach(() => {
cy.stopDockerHost();
});
it("Can perform the appropriate basic global maintainer actions", () => {
cy.login("mary@organization.com", "user123#");
cy.visit("/");
// Ensure page is loaded
cy.contains("All hosts");
// Host manage page: Teams column, select a team
cy.visit("/hosts/manage");
cy.get("thead").within(() => {
cy.findByText(/team/i).should("exist");
describe(
"Basic tier - Maintainer user",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
cy.seedBasic();
cy.seedQueries();
cy.addDockerHost();
cy.logout();
});
cy.contains("button", /add new host/i).click();
// TODO: Check Team Apples is in Select a team dropdown
cy.contains("button", /done/i).click();
// Host details page: Can see team UI
cy.get("tbody").within(() => {
// Test host text varies
cy.findByRole("button").click();
});
cy.get(".title").within(() => {
cy.findByText("Team").should("exist");
});
cy.contains("button", /transfer/i).click();
cy.get(".Select-control").click();
cy.findByText(/create a team/i).should("not.exist");
cy.get(".Select-menu").within(() => {
cy.findByText(/no team/i).should("exist");
cy.findByText(/apples/i).should("exist");
cy.findByText(/oranges/i).click();
});
cy.get(".transfer-action-btn").click();
cy.findByText(/transferred to oranges/i).should("exist");
cy.findByText(/team/i).next().contains("Oranges");
cy.contains("button", /delete/i).should("exist");
cy.contains("button", /query/i).click();
cy.contains("button", /create custom query/i).should("exist");
// Query pages: Can see teams UI for create, edit, and run query
cy.visit("/queries/manage");
cy.findByRole("button", { name: /create new query/i }).click();
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/i).should("exist");
afterEach(() => {
cy.stopDockerHost();
});
cy.visit("/queries/manage");
it("Can perform the appropriate basic global maintainer actions", () => {
cy.login("mary@organization.com", "user123#");
cy.visit("/");
cy.findByText(/detect presence/i).click();
// Ensure page is loaded
cy.contains("All hosts");
cy.findByText(/edit & run query/i).should("exist");
// Host manage page: Teams column, select a team
cy.visit("/hosts/manage");
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/i).should("exist");
cy.wait(10000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.get("thead").within(() => {
cy.findByText(/team/i).should("exist");
});
cy.contains("button", /add new host/i).click();
// TODO: Check Team Apples is in Select a team dropdown
cy.contains("button", /done/i).click();
// Host details page: Can see team UI
cy.get("tbody").within(() => {
// Test host text varies
cy.findByRole("button").click();
});
cy.get(".title").within(() => {
cy.findByText("Team").should("exist");
});
cy.contains("button", /transfer/i).click();
cy.get(".Select-control").click();
cy.findByText(/create a team/i).should("not.exist");
cy.get(".Select-menu").within(() => {
cy.findByText(/no team/i).should("exist");
cy.findByText(/apples/i).should("exist");
cy.findByText(/oranges/i).click();
});
cy.get(".transfer-action-btn").click();
cy.findByText(/transferred to oranges/i).should("exist");
cy.findByText(/team/i).next().contains("Oranges");
cy.contains("button", /delete/i).should("exist");
cy.contains("button", /query/i).click();
cy.contains("button", /create custom query/i).should("exist");
// Query pages: Can see teams UI for create, edit, and run query
cy.visit("/queries/manage");
cy.findByRole("button", { name: /create new query/i }).click();
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/i).should("exist");
});
cy.visit("/queries/manage");
cy.findByText(/detect presence/i).click();
cy.findByText(/edit & run query/i).should("exist");
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/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 core/maintainer.spec.ts
// On the Profile page, they should…
// See Global in the Team section and Maintainer in the Role section
cy.visit("/profile");
cy.findByText(/team/i)
.next()
.contains(/global/i);
cy.findByText("Role")
.next()
.contains(/maintainer/i);
});
// 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 core/maintainer.spec.ts
// On the Profile page, they should…
// See Global in the Team section and Maintainer in the Role section
cy.visit("/profile");
cy.findByText(/team/i)
.next()
.contains(/global/i);
cy.findByText("Role")
.next()
.contains(/maintainer/i);
});
});
}
);

View file

@ -1,126 +1,132 @@
describe("Core tier - Admin user", () => {
beforeEach(() => {
cy.setup();
cy.login();
cy.setupSMTP();
cy.seedCore();
cy.seedQueries();
cy.addDockerHost();
cy.logout();
});
afterEach(() => {
cy.stopDockerHost();
});
it("Can perform the appropriate core-tier admin actions", () => {
cy.login("anna@organization.com", "user123#");
cy.visit("/");
// Ensure page is loaded
cy.contains("All hosts");
// On the hosts page, they should…
// Not see "team" anywhere on the page
cy.contains(/team/i).should("not.exist");
// See all navigation items
cy.get("nav").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/settings/i).should("exist");
describe(
"Core tier - Admin user",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
cy.setupSMTP();
cy.seedCore();
cy.seedQueries();
cy.addDockerHost();
cy.logout();
});
afterEach(() => {
cy.stopDockerHost();
});
// See and select "add new host"
cy.findByRole("button", { name: /new host/i }).click();
cy.contains(/team/i).should("not.exist");
cy.findByRole("button", { name: /done/i }).click();
it("Can perform the appropriate core-tier admin actions", () => {
cy.login("anna@organization.com", "user123#");
cy.visit("/");
// See the “Show enroll secret” button. A modal appears after the user selects the button
cy.contains("button", /show enroll secret/i).click();
cy.contains("button", /done/i).click();
// Ensure page is loaded
cy.contains("All hosts");
// See and select "add label"
cy.findByRole("button", { name: /add label/i }).click();
cy.findByRole("button", { name: /cancel/i }).click();
// On the hosts page, they should…
// On the Host details page, they should…
cy.visit("/hosts/1");
// Not see "team" anywhere on the page
cy.contains(/team/i).should("not.exist");
// Not see "team" information or transfer button
cy.findByText(/team/i).should("not.exist");
cy.contains("button", /transfer/i).should("not.exist");
// See all navigation items
cy.get("nav").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/settings/i).should("exist");
});
// See and select the “Delete” button
cy.findByRole("button", { name: /delete/i }).click();
cy.findByText(/delete host/i).should("exist");
cy.findByRole("button", { name: /cancel/i }).click();
// See and select "add new host"
cy.findByRole("button", { name: /new host/i }).click();
cy.contains(/team/i).should("not.exist");
cy.findByRole("button", { name: /done/i }).click();
// See and select the “Query” button
cy.findByRole("button", { name: /query/i }).click();
cy.findByRole("button", { name: /create custom query/i }).should("exist");
cy.get(".modal__ex").within(() => {
cy.findByRole("button").click();
});
// See the “Show enroll secret” button. A modal appears after the user selects the button
cy.contains("button", /show enroll secret/i).click();
cy.contains("button", /done/i).click();
// On the queries manage page, they should…
cy.contains("a", "Queries").click();
// See the "observer can run column"
cy.contains(/observer can run/i);
// See and select the "create new query" button
cy.findByRole("button", { name: /new query/i }).click();
// See and select "add label"
cy.findByRole("button", { name: /add label/i }).click();
cy.findByRole("button", { name: /cancel/i }).click();
// On the Queries - new/edit/run page, they should…
// Edit the “Query name,” “SQL,” “Description,” “Observers can run,” and “Select targets” input fields.
cy.findByLabelText(/query name/i)
.click()
.type("Cypress test query");
// ACE editor requires special handling to get typing to work sometimes
cy.get(".ace_text-input")
.first()
.click({ force: true })
.type("{selectall}{backspace}SELECT * FROM cypress;", { force: true });
cy.findByLabelText(/description/i)
.click()
.type("Cypress test of create new query flow.");
cy.findByLabelText(/observers can run/i).click({ force: true });
// On the Host details page, they should…
cy.visit("/hosts/1");
// See and select the “Save changes,” “Save as new,” and “Run” buttons.
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /new/i }).click();
cy.findByRole("button", { name: /run/i }).should("exist");
// Not see "team" information or transfer button
cy.findByText(/team/i).should("not.exist");
cy.contains("button", /transfer/i).should("not.exist");
// NOT see the “Teams” section in the Select target picker. This picker is summoned when the “Select targets” field is selected.
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
// See and select the “Delete” button
cy.findByRole("button", { name: /delete/i }).click();
cy.findByText(/delete host/i).should("exist");
cy.findByRole("button", { name: /cancel/i }).click();
// See and select the “Query” button
cy.findByRole("button", { name: /query/i }).click();
cy.findByRole("button", { name: /create custom query/i }).should("exist");
cy.get(".modal__ex").within(() => {
cy.findByRole("button").click();
});
// On the queries manage page, they should…
cy.contains("a", "Queries").click();
// See the "observer can run column"
cy.contains(/observer can run/i);
// See and select the "create new query" button
cy.findByRole("button", { name: /new query/i }).click();
// On the Queries - new/edit/run page, they should…
// Edit the “Query name,” “SQL,” “Description,” “Observers can run,” and “Select targets” input fields.
cy.findByLabelText(/query name/i)
.click()
.type("Cypress test query");
// ACE editor requires special handling to get typing to work sometimes
cy.get(".ace_text-input")
.first()
.click({ force: true })
.type("{selectall}{backspace}SELECT * FROM cypress;", { force: true });
cy.findByLabelText(/description/i)
.click()
.type("Cypress test of create new query flow.");
cy.findByLabelText(/observers can run/i).click({ force: true });
// See and select the “Save changes,” “Save as new,” and “Run” buttons.
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /new/i }).click();
cy.findByRole("button", { name: /run/i }).should("exist");
// NOT see the “Teams” section in the Select target picker. This picker is summoned when the “Select targets” field is selected.
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/i).should("not.exist");
});
cy.contains("a", /back to queries/i).click({ force: true });
cy.findByText(/cypress test query/i).click({ force: true });
cy.findByText(/edit & run query/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
// On the Settings pages, they should…
// See everything except for the “Teams” pages
cy.visit("/settings/organization");
cy.findByText(/teams/i).should("not.exist");
cy.get(".react-tabs").within(() => {
cy.findByText(/organization settings/i).should("exist");
cy.findByText(/users/i).click();
});
cy.findByRole("button", { name: /create user/i }).click();
cy.findByText(/team/i).should("not.exist");
cy.visit("/settings/teams");
cy.findByText(/you do not have permissions/i).should("exist");
// On the Profile page, they should…
// See Admin in Role section, and no Team section
cy.visit("/profile");
cy.findByText(/teams/i).should("not.exist");
cy.findByText("Role").next().contains(/admin/i);
});
cy.contains("a", /back to queries/i).click({ force: true });
cy.findByText(/cypress test query/i).click({ force: true });
cy.findByText(/edit & run query/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
// On the Settings pages, they should…
// See everything except for the “Teams” pages
cy.visit("/settings/organization");
cy.findByText(/teams/i).should("not.exist");
cy.get(".react-tabs").within(() => {
cy.findByText(/organization settings/i).should("exist");
cy.findByText(/users/i).click();
});
cy.findByRole("button", { name: /create user/i }).click();
cy.findByText(/team/i).should("not.exist");
cy.visit("/settings/teams");
cy.findByText(/you do not have permissions/i).should("exist");
// On the Profile page, they should…
// See Admin in Role section, and no Team section
cy.visit("/profile");
cy.findByText(/teams/i).should("not.exist");
cy.findByText("Role").next().contains(/admin/i);
});
});
}
);

View file

@ -1,138 +1,146 @@
describe("Core tier - Maintainer user", () => {
beforeEach(() => {
cy.setup();
cy.login();
cy.seedCore();
cy.seedQueries();
cy.addDockerHost();
cy.logout();
});
afterEach(() => {
cy.stopDockerHost();
});
it("Can perform the appropriate core global maintainer actions", () => {
cy.login("mary@organization.com", "user123#");
cy.visit("/");
// Ensure page is loaded
cy.contains("All hosts");
// Settings restrictions
cy.findByText(/settings/i).should("not.exist");
cy.visit("/settings/organization");
cy.findByText(/you do not have permissions/i).should("exist");
// Host manage page: No team UI, can add host and label
cy.visit("/hosts/manage");
cy.findByText(/teams/i).should("not.exist");
cy.contains("button", /add new host/i).click();
cy.findByText("select a team").should("not.exist");
cy.contains("button", /done/i).click();
// See the “Show enroll secret” button. A modal appears after the user selects the button
cy.contains("button", /show enroll secret/i).click();
cy.contains("button", /done/i).click();
cy.contains("button", /add label/i).click();
cy.contains("button", /cancel/i).click();
// Host details page: No team UI, can delete and create new query
cy.get("tbody").within(() => {
// Test host text varies
cy.findByRole("button").click();
});
cy.get(".title").within(() => {
cy.findByText(/team/i).should("not.exist");
});
cy.contains("button", /transfer/i).should("not.exist");
cy.contains("button", /delete/i).click();
cy.contains("button", /cancel/i).click();
cy.contains("button", /query/i).click();
cy.contains("button", /create custom query/i).click();
// Queries pages: Can create, edit, and run query
cy.visit("/queries/manage");
cy.get("thead").within(() => {
cy.findByText(/observer can run/i).should("exist");
describe(
"Core tier - Maintainer user",
{
defaultCommandTimeout: 20000,
},
() => {
beforeEach(() => {
cy.setup();
cy.login();
cy.seedCore();
cy.seedQueries();
cy.addDockerHost();
cy.logout();
});
cy.findByRole("button", { name: /create new query/i }).click();
afterEach(() => {
cy.stopDockerHost();
});
cy.findByLabelText(/query name/i)
.click()
.type("Query all window crashes");
it("Can perform the appropriate core global maintainer actions", () => {
cy.login("mary@organization.com", "user123#");
cy.visit("/");
cy.get(".ace_scroller")
.click({ force: true })
.type("{selectall}{backspace}SELECT * FROM windows_crashes;");
// Ensure page is loaded
cy.contains("All hosts");
cy.findByLabelText(/description/i)
.click()
.type("See all window crashes");
// Settings restrictions
cy.findByText(/settings/i).should("not.exist");
cy.visit("/settings/organization");
cy.findByText(/you do not have permissions/i).should("exist");
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save as new/i }).click();
cy.findByLabelText(/observers can run/i).click({ force: true });
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
// Host manage page: No team UI, can add host and label
cy.visit("/hosts/manage");
cy.findByText(/teams/i).should("not.exist");
cy.contains("button", /add new host/i).click();
cy.findByText("select a team").should("not.exist");
cy.contains("button", /done/i).click();
// See the “Show enroll secret” button. A modal appears after the user selects the button
cy.contains("button", /show enroll secret/i).click();
cy.contains("button", /done/i).click();
cy.contains("button", /add label/i).click();
cy.contains("button", /cancel/i).click();
// Host details page: No team UI, can delete and create new query
cy.get("tbody").within(() => {
// Test host text varies
cy.findByRole("button").click();
});
cy.get(".title").within(() => {
cy.findByText(/team/i).should("not.exist");
});
cy.contains("button", /transfer/i).should("not.exist");
cy.contains("button", /delete/i)
.should("exist")
.click();
cy.contains("button", /cancel/i).click();
cy.contains("button", /query/i).click();
cy.contains("button", /create custom query/i).click();
// Queries pages: Can create, edit, and run query
cy.visit("/queries/manage");
cy.get("thead").within(() => {
cy.findByText(/observer can run/i).should("exist");
});
cy.findByRole("button", { name: /create new query/i }).click();
cy.findByLabelText(/query name/i)
.click()
.type("Query all window crashes");
cy.get(".ace_scroller")
.click({ force: true })
.type("{selectall}{backspace}SELECT * FROM windows_crashes;");
cy.findByLabelText(/description/i)
.click()
.type("See all window crashes");
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save as new/i }).click();
cy.findByLabelText(/observers can run/i).click({ force: true });
cy.get(".target-select").within(() => {
cy.findByText(/Label name, host name, IP address, etc./i).click();
cy.findByText(/teams/i).should("not.exist");
});
cy.findByRole("button", { name: /run/i }).should("exist");
cy.visit("/queries/manage");
cy.findByText(/query all/i).click();
cy.findByText(/edit & run query/i).should("exist");
// Packs pages: Can create, edit, delete a pack
cy.visit("/packs/manage");
cy.findByRole("button", { name: /create new pack/i }).click();
cy.findByLabelText(/query pack title/i)
.click()
.type("Errors and crashes");
cy.findByLabelText(/description/i)
.click()
.type("See all user errors and window crashes.");
cy.findByRole("button", { name: /save query pack/i }).click();
cy.visit("/packs/manage");
cy.get(".fleet-checkbox__input").check({ force: true });
cy.findByRole("button", { name: /delete/i }).click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".remove-pack-modal__btn-wrap > .button--alert")
.contains("button", /delete/i)
.click();
cy.findByText(/successfully deleted/i).should("be.visible");
cy.findByText(/server errors/i).should("not.exist");
// Schedule page: Can create, edit, remove a schedule
// TODO: Copy flow from queryflow.spec.ts here to ensure maintainers have access
// On the Profile page, they should…
// See Maintainer in Role section, and no Team section
cy.visit("/profile");
cy.findByText(/teams/i).should("not.exist");
cy.findByText("Role")
.next()
.contains(/maintainer/i);
});
cy.findByRole("button", { name: /run/i }).should("exist");
cy.visit("/queries/manage");
cy.findByText(/query all/i).click();
cy.findByText(/edit & run query/i).should("exist");
// Packs pages: Can create, edit, delete a pack
cy.visit("/packs/manage");
cy.findByRole("button", { name: /create new pack/i }).click();
cy.findByLabelText(/query pack title/i)
.click()
.type("Errors and crashes");
cy.findByLabelText(/description/i)
.click()
.type("See all user errors and window crashes.");
cy.findByRole("button", { name: /save query pack/i }).click();
cy.visit("/packs/manage");
cy.get(".fleet-checkbox__input").check({ force: true });
cy.findByRole("button", { name: /delete/i }).click();
// Can't figure out how attach findByRole onto modal button
// Can't use findByText because delete button under modal
cy.get(".remove-pack-modal__btn-wrap > .button--alert")
.contains("button", /delete/i)
.click();
cy.findByText(/successfully deleted/i).should("be.visible");
cy.findByText(/server errors/i).should("not.exist");
// Schedule page: Can create, edit, remove a schedule
// TODO: Copy flow from queryflow.spec.ts here to ensure maintainers have access
// On the Profile page, they should…
// See Maintainer in Role section, and no Team section
cy.visit("/profile");
cy.findByText(/teams/i).should("not.exist");
cy.findByText("Role")
.next()
.contains(/maintainer/i);
});
});
}
);