Complete removal of Cypress (#13389)

Remove the last of the dependencies and configuration around Cypress
since we no longer use it for testing.
This commit is contained in:
Zach Wasserman 2023-08-18 11:06:12 -06:00 committed by GitHub
parent 19a5ae6465
commit 4ecc7db6d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 25 additions and 7419 deletions

View File

@ -5,7 +5,6 @@ module.exports = {
"plugin:jest/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:cypress/recommended",
"plugin:prettier/recommended",
"plugin:storybook/recommended",
],
@ -83,13 +82,6 @@ module.exports = {
"jsx-a11y/anchor-has-content": "off",
},
overrides: [
{
files: ["cypress/**/*.ts"],
// Set to turn off jest linting error on cypress library
rules: {
"jest/valid-expect": "off",
},
},
],
settings: {
"import/resolver": {

View File

@ -44,7 +44,6 @@ jobs:
with:
path: |
**/node_modules
~/.cache/Cypress
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-modules-
@ -78,7 +77,6 @@ jobs:
with:
path: |
**/node_modules
~/.cache/Cypress
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-modules-

5
.gitignore vendored
View File

@ -41,11 +41,6 @@ helm-temp
#editors
.idea
# Cypress e2e testing
cypress/screenshots
cypress/videos
cypress/downloads
# Fleet local development DB backups
backup.sql.gz

View File

@ -28,11 +28,6 @@ tmp/
.vscode
.idea
# Cypress e2e testing
cypress/screenshots
cypress/videos
cypress/downloads
# fleetdm.com website (uses its own formatting conventions)
website/

View File

@ -1,42 +0,0 @@
# Cypress testing
Cypress tests are designed solely for end-to-end testing. If this is your first time developing or running end-to-end tests, [Fleet testing documentation](../docs/Contributing/Testing-and-local-development.md) includes git instructions for test preparation and running tests.
## Fleet Cypress directories
### Integration directory
Cypress tests the integration of [entire features](integration/all/app) of the app.
With the roll out of teams, Cypress tests the user interface of each role of a user on the Premium Tier ([Fleet Premium Documentation](integration/premium/README.md)) and Free Tier ([Fleet Free Documentation](integration/free/README.md)).
### Support directory
[Commands](support/commands.ts) that are shared across tests are located in the support directory.
## Opening Cypress locally
To open simply run:
`yarn cypress:open`
This will open up cypress locally and
allow you to view the current test suite, as well as start writing new tests.
## Building best practices
As much as possible, build from a user's perspective. Use `.within` cypress command as needed to scope a command within a specific element (e.g. table, nav).
As much as possible, assert that the code is only selecting 1 item or that the final assertion is the appropriate count.
### Prioritization of selecting elements
1. By **element tag** using elements (e.g. buttons), we can target text within. Confirm what the user is seeing with target text. If this is not specific enough, add on Role.
2. By **role** using default or explicitly assigned roles of elements. If this is not specific enough, add on element class.
3. By **element class** is least preferred as it does not follow a user's perspective. Occasionally this may be the only option. If that is the case, prioritize using the class name that specifies what the element is doing.
## Resources
- [Fleet testing documentation](../docs/Contributing/Testing-and-local-development.md)
- [Cypress documentation](https://docs.cypress.io/api/table-of-contents)
- [React testing-library query documentation](https://testing-library.com/docs/queries/about/)

View File

@ -1,13 +0,0 @@
{
"baseUrl": "https://localhost:8642",
"fixturesFolder": false,
"experimentalSessionSupport": true,
"testFiles": "{all,free}/**/*.spec.ts",
"retries": {
"runMode": 2,
"openMode": 0
},
"video": false,
"videoUploadOnPasses": false,
"defaultCommandTimeout": 8000
}

View File

@ -1,13 +0,0 @@
{
"baseUrl": "https://localhost:8642",
"fixturesFolder": false,
"experimentalSessionSupport": true,
"testFiles": "{all,premium}/**/*.spec.ts",
"retries": {
"runMode": 2,
"openMode": 0
},
"video": false,
"videoUploadOnPasses": false,
"defaultCommandTimeout": 8000
}

View File

@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@ -1,114 +0,0 @@
import CONSTANTS from "../../../support/constants";
const {
GOOD_PASSWORD,
BAD_PASSWORD_LENGTH,
BAD_PASSWORD_NO_NUMBER,
BAD_PASSWORD_NO_SYMBOL,
} = CONSTANTS;
describe("Activate user flow", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.setupSMTP();
cy.viewport(1600, 900);
});
after(() => {
cy.logout();
});
describe("Users settings page", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.viewport(1600, 900);
cy.visit("/settings/organization");
cy.getAttached(".component__tabs-wrapper").within(() => {
cy.findByRole("tab", { name: /^users$/i }).click();
});
});
it("invites and activates a user", () => {
cy.getAttached(".user-management").within(() => {
cy.contains("button", /create user/i).click();
});
cy.getAttached(".create-user-modal").within(() => {
cy.findByLabelText(/name/i).click().type("Ash Ketchum");
cy.findByLabelText(/email/i).click().type("ash@example.com");
cy.getAttached(".create-user-form__new-user-radios").within(() => {
cy.findByRole("radio", { name: "Invite user" }).parent().click();
});
cy.findByRole("button", { name: /^create$/i }).click();
});
// Ensures the email has been delivered
cy.wait(3000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.logout();
// Retrieves user invite in email
const inviteLink = { url: "" };
const regex = /\/login\/invites\/[a-zA-Z0-9=?%&@._-]*/gm;
cy.getEmails().then((response) => {
expect(response.body.items[0].To[0]).to.have.property("Domain");
expect(response.body.items[0].To[0].Mailbox).to.equal("ash");
expect(response.body.items[0].To[0].Domain).to.equal("example.com");
expect(response.body.items[0].From.Mailbox).to.equal("fleet");
expect(response.body.items[0].From.Domain).to.equal("example.com");
const match = response.body.items[0].Content.Body.match(regex);
inviteLink.url = match[0];
});
// Activates user
cy.visit(inviteLink);
cy.getAttached(".confirm-invite-page").within(() => {
cy.findByLabelText(/full name/i)
.clear()
.type("Ash Ketchum");
cy.findByLabelText(/^password$/i)
.click()
.type(BAD_PASSWORD_LENGTH);
cy.findByLabelText(/confirm password/i)
.click()
.type(BAD_PASSWORD_LENGTH);
cy.findByRole("button", { name: /submit/i }).click();
});
cy.findByText(/password does not meet required criteria/i).should(
"exist"
);
cy.getAttached("#password").clear().type(BAD_PASSWORD_NO_NUMBER);
cy.getAttached("#password_confirmation")
.clear()
.type(BAD_PASSWORD_NO_NUMBER);
cy.findByRole("button", { name: /submit/i }).click();
cy.findByText(/password does not meet required criteria/i).should(
"exist"
);
cy.getAttached("#password").clear().type(BAD_PASSWORD_NO_SYMBOL);
cy.getAttached("#password_confirmation")
.clear()
.type(BAD_PASSWORD_NO_SYMBOL);
cy.findByRole("button", { name: /submit/i }).click();
cy.findByText(/password does not meet required criteria/i).should(
"exist"
);
cy.getAttached("#password").clear().type(GOOD_PASSWORD);
cy.getAttached("#password_confirmation").clear().type(GOOD_PASSWORD);
cy.findByRole("button", { name: /submit/i }).click();
cy.getAttached(".login-form").within(() => {
cy.findByLabelText(/email/i).clear().type("ash@example.com");
cy.findByLabelText(/^password$/i)
.click()
.type(GOOD_PASSWORD);
cy.findByRole("button", { name: /login/i }).click();
});
Cypress.session.clearAllSavedSessions(); // Switch back to admin user
});
it("shows new user in admin settings", () => {
cy.getAttached("tbody>tr>td")
.contains("Ash Ketchum")
.parent()
.parent()
.within(() => {
cy.findByText(/active/i).should("exist");
});
});
});
});

View File

@ -1,59 +0,0 @@
import dashboardPage from "../../pages/dashboardPage";
describe("Dashboard", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Operating systems card", () => {
beforeEach(() => {
cy.loginWithCySession();
dashboardPage.visitsDashboardPage();
});
it("displays operating systems card if macOS platform is selected", () => {
dashboardPage.switchesPlatform("macOS");
});
it("displays operating systems card if Windows platform is selected", () => {
dashboardPage.switchesPlatform("Windows");
});
it("displays operating systems card if Linux platform is selected", () => {
dashboardPage.switchesPlatform("Linux");
});
});
describe("Hosts filter by dashboard host summary", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/dashboard");
});
it("filters macOS hosts", () => {
cy.findByText(/macos hosts/i).click();
cy.findByRole("status", {
name: /hosts filtered by macos/i,
}).should("exist");
});
it("filters Windows hosts", () => {
cy.findByText(/windows hosts/i).click();
cy.findByRole("status", {
name: /hosts filtered by windows/i,
}).should("exist");
});
it("filters linux hosts", () => {
cy.findByText(/macos hosts/i).click();
cy.findByRole("status", {
name: /hosts filtered by macos/i,
}).should("exist");
});
// filters missing hosts and low disk space hosts on premium only, premium/admin.spec.ts
});
});

View File

@ -1,88 +0,0 @@
const fakeDeviceToken = "phAK3d3vIC37OK3n";
describe("Fleet Desktop", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.addDockerHost();
cy.setDesktopToken(1, fakeDeviceToken);
cy.viewport(1200, 660);
});
after(() => {
cy.stopDockerHost();
});
describe("Fleet Desktop device user page", () => {
beforeEach(() => {
Cypress.session.clearAllSavedSessions();
cy.visit(`/device/${fakeDeviceToken}`);
});
it("renders the device user information and info modal", () => {
cy.findByText(/my device/i).should("exist");
cy.getAttached(".status--online").should("exist");
cy.getAttached(".info-flex").within(() => {
cy.findByText(/ubuntu 20/i)
.prev()
.contains(/operating system/i);
});
cy.getAttached(".info-grid").within(() => {
cy.findByText(/private ip address/i)
.next()
.findByText(/---/i)
.should("not.exist");
});
cy.getAttached(".device-user__action-button-container").within(() => {
cy.getAttached('img[alt="Host info icon"]').click();
});
cy.getAttached(".device-user-info__modal").within(() => {
cy.findByRole("button", { name: /ok/i }).click();
});
});
it("renders and searches the host's software", () => {
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/software/i).click();
});
let initialCount = 0;
cy.getAttached(".section--software").within(() => {
cy.getAttached(".table-container__results-count")
.invoke("text")
.then((text) => {
const fullText = text;
const pattern = /[0-9]+/g;
const newCount = fullText.match(pattern);
initialCount = parseInt(newCount[0], 10);
expect(initialCount).to.be.at.least(1);
});
cy.findByPlaceholderText(/search software/i).type("lib");
// Ensures search completes
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.getAttached(".table-container__results-count")
.invoke("text")
.then((text) => {
const fullText = text;
const pattern = /[0-9]+/g;
const newCount = fullText.match(pattern);
const searchCount = parseInt(newCount[0], 10);
expect(searchCount).to.be.lessThan(initialCount);
});
});
});
it(
"refetches host vitals",
{
retries: {
runMode: 2,
},
defaultCommandTimeout: 15000,
},
() => {
cy.getAttached(".display-name-container").within(() => {
cy.contains("button", /refetch/i).click();
cy.findByText(/fetching/i).should("exist");
cy.contains("button", /refetch/i).should("exist");
cy.findByText(/less than a minute/i).should("exist");
});
}
);
});
});

View File

@ -1,261 +0,0 @@
import * as path from "path";
import { format } from "date-fns";
import manageHostsPage from "../../pages/manageHostsPage";
import hostDetailsPage from "../../pages/hostDetailsPage";
let hostname = "";
describe("Hosts flow", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.addDockerHost();
cy.clearDownloads();
cy.seedQueries();
cy.seedSchedule();
cy.seedPolicies();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Manage hosts page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageHostsPage.visitsManageHostsPage();
});
it("adds a new host and downloads installation files", () => {
// Download add hosts files
cy.getAttached(".manage-hosts").within(() => {
cy.contains("button", /add hosts/i).click();
});
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/advanced/i)
.first()
.should("exist")
.click();
});
cy.getAttached(".reveal-button").click();
cy.getAttached('a[href*="#downloadEnrollSecret"]').click();
cy.getAttached('a[href*="#downloadCertificate"]').last().click();
cy.getAttached('a[href*="#downloadFlagfile"]').click();
// 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)
if (Cypress.platform !== "win32") {
// windows has issues with downloads location
// Feature pushed back from 4.13 release
// const formattedTime = format(new Date(), "yyyy-MM-dd");
// const filename = `Hosts ${formattedTime}.csv`;
// cy.readFile(path.join(Cypress.config("downloadsFolder"), filename), {
// timeout: 5000,
// });
cy.readFile(
path.join(Cypress.config("downloadsFolder"), "secret.txt"),
{
timeout: 5000,
}
);
cy.readFile(
path.join(Cypress.config("downloadsFolder"), "flagfile.txt"),
{
timeout: 5000,
}
);
cy.readFile(path.join(Cypress.config("downloadsFolder"), "fleet.pem"), {
timeout: 5000,
});
}
});
it(`exports hosts to CSV`, () => {
cy.getAttached(".manage-hosts").within(() => {
cy.getAttached(".manage-hosts__export-btn").click();
});
if (Cypress.platform !== "win32") {
// windows has issues with downloads location
const formattedTime = format(new Date(), "yyyy-MM-dd");
const filename = `Hosts ${formattedTime}.csv`;
cy.readFile(path.join(Cypress.config("downloadsFolder"), filename), {
timeout: 5000,
});
}
});
it(`hides and shows "Used by" column`, () => {
cy.getAttached("thead").within(() =>
cy.findByText(/used by/i).should("not.exist")
);
cy.getAttached(".table-container").within(() => {
cy.contains("button", /edit columns/i).click();
});
cy.getAttached(".edit-columns-modal").within(() => {
cy.findByLabelText(/used by/i).check({ force: true });
cy.contains("button", /save/i).click();
});
cy.getAttached("thead").within(() =>
cy.findByText(/used by/i).should("exist")
);
});
});
describe("Manage policies page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageHostsPage.visitsManageHostsPage();
});
it(
"runs policy on an existing host",
{
retries: {
runMode: 2,
},
defaultCommandTimeout: 10000,
},
() => {
cy.getAttached("tbody").within(() => {
cy.get(".button--text-link").first().as("hostLink");
});
cy.getAttached("@hostLink")
// Set hostname variable for later assertions
.then((el) => {
hostname = el.text();
return el;
})
.click();
// Go to host details page
cy.location("pathname").should("match", /hosts\/[0-9]/i);
cy.getAttached(".status--online").should("exist");
// Run policy on host
cy.contains("a", "Policies").click();
cy.getAttached("tbody").within(() => {
cy.get(".button--text-link").first().as("policyLink");
});
cy.getAttached("@policyLink")
// Set policyname variable for later assertions
.then((el) => {
console.log(el);
return el;
});
cy.findByText(/filevault/i)
.should("exist")
.click();
cy.getAttached(".policy-form__run").should("exist").click();
cy.findByText(/all hosts/i)
.should("exist")
.click()
.then(() => {
cy.findByText(/run/i).click();
});
cy.getAttached(".data-table").within(() => {
cy.findByText(hostname).should("exist");
});
}
);
});
describe("Host details page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageHostsPage.visitsManageHostsPage();
cy.getAttached("tbody").within(() => {
cy.getAttached(".button--text-link").first().click();
});
});
it("renders and searches the host's users", () => {
cy.getAttached(".section--users").within(() => {
cy.getAttached("tbody>tr").should("have.length.greaterThan", 0);
cy.findByPlaceholderText(/search/i).type("Ash");
cy.getAttached("tbody>tr").should("have.length", 0);
cy.getAttached(".empty-table__container").within(() => {
cy.findByText(/no users match/i).should("exist");
});
});
});
it("renders and searches the host's software", () => {
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/software/i).click();
});
let initialCount = 0;
cy.getAttached(".section--software").within(() => {
cy.getAttached(".table-container__results-count")
.invoke("text")
.then((text) => {
const fullText = text;
const pattern = /[0-9]+/g;
const newCount = fullText.match(pattern);
initialCount = parseInt(newCount[0], 10);
expect(initialCount).to.be.at.least(1);
});
cy.findByPlaceholderText(/search software/i).type("lib");
// Ensures search completes
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.getAttached(".table-container__results-count")
.invoke("text")
.then((text) => {
const fullText = text;
const pattern = /[0-9]+/g;
const newCount = fullText.match(pattern);
const searchCount = parseInt(newCount[0], 10);
expect(searchCount).to.be.lessThan(initialCount);
});
});
});
it("host's software table links to filter hosts by software", () => {
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/software/i).click();
});
cy.getAttached(".software-link").first().click({ force: true });
cy.findByText(/adduser 3.118ubuntu2/i).should("exist"); // first seeded software item
cy.getAttached(".data-table").within(() => {
cy.findByText(hostname).should("exist");
});
});
it("host's software table links to software details", () => {
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/software/i).click();
});
cy.contains(/adduser/i).click();
cy.findByText(/adduser, 3.118ubuntu2/i).should("exist");
});
it("renders host's schedule", () => {
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/schedule/i).click();
});
cy.getAttached(".data-table").within(() => {
cy.getAttached(".query_name__header").should("exist");
});
});
it("renders host's policies and links to filter hosts by policy status", () => {
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/policies/i).click();
});
cy.getAttached(".section--policies").within(() => {
cy.findByText(/failing 1 policy/i).should("exist");
cy.getAttached(".policy-link").first().click({ force: true });
});
cy.findAllByText(/Is Filevault enabled on macOS devices/i).should(
"exist"
);
cy.getAttached(".data-table").within(() => {
cy.findByText(hostname).should("exist");
});
});
it(
"refetches host vitals",
{
retries: {
runMode: 2,
},
defaultCommandTimeout: 15000,
},
() => {
cy.getAttached(".display-name-container").within(() => {
cy.contains("button", /refetch/i).click();
cy.findByText(/fetching/i).should("exist");
cy.contains("button", /refetch/i).should("exist");
cy.findByText(/less than a minute/i).should("exist");
});
}
);
});
});

View File

@ -1,89 +0,0 @@
import manageHostsPage from "../../pages/manageHostsPage";
describe("Labels flow", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.addDockerHost();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Manage hosts page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageHostsPage.visitsManageHostsPage();
});
it("creates a custom label", () => {
cy.getAttached(".label-filter-select__control").click();
cy.findByRole("button", { name: /add label/i }).click();
cy.getAttached(".label-form__text-editor-wrapper .ace_content").type(
"{selectall}{backspace}SELECT * FROM users;"
);
cy.findByLabelText(/name/i).click().type("Show all MAC users");
cy.findByLabelText(/description/i)
.click()
.type("Select all MAC users.");
cy.getAttached(".label-form__form-field--platform > .Select").click();
cy.getAttached(".Select-menu-outer").within(() => {
cy.findByText(/macOS/i).click();
});
cy.findByRole("button", { name: /save label/i }).click();
cy.findByText(/label created/i).should("exist");
});
it("edits a custom label", () => {
cy.getAttached(".label-filter-select__control").click();
cy.findByText(/Show all MAC users/i).click();
cy.findByRole("button", { name: /edit label/i }).click();
// SQL and Platform are immutable fields
cy.findByLabelText(/name/i).clear().type("Show all mac usernames");
cy.findByLabelText(/description/i)
.clear()
.type("Select all usernames on Mac.");
cy.findByText(/select one/i).should("not.exist");
cy.findByRole("button", { name: /update label/i }).click();
cy.findByText(/label updated/i).should("exist");
});
it("deletes a custom label", () => {
cy.getAttached(".label-filter-select__control").click();
cy.findByText(/Show all mac usernames/i).click();
cy.findByRole("button", { name: /delete label/i }).click();
cy.getAttached(".delete-label-modal")
.contains("button", /delete/i)
.click();
cy.getAttached(".label-filter-select__control").within(() => {
cy.findByText(/show all mac usernames/i).should("not.exist");
});
});
it("creates labels with special characters", () => {
cy.getAttached(".label-filter-select__control").click();
cy.findByRole("button", { name: /add label/i }).click();
cy.getAttached(".label-form__text-editor-wrapper .ace_content").type(
"{selectall}{backspace}SELECT * FROM users;"
);
cy.findByLabelText(/name/i)
.click()
.type("** Special label (Mac / Users)");
cy.findByLabelText(/description/i)
.click()
.type("Select all MAC users using special characters.");
cy.getAttached(".label-form__form-field--platform > .Select").click();
cy.getAttached(".Select-menu-outer").within(() => {
cy.findByText(/macOS/i).click();
});
cy.findByRole("button", { name: /save label/i }).click();
cy.findByText(/label created/i).should("exist");
});
it("searches labels with special characters", () => {
cy.getAttached(".label-filter-select__control").click();
cy.findByPlaceholderText(/filter labels by name.../i).type(
"{selectall}{backspace}**"
);
cy.findByText(/Special label/i).should("exist");
});
});
});

View File

