Skip to content

Commit

Permalink
test: improve and cleanup invitation tests (#368)
Browse files Browse the repository at this point in the history
Co-authored-by: yoko <[email protected]>
  • Loading branch information
ojeytonwilliams and sidemt authored Dec 5, 2023
1 parent d5942fb commit 51efef9
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 93 deletions.
80 changes: 0 additions & 80 deletions e2e/auth.spec.ts

This file was deleted.

70 changes: 57 additions & 13 deletions e2e/helpers/user.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
import type { Page, APIRequestContext } from "@playwright/test";
import { expect } from "@playwright/test";

import { API_URL } from "./constants";
import { API_URL, EDITOR_CREDENTIALS } from "./constants";

export async function getBearerToken(
request: APIRequestContext,
credentials: { identifier: string; password: string }
data: { identifier: string; password: string }
) {
const editorRes = await request.post(API_URL + "/api/auth/local", {
data: credentials,
data,
});
expect(editorRes.status()).toBe(200);
return (await editorRes.json()).jwt;
}

async function getUsersHelper(
request: APIRequestContext,
data: { identifier: string; jwt: string }
) {
const usersRes = await request.get(
`${API_URL}/api/users?filters[email][$eq]=${data.identifier}`,
{
headers: {
Authorization: `Bearer ${data.jwt}`,
},
}
);
return await usersRes.json();
}

export async function deleteUser(
request: APIRequestContext,
data: { identifier: string }
) {
const jwt = await getBearerToken(request, EDITOR_CREDENTIALS);
const user = await getUsersHelper(request, { ...data, jwt });
if (user.length) {
await request.delete(`${API_URL}/api/users/${user[0].id}`, {
headers: {
Authorization: `Bearer ${jwt}`,
},
});
}
}

export async function signIn(
page: Page,
credentials: { identifier: string; password: string }
Expand All @@ -39,18 +70,31 @@ export async function signIn(

export async function getUserByEmail(
request: APIRequestContext,
data: { email: string; jwt: string }
data: { identifier: string }
) {
const usersRes = await request.get(
`${API_URL}/api/users?filters[email][$eq]=${data.email}`,
{
headers: {
Authorization: `Bearer ${data.jwt}`,
},
}
);
const users = await usersRes.json();
const jwt = await getBearerToken(request, EDITOR_CREDENTIALS);
const users = await getUsersHelper(request, { ...data, jwt });
// There should only be one user with this username, so we should assert that.
expect(users).toHaveLength(1);
return users[0];
}

// By default an invited user has the Auth0 provider. To allow the user to sign
// in in testing, we need to change the provider to local and set a password.
export async function useCredentialsForAuth(
request: APIRequestContext,
data: { identifier: string; password: string }
) {
const { password } = data;
const jwt = await getBearerToken(request, EDITOR_CREDENTIALS);
const user = await getUserByEmail(request, data);
const updateUserUrl = `${API_URL}/api/users/${user.id}`;
const userRes = await request.put(updateUserUrl, {
headers: {
Authorization: `Bearer ${jwt}`,
},
data: { provider: "local", password },
});
expect(userRes.status()).toBe(200);
return await userRes.json();
}
38 changes: 38 additions & 0 deletions e2e/pages/users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { Page, Locator } from "@playwright/test";

export class UsersPage {
private readonly activeUsers: Locator;
private readonly invitedUsers: Locator;

constructor(public readonly page: Page) {
this.activeUsers = page.locator('[data-testid="active-user"]');
this.invitedUsers = page.locator('[data-testid="invited-user"]');
}

async getInvitedUser(email: string) {
return this.invitedUsers.filter({ hasText: email });
}

async getActiveUser(email: string) {
return this.activeUsers.filter({ hasText: email });
}

async inviteUser(email: string) {
await this.page.getByRole("button", { name: "Invite user" }).click();
await this.page.getByLabel("Email*").click();
await this.page.getByLabel("Email*").fill(email);
await this.page.getByRole("button", { name: "Send invitation" }).click();
}

async revokeUser(email: string) {
const revokeButton = (await this.getInvitedUser(email)).getByRole(
"button",
{ name: "Revoke" }
);
await revokeButton.click();
}

async goto() {
await this.page.goto("/users");
}
}
57 changes: 57 additions & 0 deletions e2e/users.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { test, expect } from "@playwright/test";

import { UsersPage } from "./pages/users";
import { useCredentialsForAuth, signIn, deleteUser } from "./helpers/user";

const NEW_USER_CREDENTIALS = {
identifier: "[email protected]",
password: "password",
};

test.describe("inviting a user", () => {
let usersPage: UsersPage;

test.beforeEach(async ({ browser }) => {
// To avoid using the invitee's credentials, we have to create a new context
const editorContext = await browser.newContext({
storageState: "playwright/.auth/editor.json",
});
usersPage = new UsersPage(await editorContext.newPage());
await usersPage.goto();
});

test.afterEach(async ({ request }) => {
// Delete the user if it exists
await deleteUser(request, NEW_USER_CREDENTIALS);
});

test("invitations can be created and revoked", async () => {
await usersPage.inviteUser(NEW_USER_CREDENTIALS.identifier);
await expect(
await usersPage.getInvitedUser(NEW_USER_CREDENTIALS.identifier)
).toBeVisible();

await usersPage.revokeUser(NEW_USER_CREDENTIALS.identifier);
await expect(
await usersPage.getInvitedUser(NEW_USER_CREDENTIALS.identifier)
).toBeHidden();
});

test("invited users become active by signing in", async ({
page,
request,
}) => {
await usersPage.inviteUser(NEW_USER_CREDENTIALS.identifier);

// Allow the user to sign in with email/password, not Auth0.
await useCredentialsForAuth(request, NEW_USER_CREDENTIALS);

await signIn(page, NEW_USER_CREDENTIALS);

// After signing in, the invited user should be in the active list
await usersPage.page.reload();
await expect(
await usersPage.getActiveUser(NEW_USER_CREDENTIALS.identifier)
).toBeVisible();
});
});

0 comments on commit 51efef9

Please sign in to comment.