snapshot of https://github.com/toeverything/AFFiNE.git (canary, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 1s
Release / Prepare (push) Failing after 2s
Release / Release Cloud (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Mobile (push) Has been skipped
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 1s
Release / Prepare (push) Failing after 2s
Release / Release Cloud (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Mobile (push) Has been skipped
This commit is contained in:
207
tests/affine-cloud/e2e/collaboration.spec.ts
Normal file
207
tests/affine-cloud/e2e/collaboration.spec.ts
Normal file
@@ -0,0 +1,207 @@
|
||||
import { Path, skipOnboarding, test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
addUserToWorkspace,
|
||||
createRandomUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { clickUserInfoCard } from '@affine-test/kit/utils/setting';
|
||||
import { clickSideBarSettingButton } from '@affine-test/kit/utils/sidebar';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
// SKIP until BS-671 fix
|
||||
test.skip('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);
|
||||
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');
|
||||
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('navigation-panel-bar-add-collection-button').click();
|
||||
const title = page.getByTestId('prompt-modal-input');
|
||||
await title.isVisible();
|
||||
await title.fill('test collection');
|
||||
await page.getByTestId('prompt-modal-confirm').click();
|
||||
|
||||
{
|
||||
const context = await browser.newContext();
|
||||
await skipOnboarding(context);
|
||||
const page2 = await context.newPage();
|
||||
await loginUser(page2, user);
|
||||
await page2.goto(page.url());
|
||||
const collections = page2.getByTestId('navigation-panel-collections');
|
||||
await collections.getByTestId('category-divider-collapse-button').click();
|
||||
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;
|
||||
await fileChooser.setFiles(Path.dir(import.meta.url).join('logo.svg').value);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
});
|
||||
121
tests/affine-cloud/e2e/comments.spec.ts
Normal file
121
tests/affine-cloud/e2e/comments.spec.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test.describe('comments', () => {
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test('can create and display a comment on selected text', async ({
|
||||
page,
|
||||
}) => {
|
||||
// Reload page and wait for editor - following the pattern from working collaboration test
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
|
||||
// Create a new workspace
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test-comment-workspace',
|
||||
},
|
||||
page
|
||||
);
|
||||
|
||||
// Enable cloud workspace for comments feature
|
||||
await enableCloudWorkspace(page);
|
||||
|
||||
// Create a new doc
|
||||
await clickNewPageButton(page);
|
||||
await waitForEditorLoad(page);
|
||||
|
||||
// Add title and content
|
||||
const title = getBlockSuiteEditorTitle(page);
|
||||
await title.click();
|
||||
await title.fill('Test Comment Document');
|
||||
|
||||
// Add some text content
|
||||
await page.keyboard.press('Enter');
|
||||
await page.keyboard.type(
|
||||
'This is a test paragraph with some text that we will comment on.',
|
||||
{ delay: 50 }
|
||||
);
|
||||
|
||||
for (let i = 0; i < 11; i++) {
|
||||
await page.keyboard.press('Shift+ArrowLeft');
|
||||
}
|
||||
|
||||
// Wait for the toolbar to appear after text selection
|
||||
const toolbar = page.locator('editor-toolbar');
|
||||
await expect(toolbar).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Click the comment button in the toolbar
|
||||
// The comment button has tooltip "Comment" based on blockCommentToolbarButton
|
||||
const commentButton = page.locator(
|
||||
'editor-icon-button[aria-label="Comment"]'
|
||||
);
|
||||
await expect(commentButton).toBeVisible();
|
||||
await commentButton.click();
|
||||
|
||||
// Verify comment sidebar is opened by checking comment editor is visible
|
||||
await page.waitForTimeout(300); // Wait for sidebar animation
|
||||
|
||||
// Find the comment editor
|
||||
const commentEditor = page.locator(
|
||||
'.comment-editor-viewport .page-editor-container'
|
||||
);
|
||||
await expect(commentEditor).toBeVisible();
|
||||
|
||||
// Enter comment text
|
||||
await commentEditor.click();
|
||||
await commentEditor.focus();
|
||||
await page.keyboard.type('This is my first comment on this text', {
|
||||
delay: 50,
|
||||
});
|
||||
|
||||
// Commit the comment (click the commit button or press Cmd/Ctrl+Enter)
|
||||
// The commit button is in the footer with an arrow icon
|
||||
const commitButton = page.locator('.comment-editor-viewport button').last();
|
||||
await expect(commitButton).toBeVisible();
|
||||
await commitButton.click();
|
||||
|
||||
// Wait for comment to be saved
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Verify the comment appears in the sidebar
|
||||
await expect(page.locator('text=Comments')).toBeVisible();
|
||||
await expect(
|
||||
page.locator('text=This is my first comment on this text')
|
||||
).toBeVisible();
|
||||
|
||||
// Verify the preview text appears in the sidebar
|
||||
// The preview should show the selected text that was commented on
|
||||
// Target specifically the sidebar tab content to avoid conflicts with editor content
|
||||
const sidebarTab = page.getByTestId('sidebar-tab-content-comment');
|
||||
await expect(sidebarTab.locator('text=comment on.')).toBeVisible();
|
||||
|
||||
// This text should appear in the sidebar as the preview of what was commented on
|
||||
|
||||
// Verify the comment is successfully created by checking the sidebar content
|
||||
const commentSidebar = page.locator('text=Comments').locator('..');
|
||||
await expect(commentSidebar).toBeVisible();
|
||||
});
|
||||
});
|
||||
110
tests/affine-cloud/e2e/login.spec.ts
Normal file
110
tests/affine-cloud/e2e/login.spec.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import { waitForEditorLoad } from '@affine-test/kit/utils/page-logic';
|
||||
import { clickUserInfoCard } from '@affine-test/kit/utils/setting';
|
||||
import {
|
||||
clickSideBarAllPageButton,
|
||||
clickSideBarSettingButton,
|
||||
clickSideBarUseAvatar,
|
||||
} from '@affine-test/kit/utils/sidebar';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('can open login modal in workspace list', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await page.getByTestId('sidebar-user-avatar').click({
|
||||
delay: 200,
|
||||
});
|
||||
await expect(page.getByTestId('auth-modal')).toBeVisible();
|
||||
});
|
||||
|
||||
test.describe('login first', () => {
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test('exit successfully and re-login', async ({ page }) => {
|
||||
await page.reload();
|
||||
await clickSideBarAllPageButton(page);
|
||||
await page.waitForTimeout(200);
|
||||
const url = page.url();
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspace(page);
|
||||
await clickSideBarSettingButton(page);
|
||||
await clickUserInfoCard(page);
|
||||
await page.getByTestId('sign-out-button').click();
|
||||
await page.getByTestId('confirm-sign-out-button').click();
|
||||
await page.waitForTimeout(5000);
|
||||
expect(page.url()).toBe(url);
|
||||
});
|
||||
|
||||
test('can sign out', async ({ page }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await clickSideBarAllPageButton(page);
|
||||
const currentUrl = page.url();
|
||||
await clickSideBarUseAvatar(page);
|
||||
await page.getByTestId('workspace-modal-sign-out-option').click();
|
||||
await page.getByTestId('confirm-sign-out-button').click();
|
||||
await page.reload();
|
||||
await clickSideBarUseAvatar(page);
|
||||
const authModal = page.getByTestId('auth-modal');
|
||||
await expect(authModal).toBeVisible();
|
||||
expect(page.url()).toBe(currentUrl);
|
||||
});
|
||||
|
||||
test('can see and change email and password in setting panel', async ({
|
||||
page,
|
||||
}) => {
|
||||
const newName = 'test name';
|
||||
{
|
||||
await clickSideBarSettingButton(page);
|
||||
const locator = page.getByTestId('user-info-card');
|
||||
await expect(locator.getByText(user.email)).toBeVisible();
|
||||
await expect(locator.getByText(user.name)).toBeVisible();
|
||||
await locator.click({
|
||||
delay: 50,
|
||||
});
|
||||
const nameInput = page.getByPlaceholder('Input account name');
|
||||
await nameInput.clear();
|
||||
await nameInput.pressSequentially(newName, {
|
||||
delay: 50,
|
||||
});
|
||||
await page.getByTestId('save-user-name').click({
|
||||
delay: 50,
|
||||
});
|
||||
}
|
||||
await page.reload();
|
||||
{
|
||||
await clickSideBarSettingButton(page);
|
||||
const locator = page.getByTestId('user-info-card');
|
||||
await expect(locator.getByText(user.email)).toBeVisible();
|
||||
await expect(locator.getByText(newName)).toBeVisible();
|
||||
}
|
||||
});
|
||||
});
|
||||
1
tests/affine-cloud/e2e/logo.svg
Normal file
1
tests/affine-cloud/e2e/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#000000;}</style></defs><g id="_20230202-pull_request"><path class="cls-1" d="m512,133.82L342.5,0,0,67.88v310.26l169.56,133.86,342.44-67.88V133.82Zm-203.39-84.81v89.67l51.84-10.27v-56.25l74.87,59.09-249.93,49.53-108.71-85.8,231.93-45.96ZM51.84,133.32l99.71,78.7v93.92l51.84-10.27v-76.15l256.78-50.89v210.06l-99.71-78.7v-93.92l-51.84,10.27v76.16l-256.78,50.89v-210.06Zm151.55,329.67v-89.67l-51.84,10.27v56.25l-74.87-59.09,249.93-49.53,108.71,85.8-231.93,45.96Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 608 B |
109
tests/affine-cloud/e2e/migration.spec.skip.ts
Normal file
109
tests/affine-cloud/e2e/migration.spec.skip.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
import { Path, test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
deleteUser,
|
||||
enableCloudWorkspace,
|
||||
getLoginCookie,
|
||||
loginUser,
|
||||
runPrisma,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { coreUrl } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async () => {
|
||||
user = await createRandomUser();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, context }) => {
|
||||
await loginUser(page, user, {
|
||||
beforeLogin: async () => {
|
||||
expect(await getLoginCookie(context)).toBeUndefined();
|
||||
},
|
||||
afterLogin: async () => {
|
||||
expect(await getLoginCookie(context)).toBeTruthy();
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
expect(await getLoginCookie(context)).toBeTruthy();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
// if you want to keep the user in the database for debugging,
|
||||
// comment this line
|
||||
await deleteUser(user.email);
|
||||
});
|
||||
|
||||
// TODO(@eyhn) mock migration from server data after page level upgrade implemented.
|
||||
test.skip('migration', async ({ page, browser }) => {
|
||||
let workspaceId: string;
|
||||
{
|
||||
// create the old cloud workspace in another browser
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await loginUser(page, user);
|
||||
await page.reload();
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspace(page);
|
||||
await clickNewPageButton(page);
|
||||
await waitForEditorLoad(page);
|
||||
// http://localhost:8080/workspace/2bc0b6c8-f68d-4dd3-98a8-be746754f9e1/xxx
|
||||
workspaceId = page.url().split('/')[4];
|
||||
await runPrisma(async client => {
|
||||
const sqls = (
|
||||
await readFile(
|
||||
Path.dir(import.meta.url).join(
|
||||
'fixtures',
|
||||
'0.9.0-canary.9-snapshots.sql'
|
||||
).value,
|
||||
'utf-8'
|
||||
)
|
||||
)
|
||||
.replaceAll('2bc0b6c8-f68d-4dd3-98a8-be746754f9e1', workspaceId)
|
||||
.split('\n');
|
||||
await client.snapshot.deleteMany({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
for (const sql of sqls) {
|
||||
await client.$executeRawUnsafe(sql);
|
||||
}
|
||||
});
|
||||
await page.close();
|
||||
}
|
||||
await page.reload();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.goto(`${coreUrl}/workspace/${workspaceId}/all`);
|
||||
await page.getByTestId('upgrade-workspace-button').click();
|
||||
await expect(page.getByText('Refresh Current Page')).toBeVisible({
|
||||
timeout: 60000,
|
||||
});
|
||||
await page.goto(
|
||||
// page 'F1SX6cgNxy' has edgeless mode
|
||||
`${coreUrl}/workspace/${workspaceId}/F1SX6cgNxy`
|
||||
);
|
||||
await page.waitForTimeout(5000);
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
});
|
||||
59
tests/affine-cloud/e2e/open-in-app.spec.ts
Normal file
59
tests/affine-cloud/e2e/open-in-app.spec.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
deleteUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { waitForEditorLoad } from '@affine-test/kit/utils/page-logic';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
await enableCloudWorkspace(page);
|
||||
await waitForEditorLoad(page);
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
// if you want to keep the user in the database for debugging,
|
||||
// comment this line
|
||||
await deleteUser(user.email);
|
||||
});
|
||||
|
||||
test('open in app card should be shown for cloud workspace', async ({
|
||||
page,
|
||||
}) => {
|
||||
await expect(page.getByTestId('open-in-app-card')).toBeVisible();
|
||||
|
||||
await page
|
||||
.getByTestId('open-in-app-card')
|
||||
.getByRole('checkbox', {
|
||||
name: 'Remember choice',
|
||||
})
|
||||
.locator('input')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Dismiss',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId('open-in-app-card')).not.toBeInViewport();
|
||||
|
||||
await page.reload();
|
||||
|
||||
await expect(page.getByTestId('open-in-app-card')).not.toBeInViewport();
|
||||
|
||||
// seems there is no way to bypass the open popup blocker via playwright
|
||||
});
|
||||
185
tests/affine-cloud/e2e/page-history.spec.ts
Normal file
185
tests/affine-cloud/e2e/page-history.spec.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
deleteUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
runPrisma,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import {
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import type { Page } from '@playwright/test';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
// if you want to keep the user in the database for debugging,
|
||||
// comment this line
|
||||
await deleteUser(user.email);
|
||||
});
|
||||
|
||||
test('newly created page shows empty history', async ({ page }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspace(page);
|
||||
|
||||
// click the history button
|
||||
await page.getByTestId('header-dropDownButton').click();
|
||||
await page.getByTestId('editor-option-menu-history').click();
|
||||
|
||||
const modal = page.getByTestId('page-history-modal');
|
||||
|
||||
// expect history modal shown up
|
||||
await expect(modal).toBeVisible();
|
||||
|
||||
await expect(page.getByTestId('empty-history-prompt')).toBeVisible();
|
||||
});
|
||||
|
||||
const pushCurrentPageUpdates = async (page: Page) => {
|
||||
const [workspaceId, guid, updates, state] = await page.evaluate(() => {
|
||||
// @ts-expect-error ignore the type error
|
||||
const Y = window.Y;
|
||||
// @ts-expect-error ignore the type error
|
||||
const spaceDoc = window.currentEditor.page.spaceDoc;
|
||||
// @ts-expect-error ignore the type error
|
||||
const workspaceId: string = window.currentWorkspace.id;
|
||||
const updates: Uint8Array = Y.encodeStateAsUpdate(spaceDoc);
|
||||
const state: Uint8Array = Y.encodeStateVector(spaceDoc);
|
||||
|
||||
return [workspaceId, spaceDoc.guid, [...updates], [...state]] as const;
|
||||
});
|
||||
|
||||
const toBuffer = (arr: readonly number[]) => Buffer.from(arr);
|
||||
|
||||
await runPrisma(async client => {
|
||||
await client.snapshotHistory.create({
|
||||
data: {
|
||||
workspaceId: workspaceId,
|
||||
id: guid,
|
||||
blob: toBuffer(updates),
|
||||
state: toBuffer(state),
|
||||
timestamp: new Date(Date.now() - 10000),
|
||||
expiredAt: new Date(Date.now() + 100000),
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
test('can restore page to a history version', async ({ page }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspace(page);
|
||||
|
||||
await pushCurrentPageUpdates(page);
|
||||
|
||||
const title = getBlockSuiteEditorTitle(page);
|
||||
|
||||
await title.focus();
|
||||
|
||||
await title.pressSequentially('TEST TITLE', {
|
||||
delay: 50,
|
||||
});
|
||||
|
||||
// write something and push to history
|
||||
await pushCurrentPageUpdates(page);
|
||||
|
||||
await title.selectText();
|
||||
|
||||
await title.press('Backspace');
|
||||
|
||||
await title.pressSequentially('New Title', {
|
||||
delay: 50,
|
||||
});
|
||||
|
||||
// click the history button
|
||||
await page.getByTestId('header-dropDownButton').click();
|
||||
await page.getByTestId('editor-option-menu-history').click();
|
||||
|
||||
const modal = page.getByTestId('page-history-modal');
|
||||
|
||||
// expect history modal shown up
|
||||
await expect(modal).toBeVisible();
|
||||
|
||||
// expect history list to have 2 items
|
||||
await expect(modal.getByTestId('version-history-item')).toHaveCount(2);
|
||||
|
||||
// check the first item in the preview should have title 'TEST TITLE'
|
||||
await expect(modal.locator('[data-block-is-title]')).toHaveText('TEST TITLE');
|
||||
|
||||
// click restore
|
||||
await modal
|
||||
.getByRole('button', {
|
||||
name: 'Restore current version',
|
||||
})
|
||||
.click();
|
||||
|
||||
const confirm = page.getByTestId('confirm-restore-history-modal');
|
||||
|
||||
// expect confirm dialog to show up
|
||||
await expect(confirm).toBeVisible();
|
||||
|
||||
// click restore
|
||||
await confirm
|
||||
.getByRole('button', {
|
||||
name: 'Restore',
|
||||
})
|
||||
.click();
|
||||
|
||||
// title should be restored to 'TEST TITLE'
|
||||
await expect(title).toContainText('TEST TITLE');
|
||||
});
|
||||
|
||||
test('empty history doc should not show starter bar', async ({ page }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace({ name: 'test' }, page);
|
||||
await enableCloudWorkspace(page);
|
||||
|
||||
await pushCurrentPageUpdates(page);
|
||||
|
||||
const title = getBlockSuiteEditorTitle(page);
|
||||
await title.focus();
|
||||
await title.pressSequentially('TEST TITLE', {
|
||||
delay: 50,
|
||||
});
|
||||
// write something and push to history
|
||||
await pushCurrentPageUpdates(page);
|
||||
|
||||
// click the history button
|
||||
await page.getByTestId('header-dropDownButton').click();
|
||||
await page.getByTestId('editor-option-menu-history').click();
|
||||
|
||||
const modal = page.getByTestId('page-history-modal');
|
||||
|
||||
// expect history modal shown up
|
||||
await expect(modal).toBeVisible();
|
||||
|
||||
const aiBadge = modal.getByTestId('start-with-ai-badge');
|
||||
await expect(aiBadge).not.toBeVisible();
|
||||
});
|
||||
257
tests/affine-cloud/e2e/share-page-1.spec.ts
Normal file
257
tests/affine-cloud/e2e/share-page-1.spec.ts
Normal file
@@ -0,0 +1,257 @@
|
||||
import { skipOnboarding, test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
enableCloudWorkspaceFromShareButton,
|
||||
enableShare,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor';
|
||||
import { importImage } from '@affine-test/kit/utils/image';
|
||||
import {
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test('can enable share page', 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 });
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').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');
|
||||
await expect(page2.locator('affine-paragraph').first()).toContainText(
|
||||
'TEST CONTENT'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('share page should have toc', 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('# Heading 1');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.keyboard.type('# Heading 2');
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').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 tocIndicators = page2.locator(
|
||||
'affine-outline-viewer .outline-viewer-indicator'
|
||||
);
|
||||
await expect(tocIndicators).toHaveCount(3);
|
||||
await expect(tocIndicators.nth(0)).toBeVisible();
|
||||
await expect(tocIndicators.nth(1)).toBeVisible();
|
||||
await expect(tocIndicators.nth(2)).toBeVisible();
|
||||
|
||||
const viewer = page2.locator('affine-outline-viewer');
|
||||
await tocIndicators.first().hover({ force: true });
|
||||
await expect(viewer).toBeVisible();
|
||||
|
||||
const toggleButton = viewer.locator(
|
||||
'[data-testid="toggle-outline-panel-button"]'
|
||||
);
|
||||
await expect(toggleButton).toHaveCount(0);
|
||||
}
|
||||
});
|
||||
|
||||
test('append paragraph should be disabled in shared mode', 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,
|
||||
});
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').click();
|
||||
|
||||
{
|
||||
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 paragraph = page2.locator('affine-paragraph');
|
||||
const numParagraphs = await paragraph.count();
|
||||
|
||||
let error = null;
|
||||
try {
|
||||
await page2.locator('[data-testid=page-editor-blank]').click();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
expect(error).toBeNull();
|
||||
|
||||
await expect(paragraph).toHaveCount(numParagraphs);
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
await expect(page.locator('affine-edgeless-root')).toBeVisible({
|
||||
timeout: 1000,
|
||||
});
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-edgeless').click();
|
||||
|
||||
// check share page is accessible
|
||||
{
|
||||
const context = await browser.newContext();
|
||||
await skipOnboarding(context);
|
||||
const url = new URL(
|
||||
await page.evaluate(() => navigator.clipboard.readText())
|
||||
);
|
||||
url.searchParams.delete('mode');
|
||||
const page2 = await context.newPage();
|
||||
await page2.goto(url.toString());
|
||||
await waitForEditorLoad(page2);
|
||||
await expect(page2.locator('affine-edgeless-root')).toBeVisible({
|
||||
timeout: 1000,
|
||||
});
|
||||
await expect(page2.locator('affine-paragraph').first()).toContainText(
|
||||
'TEST CONTENT'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('image preview should be shown', async ({ page, browser }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspaceFromShareButton(page);
|
||||
const title = getBlockSuiteEditorTitle(page);
|
||||
await title.click();
|
||||
await page.keyboard.press('Enter');
|
||||
await importImage(page, 'large-image.png');
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').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);
|
||||
|
||||
await page.locator('affine-page-image').first().dblclick();
|
||||
const locator = page.getByTestId('image-preview-modal');
|
||||
await expect(locator).toBeVisible();
|
||||
await page.getByTestId('image-preview-close-button').first().click();
|
||||
await page.waitForTimeout(500);
|
||||
await expect(locator).not.toBeVisible();
|
||||
}
|
||||
});
|
||||
284
tests/affine-cloud/e2e/share-page-2.spec.ts
Normal file
284
tests/affine-cloud/e2e/share-page-2.spec.ts
Normal file
@@ -0,0 +1,284 @@
|
||||
import { skipOnboarding, test } from '@affine-test/kit/playwright';
|
||||
import { importAttachment } from '@affine-test/kit/utils/attachment';
|
||||
import {
|
||||
createRandomUser,
|
||||
enableCloudWorkspaceFromShareButton,
|
||||
enableShare,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { getParagraphIds, locateToolbar } from '@affine-test/kit/utils/editor';
|
||||
import { copyByKeyboard } from '@affine-test/kit/utils/keyboard';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { setSelection } from '@affine-test/kit/utils/selection';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test('The reference links in the shared page should be accessible normally and can go back and forward', async ({
|
||||
page,
|
||||
browser,
|
||||
}) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspaceFromShareButton(page);
|
||||
|
||||
// create linked page and share
|
||||
const title = getBlockSuiteEditorTitle(page);
|
||||
await title.pressSequentially('Test linked doc', {
|
||||
delay: 50,
|
||||
});
|
||||
await page.keyboard.press('Enter', { delay: 50 });
|
||||
await page.keyboard.type('Test linked content', { delay: 50 });
|
||||
await enableShare(page);
|
||||
|
||||
// create a new page and link to the shared page
|
||||
await clickNewPageButton(page, 'Test Page');
|
||||
await waitForEditorLoad(page);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.keyboard.type('@', { delay: 50 });
|
||||
const linkedPagePopover = page.locator('.linked-doc-popover');
|
||||
await expect(linkedPagePopover).toBeVisible();
|
||||
await page.keyboard.type('Test linked doc', { delay: 50 });
|
||||
await page.locator('icon-button:has-text("Test linked doc")').first().click();
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').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 Page');
|
||||
|
||||
// check linked page
|
||||
const link = page2.locator('.affine-reference');
|
||||
await expect(link).toBeVisible();
|
||||
await expect(link).toContainText('Test linked doc');
|
||||
await link.click();
|
||||
await waitForEditorLoad(page2);
|
||||
await expect(
|
||||
page2.locator('.doc-title-container:has-text("Test linked doc")')
|
||||
).toBeVisible();
|
||||
await expect(page2.locator('affine-paragraph').first()).toContainText(
|
||||
'Test linked content'
|
||||
);
|
||||
|
||||
// go back and forward
|
||||
await page2.goBack();
|
||||
await waitForEditorLoad(page2);
|
||||
await expect(title).toContainText('Test Page');
|
||||
await expect(link).toBeVisible();
|
||||
await expect(link).toContainText('Test linked doc');
|
||||
|
||||
await page2.goForward();
|
||||
await waitForEditorLoad(page2);
|
||||
await expect(
|
||||
page2.locator('.doc-title-container:has-text("Test linked doc")')
|
||||
).toBeVisible();
|
||||
await expect(page2.locator('affine-paragraph').first()).toContainText(
|
||||
'Test linked content'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('Should show no permission page when the share page is not found', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto('http://localhost:8080/workspace/abc/123');
|
||||
|
||||
await expect(
|
||||
page.getByText(
|
||||
'Sorry, you do not have access or this content does not exist...'
|
||||
)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('Inline latex modal should be not shown in shared mode when clicking', 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('$$E=mc^2$$');
|
||||
await page.keyboard.press('Space');
|
||||
|
||||
// there should be a inline latex node
|
||||
const latexLocator = page.locator('affine-latex-node');
|
||||
await expect(latexLocator).toBeVisible();
|
||||
|
||||
// click the latex node
|
||||
// the latex editor should be shown when the doc can be editing
|
||||
await latexLocator.click();
|
||||
const modalLocator = page.locator('.latex-editor-container');
|
||||
await expect(modalLocator).toBeVisible();
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').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);
|
||||
|
||||
// click the latex node
|
||||
const latexLocator = page2.locator('affine-latex-node');
|
||||
await latexLocator.click();
|
||||
|
||||
// the latex editor should not be shown when the doc is readonly
|
||||
const modalLocator = page2.locator('.latex-editor-container');
|
||||
await expect(modalLocator).not.toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test('share page should support copying content', 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('Hello World');
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').click();
|
||||
|
||||
// check share page is accessible and content can be copied
|
||||
{
|
||||
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 { blockIds: paragraphIds } = await getParagraphIds(page2);
|
||||
await setSelection(page2, paragraphIds[0], 0, paragraphIds[0], 11);
|
||||
await copyByKeyboard(page2);
|
||||
|
||||
// Verify copied content
|
||||
const copiedText = await page2.evaluate(() =>
|
||||
navigator.clipboard.readText()
|
||||
);
|
||||
expect(copiedText).toContain('Hello World');
|
||||
}
|
||||
});
|
||||
|
||||
test('should enable opening peek view with pdf viewer in readonly and sharing modes', async ({
|
||||
page,
|
||||
browser,
|
||||
}) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspaceFromShareButton(page);
|
||||
const title = getBlockSuiteEditorTitle(page);
|
||||
await title.click();
|
||||
await page.keyboard.press('Enter');
|
||||
await importAttachment(page, 'lorem-ipsum.pdf');
|
||||
|
||||
const toolbar = locateToolbar(page);
|
||||
const switchViewButton = toolbar.getByLabel('Switch view');
|
||||
const embedViewButton = toolbar.getByLabel('Embed view');
|
||||
|
||||
const attachment = page.locator('affine-attachment');
|
||||
await attachment.click();
|
||||
|
||||
await switchViewButton.click();
|
||||
await embedViewButton.click();
|
||||
|
||||
await expect(attachment.locator('lit-react-portal')).toBeVisible();
|
||||
|
||||
// enable share page and copy page link
|
||||
await enableShare(page);
|
||||
await page.getByTestId('share-menu-copy-link-button').click();
|
||||
await page.getByTestId('share-link-menu-copy-page').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 attachment = page2.locator('affine-attachment');
|
||||
|
||||
await expect(attachment.locator('lit-react-portal')).toBeVisible();
|
||||
|
||||
await attachment.dblclick();
|
||||
|
||||
const pdfViewer = page2.getByTestId('pdf-viewer');
|
||||
await expect(pdfViewer).not.toBeVisible();
|
||||
}
|
||||
});
|
||||
81
tests/affine-cloud/e2e/storage.spec.ts
Normal file
81
tests/affine-cloud/e2e/storage.spec.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
deleteUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { getPageByTitle } from '@affine-test/kit/utils/page-logic';
|
||||
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
// if you want to keep the user in the database for debugging,
|
||||
// comment this line
|
||||
await deleteUser(user.email);
|
||||
});
|
||||
|
||||
test('should delete unused blobs after permanently deleting a doc', async ({
|
||||
page,
|
||||
}) => {
|
||||
await enableCloudWorkspace(page);
|
||||
|
||||
await clickSideBarAllPageButton(page);
|
||||
|
||||
// delete the welcome page ('Getting Started')
|
||||
await getPageByTitle(page, 'Getting Started')
|
||||
.getByTestId('doc-list-operation-button')
|
||||
.click();
|
||||
const deleteBtn = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn.click();
|
||||
await expect(page.getByText('Delete doc?')).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await page.getByTestId('trash-page').click();
|
||||
await getPageByTitle(page, 'Getting Started')
|
||||
.getByTestId('delete-page-button')
|
||||
.click();
|
||||
const confirmDelete = page.getByRole('dialog', {
|
||||
name: 'Delete permanently?',
|
||||
});
|
||||
await expect(confirmDelete).toBeVisible();
|
||||
await confirmDelete
|
||||
.getByRole('button', { name: 'Delete', exact: true })
|
||||
.click();
|
||||
await expect(getPageByTitle(page, 'Getting Started')).toBeHidden();
|
||||
|
||||
await page.getByTestId('slider-bar-workspace-setting-button').click();
|
||||
await expect(page.getByTestId('setting-modal')).toBeVisible();
|
||||
await page.getByTestId('workspace-setting:storage').click();
|
||||
await expect(page.getByText(/Unused blobs \([1-9]\d*\)/)).toBeVisible();
|
||||
|
||||
// get the unused blobs count
|
||||
const count = await page.getByText(/Unused blobs \(\d+\)/).textContent();
|
||||
const unusedBlobsCount = parseInt(count?.match(/\d+/)?.[0] ?? '0');
|
||||
|
||||
expect(unusedBlobsCount).toBeGreaterThan(0);
|
||||
await expect(page.getByTestId('blob-preview-card')).toHaveCount(
|
||||
Math.min(9, unusedBlobsCount)
|
||||
);
|
||||
await page.getByTestId('blob-preview-card').nth(0).click();
|
||||
await expect(page.getByText('1 Selected')).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await expect(page.getByText('Delete blob files')).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
|
||||
await expect(
|
||||
page.getByText(`Unused blobs (${unusedBlobsCount - 1})`)
|
||||
).toBeVisible();
|
||||
});
|
||||
35
tests/affine-cloud/e2e/template.spec.ts
Normal file
35
tests/affine-cloud/e2e/template.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import { createRandomUser, loginUser } from '@affine-test/kit/utils/cloud';
|
||||
import { waitForEditorLoad } from '@affine-test/kit/utils/page-logic';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
const user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test('import from template should work', async ({ page }) => {
|
||||
await page.goto('https://affine.pro/templates', { waitUntil: 'load' });
|
||||
|
||||
await page.click('.template-list > a:first-child');
|
||||
const importButton = page.getByRole('button', {
|
||||
name: 'Use this template',
|
||||
});
|
||||
|
||||
const href = await importButton.evaluate((el: HTMLElement) => {
|
||||
const a = el.closest('a');
|
||||
if (!a) {
|
||||
throw new Error('Import link not found');
|
||||
}
|
||||
return a.href;
|
||||
});
|
||||
|
||||
const url = new URL(href);
|
||||
|
||||
await page.goto(url.pathname + url.search);
|
||||
|
||||
const btn = page.getByTestId('import-template-to-workspace-btn');
|
||||
|
||||
await btn.isVisible();
|
||||
await btn.click();
|
||||
await waitForEditorLoad(page);
|
||||
});
|
||||
57
tests/affine-cloud/e2e/workspace.spec.ts
Normal file
57
tests/affine-cloud/e2e/workspace.spec.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
createRandomUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { clickPageModeButton } from '@affine-test/kit/utils/editor';
|
||||
import {
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForEditorLoad,
|
||||
waitForEmptyEditor,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
user = await createRandomUser();
|
||||
await loginUser(page, user);
|
||||
});
|
||||
|
||||
test('should transform local favorites data', async ({ page }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await page
|
||||
.getByTestId('navigation-panel-bar-add-favorite-button')
|
||||
.first()
|
||||
.click();
|
||||
await clickPageModeButton(page);
|
||||
await waitForEmptyEditor(page);
|
||||
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new fav page');
|
||||
await expect(
|
||||
page
|
||||
.getByTestId('navigation-panel-favorites')
|
||||
.locator('[draggable] >> text=this is a new fav page')
|
||||
).toBeVisible();
|
||||
|
||||
await enableCloudWorkspace(page);
|
||||
await expect(
|
||||
page
|
||||
.getByTestId('navigation-panel-favorites')
|
||||
.locator('[draggable] >> text=this is a new fav page')
|
||||
).toBeVisible();
|
||||
});
|
||||
13
tests/affine-cloud/package.json
Normal file
13
tests/affine-cloud/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@affine-test/affine-cloud",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"e2e": "yarn playwright test --reporter=list"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@affine-test/kit": "workspace:*",
|
||||
"@playwright/test": "=1.58.2"
|
||||
},
|
||||
"version": "0.27.5"
|
||||
}
|
||||
77
tests/affine-cloud/playwright.config.ts
Normal file
77
tests/affine-cloud/playwright.config.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { testResultDir } from '@affine-test/kit/playwright';
|
||||
import type {
|
||||
PlaywrightTestConfig,
|
||||
PlaywrightWorkerOptions,
|
||||
} from '@playwright/test';
|
||||
|
||||
const runtimeConfigPath = fileURLToPath(
|
||||
new URL('./runtime-config.json', import.meta.url)
|
||||
);
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: './e2e',
|
||||
fullyParallel: !process.env.CI,
|
||||
timeout: 120_000,
|
||||
outputDir: testResultDir,
|
||||
use: {
|
||||
baseURL: 'http://localhost:8080/',
|
||||
browserName:
|
||||
(process.env.BROWSER as PlaywrightWorkerOptions['browserName']) ??
|
||||
'chromium',
|
||||
permissions: ['clipboard-read', 'clipboard-write'],
|
||||
viewport: { width: 1440, height: 800 },
|
||||
actionTimeout: 10 * 1000,
|
||||
locale: 'en-US',
|
||||
trace: 'retain-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
},
|
||||
forbidOnly: !!process.env.CI,
|
||||
workers: process.env.CI && !process.env.COPILOT ? 1 : 4,
|
||||
retries: process.env.COPILOT || !process.env.CI ? 1 : 3,
|
||||
reporter: process.env.CI ? 'github' : 'list',
|
||||
webServer: [
|
||||
{
|
||||
// TODO(@forehalo):
|
||||
// in ci, all the target will be built,
|
||||
// we could download the builds from archives
|
||||
// and then run the web with simple http serve, it's will be faster
|
||||
command: 'yarn run -T affine dev -p @affine/web',
|
||||
timeout: 120 * 1000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
env: {
|
||||
COVERAGE: process.env.COVERAGE || 'false',
|
||||
},
|
||||
url: 'http://localhost:8080',
|
||||
},
|
||||
{
|
||||
command: 'yarn run -T affine dev -p @affine/server',
|
||||
timeout: 120 * 1000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
env: {
|
||||
DATABASE_URL:
|
||||
process.env.DATABASE_URL ??
|
||||
'postgresql://affine:affine@localhost:5432/affine',
|
||||
NODE_ENV: 'test',
|
||||
AFFINE_ENV: process.env.AFFINE_ENV ?? 'dev',
|
||||
AFFINE_BACKEND_RUNTIME_CONFIG_PATH: runtimeConfigPath,
|
||||
DEBUG: 'affine:*',
|
||||
FORCE_COLOR: 'true',
|
||||
DEBUG_COLORS: 'true',
|
||||
MAILER_HOST: '0.0.0.0',
|
||||
MAILER_PORT: '1025',
|
||||
MAILER_SENDER: 'noreply@toeverything.info',
|
||||
MAILER_USER: 'noreply@toeverything.info',
|
||||
MAILER_PASSWORD: 'affine',
|
||||
},
|
||||
url: 'http://localhost:3010/graphql',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (process.env.CI) {
|
||||
config.retries = 3;
|
||||
}
|
||||
|
||||
export default config;
|
||||
9
tests/affine-cloud/runtime-config.json
Normal file
9
tests/affine-cloud/runtime-config.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"indexer": {
|
||||
"enabled": true,
|
||||
"provider": {
|
||||
"type": "embedded",
|
||||
"endpoint": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
10
tests/affine-cloud/tsconfig.json
Normal file
10
tests/affine-cloud/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./e2e",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
|
||||
},
|
||||
"include": ["e2e"],
|
||||
"references": [{ "path": "../kit" }]
|
||||
}
|
||||
Reference in New Issue
Block a user