@ -1,132 +0,0 @@
import CONSTANTS from "../,,/../../../support/constants";
const {
GOOD_PASSWORD,
BAD_PASSWORD_LENGTH,
BAD_PASSWORD_NO_NUMBER,
BAD_PASSWORD_NO_SYMBOL,
} = CONSTANTS;
describe("Manage users flow", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
cy.setupSMTP();
});
after(() => {
cy.logout();
});
describe("User management page", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/settings/users");
});
it("searches for an existing user", () => {
cy.findByText("admin@example.com").should("exist");
cy.findByText("maintainer@example.com").should("exist");
cy.findByText("observer@example.com").should("exist");
cy.findByText("sso_user@example.com").should("exist");
cy.findByPlaceholderText("Search").type("admin");
cy.getAttached("tbody>tr").should("have.length", 1);
cy.findByText("admin@example.com").should("exist");
cy.findByText("maintainer@example.com").should("not.exist");
cy.findByText("observer@example.com").should("not.exist");
cy.findByText("sso_user@example.com").should("not.exist");
});
it("creates a new user", () => {
cy.contains("button:enabled", /create user/i).click();
cy.findByPlaceholderText("Full name").type("New Name");
cy.findByPlaceholderText("Email").type("new-user@example.com");
cy.getAttached(
".create-user-form__form-field--global-role > .Select"
).click();
cy.getAttached(".create-user-form__form-field--global-role").within(
() => {
cy.findByText(/maintainer/i).click();
}
);
cy.findByPlaceholderText("Password").clear().type(BAD_PASSWORD_LENGTH);
cy.getAttached(".modal-cta-wrap")
.contains("button", /create/i)
.click();
cy.findByText(/password must meet the criteria below/i).should("exist");
cy.findByLabelText(/password must meet the criteria below/i)
.clear()
.type(BAD_PASSWORD_NO_NUMBER);
cy.getAttached(".modal-cta-wrap")
.contains("button", /create/i)
.click();
cy.findByText(/password must meet the criteria below/i).should("exist");
cy.findByLabelText(/password must meet the criteria below/i)
.clear()
.type(BAD_PASSWORD_NO_NUMBER);
cy.getAttached(".modal-cta-wrap")
.contains("button", /create/i)
.click();
cy.findByText(/password must meet the criteria below/i).should("exist");
cy.findByLabelText(/password must meet the criteria below/i)
.clear()
.type(GOOD_PASSWORD);
cy.getAttached(".modal-cta-wrap")
.contains("button", /create/i)
.click();
cy.findByText(/new name/i).should("exist");
});
it("edits an existing user", () => {
cy.getAttached("tbody>tr")
.should("have.length", 5)
.eq(1)
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
});
cy.findByPlaceholderText("Full name").clear().type("New Admin");
cy.findByPlaceholderText("Email").clear().type("new-admin@example.com");
cy.getAttached(
".create-user-form__form-field--global-role > .Select"
).click();
cy.getAttached(".create-user-form__form-field--global-role").within(
() => {
cy.findByText(/admin/i).click();
}
);
cy.findByLabelText("Password").clear().type(BAD_PASSWORD_LENGTH);
cy.getAttached(".modal-cta-wrap").contains("button", /save/i).click();
cy.findByText(/password must meet the criteria below/i).should("exist");
cy.findByLabelText(/password must meet the criteria below/i)
.clear()
.type(BAD_PASSWORD_NO_NUMBER);
cy.getAttached(".modal-cta-wrap").contains("button", /save/i).click();
cy.findByText(/password must meet the criteria below/i).should("exist");
cy.findByLabelText(/password must meet the criteria below/i)
.clear()
.type(BAD_PASSWORD_NO_SYMBOL);
cy.getAttached(".modal-cta-wrap").contains("button", /save/i).click();
cy.findByText(/password must meet the criteria below/i).should("exist");
cy.findByLabelText(/password must meet the criteria below/i)
.clear()
.type(GOOD_PASSWORD);
cy.getAttached(".modal-cta-wrap").contains("button", /save/i).click();
cy.findByText(/successfully edited/i).should("exist");
});
it("deletes an existing user", () => {
cy.getAttached("tbody>tr")
.eq(1)
.within(() => {
cy.findByText(/new admin/i).should("exist");
cy.findByText(/action/i).click();
cy.findByText(/delete/i).click();
});
cy.getAttached(".modal-cta-wrap")
.contains("button", /delete/i)
.click();
cy.findByText(/successfully deleted/i).should("exist");
cy.getAttached("tbody>tr").should("have.length", 4);
cy.findByText(/new-user/i).should("not.exist");
});
});
});

View File

@ -1,92 +0,0 @@
/* NOTE: Product decision to remove packs from UI
import managePacksPage from "../../pages/managePacksPage";
describe("Pack flow (empty)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Manage packs page", () => {
beforeEach(() => {
cy.loginWithCySession();
managePacksPage.visitsManagePacksPage();
});
it("creates a new pack", () => {
managePacksPage.allowsCreatePack();
managePacksPage.verifiesCreatedPack();
});
});
});
describe("Pack flow (seeded)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedQueries();
cy.seedPacks();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Pack details page", () => {
beforeEach(() => {
cy.loginWithCySession();
managePacksPage.visitsManagePacksPage();
cy.getAttached(".name__cell > .button--text-link").first().click();
});
it("adds a query to an existing pack", () => {
cy.findByRole("button", { name: /add query/i }).click();
cy.findByText(/select query/i).click();
cy.findByText(/get authorized/i).click();
cy.getAttached(
".pack-query-editor-modal__form-field--frequency > .input-field"
)
.click()
.type("3600");
cy.getAttached(
".pack-query-editor-modal__form-field--osquer-vers > .Select"
).click();
cy.findByText(/4.7/i).click();
cy.getAttached(
".pack-query-editor-modal__form-field--shard > .input-field"
)
.click()
.type("50");
cy.getAttached(".pack-query-editor-modal .modal-cta-wrap")
.contains("button", /add query/i)
.click();
cy.findByText(/get authorized/i).should("exist");
});
it("removes a query from an existing pack", () => {
cy.getAttached(".fleet-checkbox__input").check({ force: true });
cy.findByRole("button", { name: /remove/i }).click();
cy.getAttached(".remove-pack-query-modal .modal-cta-wrap")
.contains("button", /remove/i)
.click();
});
it("edits an existing pack", () => {
managePacksPage.allowsEditPack();
managePacksPage.verifiesEditedPack();
});
});
describe("Manage packs page", () => {
beforeEach(() => {
cy.loginWithCySession();
managePacksPage.visitsManagePacksPage();
});
it("deletes an existing pack", () => {
managePacksPage.allowsDeletePack();
managePacksPage.verifiesDeletedPack();
});
});
});
*/

View File

@ -1,736 +0,0 @@
import CONSTANTS from "../../../support/constants";
import managePoliciesPage from "../../pages/managePoliciesPage";
const {
CONFIG_INTEGRATIONS_AUTOMATIONS,
CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED,
} = CONSTANTS;
const enableJiraPoliciesIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: true,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: false,
destination_url: "",
host_percentage: 0,
days_count: 0,
},
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://www.foo.com/bar",
policy_ids: [5, 10],
host_batch_size: 0,
},
vulnerabilities_webhook: {
destination_url: "https://www.foo.com/bar",
enable_vulnerabilities_webhook: false,
},
},
};
const enableZendeskPoliciesIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: true,
enable_software_vulnerabilities: false,
},
],
},
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: false,
destination_url: "",
host_percentage: 0,
days_count: 0,
},
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://www.foo.com/bar",
policy_ids: [5, 10],
host_batch_size: 0,
},
vulnerabilities_webhook: {
destination_url: "https://www.foo.com/bar",
enable_vulnerabilities_webhook: false,
},
},
};
describe("Policies flow (empty)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Manage policies page", () => {
beforeEach(() => {
cy.loginWithCySession();
managePoliciesPage.visitManagePoliciesPage();
});
it("creates a custom policy", () => {
cy.getAttached(".empty-table__cta-buttons").within(() => {
cy.findByText(/add a policy/i).click();
});
cy.findByText(/create your own policy/i).click();
cy.getAttached(".policy-page__form .ace_scroller")
.click({ force: true })
.type(
"{selectall}SELECT 1 FROM users WHERE username = 'backup' LIMIT 1;"
);
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached(".policy-form__policy-save-modal-name")
.click()
.type("Does the device have a user named 'backup'?");
cy.getAttached(".policy-form__policy-save-modal-description")
.click()
.type("Returns yes or no for having a user named 'backup'");
cy.getAttached(".policy-form__policy-save-modal-resolution")
.click()
.type("Create a user named 'backup'");
cy.findByRole("button", { name: /save policy/i }).click();
cy.findByText(/policy created/i).should("exist");
});
it("creates a default policy", () => {
managePoliciesPage.allowsAddDefaultPolicy();
managePoliciesPage.verifiesAddedDefaultPolicy();
});
});
describe("Platform compatibility", () => {
beforeEach(() => {
cy.loginWithCySession();
managePoliciesPage.visitManagePoliciesPage();
});
const platforms = ["macOS", "Windows", "Linux"];
const testCompatibility = (
el: JQuery<HTMLElement>,
i: number,
expected: boolean[]
) => {
const check = expected[i]
? "compatible-platform"
: "incompatible-platform";
const compatibility = expected[i] ? "compatible" : "incompatible";
assert(
el.children("div").attr("class").includes(check),
`expected policy to be ${platforms[i]} ${compatibility}`
);
};
const testSelections = (
el: JQuery<HTMLElement>,
i: number,
expected: boolean[]
) => {
assert(
el.prop("checked") === expected[i],
`expected ${platforms[i]} to be ${
expected[i] ? "selected " : "not selected"
}`
);
};
it("checks sql statement for platform compatibility", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByText(/add a policy/i).click();
});
cy.getAttached(".add-policy-modal").within(() => {
cy.findByRole("button", { name: /create your own policy/i }).click();
});
cy.getAttached(".platform").each((el, i) => {
testCompatibility(el, i, [true, true, true]);
});
// Query with unknown table name displays error message
cy.getAttached(".policy-page__form .ace_scroller")
.first()
.click({ force: true })
.type("{selectall}SELECT 1 FROM foo WHERE start_time > 1;");
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(700); // wait for text input debounce
cy.getAttached(".platform-compatibility").within(() => {
cy.findByText(
"No platforms (check your query for invalid tables or tables that are supported on different platforms)"
).should("exist");
});
// Query with syntax error displays error message
cy.getAttached(".policy-page__form .ace_scroller")
.first()
.click({ force: true })
.type("{selectall}SELEC 1 FRO osquery_info WHER start_time > 1;");
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(700); // wait for text input debounce
cy.getAttached(".platform-compatibility").within(() => {
cy.findByText(
"No platforms (check your query for a possible syntax error)"
).should("exist");
});
// Query with no tables treated as compatible with all platforms
cy.getAttached(".policy-page__form .ace_scroller")
.first()
.click({ force: true })
.type("{selectall}SELECT * WHERE 1 = 1;");
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(700); // wait for text input debounce
cy.getAttached(".platform").each((el, i) => {
testCompatibility(el, i, [true, true, true]);
});
// Tables defined in common table expression not factored into compatibility check
cy.getAttached(".policy-page__form .ace_scroller")
.first()
.click({ force: true })
.type("{selectall} ")
.type(
`WITH target_jars AS ( SELECT DISTINCT path FROM ( WITH split(word, str) AS( SELECT '', cmdline || ' ' FROM processes UNION ALL SELECT substr(str, 0, instr(str, ' ')), substr(str, instr(str, ' ') + 1) FROM split WHERE str != '') SELECT word AS path FROM split WHERE word LIKE '%.jar' UNION ALL SELECT path FROM process_open_files WHERE path LIKE '%.jar' ) ) SELECT path, matches FROM yara WHERE path IN (SELECT path FROM target_jars) AND count > 0 AND sigrule IN ( 'rule log4jJndiLookup { strings: $jndilookup = "JndiLookup" condition: $jndilookup }', 'rule log4jJavaClass { strings: $javaclass = "org/apache/logging/log4j" condition: $javaclass }' );`,
{ parseSpecialCharSequences: false }
);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000); // wait for text input debounce
cy.getAttached(".platform").each((el, i) => {
testCompatibility(el, i, [true, false, true]);
});
// Query with only macOS tables treated as compatible only with macOS
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.getAttached(" .policy-page__form .ace_scroller")
.first()
.click({ force: true })
.type("{selectall} ")
.wait(300) // wait for ace to clear text before proceeding
.type(
"{selectall}SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;"
);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(700); // wait for text input debounce
cy.getAttached(".platform").each((el, i) => {
testCompatibility(el, i, [true, false, false]);
});
// Query with macadmins extension table is not treated as incompatible
cy.getAttached(".policy-page__form .ace_scroller")
.first()
.click({ force: true })
.type("{selectall}SELECT 1 FROM mdm WHERE enrolled='true';");
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(700); // wait for text input debounce
cy.getAttached(".platform").each((el, i) => {
testCompatibility(el, i, [true, false, false]);
});
});
it("preselects platforms to check based on platform compatiblity when saving new policy", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByText(/add a policy/i).click();
});
cy.getAttached(".add-policy-modal").within(() => {
cy.findByText("Automatic login disabled (macOS)").click();
});
cy.getAttached(".platform-compatibility").within(() => {
cy.getAttached(".platform").each((el, i) => {
testCompatibility(el, i, [true, false, false]);
});
});
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached(".modal__content").within(() => {
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [true, false, false]);
});
});
});
});
it("disables modal save button if no platforms are selected", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByText(/add a policy/i).click();
});
cy.getAttached(".add-policy-modal").within(() => {
cy.findByText("Automatic login disabled (macOS)").click();
});
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached(".modal__content").within(() => {
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [true, false, false]);
});
cy.getAttached(".fleet-checkbox__label").first().click(); // deselect macOS
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [false, false, false]);
});
});
cy.getAttached(".modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /save policy/i }).should(
"be.disabled"
);
});
});
});
it("allows user to overide preselected platforms when saving new policy", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByText(/add a policy/i).click();
});
cy.getAttached(".add-policy-modal").within(() => {
cy.findByText("Automatic login disabled (macOS)").click();
});
cy.getAttached(".platform-compatibility").within(() => {
cy.getAttached(".platform").each((el, i) => {
testCompatibility(el, i, [true, false, false]);
});
});
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached(".modal__content").within(() => {
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [true, false, false]);
});
cy.getAttached(".fleet-checkbox__label").first().click(); // deselect macOS
cy.getAttached(".fleet-checkbox__label").last().click(); // select Linux
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [false, false, true]);
});
});
});
cy.findByRole("button", { name: /save policy/i }).click();
cy.findByText(/policy created/i).should("exist");
// confirm that new policy was saved with user-selected platforms
managePoliciesPage.visitManagePoliciesPage();
cy.getAttached("tbody").within(() => {
cy.getAttached(".name__cell .button--text-link")
.contains("Automatic login disabled (macOS)")
.click();
});
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [false, false, true]);
});
});
});
it("allows user to edit existing policy platform selections", () => {
// add a default policy for this test
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByText(/add a policy/i).click();
});
cy.getAttached(".add-policy-modal").within(() => {
cy.findByText("Antivirus healthy (macOS)").click();
});
cy.findByRole("button", { name: /save/i }).click();
cy.findByRole("button", { name: /save policy/i }).click();
cy.findByText(/policy created/i).should("exist");
// edit platform selections for policy
managePoliciesPage.visitManagePoliciesPage();
cy.getAttached("tbody").within(() => {
cy.getAttached(".name__cell .button--text-link")
.contains("Antivirus healthy (macOS)")
.click();
});
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [true, false, false]);
});
cy.getAttached(".fleet-checkbox__label").first().click(); // deselect macOS
});
// confirm save/run buttons are disabled when no platforms are selected
cy.findByRole("button", { name: /^Save$/ }).should("be.disabled");
cy.findByRole("button", { name: /^Run$/ }).should("be.disabled");
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__label").last().click(); // select Linux
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [false, false, true]);
});
});
// save policy with new selection
cy.findByRole("button", { name: /^Save$/ }).click();
cy.findByText(/policy updated/i).should("exist");
// confirm that policy was saved with new selection
managePoliciesPage.visitManagePoliciesPage();
cy.getAttached("tbody").within(() => {
cy.getAttached(".name__cell .button--text-link")
.contains("Antivirus healthy (macOS)")
.click();
});
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [false, false, true]);
});
});
});
});
});
describe("Policies flow (seeded)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPolicies();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Manage policies page", () => {
beforeEach(() => {
cy.loginWithCySession();
managePoliciesPage.visitManagePoliciesPage();
});
it("links to manage host page filtered by policy", () => {
// Move internal clock forward 2 hours so that policies report host results
cy.clock(Date.now() + 1000 * 60 * 120);
cy.getAttached(".failing_host_count__cell")
.first()
.within(() => {
cy.getAttached(".button--text-link").click();
});
// confirm policy functionality on manage host page
cy.getAttached(".manage-hosts__labels-active-filter-wrap").within(() => {
cy.findByText(/filevault enabled/i).should("exist");
cy.findByText(/no/i).should("exist").click();
cy.findByText(/yes/i).should("exist");
cy.get('img[alt="Remove filter"]').click();
cy.findByText(/filevault enabled'/i).should("not.exist");
});
});
it("edits an existing policy", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached(".name__cell .button--text-link").first().click();
});
cy.getAttached(".policy-page__form .ace_scroller")
.click({ force: true })
.type(
"{selectall}SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;"
);
cy.getAttached(".fleet-checkbox__label").first().click();
cy.findByRole("button", { name: /save/i }).click();
cy.findByText(/policy updated/i).should("exist");
cy.visit("policies/1");
cy.getAttached(".fleet-checkbox__input").first().should("not.be.checked");
});
it("deletes an existing policy", () => {
managePoliciesPage.allowsDeletePolicy();
managePoliciesPage.verifiesDeletedPolicy();
});
it("creates a failing policies webhook", () => {
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", { name: /manage automations/i }).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
// Ensure clicking on slider after modal animation
cy.wait(300); // eslint-disable-line cypress/no-unnecessary-waiting
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
});
cy.getAttached("#webhook-url").click().type("http://www.foo.com/bar");
cy.findByRole("button", { name: /^Save$/ }).click();
// Ensure update
cy.wait(1000); // eslint-disable-line cypress/no-unnecessary-waiting
// Confirm failing policies webhook was added successfully
cy.findByText(/updated policy automations/i).should("exist");
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", { name: /manage automations/i }).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-checkbox__input").should("be.checked");
});
// reset slider for subsequent tests
cy.getAttached(".manage-automations-modal").within(() => {
// Ensure clicking on slider after modal animation
cy.wait(300); // eslint-disable-line cypress/no-unnecessary-waiting
cy.getAttached(".fleet-slider").click();
});
cy.findByRole("button", { name: /^Save$/ }).click();
// Confirm failing policies webhook was updated successfully
cy.findByText(/updated policy automations/i).should("exist");
});
it("empty automation state prompts to create an integration", () => {
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", { name: /manage automations/i }).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
});
cy.getAttached("#ticket-radio-btn").next().click();
cy.findByText(/you have no integrations/i).should("exist");
cy.getAttached(".manage-automations-modal__add-integration-link").click();
// should be redirected to integrations settings page
cy.getAttached(".table-container").within(() => {
cy.findByText(/set up integration/i).should("exist");
});
});
});
describe("Manage policies page (mock integrations)", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.viewport(1600, 900);
cy.intercept(
"GET",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS
).as("getIntegrations");
managePoliciesPage.visitManagePoliciesPage();
cy.wait("@getIntegrations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
});
it("creates jira integration failing policies automation", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-slider").click();
cy.getAttached("#ticket-radio-btn").next().click();
cy.findByText(/project 1/i).click();
cy.findByText(/project 2/i).click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
enableJiraPoliciesIntegration
).as("enableJiraPoliciesIntegration");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableJiraPoliciesIntegration
).as("enabledJiraPoliciesIntegration");
cy.findByRole("button", { name: /^Save$/ }).click();
cy.wait("@enableJiraPoliciesIntegration").then((configStub) => {
console.log(JSON.stringify(configStub));
});
// Confirm jira integration was added successfully
cy.findByText(/updated policy automations/i).should("exist");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableJiraPoliciesIntegration
).as("getIntegrations");
managePoliciesPage.visitManagePoliciesPage();
cy.wait("@getIntegrations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider--active").should("exist");
cy.findByText(/project 2/i).should("exist");
});
});
it("creates zendesk integration failing policies automation", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-slider").click();
cy.getAttached("#ticket-radio-btn").next().click();
cy.findByText(/project 1/i).click();
cy.findByText(/87654321/i).click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
enableZendeskPoliciesIntegration
).as("enableZendeskPoliciesIntegration");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableZendeskPoliciesIntegration
).as("enabledZendeskPoliciesIntegration");
cy.findByRole("button", { name: /^Save$/ }).click();
cy.wait("@enableZendeskPoliciesIntegration").then((configStub) => {
console.log(JSON.stringify(configStub));
});
// Confirm zendesk integration was added successfully
cy.findByText(/updated policy automations/i).should("exist");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableZendeskPoliciesIntegration
).as("getIntegrations");
managePoliciesPage.visitManagePoliciesPage();
cy.wait("@getIntegrations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider--active").should("exist");
cy.findByText(/87654321/i).should("exist");
});
});
it("disables failing policies automation", () => {
cy.getAttached(".manage-policies-page__header-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED
).as("disablePoliciesAutomations");
cy.intercept(
"GET",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED
).as("disabledAutomations");
cy.findByRole("button", { name: /^Save$/ }).click();
cy.wait("@disablePoliciesAutomations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
cy.wait("@disabledAutomations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
// Confirm integration was disabled successfully
cy.findByText(/updated policy automations/i).should("exist");
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.findByText(/policy automations disabled/i).should("exist");
});
});
});
describe("Platform compatibility", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/policies/manage");
});
const platforms = ["macOS", "Windows", "Linux"];
const testSelections = (
el: JQuery<HTMLElement>,
i: number,
expected: boolean[]
) => {
assert(
el.prop("checked") === expected[i],
`expected ${platforms[i]} to be ${
expected[i] ? "selected " : "not selected"
}`
);
};
it('preselects all platforms if API response contains `platform: ""`', () => {
cy.getAttached("tbody").within(() => {
cy.getAttached(".name__cell .button--text-link")
.contains("Is Ubuntu, version 16.4.0 or later, installed?")
.click();
});
cy.getAttached(".platform-selector").within(() => {
cy.getAttached(".fleet-checkbox__input").each((el, i) => {
testSelections(el, i, [true, true, true]);
});
});
});
});
});

