test: e2e oidc (#11129)
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>pull/11356/head^2
parent
c820a3937a
commit
fd507f1d12
15
.env.example
15
.env.example
|
@ -229,3 +229,18 @@ AUTH_BEARER_TOKEN_VERCEL=
|
|||
# Used for E2E tests on Apple Calendar
|
||||
E2E_TEST_APPLE_CALENDAR_EMAIL=""
|
||||
E2E_TEST_APPLE_CALENDAR_PASSWORD=""
|
||||
|
||||
# - OIDC E2E TEST *******************************************************************************************
|
||||
|
||||
# Ensure this ADMIN EMAIL is present in the SAML_ADMINS list
|
||||
E2E_TEST_SAML_ADMIN_EMAIL=
|
||||
E2E_TEST_SAML_ADMIN_PASSWORD=
|
||||
|
||||
E2E_TEST_OIDC_CLIENT_ID=
|
||||
E2E_TEST_OIDC_CLIENT_SECRET=
|
||||
E2E_TEST_OIDC_PROVIDER_DOMAIN=
|
||||
|
||||
E2E_TEST_OIDC_USER_EMAIL=
|
||||
E2E_TEST_OIDC_USER_PASSWORD=
|
||||
|
||||
# ***********************************************************************************************************
|
|
@ -438,7 +438,7 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => {
|
|||
type SupportedTestEventTypes = PrismaType.EventTypeCreateInput & {
|
||||
_bookings?: PrismaType.BookingCreateInput[];
|
||||
};
|
||||
type CustomUserOptsKeys = "username" | "password" | "completedOnboarding" | "locale" | "name";
|
||||
type CustomUserOptsKeys = "username" | "password" | "completedOnboarding" | "locale" | "name" | "email";
|
||||
type CustomUserOpts = Partial<Pick<Prisma.User, CustomUserOptsKeys>> & {
|
||||
timeZone?: TimeZoneEnum;
|
||||
eventTypes?: SupportedTestEventTypes[];
|
||||
|
@ -457,7 +457,7 @@ const createUser = (workerInfo: WorkerInfo, opts?: CustomUserOpts | null): Prism
|
|||
return {
|
||||
username: uname,
|
||||
name: opts?.name,
|
||||
email: `${uname}@example.com`,
|
||||
email: opts?.email ?? `${uname}@example.com`,
|
||||
password: hashPassword(uname),
|
||||
emailVerified: new Date(),
|
||||
completedOnboarding: opts?.completedOnboarding ?? true,
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { test } from "./lib/fixtures";
|
||||
|
||||
const SAML_DATABASE_URL = process.env.SAML_DATABASE_URL!;
|
||||
const SAML_ADMINS = process.env.SAML_ADMINS!;
|
||||
const SAML_ADMIN_EMAIL = process.env.E2E_TEST_SAML_ADMIN_EMAIL!;
|
||||
const SAML_ADMIN_PASSWORD = process.env.E2E_TEST_SAML_ADMIN_PASSWORD!;
|
||||
const OIDC_CLIENT_ID = process.env.E2E_TEST_OIDC_CLIENT_ID!;
|
||||
const OIDC_CLIENT_SECRET = process.env.E2E_TEST_OIDC_CLIENT_SECRET!;
|
||||
const OIDC_PROVIDER_DOMAIN = process.env.E2E_TEST_OIDC_PROVIDER_DOMAIN!;
|
||||
const OIDC_USER_EMAIL = process.env.E2E_TEST_OIDC_USER_EMAIL!;
|
||||
const OIDC_USER_PASSWORD = process.env.E2E_TEST_OIDC_USER_PASSWORD!;
|
||||
|
||||
const SHOULD_SKIP_TESTS =
|
||||
!SAML_DATABASE_URL ||
|
||||
!SAML_ADMINS ||
|
||||
!SAML_ADMIN_EMAIL ||
|
||||
!SAML_ADMIN_PASSWORD ||
|
||||
!OIDC_CLIENT_ID ||
|
||||
!OIDC_CLIENT_SECRET ||
|
||||
!OIDC_PROVIDER_DOMAIN ||
|
||||
!OIDC_USER_EMAIL ||
|
||||
!OIDC_USER_PASSWORD;
|
||||
|
||||
test.afterEach(({ users }) => users.deleteAll());
|
||||
// TODO: Cleanup the OIDC connection after the tests with fixtures
|
||||
test.describe("OIDC", () => {
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip(SHOULD_SKIP_TESTS, "Skipping due to missing the testing variables");
|
||||
test("Setup with SAML admin and login", async ({ page, users }) => {
|
||||
// Add the admin user provided in the environment variables to the db
|
||||
const samlAdminUser = await users.create({ email: SAML_ADMIN_EMAIL, password: SAML_ADMIN_PASSWORD });
|
||||
await samlAdminUser.apiLogin();
|
||||
await test.step("Connect with OIDC Provider", async () => {
|
||||
await page.goto("/settings/security/sso");
|
||||
await page.click('[data-testid="sso-oidc-configure"]');
|
||||
await page.fill('[data-testid="sso-oidc-client-id"]', OIDC_CLIENT_ID);
|
||||
await page.fill('[data-testid="sso-oidc-client-secret"]', OIDC_CLIENT_SECRET);
|
||||
await page.fill(
|
||||
'[data-testid="sso-oidc-well-known-url"]',
|
||||
`https://${OIDC_PROVIDER_DOMAIN}/.well-known/openid-configuration`
|
||||
);
|
||||
await page.click('[data-testid="sso-oidc-save"]');
|
||||
await page.waitForSelector('[data-testid="toast-success"]');
|
||||
});
|
||||
// Logout the SAML Admin
|
||||
await samlAdminUser.logout();
|
||||
await test.step("Login using the OIDC provider", async () => {
|
||||
// Login a user using the OIDC provider.
|
||||
// The credentials are handled by the provider, so we don't need to create a user in the db.
|
||||
await page.goto("/auth/login");
|
||||
await page.click('[data-testid="saml"]');
|
||||
// Redirected outide of the app, the user would be redirected to the OIDC provider.
|
||||
await page.waitForURL(/https:\/\/[^/]+\/oauth2\/v1\/authorize\?.*/);
|
||||
await page.getByRole("textbox", { name: "Username" }).fill(OIDC_USER_EMAIL);
|
||||
await page.getByRole("textbox", { name: "Password" }).fill(OIDC_USER_PASSWORD);
|
||||
await page.getByRole("button", { name: "Sign in" }).click();
|
||||
// The user is redirected back to the app.
|
||||
await page.waitForURL("getting-started", { waitUntil: "load" });
|
||||
});
|
||||
// Logout the user.
|
||||
await page.goto("/auth/logout");
|
||||
await test.step("Disconnect OIDC Provider", async () => {
|
||||
samlAdminUser.apiLogin();
|
||||
await page.goto("/settings/security/sso", { waitUntil: "load" });
|
||||
await page.getByTestId("delete-oidc-sso-connection").click();
|
||||
await page.getByRole("button", { name: "Yes, delete OIDC configuration" }).click();
|
||||
await page.waitForSelector('[data-testid="toast-success"]');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -57,7 +57,11 @@ export default function ConnectionInfo({
|
|||
<Dialog>
|
||||
<div>
|
||||
<DialogTrigger asChild>
|
||||
<Button color="destructive">{t("delete_sso_configuration", { connectionType })}</Button>
|
||||
<Button
|
||||
color="destructive"
|
||||
data-testid={`delete-${connectionType === "OIDC" ? "oidc" : "saml"}-sso-connection`}>
|
||||
{t("delete_sso_configuration", { connectionType })}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</div>
|
||||
<ConfirmationDialogContent
|
||||
|
|
|
@ -33,7 +33,7 @@ export default function OIDCConnection({
|
|||
</div>
|
||||
{!connection && (
|
||||
<div className="flex-shrink-0 pt-3 sm:ml-auto sm:pl-3 sm:pt-0">
|
||||
<Button color="secondary" onClick={() => setOpenModal(true)}>
|
||||
<Button data-testid="sso-oidc-configure" color="secondary" onClick={() => setOpenModal(true)}>
|
||||
{t("configure")}
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -100,6 +100,7 @@ const CreateConnectionDialog = ({
|
|||
<TextField
|
||||
name="clientId"
|
||||
label="Client id"
|
||||
data-testid="sso-oidc-client-id"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
form.setValue("clientId", e?.target.value);
|
||||
|
@ -116,6 +117,7 @@ const CreateConnectionDialog = ({
|
|||
<TextField
|
||||
name="clientSecret"
|
||||
label="Client secret"
|
||||
data-testid="sso-oidc-client-secret"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
form.setValue("clientSecret", e?.target.value);
|
||||
|
@ -132,6 +134,7 @@ const CreateConnectionDialog = ({
|
|||
<TextField
|
||||
name="wellKnownUrl"
|
||||
label="Well-Known URL"
|
||||
data-testid="sso-oidc-well-known-url"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
form.setValue("wellKnownUrl", e?.target.value);
|
||||
|
@ -152,7 +155,7 @@ const CreateConnectionDialog = ({
|
|||
tabIndex={-1}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button type="submit" loading={form.formState.isSubmitting}>
|
||||
<Button type="submit" data-testid="sso-oidc-save" loading={form.formState.isSubmitting}>
|
||||
{t("save")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
|
|
@ -211,6 +211,13 @@
|
|||
"E2E_TEST_APPLE_CALENDAR_EMAIL",
|
||||
"E2E_TEST_APPLE_CALENDAR_PASSWORD",
|
||||
"E2E_TEST_MAILHOG_ENABLED",
|
||||
"E2E_TEST_OIDC_CLIENT_ID",
|
||||
"E2E_TEST_OIDC_CLIENT_SECRET",
|
||||
"E2E_TEST_OIDC_PROVIDER_DOMAIN",
|
||||
"E2E_TEST_OIDC_USER_EMAIL",
|
||||
"E2E_TEST_OIDC_USER_PASSWORD",
|
||||
"E2E_TEST_SAML_ADMIN_EMAIL",
|
||||
"E2E_TEST_SAML_ADMIN_PASSWORD",
|
||||
"EMAIL_FROM",
|
||||
"EMAIL_SERVER_HOST",
|
||||
"EMAIL_SERVER_PASSWORD",
|
||||
|
|
Loading…
Reference in New Issue