test: cover basic collaborative (#4127)

This commit is contained in:
Alex Yang
2023-09-02 01:06:47 -05:00
committed by GitHub
parent 4f97ea8a5d
commit be9ae57a8e
4 changed files with 149 additions and 50 deletions

View File

@@ -20,7 +20,7 @@ test.beforeEach(async () => {
}); });
test.beforeEach(async ({ page, context }) => { test.beforeEach(async ({ page, context }) => {
await loginUser(page, user, { await loginUser(page, user.email, {
beforeLogin: async () => { beforeLogin: async () => {
expect(await getLoginCookie(context)).toBeUndefined(); expect(await getLoginCookie(context)).toBeUndefined();
}, },

View File

@@ -1,15 +1,20 @@
import { test } from '@affine-test/kit/playwright'; import { test } from '@affine-test/kit/playwright';
import { createRandomUser, loginUser } from '@affine-test/kit/utils/cloud'; import {
addUserToWorkspace,
createRandomUser,
enableCloudWorkspace,
loginUser,
} from '@affine-test/kit/utils/cloud';
import { import {
clickNewPageButton, clickNewPageButton,
getBlockSuiteEditorTitle, getBlockSuiteEditorTitle,
waitForEditorLoad, waitForEditorLoad,
} from '@affine-test/kit/utils/page-logic'; } from '@affine-test/kit/utils/page-logic';
import { clickSideBarSettingButton } from '@affine-test/kit/utils/sidebar';
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace'; import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test'; import { expect } from '@playwright/test';
let user: { let user: {
id: string;
name: string; name: string;
email: string; email: string;
password: string; password: string;
@@ -20,7 +25,7 @@ test.beforeEach(async () => {
}); });
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
await loginUser(page, user); await loginUser(page, user.email);
}); });
test.describe('collaboration', () => { test.describe('collaboration', () => {
@@ -33,14 +38,7 @@ test.describe('collaboration', () => {
}, },
page page
); );
await clickSideBarSettingButton(page); await enableCloudWorkspace(page);
await page.getByTestId('current-workspace-label').click();
await page.getByTestId('publish-enable-affine-cloud-button').click();
await page.getByTestId('confirm-enable-affine-cloud-button').click();
// wait for upload and delete local workspace
await page.waitForTimeout(2000);
await waitForEditorLoad(page);
await clickNewPageButton(page);
const title = getBlockSuiteEditorTitle(page); const title = getBlockSuiteEditorTitle(page);
await title.type('TEST TITLE', { await title.type('TEST TITLE', {
delay: 50, delay: 50,
@@ -67,4 +65,39 @@ test.describe('collaboration', () => {
); );
} }
}); });
test('can collaborate with other user', async ({ page, browser }) => {
await page.reload();
await waitForEditorLoad(page);
await createLocalWorkspace(
{
name: 'test',
},
page
);
await enableCloudWorkspace(page);
await clickNewPageButton(page);
const currentUrl = page.url();
// format: http://localhost:8080/workspace/${workspaceId}/xxx
const workspaceId = currentUrl.split('/')[4];
const userB = await createRandomUser();
const context = await browser.newContext();
const page2 = await context.newPage();
await loginUser(page2, userB.email);
await addUserToWorkspace(workspaceId, userB.id, 1 /* READ */);
await page2.reload();
await waitForEditorLoad(page2);
await page2.goto(currentUrl);
{
const title = getBlockSuiteEditorTitle(page);
await title.type('TEST TITLE', {
delay: 50,
});
}
await page2.waitForTimeout(200);
{
const title = getBlockSuiteEditorTitle(page2);
expect(await title.innerText()).toBe('TEST TITLE');
}
});
}); });

View File

@@ -5,5 +5,10 @@
"noEmit": false, "noEmit": false,
"outDir": "lib" "outDir": "lib"
}, },
"include": ["./*.ts", "utils"] "include": ["./*.ts", "utils"],
"references": [
{
"path": "../../apps/server"
}
]
} }

View File