View File

@ -1,98 +0,0 @@
import manageQueriesPage from "../../pages/manageQueriesPage";
import manageSchedulePage from "../../pages/manageSchedulePage";
describe("Query flow (empty)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Manage queries page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageQueriesPage.visitManageQueriesPage();
});
it("creates a new query", () => {
manageQueriesPage.allowsCreateNewQuery();
manageQueriesPage.verifiesCreatedNewQuery();
});
});
});
describe("Query flow (seeded)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedQueries();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Manage queries page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageQueriesPage.visitManageQueriesPage();
});
it("runs a live query and allows exporting results", () => {
cy.addDockerHost();
manageQueriesPage.allowsRunQuery();
manageQueriesPage.verifiesRanQuery();
manageQueriesPage.allowsViewRanQuery();
manageQueriesPage.allowsExportQueryResults();
cy.stopDockerHost();
});
it("edits an existing query", () => {
manageQueriesPage.allowsEditExistingQuery();
manageQueriesPage.verifiesEditedExistingQuery();
});
it("saves an existing query as new query", () => {
manageQueriesPage.allowsSaveAsNewQuery();
manageQueriesPage.verifiesSavedAsNewQuery();
});
it("deletes an existing query", () => {
manageQueriesPage.allowsDeleteExistingQuery();
manageQueriesPage.verifiesDeletedExistingQuery();
});
});
describe("Manage schedules page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageSchedulePage.visitManageSchedulePage();
});
it("creates a new scheduled query", () => {
manageSchedulePage.allowsAddSchedule();
manageSchedulePage.verifiesAddedSchedule();
});
it("shows sql of a scheduled query successfully", () => {
cy.getAttached("tbody>tr")
.should("have.length", 1)
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/show query/i).click();
});
cy.getAttached(".show-query-modal").within(() => {
cy.getAttached(".ace_content").within(() => {
cy.contains(/select/i).should("exist");
cy.contains(/cypress/i).should("exist");
});
});
});
it("edit a scheduled query successfully", () => {
manageSchedulePage.allowsEditSchedule();
manageSchedulePage.verifiesEditedSchedule();
});
it("remove a scheduled query successfully", () => {
manageSchedulePage.allowsRemoveSchedule();
manageSchedulePage.verifiesRemovedSchedule();
});
});
});

View File

@ -1,58 +0,0 @@
describe("Reset sessions", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.setupSMTP();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("User settings page", () => {
beforeEach(() => {
cy.loginWithCySession();
});
it("resets a user's session generating a new api token", () => {
cy.visit("/profile");
cy.getAttached(".user-side-panel").within(() => {
cy.findByRole("button", { name: /get api token/i }).click();
});
cy.getAttached(".secret-field__secret-input").within(() => {
cy.getAttached(".secret-field__show-secret").click();
cy.getAttached("input").invoke("val").as("token1");
});
cy.visit("/settings/users");
cy.getAttached("div.Select-placeholder").eq(0).click();
cy.contains(/reset sessions/i).click();
cy.get(".modal__modal_container").within(() => {
cy.findByText(/reset sessions/i).should("exist");
cy.findByRole("button", { name: /confirm/i }).click();
});
cy.findByText(/reset sessions/i).should("not.exist");
// user should be logged out so log in for new API token
cy.getAttached(".login-form__container").within(() => {
cy.findByRole("button", { name: /login/i }).should("exist");
});
cy.login();
cy.visit("/profile");
cy.getAttached(".user-side-panel").within(() => {
cy.findByRole("button", { name: /get api token/i }).click();
});
cy.getAttached(".modal__content").within(() => {
cy.getAttached(".secret-field__show-secret").click();
});
cy.getAttached(".secret-field__secret-input").within(() => {
cy.get("input").invoke("val").as("token2");
});
// new token should not equal old token
cy.get("@token1").then((val1) => {
cy.get("@token2").then((val2) => {
expect(val1).to.not.eq(val2);
});
});
});
});
});

View File

@ -1,540 +0,0 @@
import CONSTANTS from "../../../support/constants";
const { CONFIG_INTEGRATIONS_AUTOMATIONS } = CONSTANTS;
const addJiraIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira@example.com",
api_token: "jira123",
project_key: "PROJECT",
enable_software_vulnerabilities: false,
},
],
},
};
const deleteJiraIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
};
const addZendeskIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
};
const deleteZendeskIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
};
describe("App settings flow", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Organization settings page", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/settings/organization");
});
it("edits organization info", () => {
cy.getAttached(".app-config-form").within(() => {
cy.findByLabelText(/organization name/i)
.clear()
.type("TJ's Run");
cy.findByLabelText(/organization avatar url/i)
.click()
.type("http://tjsrun.com/img/logo.png");
});
cy.findByRole("button", { name: /save/i })
.invoke("attr", "disabled", false)
.click();
cy.findByText(/updated settings/i).should("exist");
// confirm edits
cy.visit("/settings/organization");
cy.getAttached(".app-config-form").within(() => {
cy.findByLabelText(/organization name/i).should(
"have.value",
"TJ's Run"
);
});
cy.findByLabelText(/organization avatar url/i).should(
"have.value",
"http://tjsrun.com/img/logo.png"
);
});
it("edits fleet web address", () => {
cy.findByText(/fleet web address/i).click();
cy.findByLabelText(/fleet app url/i)
.clear()
.type("https://localhost:5000");
cy.findByRole("button", { name: /save/i })
.invoke("attr", "disabled", false)
.click();
cy.findByText(/updated settings/i).should("exist");
// confirm edits
cy.visit("/settings/organization");
cy.findByText(/fleet web address/i).click();
cy.findByLabelText(/fleet app url/i).should(
"have.value",
"https://localhost:5000"
);
});
it("edits single sign-on settings", () => {
cy.findByText(/single sign-on options/i).click();
cy.findByLabelText(/enable single sign-on/i).check({ force: true });
cy.findByLabelText(/identity provider name/i)
.click({ force: true })
.type("Rachel");
cy.findByLabelText(/entity id/i)
.click({ force: true })
.type("my entity id");
cy.findByLabelText(/idp image url/i)
.click()
.type("https://http.cat/100");
// specifically targeting this one to avoid conflict
// with cypress seeing multiple "metadata url" - one
// in a tooltip, the other as the actual label
cy.getAttached("[for='metadataUrl']")
.click()
.type("http://github.com/fleetdm/fleet");
cy.findByLabelText(/allow sso login initiated/i).check({ force: true });
cy.findByRole("button", { name: /save/i })
.invoke("attr", "disabled", false)
.click();
cy.findByText(/updated settings/i).should("exist");
// confirm edits
cy.visit("/settings/organization");
cy.findByText(/single sign-on options/i).click();
cy.findByLabelText(/identity provider name/i).should(
"have.value",
"Rachel"
);
cy.findByLabelText(/entity id/i).should("have.value", "my entity id");
cy.findByLabelText(/idp image url/i).should(
"have.value",
"https://http.cat/100"
);
cy.getAttached("#metadataUrl").should(
"have.value",
"http://github.com/fleetdm/fleet"
);
});
it("edits smtp settings", () => {
cy.findByText(/smtp options/i).click();
cy.findByLabelText(/enable smtp/i).check({ force: true });
cy.findByLabelText(/sender address/i)
.click({ force: true })
.type("rachel@example.com");
// specifically targeting this one to avoid conflict
// with cypress seeing multiple "metadata" - one
// in a tooltip, the other as the actual label
cy.findByLabelText(/SMTP server/)
.click({ force: true })
.type("localhost");
cy.getAttached("#smtpPort").clear().type("1025");
cy.findByLabelText(/use ssl\/tls/i).check({ force: true });
cy.findByLabelText(/smtp username/i)
.click()
.type("rachelsusername");
cy.findByLabelText(/smtp password/i)
.click()
.type("rachelspassword");
cy.findByRole("button", { name: /save/i })
.invoke("attr", "disabled", false)
.click();
cy.findByText(/updated settings/i).should("exist");
// confirm edits
cy.visit("/settings/organization");
cy.findByText(/smtp options/i).click();
cy.findByLabelText(/sender address/i).should(
"have.value",
"rachel@example.com"
);
cy.getAttached("#smtpServer").should("have.value", "localhost");
cy.getAttached("#smtpPort").should("have.value", "1025");
cy.findByLabelText(/smtp username/i).should(
"have.value",
"rachelsusername"
);
cy.findByText(/single sign-on options/i).click();
cy.getAttached("#metadataUrl").should(
"have.value",
"http://github.com/fleetdm/fleet"
);
});
it("edits host status webhook", () => {
cy.findByText(/host status webhook/i).click();
cy.findByLabelText(/enable host status webhook/i).check({
force: true,
});
cy.findByLabelText(/destination url/i)
.click()
.type("http://server.com/example");
cy.getAttached(
".app-config-form__host-percentage .Select-control"
).click();
cy.getAttached(".Select-menu-outer").contains(/5%/i).click();
cy.getAttached(".app-config-form__days-count .Select-control").click();
cy.getAttached(".Select-menu-outer")
.contains(/7 days/i)
.click();
cy.findByRole("button", { name: /save/i })
.invoke("attr", "disabled", false)
.click();
cy.findByText(/updated settings/i).should("exist");
// confirm edits
cy.visit("/settings/organization");
cy.findByText(/host status webhook/i).click();
cy.findByLabelText(/destination url/i).should(
"have.value",
"http://server.com/example"
);
cy.findByText(/5%/i).should("exist");
cy.findByText(/7 days/i).should("exist");
cy.findByText(/1 day/i).should("not.exist");
cy.findByText(/select one/i).should("not.exist");
});
it("edits usage statistics", () => {
cy.findByText(/usage statistics/i).click();
cy.findByLabelText(/enable usage statistics/i).check({
force: true,
});
cy.findByRole("button", { name: /save/i })
.invoke("attr", "disabled", false)
.click();
cy.findByText(/updated settings/i).should("exist");
// confirm edits
cy.visit("/settings/organization");
cy.findByText(/usage statistics/i).click();
cy.findByLabelText(/enable usage statistics/i).should("be.checked");
});
it("edits advanced options", () => {
cy.findByText(/advanced options/i).click();
cy.findByLabelText(/domain/i)
.click()
.type("http://www.fleetdm.com");
cy.findByLabelText(/verify ssl certs/i).check({ force: true });
cy.findByLabelText(/enable starttls/i).check({ force: true });
cy.getAttached("[for='enableHostExpiry']").within(() => {
cy.getAttached("[type='checkbox']").check({ force: true });
});
// specifically targeting this one to avoid conflict
// with cypress seeing multiple "host expiry" - one
// in the checkbox above, the other as this label
cy.getAttached("[name='hostExpiryWindow']").clear().type("5");
cy.findByLabelText(/disable live queries/i).check({ force: true });
cy.findByRole("button", { name: /save/i })
.invoke("attr", "disabled", false)
.click();
cy.findByText(/updated settings/i).should("exist");
// confirm edits
cy.visit("/settings/organization");
cy.findByText(/advanced options/i).click();
cy.findByLabelText(/verify ssl certs/i).should("be.checked");
cy.findByLabelText(/enable starttls/i).should("be.checked");
cy.findByLabelText(/host expiry window/i).should("have.value", "5");
// confirm smtp configured
cy.getEmails().then((response) => {
expect(response.body.items[0].To[0]).to.have.property("Domain");
expect(response.body.items[0].To[0].Mailbox).to.equal("admin");
expect(response.body.items[0].To[0].Domain).to.equal("example.com");
expect(response.body.items[0].From.Mailbox).to.equal("rachel");
expect(response.body.items[0].From.Domain).to.equal("example.com");
expect(response.body.items[0].Content.Headers.Subject[0]).to.equal(
"Hello from Fleet"
);
});
});
});
describe("Integrations settings page (empty)", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/settings/integrations");
});
it("adds a new jira integration", () => {
cy.getAttached(".no-integrations__add-button").click();
cy.getAttached("#url").click().type("https://fleetdm.atlassian.com");
cy.getAttached("#username").click().type("jira@example.com");
cy.getAttached("#apiToken").click().type("jira123");
cy.getAttached("#projectKey").click().type("PROJECT");
cy.intercept("PATCH", "/api/latest/fleet/config", addJiraIntegration).as(
"addIntegration"
);
cy.intercept("GET", "/api/latest/fleet/config", addJiraIntegration).as(
"addedIntegration"
);
cy.findByRole("button", { name: /save/i }).click();
cy.wait("@addIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.wait("@addedIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.findByText(/successfully added/i).should("exist");
cy.getAttached(".table-container").within(() => {
cy.findByText(/fleetdm.atlassian.com - PROJECT/i).should("exist");
});
});
it("adds a new zendesk integration", () => {
cy.getAttached(".no-integrations__add-button").click();
cy.getAttached(".add-integration-modal__form-field--platform").within(
() => {
cy.findByText(/jira/i).click();
cy.findByText(/zendesk/i).click();
}
);
cy.getAttached("#url").click().type("https://fleetdm.zendesk.com");
cy.getAttached("#email").click().type("zendesk1@example.com");
cy.getAttached("#apiToken").click().type("zendesk123");
cy.getAttached("#groupId").click().type("12345678");
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
addZendeskIntegration
).as("addIntegration");
cy.intercept("GET", "/api/latest/fleet/config", addZendeskIntegration).as(
"addedIntegration"
);
cy.findByRole("button", { name: /save/i }).click();
cy.wait("@addIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.wait("@addedIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.findByText(/successfully added/i).should("exist");
cy.getAttached(".table-container").within(() => {
cy.findByText(/fleetdm.zendesk.com - 12345678/i).should("exist");
});
});
});
describe("Integrations settings page (seeded)", () => {
beforeEach(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
cy.intercept(
"GET",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS
).as("getIntegrations");
cy.visit("/settings/integrations");
cy.wait("@getIntegrations").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
});
it("deletes jira integration", () => {
cy.getAttached("tbody>tr")
.eq(1)
.within(() => {
cy.findByText(/project 2/i).should("exist");
cy.findByText(/action/i).click();
cy.findByText(/delete/i).click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
deleteJiraIntegration
).as("deleteIntegration");
cy.intercept("GET", "/api/latest/fleet/config", deleteJiraIntegration).as(
"deletedIntegration"
);
cy.getAttached(".delete-integration-modal .modal-cta-wrap")
.contains("button", /delete/i)
.click();
cy.wait("@deleteIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.wait("@deletedIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.findByText(/successfully deleted/i).should("exist");
cy.getAttached("tbody>tr").should("have.length", 3);
cy.findByText(/project 2/i).should("not.exist");
});
it("deletes zendesk integration", () => {
cy.getAttached("tbody>tr")
.eq(3)
.within(() => {
cy.findByText(/87654321/i).should("exist");
cy.findByText(/action/i).click();
cy.findByText(/delete/i).click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
deleteZendeskIntegration
).as("deleteIntegration");
cy.intercept(
"GET",
"/api/latest/fleet/config",
deleteZendeskIntegration
).as("deletedIntegration");
cy.getAttached(".delete-integration-modal .modal-cta-wrap")
.contains("button", /delete/i)
.click();
cy.wait("@deleteIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.wait("@deletedIntegration").then((configStub) => {
cy.log(JSON.stringify(configStub));
console.log(JSON.stringify(configStub));
});
cy.findByText(/successfully deleted/i).should("exist");
cy.getAttached("tbody>tr").should("have.length", 3);
cy.findByText(/87654321/i).should("not.exist");
});
});
});

View File

@ -1,422 +0,0 @@
import CONSTANTS from "../../../support/constants";
import manageSoftwarePage from "../../pages/manageSoftwarePage";
const {
CONFIG_INTEGRATIONS_AUTOMATIONS,
CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED,
} = CONSTANTS;
const enableWebhook = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: false,
destination_url: "",
host_percentage: 0,
days_count: 0,
},
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://www.foo.com/bar",
policy_ids: [5, 10],
host_batch_size: 0,
},
vulnerabilities_webhook: {
destination_url: "http://www.foo.com/bar",
enable_vulnerabilities_webhook: true,
},
},
};
const enableJiraSoftwareIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: false,
enable_software_vulnerabilities: true,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: false,
destination_url: "",
host_percentage: 0,
days_count: 0,
},
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://www.foo.com/bar",
policy_ids: [5, 10],
host_batch_size: 0,
},
vulnerabilities_webhook: {
destination_url: "http://www.foo.com/bar",
enable_vulnerabilities_webhook: false,
},
},
};
const enableZendeskSoftwareIntegration = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: false,
enable_software_vulnerabilities: true,
},
],
},
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: false,
destination_url: "",
host_percentage: 0,
days_count: 0,
},
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://www.foo.com/bar",
policy_ids: [5, 10],
host_batch_size: 0,
},
vulnerabilities_webhook: {
destination_url: "http://www.foo.com/bar",
enable_vulnerabilities_webhook: false,
},
},
};
describe("Software", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setupWithSoftware();
cy.loginWithCySession();
cy.viewport(1600, 900);
});
after(() => {
cy.logout();
});
// describe("Manage software page", () => {
// beforeEach(() => {
// cy.loginWithCySession();
// cy.viewport(1600, 900);
// manageSoftwarePage.visitManageSoftwarePage();
// });
// it("renders and searches the host's software, links to filter hosts by software", () => {
// // cy.getAttached(".manage-software-page__count").within(() => {
// // cy.findByText(/902 software items/i).should("exist");
// // });
// cy.findByPlaceholderText(/search software/i).type("lib");
// // Ensures search completes
// cy.wait(3000); // eslint-disable-line cypress/no-unnecessary-waiting
// cy.getAttached(".table-container__results-count")
// .invoke("text")
// .then((text) => {
// const fullText = text;
// const pattern = /[0-9]+/g;
// const newCount = fullText.match(pattern);
// const searchCount = parseInt(newCount[0], 10);
// expect(searchCount).to.be.equal(444);
// });
// cy.getAttached(".software-link").first().click({ force: true });
// cy.getAttached(".manage-hosts__software-filter-block").within(() => {
// cy.getAttached(".manage-hosts__software-filter-name-card").should(
// "exist"
// );
// });
// cy.getAttached(".table-container__results-count")
// .invoke("text")
// .then((text) => {
// const fullText = text;
// const pattern = /[0-9]+/g;
// const newCount = fullText.match(pattern);
// const searchCount = parseInt(newCount[0], 10);
// expect(searchCount).to.be.equal(2);
// });
// });
// });
describe("Manage software page (mock integrations)", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.viewport(1600, 900);
cy.intercept(
"GET",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS
).as("getIntegrations");
manageSoftwarePage.visitManageSoftwarePage();
cy.wait("@getIntegrations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
});
it("creates webhook software vulnerability automation", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByRole("button", { name: /manage automations/i }).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-slider").click();
cy.getAttached("#webhook-radio-btn").next().click();
});
cy.getAttached("#webhook-url").click().type("http://www.foo.com/bar");
cy.intercept("PATCH", "/api/latest/fleet/config", enableWebhook).as(
"createWebhook"
);
cy.intercept("GET", "/api/latest/fleet/config", enableWebhook).as(
"createdWebhook"
);
cy.findByRole("button", { name: /^Save$/ }).click();
cy.wait("@createWebhook").then((configStub) => {
console.log(JSON.stringify(configStub));
});
cy.wait("@createdWebhook").then((configStub) => {
console.log(JSON.stringify(configStub));
});
// Confirm manage automations webhook was added successfully
cy.findByText(/updated vulnerability automations/i).should("exist");
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider--active").should("exist");
cy.getAttached("#webhook-url").should("exist");
});
});
it("creates jira integration software vulnerability automation", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-slider").click();
cy.getAttached("#ticket-radio-btn").next().click();
cy.findByText(/project 1/i).click();
cy.findByText(/project 2/i).click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
enableJiraSoftwareIntegration
).as("enableJiraSoftwareIntegration");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableJiraSoftwareIntegration
).as("enabledJiraSoftwareIntegration");
cy.findByRole("button", { name: /^Save$/ }).click();
cy.wait("@enableJiraSoftwareIntegration").then((configStub) => {
console.log(JSON.stringify(configStub));
});
// Confirm jira integration was added successfully
cy.findByText(/updated vulnerability automations/i).should("exist");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableJiraSoftwareIntegration
).as("getIntegrations");
manageSoftwarePage.visitManageSoftwarePage();
cy.wait("@getIntegrations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider--active").should("exist");
cy.findByText(/project 2/i).should("exist");
});
});
it("creates zendesk integration software vulnerability automation", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-slider").click();
cy.getAttached("#ticket-radio-btn").next().click();
cy.findByText(/project 1/i).click();
cy.findByText(/87654321/i).click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
enableZendeskSoftwareIntegration
).as("enableZendeskSoftwareIntegration");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableZendeskSoftwareIntegration
).as("enabledZendeskIntegration");
cy.findByRole("button", { name: /^Save$/ }).click();
cy.wait("@enableZendeskSoftwareIntegration").then((configStub) => {
console.log(JSON.stringify(configStub));
});
// Confirm zendesk integration was added successfully
cy.findByText(/updated vulnerability automations/i).should("exist");
cy.intercept(
"GET",
"/api/latest/fleet/config",
enableZendeskSoftwareIntegration
).as("getIntegrations");
manageSoftwarePage.visitManageSoftwarePage();
cy.wait("@getIntegrations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider--active").should("exist");
cy.findByText(/87654321/i).should("exist");
});
});
it("disables software vulnerability automation", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
});
cy.intercept(
"PATCH",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED
).as("disableSoftwareAutomations");
cy.intercept(
"GET",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED
).as("disabledAutomations");
cy.findByRole("button", { name: /^Save$/ }).click();
cy.wait("@disableSoftwareAutomations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
cy.wait("@disabledAutomations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
// Confirm integration was disabled successfully
cy.findByText(/updated vulnerability automations/i).should("exist");
cy.getAttached(".button-wrap").within(() => {
cy.findByRole("button", {
name: /manage automations/i,
}).click();
});
cy.getAttached(".manage-automations-modal").within(() => {
cy.findByText(/vulnerability automations disabled/i).should("exist");
});
});
});
});

