AFFiNE/tests/affine-cloud/e2e/collaboration.spec.ts

368 lines
11 KiB
TypeScript
Raw Normal View History

import { resolve } from 'node:path';
import { skipOnboarding, test } from '@affine-test/kit/playwright';
import {
addUserToWorkspace,
createRandomUser,
enableCloudWorkspace,
enableCloudWorkspaceFromShareButton,
loginUser,
} from '@affine-test/kit/utils/cloud';
import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor';
2023-09-02 08:57:04 +03:00
import {
clickNewPageButton,
getBlockSuiteEditorTitle,
waitForEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { clickUserInfoCard } from '@affine-test/kit/utils/setting';
2024-03-14 09:27:49 +03:00
import {
clickSideBarCurrentWorkspaceBanner,
clickSideBarSettingButton,
} from '@affine-test/kit/utils/sidebar';
2023-09-02 08:57:04 +03:00
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
let user: {
id: string;
2023-09-02 08:57:04 +03:00
name: string;
email: string;
password: string;
};
test.beforeEach(async () => {
user = await createRandomUser();
});
test.beforeEach(async ({ page }) => {
await loginUser(page, user.email);
2023-09-02 08:57:04 +03:00
});
test('can enable share page', async ({ page, browser }) => {
await page.reload();
await waitForEditorLoad(page);
await createLocalWorkspace(
2023-09-02 08:57:04 +03:00
{
name: 'test',
},
page
);
await enableCloudWorkspaceFromShareButton(page);
const title = getBlockSuiteEditorTitle(page);
await title.pressSequentially('TEST TITLE', {
delay: 50,
2023-09-02 08:57:04 +03:00
});
await page.keyboard.press('Enter', { delay: 50 });
await page.keyboard.type('TEST CONTENT', { delay: 50 });
await page.getByTestId('cloud-share-menu-button').click();
await page.getByTestId('share-menu-create-link-button').click();
await page.getByTestId('share-menu-copy-link-button').click();
// check share page is accessible
{
const context = await browser.newContext();
await skipOnboarding(context);
const url: string = await page.evaluate(() =>
navigator.clipboard.readText()
);
const page2 = await context.newPage();
await page2.goto(url);
await waitForEditorLoad(page2);
const title = getBlockSuiteEditorTitle(page2);
await expect(title).toContainText('TEST TITLE');
expect(page2.locator('affine-paragraph').first()).toContainText(
'TEST CONTENT'
);
}
});
test('share page with default edgeless', async ({ page, browser }) => {
await page.reload();
await waitForEditorLoad(page);
await createLocalWorkspace(
{
name: 'test',
},
page
);
await enableCloudWorkspaceFromShareButton(page);
const title = getBlockSuiteEditorTitle(page);
await title.pressSequentially('TEST TITLE', {
delay: 50,
});
await page.keyboard.press('Enter', { delay: 50 });
await page.keyboard.type('TEST CONTENT', { delay: 50 });
await clickEdgelessModeButton(page);
2024-02-29 09:33:50 +03:00
await expect(page.locator('affine-edgeless-root')).toBeVisible({
timeout: 1000,
});
await page.getByTestId('cloud-share-menu-button').click();
await page.getByTestId('share-menu-create-link-button').click();
await page.getByTestId('share-menu-copy-link-button').click();
// check share page is accessible
{
const context = await browser.newContext();
await skipOnboarding(context);
const url: string = await page.evaluate(() =>
navigator.clipboard.readText()
);
const page2 = await context.newPage();
await page2.goto(url);
await waitForEditorLoad(page2);
2024-02-29 09:33:50 +03:00
await expect(page.locator('affine-edgeless-root')).toBeVisible({
timeout: 1000,
});
expect(page2.locator('affine-paragraph').first()).toContainText(
'TEST CONTENT'
);
const editButton = page2.getByTestId('share-page-edit-button');
await expect(editButton).not.toBeVisible();
}
});
test('can collaborate with other user and name should display when editing', 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();
await skipOnboarding(context);
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.pressSequentially('TEST TITLE', {
delay: 50,
});
}
await page2.waitForTimeout(200);
{
const title = getBlockSuiteEditorTitle(page2);
await expect(title).toHaveText('TEST TITLE');
2023-12-15 10:20:50 +03:00
const typingPromise = (async () => {
await page.keyboard.press('Enter', { delay: 50 });
await page.keyboard.type('TEST CONTENT', { delay: 50 });
})();
// username should be visible when editing
await expect(page2.getByText(user.name)).toBeVisible();
await typingPromise;
}
// change username
await clickSideBarSettingButton(page);
await clickUserInfoCard(page);
const input = page.getByTestId('user-name-input');
await input.clear();
await input.pressSequentially('TEST USER', {
delay: 50,
});
await page.getByTestId('save-user-name').click({
delay: 50,
});
await page.keyboard.press('Escape', {
delay: 50,
});
const title = getBlockSuiteEditorTitle(page);
await title.focus();
await page.keyboard.press('ArrowDown', { delay: 50 });
{
await expect(page2.getByText('TEST USER')).toBeVisible({
timeout: 2000,
});
}
});
test('can sync collections between different browser', async ({
page,
browser,
}) => {
await page.reload();
await waitForEditorLoad(page);
await createLocalWorkspace(
{
name: 'test',
},
page
);
await enableCloudWorkspace(page);
await page.getByTestId('slider-bar-add-collection-button').click();
const title = page.getByTestId('input-collection-title');
await title.isVisible();
await title.fill('test collection');
await page.getByTestId('save-collection').click();
{
const context = await browser.newContext();
await skipOnboarding(context);
const page2 = await context.newPage();
await loginUser(page2, user.email);
await page2.goto(page.url());
const collections = page2.getByTestId('collections');
await expect(collections.getByText('test collection')).toBeVisible();
}
});
test('can sync svg between different browsers', async ({ page, browser }) => {
await page.reload();
await waitForEditorLoad(page);
await createLocalWorkspace(
{
name: 'test',
},
page
);
await enableCloudWorkspace(page);
await clickNewPageButton(page);
await waitForEditorLoad(page);
// upload local svg
const slashMenu = page.locator(`.slash-menu`);
const image = page.locator('affine-image');
await page.evaluate(async () => {
// https://github.com/toeverything/blocksuite/blob/master/packages/blocks/src/_common/utils/filesys.ts#L20
(window as any).showOpenFilePicker = undefined;
});
const title = getBlockSuiteEditorTitle(page);
await title.pressSequentially('TEST TITLE', {
delay: 50,
});
await page.keyboard.press('Enter', { delay: 50 });
await page.waitForTimeout(100);
await page.keyboard.type('/', { delay: 50 });
await expect(slashMenu).toBeVisible();
await page.keyboard.type('image', { delay: 100 });
await expect(slashMenu).toBeVisible();
const fileChooserPromise = page.waitForEvent('filechooser');
await page.keyboard.press('Enter', { delay: 50 });
const fileChooser = await fileChooserPromise;
fileChooser.setFiles(resolve(__dirname, 'logo.svg'));
await expect(image).toBeVisible();
// the user should see the svg
// get the image src under "affine-image img"
const src1 = await page.locator('affine-image img').getAttribute('src');
expect(src1).not.toBeNull();
// fetch the actual src1 resource in the browser
const svg1 = await page.evaluate(
src =>
fetch(src!)
.then(res => res.blob())
.then(blob => blob.text()),
src1
);
{
const context = await browser.newContext();
await skipOnboarding(context);
const page2 = await context.newPage();
await loginUser(page2, user.email);
await page2.goto(page.url());
// second user should see the svg
// get the image src under "affine-image img"
const src2 = await page2.locator('affine-image img').getAttribute('src');
expect(src2).not.toBeNull();
// fetch the actual src2 resource in the browser
const svg2 = await page2.evaluate(
src =>
fetch(src!)
.then(res => res.blob())
.then(blob => blob.text()),
src2
);
expect(svg2).toEqual(svg1);
}
});
2024-03-14 09:27:49 +03:00
test('When the first sync is not completed, should always show loading', async ({
page,
browser,
}) => {
await page.reload();
await waitForEditorLoad(page);
await createLocalWorkspace(
{
name: 'test',
},
page
);
await enableCloudWorkspace(page);
await clickNewPageButton(page);
await waitForEditorLoad(page);
const title = getBlockSuiteEditorTitle(page);
await title.pressSequentially('TEST TITLE', {
delay: 50,
});
const context = await browser.newContext();
await skipOnboarding(context);
const page2 = await context.newPage();
await loginUser(page2, user.email);
// simulate sync stuck
await page2.evaluate(() => {
(window as any)._TEST_SIMULATE_SYNC_LAG = new Promise(() => {});
});
const localWorkspaceUrl = page2.url();
await clickSideBarCurrentWorkspaceBanner(page2);
await page2.getByTestId('workspace-card').getByText('test').click(); // enter "test" workspace
await page2.waitForTimeout(1000);
await expect(
page2.getByTestId('page-list-item').getByText('TEST TITLE')
).not.toBeVisible(); // should be loading
// Simulate user refresh and re-enter workspace, should still be loading
await page2.goto(localWorkspaceUrl);
// setup sync lag
await page2.evaluate(() => {
(window as any).resolveSyncLag = null;
(window as any)._TEST_SIMULATE_SYNC_LAG = new Promise(resolve => {
(window as any).resolveSyncLag = resolve;
});
});
await clickSideBarCurrentWorkspaceBanner(page2);
await page2.getByTestId('workspace-card').getByText('test').click(); // enter "test" workspace
await page2.waitForTimeout(1000);
await expect(
page2.getByTestId('page-list-item').getByText('TEST TITLE')
).not.toBeVisible(); // should be loading
await page2.evaluate(() => {
(window as any).resolveSyncLag();
}); // start syncing
await page2.getByTestId('page-list-item').getByText('TEST TITLE').click(); // should be able to click page
await waitForEditorLoad(page2);
expect(await getBlockSuiteEditorTitle(page2).innerText()).toContain(
'TEST TITLE'
);
});