@@ -1,6 +1,12 @@
import { openHomePage } from '@affine-test/kit/utils/load-page'; import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitForEditorLoad } from '@affine-test/kit/utils/page-logic'; import {
import { clickSideBarCurrentWorkspaceBanner } from '@affine-test/kit/utils/sidebar'; clickNewPageButton,
waitForEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import {
clickSideBarCurrentWorkspaceBanner,
clickSideBarSettingButton,
} from '@affine-test/kit/utils/sidebar';
import { faker } from '@faker-js/faker'; import { faker } from '@faker-js/faker';
import { hash } from '@node-rs/argon2'; import { hash } from '@node-rs/argon2';
import type { BrowserContext, Cookie, Page } from '@playwright/test'; import type { BrowserContext, Cookie, Page } from '@playwright/test';
@@ -15,61 +21,105 @@ export async function getLoginCookie(
} }
const cloudUserSchema = z.object({ const cloudUserSchema = z.object({
id: z.string(),
name: z.string(), name: z.string(),
email: z.string().email(), email: z.string().email(),
password: z.string(), password: z.string(),
}); });
export type CloudUser = z.infer<typeof cloudUserSchema>; export const runPrisma = async <T>(
cb: (
prisma: InstanceType<
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
typeof import('../../../apps/server/node_modules/@prisma/client').PrismaClient
>
) => Promise<T>
): Promise<T> => {
const {
PrismaClient,
// eslint-disable-next-line @typescript-eslint/no-var-requires
} = require('../../../apps/server/node_modules/@prisma/client');
const client = new PrismaClient();
await client.$connect();
try {
return await cb(client);
} finally {
await client.$disconnect();
}
};
export async function createRandomUser(): Promise<CloudUser> { export async function addUserToWorkspace(
workspaceId: string,
userId: string,
permission: number
) {
await runPrisma(async client => {
const workspace = await client.workspace.findUnique({
where: {
id: workspaceId,
},
});
if (workspace == null) {
throw new Error(`workspace ${workspaceId} not found`);
}
await client.userWorkspacePermission.create({
data: {
workspaceId: workspace.id,
subPageId: null,
userId,
accepted: true,
type: permission,
},
});
});
}
export async function createRandomUser(): Promise<{
name: string;
email: string;
password: string;
id: string;
}> {
const user = { const user = {
name: faker.internet.userName(), name: faker.internet.userName(),
email: faker.internet.email().toLowerCase(), email: faker.internet.email().toLowerCase(),
password: '123456', password: '123456',
} satisfies CloudUser; };
const { const result = await runPrisma(async client => {
PrismaClient, await client.user.create({
// eslint-disable-next-line @typescript-eslint/no-var-requires data: {
} = require('../../../apps/server/node_modules/@prisma/client'); ...user,
const client = new PrismaClient(); emailVerified: new Date(),
await client.$connect(); password: await hash(user.password),
await client.user.create({ },
data: { });
...user,
emailVerified: new Date(),
password: await hash(user.password),
},
});
await client.$disconnect();
const result = await client.user.findUnique({ return await client.user.findUnique({
where: { where: {
email: user.email, email: user.email,
}, },
});
}); });
cloudUserSchema.parse(result); cloudUserSchema.parse(result);
return result; return {
...result,
password: user.password,
} as any;
} }
export async function deleteUser(email: string) { export async function deleteUser(email: string) {
const { await runPrisma(async client => {
PrismaClient, await client.user.delete({
// eslint-disable-next-line @typescript-eslint/no-var-requires where: {
} = require('../../../apps/server/node_modules/@prisma/client'); email,
const client = new PrismaClient(); },
await client.$connect(); });
await client.user.delete({
where: {
email,
},
}); });
await client.$disconnect();
} }
export async function loginUser( export async function loginUser(
page: Page, page: Page,
user: CloudUser, userEmail: string,
config?: { config?: {
beforeLogin?: () => Promise<void>; beforeLogin?: () => Promise<void>;
afterLogin?: () => Promise<void>; afterLogin?: () => Promise<void>;
@@ -82,7 +132,7 @@ export async function loginUser(
await page.getByTestId('cloud-signin-button').click({ await page.getByTestId('cloud-signin-button').click({
delay: 200, delay: 200,
}); });
await page.getByPlaceholder('Enter your email address').type(user.email, { await page.getByPlaceholder('Enter your email address').type(userEmail, {
delay: 50, delay: 50,
}); });
await page.getByTestId('continue-login-button').click({ await page.getByTestId('continue-login-button').click({
@@ -104,3 +154,14 @@ export async function loginUser(
await config.afterLogin(); await config.afterLogin();
} }
} }
export async function enableCloudWorkspace(page: Page) {
await clickSideBarSettingButton(page);
await page.getByTestId('current-workspace-label').click();
await page.getByTestId('publish-enable-affine-cloud-button').click();
await page.getByTestId('confirm-enable-affine-cloud-button').click();
// wait for upload and delete local workspace
await page.waitForTimeout(2000);
await waitForEditorLoad(page);
await clickNewPageButton(page);
}