View File

@ -1,38 +0,0 @@
import CONSTANTS from "../../../support/constants";
import manageHostsPage from "../../pages/manageHostsPage";
const { GOOD_PASSWORD } = CONSTANTS;
describe("Sessions", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
});
it("logs in and out successfully", () => {
cy.visit("/");
cy.getAttached(".login-form__forgot-link").should("exist");
// Log in
cy.getAttached("input").first().type("admin@example.com");
cy.getAttached("input").last().type(GOOD_PASSWORD);
cy.getAttached("button").click();
// Verify dashboard
cy.url().should("include", "/dashboard");
cy.contains("Host");
// Log out
cy.getAttached(".user-menu button").first().click();
cy.contains("button", "Sign out").click();
cy.url().should("match", /\/login$/);
});
it("fails login with invalid password", () => {
cy.visit("/");
cy.getAttached("input").first().type("admin@example.com");
cy.getAttached("input").last().type("bad_password");
cy.getAttached(".button").click();
cy.url().should("match", /\/login$/);
cy.contains("Authentication failed");
});
it("fails to access authenticated resource", () => {
manageHostsPage.visitsManageHostsPage();
cy.url().should("match", /\/login$/);
});
});

View File

@ -1,64 +0,0 @@
import CONSTANTS from "../../../support/constants";
const { GOOD_PASSWORD } = CONSTANTS;
const enable_sso_idp_login = true;
describe("SSO Sessions", () => {
beforeEach(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
});
it("non-SSO user can login with username/password", () => {
cy.login();
cy.setupSSO({ enable_sso_idp_login });
cy.logout();
cy.visit("/");
cy.getAttached(".login-form__forgot-link").should("exist");
// Log in
cy.getAttached("input").first().type("admin@example.com");
cy.getAttached("input").last().type(GOOD_PASSWORD);
cy.contains("button", "Login").click();
// Verify dashboard
cy.url().should("include", "/dashboard");
cy.contains("Hosts");
// Log out
cy.getAttached(".user-menu button").first().click();
cy.contains("button", "Sign out").click();
cy.url().should("match", /\/login$/);
});
it("can login via SSO", () => {
cy.login();
cy.setupSSO({ enable_sso_idp_login });
cy.logout();
cy.visit("/");
// Log in
cy.contains("button", "Sign on with SimpleSAML");
cy.loginSSO();
cy.contains("Hosts");
});
it("can't login if doesn't have an account", () => {
cy.login();
cy.setupSSO({ enable_sso_idp_login });
cy.logout();
cy.visit("/");
// Log in
cy.contains("button", "Sign on with SimpleSAML");
cy.loginSSO({ username: "sso_user2" });
cy.visit("/login?status=account_invalid");
});
it("fails when IdP login disabled", () => {
cy.login();
cy.setupSSO();
cy.logout();
cy.visit("/");
cy.contains("button", "Sign on with SimpleSAML");
cy.loginSSO();
// Log in should fail
cy.contains("Password");
});
it("displays an error message when status is set", () => {
cy.visit("/login?status=account_disabled");
cy.getAttached(".flash-message");
});
});

View File

@ -1,64 +0,0 @@
import CONSTANTS from "../../../support/constants";
const { GOOD_PASSWORD } = CONSTANTS;
const fillOutForm = () => {
// Page 1
cy.findByLabelText(/full name/i).type("Test name");
cy.findByLabelText(/email/i).type("test@example.com");
cy.findByLabelText(/^password/i)
.first()
.type(GOOD_PASSWORD);
cy.findByLabelText(/confirm password/i)
.last()
.type(GOOD_PASSWORD);
cy.contains("button:enabled", /next/i).click();
// Page 2
cy.findByLabelText(/organization name/i).type("Fleet Test");
cy.contains("button:enabled", /next/i).click();
// Page 3
cy.contains("button:enabled", /next/i).click();
// Page 4
cy.contains("button:enabled", /confirm/i).click();
};
describe("Setup", () => {
// Different than normal beforeEach because we don't run the fleetctl setup.
beforeEach(() => {
const SHELL = Cypress.platform === "win32" ? "cmd" : "bash";
cy.exec("make e2e-reset-db", {
timeout: 20000,
env: { SHELL },
});
});
it("Completes setup", () => {
cy.visit("/");
cy.url().should("match", /\/setup$/);
cy.contains(/setup/i);
fillOutForm();
cy.url().should("match", /\/hosts\/manage$/i);
cy.contains(/add your devices/i);
});
it("shows messaging when there is an error during setup", () => {
cy.visit("/");
cy.intercept("POST", "/api/v1/setup", { forceNetworkError: true });
fillOutForm();
cy.findByText(
"We were unable to configure Fleet. If your Fleet server is behind a proxy, please ensure the server can be reached."
).should("exist");
});
});

View File

@ -1,23 +0,0 @@
# Free tier tests
These tests should only run when the server is in `free` tier.
To enable the tests:
```sh
export CYPRESS_FLEET_TIER=free
```
Before running the appropriate `yarn cypress (open|run)` command.
## Filtering
Any test suite in this directory should use the following pattern for filtering:
**FIXME**: There must be a better way to do this for all tests in the directory rather than having to add the check in each file?
```js
if (Cypress.env("FLEET_TIER") === "free") {
// test suite here
}
```

View File

@ -1,226 +0,0 @@
import CONSTANTS from "../../support/constants";
import dashboardPage from "../pages/dashboardPage";
import hostDetailsPage from "../pages/hostDetailsPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageHostsPage from "../pages/manageHostsPage";
import manageQueriesPage from "../pages/manageQueriesPage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import userProfilePage from "../pages/userProfilePage";
const { GOOD_PASSWORD } = CONSTANTS;
describe(
"Free tier - Admin user",
{
defaultCommandTimeout: 20000,
},
() => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.setupSMTP();
cy.seedFree();
cy.seedQueries();
cy.seedPolicies();
cy.addDockerHost();
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Navigation", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
dashboardPage.visitsDashboardPage();
});
it("displays intended admin top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/organization/i).should("exist");
});
cy.getAttached(".site-nav-container").within(() => {
cy.getAttached(".user-menu").click();
cy.findByText(/manage users/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/users/i).should("exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
dashboardPage.visitsDashboardPage();
});
it("displays cards for all platforms and does not filter host platform", () => {
dashboardPage.displaysCards("All");
dashboardPage.verifiesFilteredHostByPlatform("none");
});
it("displays cards for windows only and filters hosts by Windows platform", () => {
dashboardPage.switchesPlatform("Windows");
dashboardPage.displaysCards("Windows");
dashboardPage.verifiesFilteredHostByPlatform("Windows");
});
it("displays cards for linux only and filters hosts by Linux platform", () => {
dashboardPage.switchesPlatform("Linux");
dashboardPage.displaysCards("Linux");
dashboardPage.verifiesFilteredHostByPlatform("Linux");
});
it("displays cards for macOS only and filters hosts by macOS platform", () => {
dashboardPage.switchesPlatform("macOS");
dashboardPage.displaysCards("macOS");
dashboardPage.verifiesFilteredHostByPlatform("macOS");
});
});
describe("Manage hosts page", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
manageHostsPage.visitsManageHostsPage();
});
it("verifies teams is disabled on Manage hosts page", () => {
manageHostsPage.verifiesTeamsIsDisabled();
});
it("allows admin to see and click CTA buttons", () => {
manageHostsPage.allowsAddLabelForm();
manageHostsPage.allowsAddHosts();
manageHostsPage.allowsManageAndAddSecrets();
});
});
describe("Host details page", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
hostDetailsPage.visitsHostDetailsPage(1);
});
it("verifies teams is disabled on Host Details page", () => {
hostDetailsPage.verifiesTeamsisDisabled();
hostDetailsPage.hidesButton("Transfer");
});
});
describe("Manage software page", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
manageSoftwarePage.visitManageSoftwarePage();
});
it("allows admin to click 'Manage automations' button", () => {
manageSoftwarePage.allowsManageAutomations();
});
});
describe("Query pages", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
manageQueriesPage.visitManageQueriesPage();
});
it("allows admin add a new query", () => {
manageQueriesPage.allowsCreateNewQuery();
manageQueriesPage.verifiesCreatedNewQuery();
});
it("allows admin to edit a query", () => {
manageQueriesPage.allowsEditExistingQuery();
manageQueriesPage.verifiesEditedExistingQuery();
});
it("allows admin to run a query", () => {
manageQueriesPage.allowsRunQuery();
manageQueriesPage.verifiesRanQuery();
});
});
describe("Manage policies page", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
managePoliciesPage.visitManagePoliciesPage();
});
it("allows admin to click 'Manage automations' button", () => {
managePoliciesPage.allowsAutomatePolicy();
managePoliciesPage.verifiesAutomatedPolicy();
});
it("allows admin to add a new policy", () => {
managePoliciesPage.allowsAddDefaultPolicy();
managePoliciesPage.verifiesAddedDefaultPolicy();
});
it("allows admin to delete a policy", () => {
managePoliciesPage.allowsDeletePolicy();
});
it("allows admin to select a policy and see CTAs to run and save", () => {
managePoliciesPage.allowsSelectRunSavePolicy();
});
});
describe("Admin settings page", () => {
// cypress tends to fail on uncaught exceptions. since we have
// our own error handling, it's suggested to use this block to
// suppress so the tests will keep running
Cypress.on("uncaught:exception", () => {
return false;
});
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
cy.visit("/settings/users");
});
it("hides access to Fleet Desktop settings", () => {
cy.visit("settings/organization");
cy.findByRole("navigation", { name: "settings" }).within(() => {
cy.findByText(/organization info/i).should("exist");
cy.findByText(/fleet desktop/i).should("not.exist");
});
cy.visit("settings/organization/fleet-desktop");
cy.findAllByText(/access denied/i).should("exist");
});
it("hides access team settings", () => {
cy.findByText(/teams/i).should("not.exist");
});
it("allows admin to access integrations and users settings", () => {
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/organization settings/i).should("exist");
cy.findByText(/integrations/i).click();
});
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/users/i).click();
});
});
it("displays the 'Create user' button", () => {
cy.findByRole("button", { name: /create user/i }).click({
force: true,
});
});
it("hides assigning a user to a team", () => {
cy.findByText(/team/i).should("not.exist");
});
it("allows admin to edit existing user password", () => {
cy.visit("/settings/users");
cy.getAttached("tbody").within(() => {
cy.findByText(/mary@organization.com/i)
.parent()
.next()
.within(() => cy.getAttached(".Select-placeholder").click());
});
cy.getAttached(".Select-menu").within(() => {
cy.findByText(/edit/i).click();
});
cy.getAttached(".create-user-form").within(() => {
cy.findByLabelText(/email/i).should("exist");
cy.findByLabelText(/password/i).should("exist");
});
});
it("verifies admin is not authorized to reach the Team Settings page", () => {
cy.visit("/settings/teams");
cy.findByText(/you do not have permissions/i).should("exist");
});
});
describe("User profile page", () => {
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
userProfilePage.visitUserProfilePage();
});
it("verifies admin role and team", () => {
userProfilePage.showRole("Admin");
});
});
}
);

View File

@ -1,191 +0,0 @@
import CONSTANTS from "../../support/constants";
import dashboardPage from "../pages/dashboardPage";
import hostDetailsPage from "../pages/hostDetailsPage";
import manageHostsPage from "../pages/manageHostsPage";
import manageQueriesPage from "../pages/manageQueriesPage";
import managePacksPage from "../pages/managePacksPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import userProfilePage from "../pages/userProfilePage";
const { GOOD_PASSWORD } = CONSTANTS;
describe(
"Free tier - Maintainer user",
{
defaultCommandTimeout: 20000,
},
() => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.setupSMTP();
cy.seedFree();
cy.seedQueries();
cy.seedPolicies();
cy.addDockerHost();
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Navigation", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
dashboardPage.visitsDashboardPage();
});
it("displays intended global maintainer top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/manage users/i).should("not.exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
dashboardPage.visitsDashboardPage();
});
it("displays cards for all platforms and does not filter host platform", () => {
dashboardPage.displaysCards("All");
dashboardPage.verifiesFilteredHostByPlatform("none");
});
it("displays cards for windows only and filters hosts by Windows platform", () => {
dashboardPage.switchesPlatform("Windows");
dashboardPage.displaysCards("Windows");
dashboardPage.verifiesFilteredHostByPlatform("Windows");
});
it("displays cards for linux only and filters hosts by Linux platform", () => {
dashboardPage.switchesPlatform("Linux");
dashboardPage.displaysCards("Linux");
dashboardPage.verifiesFilteredHostByPlatform("Linux");
});
it("displays cards for macOS only and filters hosts by macOS platform", () => {
dashboardPage.switchesPlatform("macOS");
dashboardPage.displaysCards("macOS");
dashboardPage.verifiesFilteredHostByPlatform("macOS");
});
});
describe("Manage hosts page", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
manageHostsPage.visitsManageHostsPage();
});
it("verifies teams is disabled", () => {
manageHostsPage.verifiesTeamsIsDisabled();
});
it("allows maintainer to see and click 'Add label', 'Add hosts', and 'Manage enroll secrets' buttons", () => {
manageHostsPage.allowsAddHosts();
manageHostsPage.allowsManageAndAddSecrets();
});
});
describe("Host details page", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
hostDetailsPage.visitsHostDetailsPage(1);
});
it("verifies teams is disabled", () => {
hostDetailsPage.verifiesTeamsisDisabled();
hostDetailsPage.hidesButton("Transfer");
});
it("allows maintainer to create an operating system policy", () => {
hostDetailsPage.allowsCreateOsPolicy();
});
});
describe("Manage software page", () => {
beforeEach(() => manageSoftwarePage.visitManageSoftwarePage());
it("hides 'Manage automations' button from global maintainer", () => {
manageSoftwarePage.hidesButton("Manage automations");
});
});
describe("Query pages", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
manageQueriesPage.visitManageQueriesPage();
});
it("allows maintainer to add a new query", () => {
manageQueriesPage.allowsCreateNewQuery();
manageQueriesPage.verifiesCreatedNewQuery();
});
it("allows maintainer to edit a query", () => {
manageQueriesPage.allowsEditExistingQuery();
manageQueriesPage.verifiesEditedExistingQuery();
});
it("allows maintainer to run a query", () => {
manageQueriesPage.allowsRunQuery();
manageQueriesPage.verifiesRanQuery();
});
});
describe("Manage policies page", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
managePoliciesPage.visitManagePoliciesPage();
});
it("hides manage automations from maintainer", () => {
managePoliciesPage.hidesButton("Manage automations");
});
it("allows maintainer to add a policy", () => {
managePoliciesPage.allowsAddDefaultPolicy();
managePoliciesPage.verifiesAddedDefaultPolicy();
});
it("allows maintainer to delete a policy", () => {
managePoliciesPage.allowsDeletePolicy();
});
it("allows maintainer to select a policy and see CTAs to run and save", () => {
managePoliciesPage.allowsRunSavePolicy();
});
});
/* NOTE: Product decision to remove packs from UI
describe("Manage packs page", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
managePacksPage.visitsManagePacksPage();
});
it("allows maintainer to create a pack", () => {
managePacksPage.allowsCreatePack();
managePacksPage.verifiesCreatedPack();
});
it("allows maintainer to delete a pack", () => {
managePacksPage.allowsDeletePack();
managePacksPage.verifiesDeletedPack();
});
});
*/
describe("User profile page", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
userProfilePage.visitUserProfilePage();
});
it("verifies maintainer role and teams is disabled", () => {
userProfilePage.showRole("Maintainer");
});
});
// nav restrictions are at the end because we expect to see a
// 403 error overlay which will hide the nav and make the test fail
describe("Nav restrictions", () => {
// cypress tends to fail on uncaught exceptions. since we have
// our own error handling, it's suggested to use this block to
// suppress so the tests will keep running
Cypress.on("uncaught:exception", () => {
return false;
});
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
});
it("verifies maintainer does not have access to settings", () => {
cy.findByText(/settings/i).should("not.exist");
cy.visit("/settings/organization");
cy.findByText(/you do not have permissions/i).should("exist");
});
});
}
);

View File

@ -1,180 +0,0 @@
import CONSTANTS from "../../support/constants";
import dashboardPage from "../pages/dashboardPage";
import hostDetailsPage from "../pages/hostDetailsPage";
import manageHostsPage from "../pages/manageHostsPage";
import managePacksPage from "../pages/managePacksPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageQueriesPage from "../pages/manageQueriesPage";
import manageSchedulePage from "../pages/manageSchedulePage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import userProfilePage from "../pages/userProfilePage";
const { GOOD_PASSWORD } = CONSTANTS;
describe("Free tier - Observer user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.setupSMTP();
cy.seedFree();
cy.seedQueries();
cy.seedPolicies();
cy.addDockerHost();
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Navigation", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
dashboardPage.visitsDashboardPage();
});
it("displays intended global observer top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("not.exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/manage users/i).should("not.exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
dashboardPage.visitsDashboardPage();
});
it("displays cards for all platforms and does not filter host platform", () => {
dashboardPage.displaysCards("All");
dashboardPage.verifiesFilteredHostByPlatform("none");
});
it("displays cards for windows only and filters hosts by Windows platform", () => {
dashboardPage.switchesPlatform("Windows");
dashboardPage.displaysCards("Windows");
dashboardPage.verifiesFilteredHostByPlatform("Windows");
});
it("displays cards for linux only and filters hosts by Linux platform", () => {
dashboardPage.switchesPlatform("Linux");
dashboardPage.displaysCards("Linux");
dashboardPage.verifiesFilteredHostByPlatform("Linux");
});
it("displays cards for macOS only and filters hosts by macOS platform", () => {
dashboardPage.switchesPlatform("macOS");
dashboardPage.displaysCards("macOS");
dashboardPage.verifiesFilteredHostByPlatform("macOS");
});
});
describe("Manage hosts page", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
manageHostsPage.visitsManageHostsPage();
});
it("verifies teams is disabled", () => {
manageHostsPage.verifiesTeamsIsDisabled();
});
it("hides 'Add hosts', 'Add label', and 'Manage enroll secrets' buttons", () => {
manageHostsPage.hidesButton("Add label");
manageHostsPage.hidesButton("Add hosts");
manageHostsPage.hidesButton("Manage enroll secret");
});
});
describe("Host details page", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
hostDetailsPage.visitsHostDetailsPage(1);
});
it("verifies teams is disabled on Host Details page", () => {
hostDetailsPage.verifiesTeamsisDisabled();
});
it("hides all cta buttons", () => {
hostDetailsPage.hidesButton("Transfer");
hostDetailsPage.hidesButton("Query");
hostDetailsPage.hidesButton("Delete");
hostDetailsPage.hidesCreateOSPolicy();
});
});
describe("Manage software page", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
manageSoftwarePage.visitManageSoftwarePage();
});
it("hides manage automations button", () => {
manageSoftwarePage.hidesButton("Manage automations");
});
});
describe("Query page", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
manageQueriesPage.visitManageQueriesPage();
});
it("hides 'Create a query' button", () => {
manageQueriesPage.hidesButton("Create new query");
});
it("verifies observer can select a query and only run it", () => {
cy.getAttached(".data-table__table").within(() => {
cy.findByRole("button", { name: /detect presence/i }).click();
});
cy.findByText(/packs/i).should("not.exist");
cy.findByLabelText(/query name/i).should("not.exist");
cy.findByLabelText(/sql/i).should("not.exist");
cy.findByLabelText(/description/i).should("not.exist");
cy.findByLabelText(/observer can run/i).should("not.exist");
cy.findByText(/show sql/i).click();
cy.findByRole("button", { name: /run query/i }).should("exist");
});
});
describe("Manage policies page", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
managePoliciesPage.visitManagePoliciesPage();
});
it("hides manage automations button", () => {
managePoliciesPage.hidesButton("Manage automations");
});
it("hides 'Add a policy' button", () => {
managePoliciesPage.hidesButton("Add a policy");
});
it("hides 'Run', 'Edit', and 'Delete' a policy", () => {
managePoliciesPage.allowsViewPolicyOnly();
});
});
describe("User profile page", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
userProfilePage.visitUserProfilePage();
});
it("verifies user role and teams is disabled", () => {
userProfilePage.showRole("Observer");
});
});
// nav restrictions are at the end because we expect to see a
// 403 error overlay which will hide the nav and make the test fail
describe("Nav restrictions", () => {
// cypress tends to fail on uncaught exceptions. since we have
// our own error handling, it's suggested to use this block to
// suppress so the tests will keep running
Cypress.on("uncaught:exception", () => {
return false;
});
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
});
it("should restrict navigation according to role-based access controls", () => {
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/schedule/i).should("not.exist");
cy.visit("/settings/organization");
cy.findByText(/you do not have permissions/i).should("exist");
managePacksPage.visitsManagePacksPage();
cy.findByText(/you do not have permissions/i).should("exist");
manageSchedulePage.visitManageSchedulePage();
cy.findByText(/you do not have permissions/i).should("exist");
});
});
});

View File

