diff --git a/pkg/ui/workspaces/e2e-tests/cypress/e2e/health-check/authenticated.cy.ts b/pkg/ui/workspaces/e2e-tests/cypress/e2e/health-check/authenticated.cy.ts index c16cf3e9c9fe..7308643d2daf 100644 --- a/pkg/ui/workspaces/e2e-tests/cypress/e2e/health-check/authenticated.cy.ts +++ b/pkg/ui/workspaces/e2e-tests/cypress/e2e/health-check/authenticated.cy.ts @@ -8,9 +8,14 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. +import { SQLPrivilege } from "../../support/types"; + describe("health check: authenticated user", () => { it("serves a DB Console overview page", () => { - cy.login(); + cy.getUserWithExactPrivileges([SQLPrivilege.ADMIN]); + cy.fixture("users").then((users) => { + cy.login(users[0].username, users[0].password); + }); // Ensure that something reasonable renders at / when authenticated, making // just enough assertions to ensure the right page loaded. If this test diff --git a/pkg/ui/workspaces/e2e-tests/cypress/e2e/statementBundles/statementBundles.cy.ts b/pkg/ui/workspaces/e2e-tests/cypress/e2e/statementBundles/statementBundles.cy.ts new file mode 100644 index 000000000000..11fa08462ff5 --- /dev/null +++ b/pkg/ui/workspaces/e2e-tests/cypress/e2e/statementBundles/statementBundles.cy.ts @@ -0,0 +1,91 @@ +// Copyright 2024 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +import { SQLPrivilege } from "../../support/types"; + +// TODO (xinhaoz): This test currently only works when running pnpm run cy:run +// directly against a local cluster set up with sql activity in the last hour +// and the expected cypress users in fixtures. We need to automate this server +// setup for e2e testing. +describe("statement bundles", () => { + const runTestsForPrivilegedUser = (privilege: SQLPrivilege) => { + describe(`${privilege} user`, () => { + beforeEach(() => { + cy.getUserWithExactPrivileges([privilege]).then((user) => { + cy.login(user.username, user.password); + }); + }); + + it("can request statement bundles", () => { + cy.visit("#/sql-activity"); + cy.contains("button", "Apply").click(); + // Open modal. + cy.contains("button", "Activate").click(); + // Wait for modal. + cy.findByText(/activate statement diagnostics/i).should("be.visible"); + // Click the Activate button within the modal + cy.get(`[role="dialog"]`) // Adjust this selector to match your modal's structure + .contains("button", "Activate") + .click(); + cy.findByText(/statement diagnostics were successfully activated/i); + }); + + it("can view statement bundles", () => { + cy.visit("#/reports/statements/diagnosticshistory"); + cy.get("table tbody tr").should("have.length.at.least", 1); + }); + + it("can cancel statement bundles", () => { + cy.visit("#/reports/statements/diagnosticshistory"); + cy.get("table tbody tr").should("have.length.at.least", 1); + cy.contains("button", "Cancel").click(); + cy.findByText(/statement diagnostics were successfully cancelled/i); + }); + }); + }; + + const runTestsForNonPrivilegedUser = (privilege?: SQLPrivilege) => { + beforeEach(() => { + cy.getUserWithExactPrivileges(privilege ? [privilege] : []).then( + (user) => { + cy.login(user.username, user.password); + }, + ); + }); + + it("cannot request statement bundles", () => { + cy.visit("#/sql-activity"); + cy.contains("button", "Apply").click(); + // Should not see an Activate button. + cy.contains("button", "Activate").should("not.exist"); + }); + + it("cannot view statement bundles", () => { + cy.visit("#/reports/statements/diagnosticshistory"); + cy.findByText(/no statement diagnostics to show/i); + }); + }; + + describe("view activity user", () => { + runTestsForPrivilegedUser(SQLPrivilege.VIEWACTIVITY); + }); + + describe("admin user", () => { + runTestsForPrivilegedUser(SQLPrivilege.ADMIN); + }); + + describe("non-privileged VIEWACTIVITYREDACTED user", () => { + runTestsForNonPrivilegedUser(SQLPrivilege.VIEWACTIVITYREDACTED); + }); + + describe("non-privileged user", () => { + runTestsForNonPrivilegedUser(); + }); +}); diff --git a/pkg/ui/workspaces/e2e-tests/cypress/fixtures/users.json b/pkg/ui/workspaces/e2e-tests/cypress/fixtures/users.json new file mode 100644 index 000000000000..606d8e4a91f6 --- /dev/null +++ b/pkg/ui/workspaces/e2e-tests/cypress/fixtures/users.json @@ -0,0 +1,28 @@ +[ + { + "username": "cypress", + "password": "tests", + "sqlPrivileges": [ + "ADMIN" + ] + }, + { + "username": "va_user", + "password": "cypress", + "sqlPrivileges": [ + "VIEWACTIVITY" + ] + }, + { + "username": "va_redacted_user", + "password": "cypress", + "sqlPrivileges": [ + "VIEWACTIVITYREDACTED" + ] + }, + { + "username": "no_privs_user", + "password": "cypress", + "sqlPrivileges": [] + } +] diff --git a/pkg/ui/workspaces/e2e-tests/cypress/support/commands.ts b/pkg/ui/workspaces/e2e-tests/cypress/support/commands.ts index f7b291b090fa..d24216d00675 100644 --- a/pkg/ui/workspaces/e2e-tests/cypress/support/commands.ts +++ b/pkg/ui/workspaces/e2e-tests/cypress/support/commands.ts @@ -9,15 +9,16 @@ // licenses/APL.txt. import "@testing-library/cypress/add-commands"; +import { SQLPrivilege, User } from "./types"; -Cypress.Commands.add("login", () => { +Cypress.Commands.add("login", (username: string, password: string) => { cy.request({ method: "POST", url: "/api/v2/login/", form: true, body: { - username: Cypress.env("username"), - password: Cypress.env("password"), + username: username, + password: password, }, failOnStatusCode: true, }).then(({ body }) => { @@ -33,3 +34,14 @@ Cypress.Commands.add("login", () => { } }); }); + +// Gets a user from the users.json fixture with the given privileges. +Cypress.Commands.add("getUserWithExactPrivileges", (privs: SQLPrivilege[]) => { + return cy.fixture("users").then((users) => { + return users.find( + (user: User) => + privs.every((priv) => user.sqlPrivileges.includes(priv)) || + (privs.length === 0 && user.sqlPrivileges.length === 0), + ); + }); +}); diff --git a/pkg/ui/workspaces/e2e-tests/cypress/support/index.ts b/pkg/ui/workspaces/e2e-tests/cypress/support/index.ts index f017e842a498..c7cc68479de4 100644 --- a/pkg/ui/workspaces/e2e-tests/cypress/support/index.ts +++ b/pkg/ui/workspaces/e2e-tests/cypress/support/index.ts @@ -24,6 +24,7 @@ // *********************************************************** import "./commands"; +import { SQLPrivilege, User } from "./types"; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace -- required for declaration merging @@ -33,10 +34,11 @@ declare global { * Sets a session cookie for the demo user on the current * database. * @example - * cy.login(); + * cy.login("cypress", "tests"); * cy.visit("#/some/authenticated/route"); */ - login(): void; + login(username: string, password: string): Chainable; + getUserWithExactPrivileges(privs: SQLPrivilege[]): Chainable; } } } diff --git a/pkg/ui/workspaces/e2e-tests/cypress/support/types.ts b/pkg/ui/workspaces/e2e-tests/cypress/support/types.ts new file mode 100644 index 000000000000..e545d0ee7374 --- /dev/null +++ b/pkg/ui/workspaces/e2e-tests/cypress/support/types.ts @@ -0,0 +1,22 @@ +// Copyright 2024 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +export enum SQLPrivilege { + ADMIN = "ADMIN", + VIEWACTIVITY = "VIEWACTIVITY", + VIEWACTIVITYREDACTED = "VIEWACTIVITYREDACTED", + NONE = "NONE", +} + +export type User = { + username: string; + password: string; + sqlPrivileges: SQLPrivilege[]; +};