@ -1,116 +0,0 @@
const dashboardPage = {
visitsDashboardPage: () => {
cy.visit("/dashboard");
},
switchesPlatform: (platform = "") => {
cy.getAttached(".dashboard-page__platform_dropdown").click();
cy.getAttached(".Select-menu-outer").within(() => {
cy.findAllByText(platform).click();
});
},
displaysCards: (platform = "", tier = "free") => {
switch (platform) {
case "macOS":
cy.getAttached(".dashboard-page__wrapper").within(() => {
cy.findByText(/platform/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".operating-systems").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
if (tier === "premium") {
cy.getAttached(".hosts-missing").should("exist");
cy.getAttached(".hosts-low-space").should("exist");
} else {
cy.get(".hosts-missing").should("not.exist");
cy.get(".hosts-low-space").should("not.exist");
}
});
break;
case "Windows":
cy.getAttached(".dashboard-page__wrapper").within(() => {
cy.findByText(/platform/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".operating-systems").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
if (tier === "premium") {
cy.getAttached(".hosts-missing").should("exist");
cy.getAttached(".hosts-low-space").should("exist");
} else {
cy.get(".hosts-missing").should("not.exist");
cy.get(".hosts-low-space").should("not.exist");
}
});
break;
case "Linux":
cy.getAttached(".dashboard-page__wrapper").within(() => {
cy.findByText(/platform/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
// "get" because we expect it not to exist
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
if (tier === "premium") {
cy.getAttached(".hosts-missing").should("exist");
cy.getAttached(".hosts-low-space").should("exist");
} else {
cy.get(".hosts-missing").should("not.exist");
cy.get(".hosts-low-space").should("not.exist");
}
});
break;
case "All":
cy.getAttached(".dashboard-page__wrapper").within(() => {
cy.findByText(/platform/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
cy.getAttached(".activity-feed").should("exist");
// hidden if no software
cy.get(".home-software").should("not.exist");
if (tier === "premium") {
cy.getAttached(".hosts-missing").should("exist");
cy.getAttached(".hosts-low-space").should("exist");
} else {
cy.get(".hosts-missing").should("not.exist");
cy.get(".hosts-low-space").should("not.exist");
}
});
break;
default:
// no activity feed on team dashboard
cy.getAttached(".dashboard-page__wrapper").within(() => {
cy.findByText(/platform/i).should("exist");
cy.getAttached(".hosts-summary").should("exist");
// hidden if no software
cy.get(".home-software").should("not.exist");
cy.get(".activity-feed").should("not.exist");
if (tier === "premium") {
cy.getAttached(".hosts-missing").should("exist");
cy.getAttached(".hosts-low-space").should("exist");
} else {
cy.get(".hosts-missing").should("not.exist");
cy.get(".hosts-low-space").should("not.exist");
}
});
break;
}
},
verifiesFilteredHostByPlatform: (platform: string) => {
if (platform === "none") {
cy.findByText(/view all hosts/i).click();
cy.findByRole("status", { name: /hosts filtered by/i }).should(
"not.exist"
);
} else {
cy.findByText(/view all hosts/i).click();
cy.findByRole("status", {
name: `hosts filtered by ${platform}`,
}).should("exist");
}
},
};
export default dashboardPage;

View File

@ -1,46 +0,0 @@
const hostDetailsPage = {
visitsHostDetailsPage: (hostId: number) => {
cy.visit(`/hosts/${hostId}`);
},
verifiesTeamsisDisabled: () => {
cy.findByText(/team/i).should("not.exist");
},
verifiesTeam: (teamName: string) => {
cy.getAttached(".info-flex").within(() => {
// Team is shown for host
cy.findByText(teamName).should("exist");
});
},
hidesButton: (text: string) => {
cy.contains("button", text).should("not.exist");
},
allowsCreateOsPolicy: () => {
cy.getAttached(".info-flex").within(() => {
cy.findByText(/ubuntu/i).should("exist");
cy.getAttached(".host-summary__os-policy-button").click();
});
cy.getAttached(".modal__content")
.findByRole("button", { name: /create new policy/i })
.should("be.enabled");
},
hidesCreateOSPolicy: () => {
cy.getAttached(".info-flex").within(() => {
cy.findByText("Operating system")
.next()
.findByText(/ubuntu/i)
.should("exist");
cy.findByText("Operating system")
.next()
.findByRole("button")
.should("not.exist");
});
},
};
export default hostDetailsPage;

View File

@ -1,57 +0,0 @@
const manageHostsPage = {
visitsManageHostsPage: () => {
cy.visit("/hosts/manage");
},
allowsManageAndAddSecrets: () => {
cy.getAttached(".button-wrap")
.contains("button", /manage enroll secret/i)
.click();
cy.wait(500); // eslint-disable-line cypress/no-unnecessary-waiting
cy.contains("button", /add secret/i).click();
cy.wait(500); // eslint-disable-line cypress/no-unnecessary-waiting
cy.contains("button", /save/i).click();
cy.findByText(/successfully added/i);
},
allowsAddHosts: () => {
cy.getAttached(".button-wrap")
.contains("button", /add hosts/i)
.click();
cy.getAttached(".modal__content").contains("button", /done/i).click();
},
allowsAddLabelForm: () => {
cy.getAttached(".label-filter-select__control").click();
cy.findByRole("button", { name: /add label/i }).click();
cy.findByText(/new label/i).should("exist");
cy.getAttached(".label-form__button-wrap")
.contains("button", /cancel/i)
.click();
},
hidesButton: (text: string) => {
if (text === "Add label") {
cy.getAttached(".label-filter-select__control").click();
cy.contains("button", /add label/i).should("not.exist");
} else {
cy.contains("button", text).should("not.exist");
}
},
includesTeamColumn: () => {
cy.getAttached("thead").within(() => {
cy.findByText(/team/i).should("exist");
});
},
includesTeamDropdown: (teamName = "All teams") => {
cy.getAttached(".Select-value-label").contains(teamName);
},
verifiesTeamsIsDisabled: () => {
cy.findByText(/teams/i).should("not.exist");
},
};
export default manageHostsPage;

View File

@ -1,62 +0,0 @@
const managePacksPage = {
visitsManagePacksPage: () => {
cy.visit("/packs/manage");
},
hidesButton: (text: string) => {
cy.contains("button", text).should("not.exist");
},
allowsCreatePack: () => {
cy.getAttached(".empty-table__container");
cy.findByRole("button", { name: /create new pack/i }).click();
cy.findByLabelText(/name/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 }).should("be.enabled");
},
verifiesCreatedPack: () => {
cy.findByRole("button", { name: /save query pack/i }).click();
},
allowsEditPack: () => {
cy.findByLabelText(/name/i).clear().type("Server errors");
cy.findByLabelText(/description/i)
.clear()
.type("See all server errors.");
cy.findByRole("button", { name: /save/i }).should("be.enabled");
},
verifiesEditedPack: () => {
cy.findByRole("button", { name: /save/i }).click();
},
allowsDeletePack: () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({ force: true });
});
});
cy.findByRole("button", { name: /delete/i }).click();
cy.getAttached(".remove-pack-modal .modal-cta-wrap > .button--alert")
.contains("button", /delete/i)
.should("be.enabled");
},
verifiesDeletedPack: () => {
cy.getAttached(".remove-pack-modal .modal-cta-wrap > .button--alert")
.contains("button", /delete/i)
.click({ force: true });
cy.findByText(/successfully deleted/i).should("be.visible");
managePacksPage.visitsManagePacksPage();
cy.getAttached(".table-container").within(() => {
cy.findByText(/windows starter pack/i).should("not.exist");
});
},
};
export default managePacksPage;

View File

@ -1,115 +0,0 @@
const managePoliciesPage = {
visitManagePoliciesPage: () => {
cy.visit("/policies/manage");
},
hidesButton: (text: string) => {
cy.contains("button", text).should("not.exist");
},
allowsAddDefaultPolicy: () => {
cy.findByRole("button", { name: /add a policy/i }).click();
// Add a default policy
cy.findByText(/gatekeeper enabled/i).click();
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save/i }).click();
});
},
verifiesAddedDefaultPolicy: () => {
cy.getAttached(".modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /save policy/i }).click();
});
cy.findByText(/policy created/i).should("exist");
cy.findByText(/gatekeeper enabled/i).should("exist");
},
allowsAutomatePolicy: () => {
cy.getAttached(".button-wrap")
.findByRole("button", { name: /manage automations/i })
.click();
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
cy.getAttached("#webhook-url").clear().type("https://example.com/admin");
});
},
verifiesAutomatedPolicy: () => {
cy.getAttached(".manage-automations-modal").within(() => {
cy.findByRole("button", { name: /save/i }).click();
});
cy.findByText(/successfully updated policy automations/i).should("exist");
},
allowsDeletePolicy: () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
});
cy.findByRole("button", { name: /delete/i }).click();
cy.getAttached(".delete-policy-modal").within(() => {
cy.findByRole("button", { name: /delete/i }).should("be.enabled");
});
},
verifiesDeletedPolicy: () => {
cy.getAttached(".delete-policy-modal").within(() => {
cy.findByRole("button", { name: /delete/i }).click();
});
cy.findByText(/deleted policy/i).should("exist");
cy.findByText(/backup/i).should("not.exist");
},
allowsSelectRunSavePolicy: (name = "gatekeeper") => {
cy.getAttached(".data-table__table").within(() => {
cy.findByRole("button", { name: RegExp(name, "i") }).click();
});
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save/i }).should("exist");
});
},
allowsViewPolicyOnly: () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.contains(".fleet-checkbox__input").should("not.exist");
cy.findByRole("button", { name: /filevault/i }).click();
});
});
cy.getAttached(".policy-form__wrapper").within(() => {
cy.findByRole("button", { name: /run/i }).should("not.exist");
cy.findByRole("button", { name: /save/i }).should("not.exist");
});
},
allowsRunSavePolicy: () => {
cy.getAttached(".data-table__table").within(() => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.findByRole("button", {
name: /gatekeeper/i,
}).click();
});
});
});
cy.getAttached(".policy-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).should("exist");
cy.findByRole("button", { name: /save/i }).should("exist");
});
},
};
export default managePoliciesPage;

View File

@ -1,163 +0,0 @@
import * as path from "path";
import { format } from "date-fns";
const manageQueriesPage = {
visitManageQueriesPage: () => {
cy.visit("/queries/manage");
},
hidesButton: (text: string) => {
cy.contains("button", text).should("not.exist");
},
allowsCreateNewQuery: () => {
cy.getAttached(".button--brand"); // ensures cta button loads
cy.findByRole("button", { name: /new query/i }).click();
cy.getAttached(".query-page__form .ace_scroller")
.click({ force: true })
.type("{selectall}SELECT * FROM windows_crashes;");
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached(".modal__background").within(() => {
cy.getAttached(".modal__modal_container").within(() => {
cy.getAttached(".modal__content").within(() => {
cy.getAttached("form").within(() => {
cy.findByLabelText(/name/i).click().type("Cypress test query");
cy.findByLabelText(/description/i)
.click()
.type("Cypress test of create new query flow.");
cy.findByLabelText(/observers can run/i).click({ force: true });
});
});
});
});
},
verifiesCreatedNewQuery: () => {
cy.getAttached(".modal__background").within(() => {
cy.getAttached(".modal__modal_container").within(() => {
cy.getAttached(".modal__content").within(() => {
cy.getAttached("form").within(() => {
cy.findByRole("button", { name: /save query/i }).click();
});
});
});
});
cy.findByText(/query created/i).should("exist");
cy.getAttached(".query-form__query-name").within(() => {
cy.findByText(/cypress test query/i).should("exist");
});
},
allowsEditExistingQuery: () => {
cy.getAttached(".name__cell .button--text-link")
.first()
.click({ force: true });
cy.getAttached(".query-page__form .ace_text-input")
.click({ force: true })
.clear({ force: true })
.type("SELECT 1 FROM cypress;", {
force: true,
});
},
verifiesEditedExistingQuery: () => {
cy.findByRole("button", { name: "Save" }).click(); // we have 'save as new' also
cy.findByText(/query updated/i).should("be.visible");
},
allowsSaveAsNewQuery: () => {
cy.getAttached(".name__cell .button--text-link")
.eq(1)
.within(() => {
cy.findByText(/get authorized/i).click();
});
cy.findByRole("button", { name: /run query/i }).should("exist");
cy.getAttached(".query-page__form .ace_scroller")
.click()
.type("{selectall}SELECT datetime, username FROM windows_crashes;");
cy.findByRole("button", { name: /save as new/i }).should("be.enabled");
},
verifiesSavedAsNewQuery: () => {
cy.findByRole("button", { name: /save as new/i }).click();
cy.findByText(/successfully added query/i).should("be.visible");
cy.findByText(/copy of/i).should("be.visible");
},
allowsDeleteExistingQuery: () => {
cy.findByText(/detect presence of authorized ssh keys/i)
.parent()
.parent()
.parent()
.within(() => {
cy.getAttached(".fleet-checkbox__input").check({
force: true,
});
});
cy.findByRole("button", { name: /delete/i }).click();
cy.getAttached(".delete-query-modal .modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /delete/i }).should("exist");
});
},
verifiesDeletedExistingQuery: () => {
cy.getAttached(".delete-query-modal .modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /delete/i }).click();
});
cy.findByText(/successfully deleted query/i).should("be.visible");
cy.findByText(/detect presence of authorized ssh keys/i).should(
"not.exist"
);
},
// TODO: Allows delete of self authored query only (Team Admin, team maintainer)
allowsSelectTeamTargets: () => {
cy.getAttached("tbody").within(() => {
cy.findAllByText(/detect presence/i).click();
});
cy.getAttached(".query-form__button-wrap").within(() => {
cy.findByRole("button", { name: /run/i }).click();
});
cy.contains("h3", /teams/i).should("exist");
cy.contains(".selector-name", /apples/i).should("exist");
},
allowsRunQuery: () => {
cy.getAttached(".name__cell .button--text-link").first().click();
cy.findByRole("button", { name: /run query/i }).click();
cy.findByText(/select targets/i).should("exist");
cy.findByText(/all hosts/i).click();
cy.findByText(/host targeted/i).should("exist"); // target count
},
verifiesRanQuery: () => {
cy.findByRole("button", { name: /run/i }).click();
cy.findByText(/querying selected host/i).should("exist"); // target count
},
allowsViewRanQuery: () => {
// Ensures live query runs
cy.wait(10000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.getAttached(".table-container").within(() => {
cy.findByRole("button", { name: /show query/i }).click();
});
cy.getAttached(".show-query-modal").within(() => {
cy.findByRole("button", { name: /done/i }).click();
});
},
allowsExportQueryResults: () => {
cy.getAttached(".table-container").within(() => {
cy.findByRole("button", { name: /export results/i }).click();
const formattedTime = format(new Date(), "MM-dd-yy hh-mm-ss");
const filename = `Query Results (${formattedTime}).csv`;
cy.readFile(path.join(Cypress.config("downloadsFolder"), filename), {
timeout: 5000,
});
});
},
};
export default manageQueriesPage;

View File

@ -1,124 +0,0 @@
const manageSchedulePage = {
visitManageSchedulePage: () => {
cy.visit("/schedule/manage");
},
hidesButton: (text: string) => {
if (text === "Advanced") {
cy.getAttached(".empty-table__cta-buttons").within(() => {
cy.contains("button", text).should("not.exist");
});
} else cy.contains("button", text).should("not.exist");
},
changesTeam: (team1: string, team2: string) => {
cy.getAttached(".manage-schedule-page__header").within(() => {
cy.contains(team1).click({ force: true });
cy.contains(team2).click({ force: true });
});
},
confirmsTeam: (team: string) => {
cy.getAttached(".manage-schedule-page__header-wrap").within(() => {
cy.findByText(team).should("exist");
});
},
allowsAddSchedule: () => {
cy.getAttached(".empty-table__cta-buttons").within(() => {
cy.findByRole("button", { name: /schedule a query/i }).click({
force: true,
});
});
cy.getAttached(".schedule-editor-modal__form").within(() => {
cy.findByText(/select query/i).click();
cy.findByText(/get local/i).click();
cy.findByText(/every day/i).click();
cy.findByText(/every 6 hours/i).click();
cy.findByText(/show advanced options/i).click();
cy.findByText(/snapshot/i).click();
cy.findByText(/ignore removals/i).click();
cy.getAttached(".schedule-editor-modal__form-field--platform").within(
() => {
cy.findByText(/select/i).click();
cy.findByText(/linux/i).click();
}
);
cy.getAttached(".schedule-editor-modal__form-field--osquer-vers").within(
() => {
cy.findByText(/all/i).click();
cy.findByText(/4.6.0/i).click();
}
);
cy.getAttached(".schedule-editor-modal__form-field--shard").within(() => {
cy.getAttached(".input-field").click().type("50");
});
cy.getAttached(".modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).should("be.enabled");
});
});
},
verifiesAddedSchedule: () => {
cy.getAttached(".modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).click();
});
cy.findByText(/successfully added/i).should("be.visible");
cy.getAttached("tbody>tr").should("have.length", 1);
},
allowsEditSchedule: () => {
cy.getAttached(".manage-schedule-page");
cy.getAttached("tbody>tr")
.should("have.length", 1)
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
});
cy.getAttached(".schedule-editor-modal__form").within(() => {
cy.findByText(/every 6 hours/i).click();
cy.findByText(/every day/i).click();
cy.getAttached(".modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).should("be.enabled");
});
});
},
verifiesEditedSchedule: () => {
cy.getAttached(".modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /schedule/i }).click();
});
cy.findByText(/successfully updated/i).should("be.visible");
},
allowsRemoveSchedule: () => {
cy.getAttached(".manage-schedule-page");
cy.getAttached("tbody>tr")
.should("have.length", 1)
.within(() => {
cy.getAttached(".Select-placeholder").within(() => {
cy.findByText(/action/i).click();
});
cy.getAttached(".Select-menu").within(() => {
cy.findByText(/remove/i).click();
});
});
cy.getAttached(".remove-scheduled-query-modal .modal-cta-wrap").within(
() => {
cy.findByRole("button", { name: /remove/i }).should("be.enabled");
}
);
},
verifiesRemovedSchedule: () => {
cy.getAttached(".remove-scheduled-query-modal .modal-cta-wrap").within(
() => {
cy.findByRole("button", { name: /remove/i }).click();
}
);
cy.findByText(/successfully removed/i).should("be.visible");
},
};
export default manageSchedulePage;

View File

@ -1,16 +0,0 @@
const manageSoftwarePage = {
visitManageSoftwarePage: () => {
cy.visit("/software/manage");
},
hidesButton: (text: string) => {
cy.contains("button", text).should("not.exist");
},
allowsManageAutomations: () => {
cy.findByRole("button", { name: /manage automations/i }).click();
cy.findByRole("button", { name: /cancel/i }).click();
},
};
export default manageSoftwarePage;

View File

@ -1,10 +0,0 @@
const teamsDropdown = {
switchTeams: (team1: string, team2: string) => {
cy.getAttached(".component__team-dropdown").within(() => {
cy.findByText(team1).click({ force: true });
});
cy.getAttached(".Select-menu").contains(team2).click({ force: true });
},
};
export default teamsDropdown;

View File

@ -1,21 +0,0 @@
const userProfilePage = {
visitUserProfilePage: () => {
cy.visit("/profile");
},
showRole: (role: string, team?: string) => {
cy.getAttached(".user-side-panel").within(() => {
if (team) {
cy.getAttached(".user-side-panel__header")
.contains(/team/i)
.next()
.contains(team);
} else {
cy.findByText(/teams/i).should("not.exist");
}
cy.findByText("Role").next().contains(role);
});
},
};
export default userProfilePage;

View File

@ -1,23 +0,0 @@
# Premium tier tests
These tests should only run when the server is in `premium` tier.
To enable the tests:
```sh
export CYPRESS_FLEET_TIER=premium
```
Before running the appropriate `yarn cypress (open|run)` command.
## Filtering
Any test suite in this directory should use the following pattern for filtering:
**FIXME**: There must be a better way to do this for all tests in the directory rather than having to add the check in each file?
```js
if (Cypress.env("FLEET_TIER") === "premium") {
// test suite here
}
```

View File

@ -1,596 +0,0 @@
import CONSTANTS from "../../support/constants";
import hostDetailsPage from "../pages/hostDetailsPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageHostsPage from "../pages/manageHostsPage";
import manageQueriesPage from "../pages/manageQueriesPage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import teamsDropdown from "../pages/teamsDropdown";
import userProfilePage from "../pages/userProfilePage";
import dashboardPage from "../pages/dashboardPage";
const { GOOD_PASSWORD, CONFIG_INTEGRATIONS_AUTOMATIONS } = CONSTANTS;
const patchTeamJiraPoliciesIntegration = {
integrations: {
jira: [
{
enable_failing_policies: false,
project_key: "PROJECT 1",
url: "https://fleetdm.atlassian.com",
},
{
enable_failing_policies: true,
project_key: "PROJECT 2",
url: "https://fleetdm.atlassian.com",
},
],
zendesk: [
{
enable_failing_policies: false,
group_id: 12345678,
url: "https://fleetdm.zendesk.com",
},
{
enable_failing_policies: false,
group_id: 87654321,
url: "https://fleetdm.zendesk.com",
},
],
},
webhook_settings: {
failing_policies_webhook: {
destination_url: "https://example.com/global_admin",
enable_failing_policies_webhook: false,
policy_ids: [1, 3, 2],
},
},
};
const getTeamJiraPoliciesIntegration = {
team: {
id: 1,
created_at: "2022-07-01T19:31:46Z",
name: "Apples",
description: "",
agent_options: {
config: {
options: {
pack_delimiter: "/",
logger_tls_period: 10,
distributed_plugin: "tls",
disable_distributed: false,
logger_tls_endpoint: "/api/osquery/log",
distributed_interval: 10,
distributed_tls_max_attempts: 3,
},
decorators: {
load: [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;",
],
},
},
overrides: {},
},
webhook_settings: {
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://example.com/global_admin",
policy_ids: [1, 3, 2],
host_batch_size: 0,
},
},
integrations: {
jira: [
{
enable_failing_policies: false,
project_key: "PROJECT 1",
url: "https://fleetdm.atlassian.com",
},
{
enable_failing_policies: true,
project_key: "PROJECT 2",
url: "https://fleetdm.atlassian.com",
},
],
zendesk: [
{
enable_failing_policies: false,
group_id: 12345678,
url: "https://fleetdm.zendesk.com",
},
{
enable_failing_policies: false,
group_id: 87654321,
url: "https://fleetdm.zendesk.com",
},
],
},
user_count: 0,
users: [
{
created_at: "0001-01-01T00:00:00Z",
updated_at: "0001-01-01T00:00:00Z",
id: 8,
name: "Marco",
email: "marco@organization.com",
force_password_reset: false,
gravatar_url: "",
sso_enabled: false,
global_role: null,
api_only: false,
teams: null,
role: "observer",
},
{
created_at: "0001-01-01T00:00:00Z",
updated_at: "0001-01-01T00:00:00Z",
id: 9,
name: "Anita T. Admin",
email: "anita@organization.com",
force_password_reset: false,
gravatar_url: "",
sso_enabled: false,
global_role: null,
api_only: false,
teams: null,
role: "admin",
},
{
created_at: "0001-01-01T00:00:00Z",
updated_at: "0001-01-01T00:00:00Z",
id: 10,
name: "Toni",
email: "toni@organization.com",
force_password_reset: false,
gravatar_url: "",
sso_enabled: false,
global_role: null,
api_only: false,
teams: null,
role: "observer",
},
],
host_count: 0,
secrets: [
{
secret: "OgkyoX/SGsuvLXPaNHUVIJoYSx1PTV+S",
created_at: "2022-07-01T19:31:46Z",
team_id: 1,
},
],
},
};
const patchTeamZendeskPoliciesIntegration = {
integrations: {
jira: [
{
enable_failing_policies: false,
project_key: "PROJECT 1",
url: "https://fleetdm.atlassian.com",
},
{
enable_failing_policies: false,
project_key: "PROJECT 2",
url: "https://fleetdm.atlassian.com",
},
],
zendesk: [
{
enable_failing_policies: false,
group_id: 12345678,
url: "https://fleetdm.zendesk.com",
},
{
enable_failing_policies: true,
group_id: 87654321,
url: "https://fleetdm.zendesk.com",
},
],
},
webhook_settings: {
failing_policies_webhook: {
destination_url: "https://example.com/global_admin",
enable_failing_policies_webhook: false,
policy_ids: [1, 3, 2],
},
},
};
const getTeamZendeskPoliciesIntegration = {
team: {
id: 1,
created_at: "2022-07-01T19:31:46Z",
name: "Apples",
description: "",
agent_options: {
config: {
options: {
pack_delimiter: "/",
logger_tls_period: 10,
distributed_plugin: "tls",
disable_distributed: false,
logger_tls_endpoint: "/api/osquery/log",
distributed_interval: 10,
distributed_tls_max_attempts: 3,
},
decorators: {
load: [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;",
],
},
},
overrides: {},
},
webhook_settings: {
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://example.com/global_admin",
policy_ids: [1, 3, 2],
host_batch_size: 0,
},
},
integrations: {
jira: [
{
enable_failing_policies: false,
project_key: "PROJECT 1",
url: "https://fleetdm.atlassian.com",
},
{
enable_failing_policies: false,
project_key: "PROJECT 2",
url: "https://fleetdm.atlassian.com",
},
],
zendesk: [
{
enable_failing_policies: false,
group_id: 12345678,
url: "https://fleetdm.zendesk.com",
},
{
enable_failing_policies: true,
group_id: 87654321,
url: "https://fleetdm.zendesk.com",
},
],
},
user_count: 0,
users: [
{
created_at: "0001-01-01T00:00:00Z",
updated_at: "0001-01-01T00:00:00Z",
id: 8,
name: "Marco",
email: "marco@organization.com",
force_password_reset: false,
gravatar_url: "",
sso_enabled: false,
global_role: null,
api_only: false,
teams: null,
role: "observer",
},
{
created_at: "0001-01-01T00:00:00Z",
updated_at: "0001-01-01T00:00:00Z",
id: 9,
name: "Anita T. Admin",
email: "anita@organization.com",
force_password_reset: false,
gravatar_url: "",
sso_enabled: false,
global_role: null,
api_only: false,
teams: null,
role: "admin",
},
{
created_at: "0001-01-01T00:00:00Z",
updated_at: "0001-01-01T00:00:00Z",
id: 10,
name: "Toni",
email: "toni@organization.com",
force_password_reset: false,
gravatar_url: "",
sso_enabled: false,
global_role: null,
api_only: false,
teams: null,
role: "observer",
},
],
host_count: 0,
secrets: [
{
secret: "OgkyoX/SGsuvLXPaNHUVIJoYSx1PTV+S",
created_at: "2022-07-01T19:31:46Z",
team_id: 1,
},
],
},
};
describe("Premium tier - Global Admin user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPremium();
cy.seedQueries();
cy.seedPolicies("apples");
cy.addDockerHost("apples"); // host not transferred
cy.addDockerHost("oranges"); // host transferred between teams by global admin
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
beforeEach(() => {
cy.loginWithCySession("anna@organization.com", GOOD_PASSWORD);
});
describe("Navigation and dashboard", () => {
beforeEach(() => dashboardPage.visitsDashboardPage());
it("displays intended global admin top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/organization/i).should("exist");
});
cy.getAttached(".site-nav-container").within(() => {
cy.getAttached(".user-menu").click();
cy.findByText(/manage users/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/users/i).should("exist");
});
});
// Premium dashboard feature
it("filters missing hosts", () => {
cy.findByText(/missing hosts/i).click();
cy.getAttached(".manage-hosts__filter-dropdowns").within(() => {
cy.findByText(/missing hosts/i).should("exist");
});
});
// Premium dashboard feature
it("filters low disk space hosts", () => {
cy.findByText(/low disk space hosts/i).click();
cy.findByRole("status", {
name: /hosts filtered by low disk space/i,
}).should("exist");
});
});
// Global Admin dashboard tested in integration/free/admin.spec.ts
// Team Admin dashboard tested below in integration/premium/admin.spec.ts
describe("Manage hosts page", () => {
beforeEach(() => manageHostsPage.visitsManageHostsPage());
it("verifies teams is enabled on Manage host page", () => {
manageHostsPage.includesTeamColumn();
});
it("allows global admin to see and click all CTA buttons", () => {
manageHostsPage.allowsAddHosts();
manageHostsPage.allowsAddLabelForm();
manageHostsPage.allowsManageAndAddSecrets();
});
});
describe("Host details page", () => {
beforeEach(() => hostDetailsPage.visitsHostDetailsPage(1));
it("allows global admin to create an operating system policy", () => {
hostDetailsPage.allowsCreateOsPolicy();
});
});
describe("Manage software page", () => {
beforeEach(() => {
manageSoftwarePage.visitManageSoftwarePage();
});
// it(`displays "Probability of exploit" column`, () => {
// cy.getAttached("thead").within(() => {
// cy.findByText(/vulnerabilities/i).should("not.exist");
// cy.findByText(/probability of exploit/i).should("exist");
// });
// });
it("allows admin to click 'Manage automations' button", () => {
manageSoftwarePage.allowsManageAutomations();
});
it("hides manage automations button since all teams not selected", () => {
cy.getAttached(".manage-software-page__header-wrap").within(() => {
teamsDropdown.switchTeams("All teams", "Apples");
manageSoftwarePage.hidesButton("Manage automations");
});
});
});
describe("Query pages", () => {
beforeEach(() => manageQueriesPage.visitManageQueriesPage());
it("allows global admin to select teams targets for query", () => {
manageQueriesPage.allowsSelectTeamTargets();
});
// TODO: Allowed to delete self-authored query only
});
// Global Admin schedule tested in integration/free/admin.spec.ts
// Team Admin team schedule tested below in integration/premium/admin.spec.ts
describe("Manage policies page", () => {
beforeEach(() => managePoliciesPage.visitManagePoliciesPage());
it("allows global admin to add a new policy", () => {
managePoliciesPage.allowsAddDefaultPolicy();
managePoliciesPage.verifiesAddedDefaultPolicy();
});
it("allows global admin to automate a global policy", () => {
managePoliciesPage.allowsAutomatePolicy();
managePoliciesPage.verifiesAutomatedPolicy();
});
it("allows global admin to automate a team policy webhook", () => {
managePoliciesPage.visitManagePoliciesPage();
teamsDropdown.switchTeams("All teams", "Apples");
managePoliciesPage.allowsAutomatePolicy();
managePoliciesPage.verifiesAutomatedPolicy();
});
it("allows global admin to delete a team policy", () => {
cy.visit("/policies/manage");
teamsDropdown.switchTeams("All teams", "Apples");
managePoliciesPage.allowsDeletePolicy();
});
it("allows global admin to edit a team policy", () => {
managePoliciesPage.visitManagePoliciesPage();
teamsDropdown.switchTeams("All teams", "Apples");
managePoliciesPage.allowsSelectRunSavePolicy("filevault");
});
});
describe("Manage policies page (mock integrations)", () => {
beforeEach(() => {
cy.intercept(
"GET",
"/api/latest/fleet/config",
CONFIG_INTEGRATIONS_AUTOMATIONS
).as("getIntegrations");
managePoliciesPage.visitManagePoliciesPage();
cy.wait("@getIntegrations").then((configStub) => {
console.log(JSON.stringify(configStub));
});
});
it("allows global admin to delete team policy", () => {
teamsDropdown.switchTeams("All teams", "Apples");
managePoliciesPage.allowsDeletePolicy();
});
it("allows global admin to automate a team policy jira integration", () => {
managePoliciesPage.visitManagePoliciesPage;
teamsDropdown.switchTeams("All teams", "Apples");
cy.getAttached(".button-wrap")
.findByRole("button", { name: /manage automations/i })
.click();
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
cy.getAttached("#ticket-radio-btn").next().click();
cy.findByText(/select integration/i).click();
cy.findByText(/project 2/i).click();
cy.intercept(
"PATCH",
"/api/latest/fleet/teams/1",
patchTeamJiraPoliciesIntegration
).as("enableJiraPoliciesIntegration");
cy.intercept(
"GET",
"/api/latest/fleet/teams/1",
getTeamJiraPoliciesIntegration
).as("enabledJiraPoliciesIntegration");
cy.findByText(/save/i).click();
});
cy.findByText(/successfully updated policy automations/i).should("exist");
});
it("allows global admin to automate a team policy zendesk integration", () => {
managePoliciesPage.visitManagePoliciesPage();
teamsDropdown.switchTeams("All teams", "Apples");
cy.getAttached(".button-wrap")
.findByRole("button", { name: /manage automations/i })
.click();
cy.getAttached(".manage-automations-modal").within(() => {
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-slider").click();
cy.getAttached(".fleet-checkbox__input").check({ force: true });
cy.getAttached("#ticket-radio-btn").next().click();
cy.findByText(/select integration/i).click();
cy.findByText(/87654321/i).click();
cy.intercept(
"PATCH",
"/api/latest/fleet/teams/1",
patchTeamZendeskPoliciesIntegration
).as("enableZendeskPoliciesIntegration");
cy.intercept(
"GET",
"/api/latest/fleet/teams/1",
getTeamZendeskPoliciesIntegration
).as("enabledZendeskPoliciesIntegration");
cy.findByText(/save/i).click();
cy.wait("@enableZendeskPoliciesIntegration").then((configStub) => {
console.log(JSON.stringify(configStub));
});
});
cy.findByText(/successfully updated policy automations/i).should("exist");
});
});
describe("Admin settings page", () => {
beforeEach(() => cy.visit("/settings/organization"));
it("allows global admin to access team settings", () => {
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/teams/i).click();
});
// Access the Settings - Team details page
cy.getAttached("tbody").within(() => {
cy.getAttached(".name__cell .button--text-link")
.eq(0)
.within(() => {
cy.findByText(/apples/i).click();
});
});
cy.findByText(/apples/i).should("exist");
cy.findByText(/manage users with global access here/i).should("exist");
});
it("displays the 'Team' section in the create user modal", () => {
cy.getAttached(".react-tabs").within(() => {
cy.findByText(/users/i).click();
});
cy.findByRole("button", { name: /create user/i }).click({ force: true });
cy.findByText(/assign teams/i).should("exist");
});
it("allows global admin to edit existing user password", () => {
cy.visit("/settings/users");
cy.getAttached("tbody").within(() => {
cy.contains("Oliver") // case-sensitive
.parent()
.next()
.next()
.next()
.next()
.next()
.within(() => cy.getAttached(".Select-placeholder").click());
});
cy.getAttached(".Select-menu").within(() => {
cy.findByText(/edit/i).click();
});
cy.getAttached(".create-user-form").within(() => {
cy.findByLabelText(/email/i).should("exist");
cy.findByLabelText(/password/i).should("exist");
});
});
it("allows access to Fleet Desktop settings", () => {
cy.visit("settings/organization");
cy.findByRole("navigation", { name: "settings" }).within(() => {
cy.findByText(/organization info/i).should("exist");
cy.findByText(/fleet desktop/i)
.should("exist")
.click();
});
cy.getAttached("[id=transparency_url")
.should("have.value", "https://fleetdm.com/transparency")
.clear()
.type("http://example.com/transparency");
cy.findByRole("button", { name: /save/i }).click();
cy.findByText(/successfully updated/i).should("exist");
cy.visit("settings/organization/fleet-desktop");
cy.getAttached("[id=transparency_url").should(
"have.value",
"http://example.com/transparency"
);
});
});
describe("User profile page", () => {
it("verifies admin user role and global access", () => {
userProfilePage.visitUserProfilePage();
userProfilePage.showRole("Admin", "Global");
});
});
});

View File

@ -1,33 +0,0 @@
const fakeDeviceToken = "phAK3d3vIC37OK3n";
describe("Fleet Desktop", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.addDockerHost();
cy.setDesktopToken(1, fakeDeviceToken);
cy.viewport(1200, 660);
cy.seedPolicies();
});
after(() => {
cy.stopDockerHost();
});
describe("Fleet Desktop device user page", () => {
beforeEach(() => {
Cypress.session.clearAllSavedSessions();
cy.visit(`/device/${fakeDeviceToken}`);
});
it("renders policies and provides instructions for self-remediation", () => {
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/policies/i).click();
});
cy.getAttached(".section--policies").within(() => {
cy.findByText(/is filevault enabled/i).click();
});
cy.getAttached(".policy-details-modal").within(() => {
cy.findByText(/click turn on filevault/i).should("exist");
});
});
});
});

View File

@ -1,127 +0,0 @@
import CONSTANTS from "../../support/constants";
import hostDetailsPage from "../pages/hostDetailsPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageHostsPage from "../pages/manageHostsPage";
import manageQueriesPage from "../pages/manageQueriesPage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import teamsDropdown from "../pages/teamsDropdown";
import userProfilePage from "../pages/userProfilePage";
import dashboardPage from "../pages/dashboardPage";
const { GOOD_PASSWORD } = CONSTANTS;
describe("Premium tier - Maintainer user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPremium();
cy.seedQueries();
cy.seedPolicies("apples");
cy.addDockerHost("apples");
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Global maintainer", () => {
beforeEach(() => {
cy.loginWithCySession("mary@organization.com", GOOD_PASSWORD);
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended global maintainer top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/manage users/i).should("not.exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => dashboardPage.visitsDashboardPage());
it("displays cards for all platforms and does not filter host platform", () => {
dashboardPage.displaysCards("All", "premium");
dashboardPage.verifiesFilteredHostByPlatform("none");
});
it("displays cards for windows only and filters hosts by Windows platform", () => {
dashboardPage.switchesPlatform("Windows");
dashboardPage.displaysCards("Windows", "premium");
dashboardPage.verifiesFilteredHostByPlatform("Windows");
});
it("displays cards for linux only and filters hosts by Linux platform", () => {
dashboardPage.switchesPlatform("Linux");
dashboardPage.displaysCards("Linux", "premium");
dashboardPage.verifiesFilteredHostByPlatform("Linux");
});
it("displays cards for macOS only and filters hosts by macOS platform", () => {
dashboardPage.switchesPlatform("macOS");
dashboardPage.displaysCards("macOS", "premium");
dashboardPage.verifiesFilteredHostByPlatform("macOS");
});
});
describe("Manage hosts page", () => {
beforeEach(() => manageHostsPage.visitsManageHostsPage());
it("renders team elements", () => {
manageHostsPage.includesTeamDropdown();
manageHostsPage.includesTeamColumn();
});
it("renders 'Add hosts', 'Add label', and 'Manage enroll secrets' buttons", () => {
manageHostsPage.allowsAddLabelForm();
manageHostsPage.allowsAddHosts();
manageHostsPage.allowsManageAndAddSecrets();
});
});
describe("Host details page", () => {
beforeEach(() => {
hostDetailsPage.visitsHostDetailsPage(1);
});
it("allows global maintainer to create an operating system policy", () => {
hostDetailsPage.allowsCreateOsPolicy();
});
});
describe("Manage software page", () => {
beforeEach(() => manageSoftwarePage.visitManageSoftwarePage());
it("hides 'Manage automations' button from global maintainer", () => {
manageSoftwarePage.hidesButton("Manage automations");
});
});
describe("Query pages", () => {
beforeEach(() => manageQueriesPage.visitManageQueriesPage());
it("allows global maintainer to select teams targets for query", () => {
manageQueriesPage.allowsSelectTeamTargets();
});
// TODO: Allowed to delete self-authored query only
});
describe("Manage policies page", () => {
beforeEach(() => managePoliciesPage.visitManagePoliciesPage());
it("hides manage automations button", () => {
managePoliciesPage.hidesButton("Manage automations");
});
it("allows global maintainer to add a new policy", () => {
managePoliciesPage.allowsAddDefaultPolicy();
managePoliciesPage.verifiesAddedDefaultPolicy();
});
it("allows global maintainer to delete a team policy", () => {
teamsDropdown.switchTeams("All teams", "Apples");
managePoliciesPage.allowsDeletePolicy();
});
it("allows global maintainer to edit a team policy", () => {
teamsDropdown.switchTeams("All teams", "Apples");
managePoliciesPage.allowsSelectRunSavePolicy("filevault");
});
});
describe("User profile page", () => {
it("verifies user role and global access", () => {
userProfilePage.visitUserProfilePage();
userProfilePage.showRole("Maintainer", "Global");
});
});
});
});

View File

@ -1,173 +0,0 @@
import CONSTANTS from "../../support/constants";
import dashboardPage from "../pages/dashboardPage";
import hostDetailsPage from "../pages/hostDetailsPage";
import manageHostsPage from "../pages/manageHostsPage";
import managePacksPage from "../pages/managePacksPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageQueriesPage from "../pages/manageQueriesPage";
import manageSchedulePage from "../pages/manageSchedulePage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import teamsDropdown from "../pages/teamsDropdown";
import userProfilePage from "../pages/userProfilePage";
const { GOOD_PASSWORD } = CONSTANTS;
describe("Premium tier - Observer user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPremium();
cy.seedQueries();
cy.seedPolicies("apples");
cy.addDockerHost("apples");
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Global observer", () => {
beforeEach(() => {
cy.loginWithCySession("oliver@organization.com", GOOD_PASSWORD);
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended global observer top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("not.exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/manage users/i).should("not.exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => dashboardPage.visitsDashboardPage());
it("displays cards for all platforms and does not filter host platform", () => {
dashboardPage.displaysCards("All", "premium");
dashboardPage.verifiesFilteredHostByPlatform("none");
});
it("displays cards for windows only and filters hosts by Windows platform", () => {
dashboardPage.switchesPlatform("Windows");
dashboardPage.displaysCards("Windows", "premium");
dashboardPage.verifiesFilteredHostByPlatform("Windows");
});
it("displays cards for linux only and filters hosts by Linux platform", () => {
dashboardPage.switchesPlatform("Linux");
dashboardPage.displaysCards("Linux", "premium");
dashboardPage.verifiesFilteredHostByPlatform("Linux");
});
it("displays cards for macOS only and filters hosts by macOS platform", () => {
dashboardPage.switchesPlatform("macOS");
dashboardPage.displaysCards("macOS", "premium");
dashboardPage.verifiesFilteredHostByPlatform("macOS");
});
});
describe("Manage hosts page", () => {
beforeEach(() => manageHostsPage.visitsManageHostsPage());
it("renders team elements", () => {
manageHostsPage.includesTeamDropdown();
manageHostsPage.includesTeamColumn();
});
it("hides 'Add hosts', 'Add label', and 'Manage enroll secrets' buttons", () => {
manageHostsPage.hidesButton("Add label");
manageHostsPage.hidesButton("Add hosts");
manageHostsPage.hidesButton("Manage enroll secret");
});
});
describe("Host details page", () => {
beforeEach(() => hostDetailsPage.visitsHostDetailsPage(1));
it("should render elements according to role-based access controls", () => {
hostDetailsPage.verifiesTeam("Apples");
hostDetailsPage.hidesCreateOSPolicy();
});
});
describe("Manage software page", () => {
beforeEach(() => manageSoftwarePage.visitManageSoftwarePage());
it("hides manage automations button", () => {
manageSoftwarePage.hidesButton("Manage automations");
});
});
describe("Query pages", () => {
beforeEach(() => manageQueriesPage.visitManageQueriesPage());
it("allows global observer to select teams targets for query", () => {
manageQueriesPage.allowsSelectTeamTargets();
});
});
describe("Policies pages", () => {
beforeEach(() => managePoliciesPage.visitManagePoliciesPage());
it("should render elements according to role-based access controls", () => {
// No global policies seeded, placeholder displayed
cy.findByText(/ask yes or no questions/i).should("exist");
cy.findByText(/all your hosts/i).should("exist");
managePoliciesPage.hidesButton("Manage automations");
managePoliciesPage.hidesButton("Add a policy");
teamsDropdown.switchTeams("All teams", "Apples");
managePoliciesPage.hidesButton("Manage automations");
managePoliciesPage.hidesButton("Add a policy");
managePoliciesPage.allowsViewPolicyOnly();
});
});
});
describe("Team observer", () => {
beforeEach(() => {
cy.loginWithCySession("toni@organization.com", GOOD_PASSWORD);
});
describe("Nav restrictions", () => {
it("should restrict navigation according to role-based access controls", () => {
// cypress tends to fail on uncaught exceptions. since we have
// our own error handling, it's suggested to use this block to
// suppress so the tests will keep running
Cypress.on("uncaught:exception", () => {
return false;
});
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/schedule/i).should("not.exist");
cy.visit("/settings/organization");
cy.findByText(/you do not have permissions/i).should("exist");
managePacksPage.visitsManagePacksPage();
cy.findByText(/you do not have permissions/i).should("exist");
manageSchedulePage.visitManageSchedulePage();
cy.findByText(/you do not have permissions/i).should("exist");
});
});
describe("Manage hosts page", () => {
it("should render elements according to role-based access controls", () => {
manageHostsPage.visitsManageHostsPage();
manageHostsPage.includesTeamColumn();
manageHostsPage.hidesButton("Add hosts");
manageHostsPage.hidesButton("Manage enroll secret");
manageHostsPage.hidesButton("Add label");
});
});
describe("Manage policies page", () => {
it("hides 'Add a policy'", () => {
managePoliciesPage.visitManagePoliciesPage();
managePoliciesPage.hidesButton("Add a policy");
cy.findByText(/all teams/i).should("not.exist");
});
});
describe("Policy detail page", () => {
it("allows viewing policies only", () => {
managePoliciesPage.visitManagePoliciesPage();
managePoliciesPage.allowsViewPolicyOnly();
});
});
describe("User profile page", () => {
it("verifies observer role and team", () => {
userProfilePage.visitUserProfilePage();
userProfilePage.showRole("Observer", "Apples");
});
});
});
});

View File

@ -1,55 +0,0 @@
describe("SSO Sessions", () => {
describe("JIT user provisioning", () => {
before(() => {
cy.setup();
});
beforeEach(() => {
Cypress.session.clearAllSavedSessions();
});
it("non-existent users can't login if JIT is not enabled", () => {
cy.login();
cy.setupSSO({
enable_sso_idp_login: true,
enable_jit_provisioning: false,
});
cy.logout();
cy.visit("/");
// Log in
cy.contains("button", "Sign on with SimpleSAML");
cy.loginSSO({ username: "sso_user2" });
cy.url().should("include", "/login?status=account_invalid");
cy.getAttached(".flash-message");
});
it("non-existent users are provisioned if JIT is enabled", () => {
cy.login();
cy.setupSSO({
enable_sso_idp_login: true,
enable_jit_provisioning: true,
});
cy.logout();
cy.visit("/");
// Log in
cy.contains("button", "Sign on with SimpleSAML");
cy.loginSSO({ username: "sso_user2" });
cy.contains("Hosts");
cy.contains("was added to Fleet by SSO");
});
it("existing users can log-in normally with JIT enabled", () => {
cy.login();
cy.setupSSO({
enable_sso_idp_login: true,
enable_jit_provisioning: true,
});
cy.logout();
cy.visit("/");
// Log in
cy.contains("button", "Sign on with SimpleSAML");
cy.loginSSO({ username: "sso_user" });
cy.contains("Hosts");
});
});
});

View File

@ -1,213 +0,0 @@
import CONSTANTS from "../../support/constants";
import dashboardPage from "../pages/dashboardPage";
import hostDetailsPage from "../pages/hostDetailsPage";
import manageHostsPage from "../pages/manageHostsPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageQueriesPage from "../pages/manageQueriesPage";
import manageSchedulePage from "../pages/manageSchedulePage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import userProfilePage from "../pages/userProfilePage";
const { GOOD_PASSWORD } = CONSTANTS;
describe("Premium tier - Team Admin user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPremium();
cy.seedQueries();
cy.seedPolicies("apples");
cy.addDockerHost("apples"); // host not transferred
cy.addDockerHost("oranges"); // host transferred between teams by global admin
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
beforeEach(() => {
cy.loginWithCySession("anita@organization.com", GOOD_PASSWORD);
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended team admin top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/manage users/i).should("not.exist");
cy.findByText(/settings/i).click();
});
cy.getAttached(".react-tabs__tab--selected").within(() => {
cy.findByText(/members/i).should("exist");
});
cy.getAttached(".react-tabs__tab-list").within(() => {
cy.findByText(/agent options/i).should("exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays cards for team only, no activity card, and does not filter host platform", () => {
dashboardPage.displaysCards("team", "premium");
dashboardPage.verifiesFilteredHostByPlatform("none");
});
it("displays cards for windows only and filters hosts by Windows platform", () => {
dashboardPage.switchesPlatform("Windows");
dashboardPage.displaysCards("Windows", "premium");
dashboardPage.verifiesFilteredHostByPlatform("Windows");
});
it("displays cards for linux only and filters hosts by Linux platform", () => {
dashboardPage.switchesPlatform("Linux");
dashboardPage.displaysCards("Linux", "premium");
dashboardPage.verifiesFilteredHostByPlatform("Linux");
});
it("displays cards for macOS only and filters hosts by macOS platform", () => {
dashboardPage.switchesPlatform("macOS");
dashboardPage.displaysCards("macOS", "premium");
dashboardPage.verifiesFilteredHostByPlatform("macOS");
});
});
describe("Manage hosts page", () => {
beforeEach(() => {
manageHostsPage.visitsManageHostsPage();
});
it("should render elements according to role-based access controls", () => {
manageHostsPage.includesTeamColumn();
manageHostsPage.allowsAddHosts();
manageHostsPage.allowsManageAndAddSecrets();
});
});
describe("Host details page", () => {
beforeEach(() => hostDetailsPage.visitsHostDetailsPage(1));
it("allows team admin to create an operating system policy", () => {
hostDetailsPage.allowsCreateOsPolicy();
});
});
describe("Manage software page", () => {
beforeEach(() => manageSoftwarePage.visitManageSoftwarePage());
it("hides manage automations button", () => {
manageSoftwarePage.hidesButton("Manage automations");
});
});
describe("Query pages", () => {
beforeEach(() => manageQueriesPage.visitManageQueriesPage());
it("allows team admin to select teams targets for query", () => {
manageQueriesPage.allowsSelectTeamTargets();
});
it("disables team admin from deleting or editing a query not authored by them", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".fleet-checkbox__input").should("be.disabled");
});
cy.findAllByText(/detect presence/i).click();
});
cy.findByRole("button", { name: "Save" }).should("be.disabled");
});
});
describe("Manage schedules page", () => {
beforeEach(() => {
manageSchedulePage.visitManageSchedulePage();
});
it("hides advanced button when team admin", () => {
manageSchedulePage.confirmsTeam("Apples");
manageSchedulePage.hidesButton("Advanced");
});
it("creates a new team scheduled query", () => {
manageSchedulePage.allowsAddSchedule();
manageSchedulePage.verifiesAddedSchedule();
});
it("edit a team's scheduled query successfully", () => {
manageSchedulePage.allowsEditSchedule();
manageSchedulePage.verifiesEditedSchedule();
});
it("remove a team's scheduled query successfully", () => {
manageSchedulePage.allowsRemoveSchedule();
manageSchedulePage.verifiesRemovedSchedule();
});
});
describe("Manage policies page", () => {
beforeEach(() => managePoliciesPage.visitManagePoliciesPage());
it("allows team admin to add a new policy", () => {
managePoliciesPage.allowsAddDefaultPolicy();
managePoliciesPage.verifiesAddedDefaultPolicy();
});
it("allows team admin to edit a team policy", () => {
managePoliciesPage.visitManagePoliciesPage();
managePoliciesPage.allowsSelectRunSavePolicy();
});
it("allows team admin to automate a team policy", () => {
managePoliciesPage.allowsAutomatePolicy();
managePoliciesPage.verifiesAutomatedPolicy();
});
it("allows team admin to delete a team policy", () => {
managePoliciesPage.allowsDeletePolicy();
});
});
describe("Team admin settings page", () => {
beforeEach(() => cy.visit("/settings/teams/1/members"));
it("allows team admin to access team settings", () => {
// Access the Settings - Team details page
cy.findByText(/apples/i).should("exist");
});
it("displays the team admin controls", () => {
cy.findByRole("button", { name: /create user/i }).click({ force: true });
cy.findByRole("button", { name: /cancel/i }).click();
cy.findByRole("button", { name: /add hosts/i }).click();
cy.findByRole("button", { name: /done/i }).click();
cy.findByRole("button", { name: /manage enroll secrets/i }).click();
cy.findByRole("button", { name: /done/i }).click();
});
it("allows team admin to edit a team member", () => {
cy.getAttached("tbody").within(() => {
cy.getAttached("tr");
cy.contains("Toni") // case-sensitive
.parent()
.next()
.within(() => {
cy.findByText(/observer/i).should("exist");
})
.next()
.next()
.within(() => {
cy.findByText(/action/i).click();
cy.findByText(/edit/i).click();
});
});
cy.getAttached(".select-role-form__role-dropdown").within(() => {
cy.findByText(/observer/i).click();
cy.findByText(/maintainer/i).click();
});
cy.findByRole("button", { name: /save/i }).click();
cy.getAttached("tbody").within(() => {
cy.getAttached("tr");
cy.contains("Toni") // case-sensitive
.parent()
.next()
.within(() => {
cy.findByText(/maintainer/i).should("exist");
});
});
});
it("allows team admin to edit team name", () => {
cy.findByRole("button", { name: /edit team/i }).click();
cy.findByLabelText(/team name/i)
.clear()
.type("Mystic");
cy.findByRole("button", { name: /save/i }).click();
cy.findByText(/updated team name/i).should("exist");
});
});
describe("User profile page", () => {
it("should render elements according to role-based access controls", () => {
userProfilePage.visitUserProfilePage();
userProfilePage.showRole("Admin", "Mystic");
});
});
});

View File

@ -1,220 +0,0 @@
import CONSTANTS from "../../support/constants";
import dashboardPage from "../pages/dashboardPage";
import manageHostsPage from "../pages/manageHostsPage";
import managePacksPage from "../pages/managePacksPage";
import managePoliciesPage from "../pages/managePoliciesPage";
import manageSchedulePage from "../pages/manageSchedulePage";
import manageSoftwarePage from "../pages/manageSoftwarePage";
import teamsDropdown from "../pages/teamsDropdown";
import userProfilePage from "../pages/userProfilePage";
const { GOOD_PASSWORD } = CONSTANTS;
describe("Premium tier - Team observer/maintainer user", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPremium();
cy.seedQueries();
cy.seedPolicies("apples");
cy.addDockerHost("apples");
cy.addDockerHost("oranges");
});
after(() => {
cy.logout();
cy.stopDockerHost();
});
describe("Team maintainer and team observer", () => {
beforeEach(() => {
cy.loginWithCySession("marco@organization.com", GOOD_PASSWORD);
});
describe("Navigation", () => {
beforeEach(() => cy.visit("/dashboard"));
it("displays intended team maintainer and team observer top navigation", () => {
cy.getAttached(".site-nav-container").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/software/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/policies/i).should("exist");
cy.getAttached(".user-menu").click();
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/manage users/i).should("not.exist");
});
});
});
describe("Dashboard", () => {
beforeEach(() => dashboardPage.visitsDashboardPage());
it("displays cards for all platforms", () => {
dashboardPage.displaysCards("team", "premium");
});
it("displays cards for windows only", () => {
dashboardPage.switchesPlatform("Windows");
dashboardPage.displaysCards("Windows", "premium");
});
it("displays cards for linux only", () => {
dashboardPage.switchesPlatform("Linux");
dashboardPage.displaysCards("Linux", "premium");
});
it("displays cards for macOS only", () => {
dashboardPage.switchesPlatform("macOS");
dashboardPage.displaysCards("macOS", "premium");
});
it("views all hosts for all platforms", () => {
cy.findByText(/view all hosts/i).click();
cy.findByRole("status", { name: /hosts filtered by/i }).should(
"not.exist"
);
});
it("views all hosts for windows only", () => {
cy.getAttached(".dashboard-page__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/windows/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.findByRole("status", { name: /hosts filtered by Windows/i }).should(
"exist"
);
});
it("views all hosts for linux only", () => {
cy.getAttached(".dashboard-page__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/linux/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.findByRole("status", { name: /hosts filtered by Linux/i }).should(
"exist"
);
});
it("views all hosts for macOS only", () => {
cy.getAttached(".dashboard-page__platforms").within(() => {
cy.getAttached(".Select-control").click();
cy.findByText(/macos/i).click();
});
cy.findByText(/view all hosts/i).click();
cy.findByRole("status", { name: /hosts filtered by macOS/i }).should(
"exist"
);
});
});
});
describe("Team observer", () => {
beforeEach(() => {
cy.loginWithCySession("marco@organization.com", GOOD_PASSWORD);
});
describe("Manage hosts page", () => {
it("should render elements according to role-based access controls", () => {
manageHostsPage.visitsManageHostsPage();
cy.contains(/apples/i).should("exist");
manageHostsPage.includesTeamColumn();
manageHostsPage.hidesButton("Add label");
manageHostsPage.hidesButton("Add hosts");
manageHostsPage.hidesButton("Manage enroll secrets");
});
});
describe("Manage policies page", () => {
it("hides 'Manage automation' and 'Add a policy' buttons", () => {
managePoliciesPage.visitManagePoliciesPage();
cy.contains(/apples/i).should("exist");
managePoliciesPage.hidesButton("Manage automations");
managePoliciesPage.hidesButton("Add a policy");
});
});
describe("Policy detail page", () => {
it("allows view policy only", () => {
managePoliciesPage.visitManagePoliciesPage();
managePoliciesPage.allowsViewPolicyOnly();
});
});
// nav restrictions are at the end because we expect to see a
// 403 error overlay which will hide the nav and make the test fail
describe("Nav restrictions", () => {
it("should restrict navigation according to role-based access controls", () => {
dashboardPage.visitsDashboardPage();
cy.findByText(/settings/i).should("not.exist");
cy.findByText(/schedule/i).should("exist");
cy.visit("/settings/organization");
cy.findByText(/you do not have permissions/i).should("exist");
managePacksPage.visitsManagePacksPage();
cy.findByText(/you do not have permissions/i).should("exist");
});
});
});
describe("Team maintainer", () => {
// cypress tends to fail on uncaught exceptions. since we have
// our own error handling, it's suggested to use this block to
// suppress so the tests will keep running
Cypress.on("uncaught:exception", () => {
return false;
});
beforeEach(() => {
cy.loginWithCySession("marco@organization.com", GOOD_PASSWORD);
manageHostsPage.visitsManageHostsPage();
});
describe("Manage hosts page", () => {
it("should render elements according to role-based access controls", () => {
manageHostsPage.includesTeamColumn();
manageHostsPage.hidesButton("Add label");
// On maintaining team, see the "add hosts" and "Manage enroll secret" buttons
teamsDropdown.switchTeams("Apples", "Oranges");
manageHostsPage.includesTeamDropdown("Oranges");
manageHostsPage.allowsAddHosts();
manageHostsPage.allowsManageAndAddSecrets();
});
});
describe("Manage software page", () => {
beforeEach(() => manageSoftwarePage.visitManageSoftwarePage());
it("hides manage automations button", () => {
manageSoftwarePage.hidesButton("Manage automations");
});
});
describe("Manage schedule page", () => {
it("should render elements according to role-based access controls", () => {
manageSchedulePage.visitManageSchedulePage();
manageSchedulePage.confirmsTeam("Oranges");
manageSchedulePage.hidesButton("Advanced");
manageSchedulePage.allowsAddSchedule();
manageSchedulePage.verifiesAddedSchedule();
});
});
describe("Manage policies page", () => {
it("allows team maintainer to add, edit a policy, but not manage automation", () => {
managePoliciesPage.visitManagePoliciesPage();
teamsDropdown.switchTeams("Apples", "Oranges");
managePoliciesPage.hidesButton("Manage automations");
managePoliciesPage.allowsAddDefaultPolicy();
managePoliciesPage.verifiesAddedDefaultPolicy();
});
});
describe("User profile page", () => {
it("verifies user role and team", () => {
userProfilePage.visitUserProfilePage();
userProfilePage.showRole("Various", "2 teams");
});
});
// nav restrictions are at the end because we expect to see a
// 403 error overlay which will hide the nav and make the test fail
describe("Nav restrictions", () => {
it("should restrict navigation according to role-based access controls", () => {
dashboardPage.visitsDashboardPage();
cy.contains("h2", "Hosts").should("exist");
cy.getAttached("nav").within(() => {
cy.findByText(/hosts/i).should("exist");
cy.findByText(/queries/i).should("exist");
cy.findByText(/schedule/i).should("exist");
cy.findByText(/packs/i).should("not.exist");
cy.findByText(/settings/i).should("not.exist");
});
});
});
});
});

View File

@ -1,147 +0,0 @@
import manageSchedulePage from "../pages/manageSchedulePage";
describe("Teams flow (empty)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Teams settings page", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/settings/teams");
});
it("creates a new team", () => {
cy.getAttached(".empty-table__cta-buttons").within(() => {
cy.contains("button", /create team/i).click();
});
cy.findByLabelText(/team name/i)
.click()
.type("Valor");
cy.getAttached(".create-team-modal .modal-cta-wrap").within(() => {
// ^$ forces exact match
cy.findByRole("button", { name: /^create$/i }).click();
});
cy.findByText(/successfully created valor/i).should("exist");
});
});
});
describe("Teams flow (seeded)", () => {
before(() => {
Cypress.session.clearAllSavedSessions();
cy.setup();
cy.loginWithCySession();
cy.seedPremium();
cy.seedQueries();
cy.viewport(1200, 660);
});
after(() => {
cy.logout();
});
describe("Teams settings page", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/settings/teams");
});
it("edits name of an existing team", () => {
cy.getAttached(".table-container").within(() => {
cy.contains("Apples");
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".Select-arrow-zone").click();
cy.findByText(/edit/i).click({ force: true });
});
});
});
cy.getAttached(".edit-team-modal").within(() => {
cy.findByLabelText(/team name/i)
.clear()
.type("Bananas");
cy.findByRole("button", { name: /save/i }).click();
});
cy.findByText(/updated team name/i).should("be.visible");
cy.findByText(/apples/i).should("not.exist");
});
it("deletes an existing team", () => {
cy.getAttached(".table-container").within(() => {
cy.contains("Bananas");
cy.getAttached("tbody").within(() => {
cy.getAttached("tr")
.first()
.within(() => {
cy.getAttached(".Select-arrow-zone").click();
cy.findByText(/delete/i).click({ force: true });
});
});
});
cy.getAttached(".delete-team-modal .modal-cta-wrap").within(() => {
cy.findByRole("button", { name: /delete/i }).click();
});
cy.findByText(/successfully deleted/i).should("be.visible");
cy.findByText(/bananas/i).should("not.exist");
});
});
describe("Manage schedules page", () => {
beforeEach(() => {
cy.loginWithCySession();
manageSchedulePage.visitManageSchedulePage();
});
it("adds a query to team schedule", () => {
manageSchedulePage.changesTeam("All teams", "Oranges");
manageSchedulePage.allowsAddSchedule();
manageSchedulePage.verifiesAddedSchedule();
});
});
describe("Team details page", () => {
beforeEach(() => {
cy.loginWithCySession();
cy.visit("/settings/teams");
cy.getAttached(".table-container").within(() => {
cy.contains("Oranges").click({ force: true });
});
});
it("allows to add new enroll secret to team", () => {
cy.getAttached(".team-details__action-buttons--secondary-buttons")
.contains("button", /manage enroll secret/i)
.click();
cy.getAttached(".enroll-secret-modal__add-secret")
.contains("button", /add secret/i)
.click();
cy.getAttached(".secret-editor-modal .modal-cta-wrap")
.contains("button", /save/i)
.click();
cy.getAttached(".enroll-secret-modal .modal-cta-wrap")
.contains("button", /done/i)
.click();
});
it("allows to see and click 'Add hosts'", () => {
cy.getAttached(".team-details__action-buttons--primary")
.contains("button", /add hosts/i)
.click();
cy.getAttached(".modal__content").contains("button", /done/i).click();
});
it("edits agent options of an existing team", () => {
cy.findByText(/agent options/i).click();
cy.contains(".ace_content", "config:");
cy.getAttached(".ace_text-input")
.first()
.focus()
.type("{selectall}{backspace}config:\n options:");
cy.findByRole("button", { name: /save options/i }).click();
cy.contains("span", /successfully updated/i).should("exist");
cy.visit("/settings/teams/2/options");
cy.contains(/config:/i).should("be.visible");
cy.contains(/options:/i).should("be.visible");
});
});
});

View File

@ -1,12 +0,0 @@
const AppSettingsPage = {
visitAgentOptions: () => {
cy.visit("/settings/organization/agents");
},
editAgentOptionsForm: (text: string) => {
cy.findByRole("textbox").type(text, { force: true });
cy.findByRole("button", { name: /save/i }).should("be.enabled").click();
},
};
export default AppSettingsPage;

View File

@ -1,12 +0,0 @@
const TeamSettingsPage = {
visitTeamAgentOptions: (id: number) => {
cy.visit(`settings/teams/${id}/options`);
},
editAgentOptionsForm: (text: string) => {
cy.findByRole("textbox").type(text, { force: true });
cy.findByRole("button", { name: /save/i }).click();
},
};
export default TeamSettingsPage;

View File

@ -1,21 +0,0 @@
// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
module.exports = () => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
};

View File

@ -1,489 +0,0 @@
import "@testing-library/cypress/add-commands";
import "cypress-wait-until";
import CONSTANTS from "./constants";
const { GOOD_PASSWORD } = CONSTANTS;
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
const SHELL = Cypress.platform === "win32" ? "cmd" : "bash";
Cypress.Commands.add("setup", () => {
cy.exec("make e2e-reset-db e2e-setup", {
timeout: 20000,
env: { SHELL },
});
});
Cypress.Commands.add("setupWithSoftware", () => {
cy.exec("make e2e-reset-db e2e-setup-with-software", {
timeout: 20000,
env: { SHELL },
});
});
Cypress.Commands.add("login", (email, password) => {
email ||= "admin@example.com";
password ||= GOOD_PASSWORD;
cy.request("POST", "/api/latest/fleet/login", { email, password }).then(
(resp) => {
window.localStorage.setItem("FLEET::auth_token", resp.body.token);
}
);
});
Cypress.Commands.add("loginWithCySession", (email, password) => {
email ||= "admin@example.com";
password ||= GOOD_PASSWORD;
cy.session([email, password], () => {
cy.request("POST", "/api/latest/fleet/login", { email, password }).then(
(resp) => {
window.localStorage.setItem("FLEET::auth_token", resp.body.token);
}
);
});
});
Cypress.Commands.add("logout", () => {
cy.request({
url: "/api/latest/fleet/logout",
method: "POST",
body: {},
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
}).then(() => {
window.localStorage.removeItem("FLEET::auth_token");
});
});
Cypress.Commands.add("setDesktopToken", (hostId, token) => {
cy.exec(`make e2e-set-desktop-token host_id=${hostId} token=${token}`, {
timeout: 20000,
env: { SHELL },
});
});
Cypress.Commands.add("seedQueries", () => {
const queries = [
{
name: "Detect presence of authorized SSH keys",
query:
"SELECT username, authorized_keys. * FROM users CROSS JOIN authorized_keys USING (uid)",
description:
"Presence of authorized SSH keys may be unusual on laptops. Could be completely normal on servers, but may be worth auditing for unusual keys and/or changes.",
observer_can_run: true,
},
{
name: "Get authorized keys for Domain Joined Accounts",
query:
"SELECT * FROM users CROSS JOIN authorized_keys USING(uid) WHERE username IN (SELECT distinct(username) FROM last);",
description: "List authorized_keys for each user on the system.",
observer_can_run: false,
},
{
name: "Get local user accounts",
query:
"SELECT uid, gid, username, description,directory, shell FROM users;",
description:
"Local user accounts (including domain accounts that have logged on locally (Windows)).",
observer_can_run: false,
},
];
queries.forEach((queryForm) => {
const { name, query, description, observer_can_run } = queryForm;
cy.request({
url: "/api/latest/fleet/queries",
method: "POST",
body: { name, query, description, observer_can_run },
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
});
});
});
Cypress.Commands.add("seedSchedule", () => {
const scheduledQueries = [
{
interval: 86400,
platform: "",
query_id: 1,
removed: false,
shard: null,
snapshot: true,
version: "",
},
{
interval: 604800,
platform: "linux",
query_id: 2,
removed: true,
shard: 50,
snapshot: false,
version: "4.6.0",
},
];
scheduledQueries.forEach((scheduleForm) => {
const {
interval,
platform,
query_id,
removed,
shard,
snapshot,
version,
} = scheduleForm;
cy.request({
url: "/api/latest/fleet/schedule",
method: "POST",
body: { interval, platform, query_id, removed, shard, snapshot, version },
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
});
});
});
// @ts-ignore
Cypress.Commands.add("seedPacks", () => {
const packs = [
{
name: "Mac starter pack",
description: "Run all queries weekly on Mac hosts",
},
{
name: "Windows starter pack",
description: "Run all queries weekly on Windows hosts",
},
];
packs.forEach((packForm) => {
const { name, description } = packForm;
cy.request({
url: "/api/latest/fleet/packs",
method: "POST",
body: { name, description, host_ids: [], label_ids: [], team_ids: [] },
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
});
});
});
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.",
platform: "darwin,linux",
},
{
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",
platform: "darwin,windows,linux",
},
{
name: "Is Ubuntu, version 16.4.0 or later, installed?",
query:
"SELECT 1 from os_version WHERE name = 'Ubuntu' AND major || '.' || minor || '.' || patch >= '16.4.0';",
description:
"Returns yes or no for detecting operating system and version",
resolution: "Update OS if needed",
platform: "",
},
];
if (team === "apples") {
policies.forEach((policyForm) => {
cy.request({
url: "/api/latest/fleet/teams/1/policies",
method: "POST",
body: { ...policyForm },
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
});
});
} else {
policies.forEach((policyForm) => {
cy.request({
url: "/api/latest/fleet/policies",
method: "POST",
body: { ...policyForm },
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
});
});
}
});
Cypress.Commands.add("setupSMTP", () => {
const body = {
smtp_settings: {
authentication_type: "authtype_none",
enable_smtp: true,
port: 1025,
sender_address: "fleet@example.com",
server: "localhost",
},
};
cy.request({
url: "/api/latest/fleet/config",
method: "PATCH",
body,
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
});
});
Cypress.Commands.add("setupSSO", (options) => {
const body = {
sso_settings: Object.assign(
{},
{
enable_sso: true,
enable_sso_idp_login: false,
enable_jit_provisioning: false,
entity_id: "https://localhost:8080",
idp_name: "SimpleSAML",
issuer_uri: "http://localhost:8080/simplesaml/saml2/idp/SSOService.php",
metadata_url: "http://localhost:9080/simplesaml/saml2/idp/metadata.php",
},
options
),
};
cy.request({
url: "/api/latest/fleet/config",
method: "PATCH",
body,
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
});
});
Cypress.Commands.add(
"loginSSO",
({ username = "sso_user", password = "user123#" } = {}) => {
// Note these requests set cookies that are required for the SSO flow to
// work properly. This is handled automatically by the browser.
cy.request({
method: "GET",
url:
"http://localhost:9080/simplesaml/saml2/idp/SSOService.php?spentityid=https://localhost:8080",
followRedirect: false,
}).then((firstResponse) => {
const redirect = firstResponse.headers.location as string;
cy.request({
method: "GET",
url: redirect,
followRedirect: false,
}).then((secondResponse) => {
const el = document.createElement("html");
el.innerHTML = secondResponse.body;
const authState = el
.getElementsByTagName("input")
.namedItem("AuthState").defaultValue;
cy.request({
method: "POST",
url: redirect,
body: `username=${username}&password=${password}&AuthState=${authState}`,
form: true,
followRedirect: false,
}).then((finalResponse) => {
el.innerHTML = finalResponse.body;
const saml = el
.getElementsByTagName("input")
.namedItem("SAMLResponse").defaultValue;
// Load the callback URL with the response from the IdP
cy.visit({
url: "/api/v1/fleet/sso/callback",
method: "POST",
body: {
SAMLResponse: saml,
},
});
});
});
});
}
);
Cypress.Commands.add("getEmails", () => {
return cy
.request("http://localhost:8025/api/v2/messages")
.then((response) => {
expect(response.status).to.eq(200);
return response;
});
});
Cypress.Commands.add("seedFree", () => {
const authToken = window.localStorage.getItem("FLEET::auth_token");
cy.exec("bash ./tools/api/fleet/teams/create_free", {
env: {
TOKEN: authToken,
CURL_FLAGS: "-k",
SERVER_URL: Cypress.config().baseUrl,
// clear any value for FLEET_ENV_PATH since we set the environment explicitly just above
FLEET_ENV_PATH: "",
SHELL,
},
});
});
Cypress.Commands.add("seedPremium", () => {
const authToken = window.localStorage.getItem("FLEET::auth_token");
cy.exec("bash ./tools/api/fleet/teams/create_premium", {
env: {
TOKEN: authToken,
CURL_FLAGS: "-k",
SERVER_URL: Cypress.config().baseUrl,
// clear any value for FLEET_ENV_PATH since we set the environment explicitly just above
FLEET_ENV_PATH: "",
SHELL,
},
});
});
Cypress.Commands.add("seedFigma", () => {
const authToken = window.localStorage.getItem("FLEET::auth_token");
cy.exec("bash ./tools/api/fleet/teams/create_figma", {
env: {
TOKEN: authToken,
CURL_FLAGS: "-k",
SERVER_URL: Cypress.config().baseUrl,
// clear any value for FLEET_ENV_PATH since we set the environment explicitly just above
FLEET_ENV_PATH: "",
SHELL,
},
});
});
Cypress.Commands.add("addUser", (options = {}) => {
let { password, email, globalRole } = options;
password ||= GOOD_PASSWORD;
email ||= `admin@example.com`;
globalRole ||= "admin";
cy.exec(
`./build/fleetctl user create --context e2e --password "${password}" --email "${email}" --global-role "${globalRole}"`,
{
timeout: 5000,
env: { SHELL },
}
);
});
// Ability to add a docker host to a team using args if ran after seedPremium()
Cypress.Commands.add("addDockerHost", (team = "") => {
const serverPort = new URL(Cypress.config().baseUrl).port;
// Get enroll secret
let enrollSecretUrl = "/api/latest/fleet/spec/enroll_secret";
if (team === "apples") {
enrollSecretUrl = "/api/latest/fleet/teams/1/secrets";
} else if (team === "oranges") {
enrollSecretUrl = "/api/latest/fleet/teams/2/secrets";
}
cy.request({
url: enrollSecretUrl,
auth: {
bearer: window.localStorage.getItem("FLEET::auth_token"),
},
}).then(({ body }) => {
const enrollSecret =
team === "" ? body.spec.secrets[0].secret : body.secrets[0].secret;
// Start up docker-compose with enroll secret
cy.exec(
"docker-compose -f tools/osquery/docker-compose.yml up -d ubuntu20-osquery",
{
env: {
ENROLL_SECRET: enrollSecret,
FLEET_SERVER: `host.docker.internal:${serverPort}`,
SHELL,
},
}
);
});
});
Cypress.Commands.add("stopDockerHost", () => {
// Start up docker-compose with enroll secret
cy.exec("docker-compose -f tools/osquery/docker-compose.yml stop", {
env: {
// Not that ENROLL_SECRET must be specified or docker-compose errors,
// even when just trying to shut down the hosts.
ENROLL_SECRET: "invalid",
SHELL,
},
});
});
Cypress.Commands.add("clearDownloads", () => {
// windows has issue with downloads location
if (Cypress.platform !== "win32") {
cy.exec(`rm -rf ${Cypress.config("downloadsFolder")}`, { env: { SHELL } });
}
});
Cypress.Commands.add("getAttached", (selector) => {
const uniqueAlias = `element_${selector}`;
return cy
.waitUntil(
() =>
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.get(selector)
.as(uniqueAlias)
.wait(1)
.then(($el) => Cypress.dom.isAttached($el)),
{ timeout: 10000, interval: 10 }
)
.get(`@${uniqueAlias}`);
});

View File

@ -1,245 +0,0 @@
const GOOD_PASSWORD = "password123#";
const BAD_PASSWORD_LENGTH = "password12#";
const BAD_PASSWORD_NO_NUMBER = "password####";
const BAD_PASSWORD_NO_SYMBOL = "password1234";
const CONFIG_INTEGRATIONS_AUTOMATIONS = {
org_info: {
org_name: "Fleet Test",
org_logo_url: "",
},
server_settings: {
server_url: "https://localhost:8642",
live_query_disabled: false,
enable_analytics: true,
deferred_save_host: false,
},
smtp_settings: {
enable_smtp: false,
configured: false,
sender_address: "",
server: "",
port: 587,
authentication_type: "authtype_username_password",
user_name: "",
password: "",
enable_ssl_tls: true,
authentication_method: "authmethod_plain",
domain: "",
verify_ssl_certs: true,
enable_start_tls: true,
},
host_expiry_settings: {
host_expiry_enabled: true,
host_expiry_window: 9,
},
features: {
enable_host_users: true,
enable_software_inventory: true,
},
agent_options: {
config: {
options: {
pack_delimiter: "/",
logger_tls_period: 10,
distributed_plugin: "tls",
disable_distributed: false,
logger_tls_endpoint: "/api/osquery/log",
distributed_interval: 10,
distributed_tls_max_attempts: 3,
},
decorators: {
load: [
"SELECT uuid AS host_uuid FROM system_info;",
"SELECT hostname AS hostname FROM system_info;",
],
},
},
overrides: {},
},
sso_settings: {
entity_id: "",
issuer_uri: "",
idp_image_url: "",
metadata: "",
metadata_url: "",
idp_name: "",
enable_sso: false,
enable_sso_idp_login: false,
enable_jit_provisioning: false,
},
vulnerability_settings: {
databases_path: "",
},
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: false,
destination_url: "",
host_percentage: 0,
days_count: 0,
},
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://www.foo.com/bar",
policy_ids: [5, 10],
host_batch_size: 0,
},
vulnerabilities_webhook: {
enable_vulnerabilities_webhook: false,
destination_url: "",
host_batch_size: 0,
},
interval: "24h0m0s",
},
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: true,
enable_software_vulnerabilities: true,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
update_interval: {
osquery_detail: 3600000000000,
osquery_policy: 3600000000000,
},
vulnerabilities: {
databases_path: "/tmp/vulndbs",
periodicity: 3600000000000,
cpe_database_url: "",
cve_feed_prefix_url: "",
current_instance_checks: "auto",
disable_data_sync: false,
recent_vulnerability_max_age: 2592000000000000,
},
license: {
tier: "premium",
organization: "development-only",
device_count: 100,
expiration: "2099-06-30T20:00:00-04:00",
note: "for development only",
},
logging: {
debug: false,
json: false,
result: {
plugin: "filesystem",
config: {
status_log_file:
"/var/folders/xh/bxm1d2615tv3vrg4zrxq540h0000gn/T/osquery_status",
result_log_file:
"/var/folders/xh/bxm1d2615tv3vrg4zrxq540h0000gn/T/osquery_result",
enable_log_rotation: false,
enable_log_compression: false,
},
},
status: {
plugin: "filesystem",
config: {
status_log_file:
"/var/folders/xh/bxm1d2615tv3vrg4zrxq540h0000gn/T/osquery_status",
result_log_file:
"/var/folders/xh/bxm1d2615tv3vrg4zrxq540h0000gn/T/osquery_result",
enable_log_rotation: false,
enable_log_compression: false,
},
},
},
};
const CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED = {
...CONFIG_INTEGRATIONS_AUTOMATIONS,
integrations: {
jira: [
{
url: "https://fleetdm.atlassian.com",
username: "jira1@example.com",
api_token: "jira123",
project_key: "PROJECT 1",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.atlassian.com",
username: "jira2@example.com",
api_token: "jira123",
project_key: "PROJECT 2",
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
zendesk: [
{
url: "https://fleetdm.zendesk.com",
email: "zendesk1@example.com",
api_token: "zendesk123",
group_id: 12345678,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
{
url: "https://fleetdm.zendesk.com",
email: "zendesk2@example.com",
api_token: "zendesk123",
group_id: 87654321,
enable_failing_policies: false,
enable_software_vulnerabilities: false,
},
],
},
webhook_settings: {
host_status_webhook: {
enable_host_status_webhook: false,
destination_url: "",
host_percentage: 0,
days_count: 0,
},
failing_policies_webhook: {
enable_failing_policies_webhook: false,
destination_url: "https://www.foo.com/bar",
policy_ids: [5, 10],
host_batch_size: 0,
},
vulnerabilities_webhook: {
destination_url: "http://www.foo.com/bar",
enable_vulnerabilities_webhook: false,
},
},
};
export default {
GOOD_PASSWORD,
BAD_PASSWORD_LENGTH,
BAD_PASSWORD_NO_NUMBER,
BAD_PASSWORD_NO_SYMBOL,
CONFIG_INTEGRATIONS_AUTOMATIONS,
CONFIG_INTEGRATIONS_AUTOMATIONS_DISABLED,
};

View File

@ -1,140 +0,0 @@
// load type definitions that come with Cypress module
// <reference types="cypress" />
declare namespace Cypress {
interface Chainable {
/**
* Custom command to setup the testing environment.
*/
setup(): Chainable<Element>;
/**
* Custom command to setup the testing environment with fixture data for software and vulnerabilities.
*/
setupWithSoftware(): Chainable<Element>;
/**
* Custom command to login the user programmatically using the fleet API.
*/
login(email?: string, password?: string): Chainable<Element>;
/**
* Custom command to login the user programmatically using the fleet API
* but with a Cypress session wrapper.
*/
loginWithCySession(email?: string, password?: string): Chainable<Element>;
/**
* Custom command to log out the current user.
*/
logout(): Chainable<Element>;
/**
* Custom command to set a Fleet Desktop token to a host.
*/
setDesktopToken(hostId?: number, token?: string): Chainable<Element>;
/**
* Custom command to add new queries by default.
*/
seedQueries(): Chainable<Element>;
/**
* Custom command to add new scheduled queries by default.
*/
seedSchedule(): Chainable<Element>;
/**
* Custom command to add new policies by default.
*/
seedPolicies(teamName?: string): Chainable<Element>;
/**
* Custom command to add a new user in Fleet (via fleetctl).
*/
addUser(options?: {
email?: string;
password?: string;
globalRole?: string;
}): Chainable<Element>;
/**
* Custom command to setup the SMTP configuration for this testing environment.
*
* NOTE: login() command is required before this, as it will make authenticated
* requests.
*/
setupSMTP(): Chainable<Element>;
/**
* Custom command to set up SSO auth with the local server.
*
* NOTE: login() command is required before this, as it will make authenticated
* requests.
*/
setupSSO(options?: {
enable_sso_idp_login?: boolean;
enable_jit_provisioning?: boolean;
}): Chainable<Element>;
/**
* Custom command to login a user1@example.com via SSO.
*/
loginSSO(options?: {
username?: string;
password?: string;
}): Chainable<Element>;
/**
* Custom command to get the emails handled by the Mailhog server.
*/
getEmails(): Chainable;
/**
* Custom command to seed the Free tier teams/users.
*
* NOTE: login() command is required before this, as it will make authenticated
* requests.
*/
seedFree(): Chainable<Element>;
/**
* Custom command to seed the Premium tier teams/users.
*
* NOTE: login() command is required before this, as it will make authenticated
* requests.
*/
seedPremium(): Chainable<Element>;
/**
* Custom command to seed the teams/users as represented in Figma.
*
* NOTE: login() command is required before this, as it will make authenticated
* requests.
*/
seedFigma(): Chainable<Element>;
/**
* Custom command to add Docker osquery host.
*
* NOTE: login() command is required before this, as it will make authenticated
* requests.
*/
addDockerHost(teamName?: string): Chainable;
/**
* Custom command to stop any running Docker hosts.
*/
stopDockerHost(): Chainable;
/**
* Custom command to clear downloaded files from test machine.
*/
clearDownloads(): Chainable;
/**
* Custom command to get any element describe only if it is attached to the DOM.
*/
getAttached(selector: string): Chainable;
}
}

View File

@ -1,17 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import "./commands";

View File

@ -1,13 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": [
"cypress",
"@testing-library/cypress",
"node",
"cypress-wait-until"
]
},
"include": ["**/*.ts"]
}

View File

@ -4,16 +4,10 @@
"description": "The premier osquery fleet manager.",
"private": true,
"scripts": {
"lint": "eslint frontend cypress --ext .js,.jsx,.ts,.tsx",
"prettier:check": "prettier --check frontend/**/*.{jsx,js,tsx,ts} ./cypress/**/*.{js,ts}",
"lint": "eslint frontend --ext .js,.jsx,.ts,.tsx",
"prettier:check": "prettier --check frontend/**/*.{jsx,js,tsx,ts}",
"test": "jest --config ./frontend/test/jest.config.ts",
"test:ci": "jest --config ./frontend/test/jest.config.ts --ci --coverage",
"e2e-browser": "cypress open",
"e2e-browser:free": "yarn cypress open --config-file cypress/cypress-free.json",
"e2e-browser:premium": "yarn cypress open --config-file cypress/cypress-premium.json",
"e2e-cli": "cypress run",
"e2e-cli:free": "yarn cypress run --config-file cypress/cypress-free.json",
"e2e-cli:premium": "yarn cypress run --config-file cypress/cypress-premium.json",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
@ -90,14 +84,12 @@
"@storybook/addon-mdx-gfm": "7.0.7",
"@storybook/react": "7.0.7",
"@storybook/react-webpack5": "7.0.7",
"@testing-library/cypress": "8.0.2",
"@testing-library/jest-dom": "5.16.2",
"@testing-library/react": "12.1.4",
"@testing-library/user-event": "14.4.3",
"@tsconfig/recommended": "1.0.1",
"@types/chrome": "0.0.237",
"@types/classnames": "0.0.32",
"@types/cypress": "1.1.3",
"@types/expect": "1.20.3",
"@types/file-saver": "2.0.5",
"@types/js-md5": "0.4.3",
@ -126,14 +118,11 @@
"bourbon": "5.1.0",
"classnames": "2.2.5",
"css-loader": "6.7.3",
"cypress": "9.5.1",
"cypress-wait-until": "1.7.2",
"esbuild-loader": "2.18.0",
"eslint": "7.32.0",
"eslint-config-airbnb": "15.1.0",
"eslint-config-prettier": "8.5.0",
"eslint-import-resolver-webpack": "0.10.0",
"eslint-plugin-cypress": "2.12.1",
"eslint-plugin-import": "2.25.4",
"eslint-plugin-jest": "20.0.3",
"eslint-plugin-jsx-a11y": "5.1.1",

595
yarn.lock

File diff suppressed because it is too large Load Diff