refactor: move test utils to package (#3206)

This commit is contained in:
Alex Yang
2023-07-13 09:05:01 +00:00
committed by GitHub
parent 4f5ed30298
commit 0230cea16e
61 changed files with 199 additions and 551 deletions
+190
View File
@@ -0,0 +1,190 @@
import { test } from '@affine-test/kit/playwright';
import {
changeFilter,
checkDatePicker,
checkDatePickerMonth,
checkFilterName,
checkPagesCount,
clickDatePicker,
createFirstFilter,
createPageWithTag,
fillDatePicker,
selectDateFromDatePicker,
selectMonthFromMonthPicker,
selectTag,
} from '@affine-test/kit/utils/filter';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
closeDownloadTip,
getBlockSuiteEditorTitle,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
function getAllPage(page: Page) {
const newPageButton = page
.locator('table')
.getByRole('button', { name: 'New Page' });
const newPageDropdown = newPageButton.locator('svg');
const edgelessBlockCard = page.locator('table').getByText('New Edgeless');
async function clickNewPageButton() {
return newPageButton.click();
}
async function clickNewEdgelessDropdown() {
await newPageDropdown.click();
await edgelessBlockCard.click();
}
return { clickNewPageButton, clickNewEdgelessDropdown };
}
test('all page', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarAllPageButton(page);
});
test('all page can create new page', async ({ page }) => {
const { clickNewPageButton } = getAllPage(page);
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarAllPageButton(page);
await clickNewPageButton();
const title = getBlockSuiteEditorTitle(page);
await title.fill('this is a new page');
await clickSideBarAllPageButton(page);
const cell = page.getByRole('cell', { name: 'this is a new page' });
expect(cell).not.toBeUndefined();
});
test('all page can create new edgeless page', async ({ page }) => {
const { clickNewEdgelessDropdown } = getAllPage(page);
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarAllPageButton(page);
await clickNewEdgelessDropdown();
await expect(page.locator('affine-edgeless-page')).toBeVisible();
});
test('allow creation of filters by favorite', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarAllPageButton(page);
await closeDownloadTip(page);
await createFirstFilter(page, 'Favourited');
await page
.locator('[data-testid="filter-arg"]', { hasText: 'true' })
.locator('div')
.click();
await expect(
await page.locator('[data-testid="filter-arg"]').textContent()
).toBe('false');
});
test('allow creation of filters by created time', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarAllPageButton(page);
await closeDownloadTip(page);
await createFirstFilter(page, 'Created');
await checkFilterName(page, 'after');
// init date
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
await checkDatePicker(page, yesterday);
await checkPagesCount(page, 1);
// change date
const today = new Date();
await fillDatePicker(page, today);
await checkPagesCount(page, 0);
// change filter
await page.locator('[data-testid="filter-name"]').click();
await page
.locator('[data-testid="filter-name-select"]')
.locator('button', { hasText: 'before' })
.click();
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
await fillDatePicker(page, tomorrow);
await checkDatePicker(page, tomorrow);
await checkPagesCount(page, 1);
});
test('creation of filters by created time, then click date picker to modify the date', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarAllPageButton(page);
await closeDownloadTip(page);
await createFirstFilter(page, 'Created');
await checkFilterName(page, 'after');
// init date
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
await checkDatePicker(page, yesterday);
await checkPagesCount(page, 1);
// change date
const today = new Date();
await selectDateFromDatePicker(page, today);
await checkPagesCount(page, 0);
// change filter
await page.locator('[data-testid="filter-name"]').click();
await page
.locator('[data-testid="filter-name-select"]')
.locator('button', { hasText: 'before' })
.click();
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
await selectDateFromDatePicker(page, tomorrow);
await checkDatePicker(page, tomorrow);
await checkPagesCount(page, 1);
});
test('use monthpicker to modify the month of datepicker', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarAllPageButton(page);
await closeDownloadTip(page);
await createFirstFilter(page, 'Created');
await checkFilterName(page, 'after');
// init date
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
await checkDatePicker(page, yesterday);
// change month
await clickDatePicker(page);
const lastMonth = new Date();
lastMonth.setMonth(lastMonth.getMonth() - 1);
await selectMonthFromMonthPicker(page, lastMonth);
await checkDatePickerMonth(page, lastMonth);
// change month
await clickDatePicker(page);
const nextMonth = new Date();
nextMonth.setMonth(nextMonth.getMonth() + 1);
await selectMonthFromMonthPicker(page, nextMonth);
await checkDatePickerMonth(page, nextMonth);
});
test('allow creation of filters by tags', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await closeDownloadTip(page);
await createPageWithTag(page, { title: 'Page A', tags: ['A'] });
await createPageWithTag(page, { title: 'Page B', tags: ['B'] });
await clickSideBarAllPageButton(page);
await createFirstFilter(page, 'Tags');
await checkFilterName(page, 'is not empty');
await checkPagesCount(page, 2);
await changeFilter(page, /^contains all/);
await checkPagesCount(page, 3);
await selectTag(page, 'A');
await checkPagesCount(page, 1);
await changeFilter(page, /^does not contains all/);
await selectTag(page, 'B');
await checkPagesCount(page, 2);
});
@@ -0,0 +1,13 @@
import { test } from '@affine-test/kit/playwright';
import { checkBlockHub } from '@affine-test/kit/utils/editor';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { newPage, waitEditorLoad } from '@affine-test/kit/utils/page-logic';
test('block-hub should work', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await checkBlockHub(page);
await newPage(page);
await page.waitForTimeout(500);
await checkBlockHub(page);
});
@@ -0,0 +1,71 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { newPage, waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
const addDatabase = async (page: Page) => {
await page.keyboard.press('/', { delay: 50 });
await page.keyboard.press('d');
await page.keyboard.press('a');
await page.keyboard.press('t');
await page.keyboard.press('a');
await page.keyboard.press('b');
await page.keyboard.press('a', { delay: 50 });
await page.keyboard.press('Enter', { delay: 50 });
};
test('database is useable', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await waitEditorLoad(page);
await page.keyboard.insertText('test title');
await page.keyboard.press('Enter');
const title = page.locator('.affine-default-page-block-title');
expect(await title.innerText()).toBe('test title');
await addDatabase(page);
const database = page.locator('.affine-database-table');
await expect(database).toBeVisible();
await page.reload();
await waitEditorLoad(page);
await newPage(page);
await waitEditorLoad(page);
await page.keyboard.insertText('test title2');
await page.keyboard.press('Enter');
const title2 = page.locator('.affine-default-page-block-title');
await page.waitForTimeout(500);
expect(await title2.innerText()).toBe('test title2');
await addDatabase(page);
const database2 = page.locator('.affine-database-table');
await expect(database2).toBeVisible();
});
test('link page is useable', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await waitEditorLoad(page);
await page.keyboard.insertText('page1');
await page.keyboard.press('Enter');
const title = page.locator('.affine-default-page-block-title');
expect(await title.innerText()).toBe('page1');
await newPage(page);
await waitEditorLoad(page);
await page.keyboard.insertText('page2');
await page.keyboard.press('Enter');
const title2 = page.locator('.affine-default-page-block-title');
expect(await title2.innerText()).toBe('page2');
await page.keyboard.press('@', { delay: 50 });
await page.keyboard.press('p');
await page.keyboard.press('a');
await page.keyboard.press('g');
await page.keyboard.press('e');
await page.keyboard.press('1');
await page.keyboard.press('Enter');
const link = page.locator('.affine-reference');
await page.waitForTimeout(500);
await expect(link).toBeVisible();
await page.click('.affine-reference');
await page.waitForTimeout(500);
expect(await title.innerText()).toBe('page1');
});
@@ -0,0 +1,64 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
clickPageMoreActions,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('Switch to edgeless by switch edgeless item', async ({ page }) => {
async function getCount(): Promise<number> {
return page.evaluate(() => {
// @ts-expect-error
return globalThis.__toastCount;
});
}
await openHomePage(page);
await waitEditorLoad(page);
const btn = await page.getByTestId('switch-edgeless-mode-button');
await page.evaluate(() => {
// @ts-expect-error
globalThis.__toastCount = 0;
window.addEventListener('affine-toast:emit', () => {
// @ts-expect-error
globalThis.__toastCount++;
});
});
await btn.click();
await page.waitForTimeout(100);
{
const count = await getCount();
expect(count).toBe(1);
}
const edgeless = page.locator('affine-edgeless-page');
expect(await edgeless.isVisible()).toBe(true);
const editorWrapperPadding = await page
.locator('.editor-wrapper.edgeless-mode')
.evaluate(element => {
return window.getComputedStyle(element).getPropertyValue('padding');
});
expect(editorWrapperPadding).toBe('0px');
{
const count = await getCount();
expect(count).toBe(1);
}
await btn.click();
await btn.click();
await btn.click();
await page.waitForTimeout(100);
{
const count = await getCount();
expect(count).toBe(1);
}
});
test('Convert to edgeless by editor header items', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await clickPageMoreActions(page);
const menusEdgelessItem = page.getByTestId('editor-option-menu-edgeless');
await menusEdgelessItem.click({ delay: 100 });
const edgeless = page.locator('affine-edgeless-page');
expect(await edgeless.isVisible()).toBe(true);
});
+19
View File
@@ -0,0 +1,19 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('Click right-bottom corner contact icon', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await page.locator('[data-testid=help-island]').click();
const rightBottomContactUs = page.locator(
'[data-testid=right-bottom-contact-us-icon]'
);
expect(await rightBottomContactUs.isVisible()).toEqual(true);
await rightBottomContactUs.click();
const title = await page.getByTestId('about-title');
await expect(title).toBeVisible();
});
@@ -0,0 +1,12 @@
import { test } from '@affine-test/kit/playwright';
import { expect } from '@playwright/test';
test('should have page0', async ({ page }) => {
await page.goto('http://localhost:8080/_debug/init-page.html');
await page.waitForSelector('v-line');
const pageId = await page.evaluate(async () => {
// @ts-expect-error
return globalThis.page.id;
});
expect(pageId).toBe('page0');
});
@@ -0,0 +1,45 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('drag a page from "All pages" list onto the "Trash" folder in the sidebar to move it to trash list', async ({
page,
}) => {
// TODO-Doma
// Init test db with known workspaces and open "All Pages" page via url directly
{
await openHomePage(page);
await waitEditorLoad(page);
await page.getByText('All Pages').click();
await page.waitForTimeout(500);
}
const title = 'AFFiNE - not just a note taking app';
// Drag-and-drop
// Ref: https://playwright.dev/docs/input#dragging-manually
await page.getByText(title).hover();
await page.mouse.down();
await page.waitForTimeout(1000);
await page.getByText('Trash').hover();
await page.mouse.up();
await expect(
page.getByText('Successfully deleted'),
'A toast containing success message is shown'
).toBeVisible();
await expect(
page.getByText(title),
'The deleted post is no longer on the All Page list'
).toHaveCount(0);
// TODO-Doma
// Visit trash page via url
await page.getByText('Trash', { exact: true }).click();
await expect(
page.getByText(title),
'The deleted post exists in the Trash list'
).toHaveCount(1);
});
@@ -0,0 +1,8 @@
import { test } from '@affine-test/kit/playwright';
import { expect } from '@playwright/test';
test('visit 404 page', async ({ page }) => {
await page.goto('http://localhost:8080/404');
const notFoundTip = page.locator('[data-testid=notFound]');
await expect(notFoundTip).toBeVisible();
});
@@ -0,0 +1,716 @@
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import type { Page } from '@playwright/test';
import { expect, test } from '@playwright/test';
import fs from 'fs';
async function importImage(page: Page, url: string) {
await page.evaluate(
([url]) => {
const clipData = {
'text/html': `<img alt={'Sample image'} src=${url} />`,
};
const e = new ClipboardEvent('paste', {
clipboardData: new DataTransfer(),
});
Object.defineProperty(e, 'target', {
writable: false,
value: document.body,
});
Object.entries(clipData).forEach(([key, value]) => {
e.clipboardData?.setData(key, value);
});
document.body.dispatchEvent(e);
},
[url]
);
await page.waitForTimeout(500);
}
async function closeImagePreviewModal(page: Page) {
await page
.getByTestId('image-preview-modal')
.getByTestId('image-preview-close-button')
.first()
.click();
await page.waitForTimeout(500);
}
test('image preview should be shown', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
const locator = page.getByTestId('image-preview-modal');
expect(locator.isVisible()).toBeTruthy();
await closeImagePreviewModal(page);
expect(await locator.isVisible()).toBeFalsy();
});
test('image go left and right', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
await closeImagePreviewModal(page);
}
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/affine-preview.png');
}
const locator = page.getByTestId('image-preview-modal');
expect(locator.isVisible()).toBeTruthy();
await page.locator('img').first().dblclick();
await page.waitForTimeout(1000);
{
const newBlobId = (await locator
.locator('img[data-blob-id]')
.first()
.getAttribute('data-blob-id')) as string;
expect(newBlobId).not.toBe(blobId);
}
await page.keyboard.press('ArrowRight');
await page.waitForTimeout(1000);
{
const newBlobId = (await locator
.locator('img[data-blob-id]')
.first()
.getAttribute('data-blob-id')) as string;
expect(newBlobId).toBe(blobId);
}
});
test('image able to zoom in and out with mouse scroll', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-content');
const naturalWidth = await locator.evaluate(
(img: HTMLImageElement) => img.naturalWidth
);
expect(locator.isVisible()).toBeTruthy();
const { width, height } = await page.evaluate(() => ({
width: window.innerWidth,
height: window.innerHeight,
}));
// zooom in
await page.mouse.move(width / 2, height / 2);
await page.mouse.wheel(0, 100);
await page.mouse.wheel(0, 100);
await page.mouse.wheel(0, 100);
await page.waitForTimeout(1000);
let imageBoundary = await locator.boundingBox();
let imageWidth = await imageBoundary?.width;
if (imageWidth) {
expect((imageWidth / naturalWidth).toFixed(2)).toBe('0.54');
}
// zooom in
await page.mouse.move(width / 2, height / 2);
await page.mouse.wheel(0, -100);
await page.mouse.wheel(0, -100);
await page.mouse.wheel(0, -100);
await page.waitForTimeout(1000);
imageBoundary = await locator.boundingBox();
imageWidth = await imageBoundary?.width;
if (imageWidth) {
expect((imageWidth / naturalWidth).toFixed(2)).toBe('0.84');
}
});
test('image able to zoom in and out with button click', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-content');
expect(locator.isVisible()).toBeTruthy();
const naturalWidth = await locator.evaluate(
(img: HTMLImageElement) => img.naturalWidth
);
await page.waitForTimeout(500);
// zoom in
{
const locator = page.getByTestId('image-preview-modal');
await locator.getByTestId('zoom-in-button').dblclick();
}
await page.waitForTimeout(1000);
let imageBoundary = await locator.boundingBox();
let imageWidth = await imageBoundary?.width;
if (imageWidth) {
expect((imageWidth / naturalWidth).toFixed(2)).toBe('1.04');
}
// zooom out
await page.getByTestId('zoom-out-button').dblclick();
imageBoundary = await locator.boundingBox();
imageWidth = await imageBoundary?.width;
if (imageWidth) {
expect((imageWidth / naturalWidth).toFixed(2)).toBe('0.84');
}
});
test('image should able to go left and right by buttons', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
await closeImagePreviewModal(page);
}
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/affine-preview.png');
}
const locator = page.getByTestId('image-preview-modal');
expect(locator.isVisible()).toBeTruthy();
await page.locator('img').first().dblclick();
// ensure the new image was imported
await page.waitForTimeout(1000);
{
const newBlobId = (await locator
.getByTestId('image-content')
.getAttribute('data-blob-id')) as string;
expect(newBlobId).not.toBe(blobId);
}
await locator.getByTestId('next-image-button').click();
await page.waitForTimeout(1000);
{
const newBlobId = (await page
.getByTestId('image-content')
.getAttribute('data-blob-id')) as string;
expect(newBlobId).toBe(blobId);
}
await locator.getByTestId('previous-image-button').click();
await page.waitForTimeout(1000);
{
const newBlobId = (await locator
.getByTestId('image-content')
.getAttribute('data-blob-id')) as string;
expect(newBlobId).not.toBe(blobId);
}
});
test('image able to fit to screen by button', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-content');
expect(locator.isVisible()).toBeTruthy();
const naturalWidth = await locator.evaluate(
(img: HTMLImageElement) => img.naturalWidth
);
const [viewportWidth, viewportHeight] = await page.evaluate(() => {
return [window.innerWidth, window.innerHeight];
});
// zooom in
{
const locator = page.getByTestId('image-preview-modal');
await locator.getByTestId('zoom-in-button').dblclick();
}
await page.waitForTimeout(1000);
let imageBoundary = await locator.boundingBox();
let imageWidth = await imageBoundary?.width;
if (imageWidth) {
expect((imageWidth / naturalWidth).toFixed(2)).toBe('1.04');
} else {
throw new Error("Image doesn't exist!");
}
//reset zoom
{
const locator = page.getByTestId('image-preview-modal');
await locator.getByTestId('fit-to-screen-button').click();
}
imageBoundary = await locator.boundingBox();
imageWidth = await imageBoundary?.width;
const imageHeight = await imageBoundary?.height;
if (imageWidth && imageHeight) {
expect(imageWidth).toBeLessThan(viewportWidth);
expect(imageHeight).toBeLessThan(viewportHeight);
} else {
throw new Error("Image doesn't exist!");
}
});
test('image able to reset zoom to 100%', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-content');
expect(locator.isVisible()).toBeTruthy();
const naturalWidth = await locator.evaluate(
(img: HTMLImageElement) => img.naturalWidth
);
await page.waitForTimeout(500);
// zooom in
{
const locator = page.getByTestId('image-preview-modal');
await locator.getByTestId('zoom-in-button').dblclick();
}
await page.waitForTimeout(1000);
let imageBoundary = await locator.boundingBox();
let imageWidth = await imageBoundary?.width;
if (imageWidth) {
expect((imageWidth / naturalWidth).toFixed(2)).toBe('1.04');
} else {
throw new Error("Image doesn't exist!");
}
//reset zoom
{
const locator = page.getByTestId('image-preview-modal');
await locator.getByTestId('reset-scale-button').click();
}
imageBoundary = await locator.boundingBox();
imageWidth = await imageBoundary?.width;
if (imageWidth) {
expect((imageWidth / naturalWidth).toFixed(2)).toBe('1.00');
} else {
throw new Error("Image doesn't exist!");
}
});
test('image able to copy to clipboard', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-preview-modal');
expect(locator.isVisible()).toBeTruthy();
await page.waitForTimeout(500);
await locator.getByTestId('copy-to-clipboard-button').click();
await page.on('console', message => {
expect(message.text()).toBe('Image copied to clipboard');
});
});
test('image able to download', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-preview-modal');
expect(locator.isVisible()).toBeTruthy();
const downloadPromise = page.waitForEvent('download');
await locator.getByTestId('download-button').click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toBe(`${blobId}.png`);
await download.saveAs(`download/ + ${download.suggestedFilename()}`);
expect(
fs.existsSync(`download/ + ${download.suggestedFilename()}`)
).toBeTruthy();
});
test('image should only able to move when image is larger than viewport', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-content');
expect(locator.isVisible()).toBeTruthy();
const { width, height } = await page.evaluate(() => ({
width: window.innerWidth,
height: window.innerHeight,
}));
let imageBoundary = await locator.boundingBox();
const initialXPos = imageBoundary?.x;
const initialYPos = imageBoundary?.y;
// check will it able to move when zoomed in
{
const locator = page.getByTestId('image-preview-modal');
await locator.getByTestId('zoom-in-button').dblclick();
await locator.getByTestId('zoom-in-button').dblclick();
}
await page.mouse.move(width / 2, height / 2);
await page.mouse.down();
await page.mouse.move(20, 20);
await page.mouse.up();
imageBoundary = await locator.boundingBox();
expect(initialXPos).not.toBe(imageBoundary?.x);
expect(initialYPos).not.toBe(imageBoundary?.y);
// check will it able to move when zoomed out
{
const locator = page.getByTestId('image-preview-modal');
await locator.getByTestId('fit-to-screen-button').click();
}
await page.mouse.move(width / 2, height / 2);
await page.mouse.down();
await page.mouse.move(20, 20);
await page.mouse.up();
imageBoundary = await locator.boundingBox();
expect(initialXPos).toBe(imageBoundary?.x);
expect(initialYPos).toBe(imageBoundary?.y);
});
test('image should able to delete and when delete, it will move to previous/next image', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
await closeImagePreviewModal(page);
}
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/affine-preview.png');
}
const locator = page.getByTestId('image-preview-modal');
expect(locator.isVisible()).toBeTruthy();
await page.locator('img').first().dblclick();
// ensure the new image was imported
await page.waitForTimeout(1000);
{
const newBlobId = (await locator
.getByTestId('image-content')
.getAttribute('data-blob-id')) as string;
expect(newBlobId).not.toBe(blobId);
}
await page.waitForTimeout(500);
await locator.getByTestId('delete-button').click();
{
const newBlobId = (await locator
.getByTestId('image-content')
.getAttribute('data-blob-id')) as string;
expect(newBlobId).toBe(blobId);
await closeImagePreviewModal(page);
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/affine-preview.png');
}
await page.locator('img').first().dblclick();
await locator.getByTestId('next-image-button').click();
await page.waitForTimeout(1000);
{
const newBlobId = (await page
.getByTestId('image-content')
.getAttribute('data-blob-id')) as string;
expect(newBlobId).toBe(blobId);
}
await locator.getByTestId('delete-button').click();
{
const newBlobId = (await locator
.getByTestId('image-content')
.getAttribute('data-blob-id')) as string;
expect(newBlobId).not.toBe(blobId);
}
await locator.getByTestId('delete-button').click();
await page.waitForTimeout(500);
{
const locator = await page.getByTestId('image-preview-modal').count();
expect(locator).toBe(0);
}
});
test('tooltips for all buttons should be visible when hovering', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
let blobId: string;
{
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
await page.waitForTimeout(500);
blobId = (await page
.locator('img')
.nth(1)
.getAttribute('data-blob-id')) as string;
expect(blobId).toBeTruthy();
}
const locator = page.getByTestId('image-preview-modal');
await page.waitForTimeout(500);
await locator.getByTestId('previous-image-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const previousImageTooltip = await element.getByText('Previous').count();
expect(previousImageTooltip).toBe(1);
}
await locator.getByTestId('next-image-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const nextImageTooltip = await element.getByText('Next').count();
expect(nextImageTooltip).toBe(1);
}
await locator.getByTestId('fit-to-screen-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const fitToScreenToolTip = await element.getByText('Fit to Screen').count();
expect(fitToScreenToolTip).toBe(1);
}
await locator.getByTestId('zoom-out-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const zoomOutToolTip = await element.getByText('Zoom out').count();
expect(zoomOutToolTip).toBe(1);
}
await locator.getByTestId('reset-scale-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const resetScaleTooltip = await element.getByText('Reset Scale').count();
expect(resetScaleTooltip).toBe(1);
}
await locator.getByTestId('zoom-in-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const zoominToolTip = await element.getByText('Zoom in').count();
expect(zoominToolTip).toBe(1);
}
await locator.getByTestId('download-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const downloadTooltip = await element.getByText('Download').count();
expect(downloadTooltip).toBe(1);
}
await locator.getByTestId('copy-to-clipboard-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const downloadTooltip = await element
.getByText('Copy to clipboard')
.count();
expect(downloadTooltip).toBe(1);
}
await locator.getByTestId('delete-button').hover();
await page.waitForTimeout(500);
{
const element = await page.getByRole('tooltip');
const downloadTooltip = await element.getByText('Delete').count();
expect(downloadTooltip).toBe(1);
}
});
test('keypress esc should close the modal', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
const locator = page.getByTestId('image-preview-modal');
expect(locator.isVisible()).toBeTruthy();
await page.keyboard.press('Escape');
await page.waitForTimeout(1000);
expect(await locator.isVisible()).toBeFalsy();
});
test('when mouse moves outside, the modal should be closed', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().dblclick();
const locator = page.getByTestId('image-preview-modal');
expect(await locator.isVisible()).toBeTruthy();
// animation delay
await page.waitForTimeout(1000);
await page.mouse.click(10, 10);
await page.waitForTimeout(1000);
expect(await locator.isVisible()).toBeFalsy();
});
test('caption should be visible and different styles were applied if image zoomed larger than viewport', async ({
page,
}) => {
const sampleCaption = 'affine owns me and all';
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
const title = await getBlockSuiteEditorTitle(page);
await title.click();
await page.keyboard.press('Enter');
await importImage(page, 'http://localhost:8081/large-image.png');
await page.locator('img').first().hover();
await page.locator('icon-button').first().click();
await page.getByPlaceholder('Write a caption').fill(sampleCaption);
await page.locator('img').first().dblclick();
const locator = page.getByTestId('image-preview-modal');
expect(await locator.isVisible()).toBeTruthy();
await page.waitForTimeout(1000);
let captionLocator = locator.getByTestId('image-caption-zoomedout');
await expect(captionLocator).toBeVisible();
expect(await captionLocator.innerText()).toBe(sampleCaption);
await page.getByTestId('zoom-in-button').click({ clickCount: 4 });
expect(await captionLocator.isVisible()).not.toBeTruthy();
captionLocator = locator.getByTestId('image-caption-zoomedin');
expect(await captionLocator.isVisible()).toBeTruthy();
expect(await captionLocator.innerText()).toBe(sampleCaption);
});
@@ -0,0 +1,8 @@
import { test } from '@affine-test/kit/playwright';
import { expect } from '@playwright/test';
test('the link has expired', async ({ page }) => {
await page.goto('http://localhost:8080//invite/abc');
await page.waitForTimeout(1000);
expect(page.getByText('The link has expired')).not.toBeUndefined();
});
+72
View File
@@ -0,0 +1,72 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('Collapse Sidebar', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await page.getByTestId('app-sidebar-arrow-button-collapse').click();
const sliderBarArea = page.getByTestId('app-sidebar');
await expect(sliderBarArea).not.toBeInViewport();
});
test('Expand Sidebar', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await page.getByTestId('app-sidebar-arrow-button-collapse').click();
const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).not.toBeInViewport();
await page.getByTestId('app-sidebar-arrow-button-expand').click();
await expect(sliderBarArea).toBeInViewport();
});
test('Click resizer can close sidebar', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).toBeVisible();
await page.getByTestId('app-sidebar-resizer').click();
await expect(sliderBarArea).not.toBeInViewport();
});
test('Drag resizer can resize sidebar', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).toBeVisible();
const sliderResizer = page.getByTestId('app-sidebar-resizer');
await sliderResizer.hover();
await page.mouse.down();
await page.mouse.move(400, 300, {
steps: 10,
});
await page.mouse.up();
const boundingBox = await page.getByTestId('app-sidebar').boundingBox();
expect(boundingBox?.width).toBe(399);
});
test('Sidebar in between sm & md breakpoint', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const sliderBarArea = page.getByTestId('sliderBar-inner');
const sliderBarModalBackground = page.getByTestId('app-sidebar-float-mask');
await expect(sliderBarArea).toBeInViewport();
await expect(sliderBarModalBackground).not.toBeVisible();
await page.setViewportSize({
width: 768,
height: 1024,
});
await expect(sliderBarModalBackground).toBeVisible();
// click modal background can close sidebar
await sliderBarModalBackground.click({
force: true,
position: { x: 600, y: 150 },
});
await expect(sliderBarArea).not.toBeInViewport();
});
@@ -0,0 +1,39 @@
import { resolve } from 'node:path';
import { rootDir, test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { newPage, waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('should create a page with a local first avatar', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await page.getByTestId('workspace-name').click();
await page.getByTestId('new-workspace').click({ delay: 50 });
await page
.getByTestId('create-workspace-input')
.type('Test Workspace 1', { delay: 50 });
await page.getByTestId('create-workspace-create-button').click();
await page.getByTestId('workspace-name').click();
await page.getByTestId('workspace-card').nth(1).click();
await page.getByTestId('settings-modal-trigger').click();
await page.getByText('current').click();
await page
.getByTestId('upload-avatar')
.setInputFiles(resolve(rootDir, 'tests', 'fixtures', 'smile.png'));
await page.mouse.click(0, 0);
await page.getByTestId('workspace-name').click();
await page.getByTestId('workspace-card').nth(0).click();
await page.waitForTimeout(1000);
await page.getByTestId('workspace-name').click();
await page.getByTestId('workspace-card').nth(1).click();
const blobUrl = await page
.getByTestId('workspace-avatar')
.locator('img')
.getAttribute('src');
// out user uploaded avatar
expect(blobUrl).toContain('blob:');
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,157 @@
import { test } from '@affine-test/kit/playwright';
import {
checkDatePicker,
selectDateFromDatePicker,
} from '@affine-test/kit/utils/filter';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
closeDownloadTip,
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
const createAndPinCollection = async (
page: Page,
options?: {
collectionName?: string;
}
) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('test page');
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'test page',
});
await expect(cell).toBeVisible();
await closeDownloadTip(page);
await page.getByTestId('create-first-filter').click();
await page
.getByTestId('variable-select')
.locator('button', { hasText: 'Created' })
.click();
await page.getByTestId('save-as-collection').click();
const title = page.getByTestId('input-collection-title');
await title.isVisible();
await title.fill(options?.collectionName ?? 'test collection');
await page.getByTestId('save-collection').click();
await page.waitForTimeout(100);
await page.getByTestId('collection-bar-option-pin').click();
await page.waitForTimeout(100);
};
test('Show collections items in sidebar', async ({ page }) => {
await createAndPinCollection(page);
const collections = page.getByTestId('collections');
const items = collections.getByTestId('collection-item');
expect(await items.count()).toBe(1);
const first = items.first();
expect(await first.textContent()).toBe('test collection');
await first.getByTestId('fav-collapsed-button').click();
const collectionPage = collections.getByTestId('collection-page').nth(1);
expect(await collectionPage.textContent()).toBe('test page');
await collectionPage.getByTestId('collection-page-options').click();
const deletePage = page
.getByTestId('collection-page-option')
.getByText('Delete');
await deletePage.click();
expect(await collections.getByTestId('collection-page').count()).toBe(1);
await first.getByTestId('collection-options').click();
const deleteCollection = page
.getByTestId('collection-option')
.getByText('Delete');
await deleteCollection.click();
await page.waitForTimeout(50);
expect(await items.count()).toBe(0);
});
test('pin and unpin collection', async ({ page }) => {
const name = 'asd';
await createAndPinCollection(page, { collectionName: name });
const collections = page.getByTestId('collections');
const items = collections.getByTestId('collection-item');
await page.waitForTimeout(50);
expect(await items.count()).toBe(1);
const first = items.first();
await first.getByTestId('collection-options').click();
const deleteCollection = page
.getByTestId('collection-option')
.getByText('Unpin');
await deleteCollection.click();
await page.waitForTimeout(50);
expect(await items.count()).toBe(0);
await page.getByTestId('collection-select').click();
const option = page.locator('[data-testid=collection-select-option]', {
hasText: name,
});
await option.hover();
await option.getByTestId('collection-select-option-pin').click();
await page.waitForTimeout(100);
expect(await items.count()).toBe(1);
});
test('edit collection', async ({ page }) => {
await createAndPinCollection(page);
const collections = page.getByTestId('collections');
const items = collections.getByTestId('collection-item');
expect(await items.count()).toBe(1);
const first = items.first();
await first.getByTestId('collection-options').click();
const editCollection = page
.getByTestId('collection-option')
.getByText('Edit Filter');
await editCollection.click();
const title = page.getByTestId('input-collection-title');
await title.fill('123');
await page.getByTestId('save-collection').click();
await page.waitForTimeout(100);
expect(await first.textContent()).toBe('123');
});
test('edit collection and change filter date', async ({ page }) => {
await createAndPinCollection(page);
const collections = page.getByTestId('collections');
const items = collections.getByTestId('collection-item');
expect(await items.count()).toBe(1);
const first = items.first();
await first.getByTestId('collection-options').click();
const editCollection = page
.getByTestId('collection-option')
.getByText('Edit Filter');
await editCollection.click();
const title = page.getByTestId('input-collection-title');
await title.fill('123');
const today = new Date();
await page.locator('[data-testid="filter-arg"]').locator('input').click();
await selectDateFromDatePicker(page, today);
await checkDatePicker(page, today);
await page.getByTestId('save-collection').click();
await page.waitForTimeout(100);
expect(await first.textContent()).toBe('123');
});
test('create temporary filter by click tag', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('test page');
await page.locator('affine-page-meta-data').click();
await page.locator('.add-tag').click();
await page.keyboard.type('TODO Tag');
await page.keyboard.press('Enter');
await page.keyboard.press('Escape');
await page.locator('.tag', { hasText: 'TODO Tag' }).click();
await closeDownloadTip(page);
const cell = page.getByRole('cell', {
name: 'test page',
});
await expect(cell).toBeVisible();
expect(await page.getByTestId('title').count()).toBe(1);
await page.getByTestId('filter-arg').click();
await page.getByRole('tooltip').getByText('TODO Tag').click();
expect(await page.getByTestId('title').count()).toBe(2);
});
@@ -0,0 +1,54 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('New a page , then delete it in all pages, permanently delete it', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to restore');
const newPageId = page.url().split('/').reverse()[0];
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to restore',
});
expect(cell).not.toBeUndefined();
await page
.getByTestId('more-actions-' + newPageId)
.getByRole('button')
.first()
.click();
const deleteBtn = page.getByTestId('move-to-trash');
await deleteBtn.click();
const confirmTip = page.getByText('Delete page?');
expect(confirmTip).not.toBeUndefined();
await page.getByRole('button', { name: 'Delete' }).click();
await page.getByTestId('trash-page').click();
// permanently delete it
await page
.getByTestId('more-actions-' + newPageId)
.getByRole('button')
.nth(1)
.click();
await page.getByText('Delete permanently?').dblclick();
// show empty tip
expect(
page.getByText(
'Tips: Click Add to Favorites/Trash and the page will appear here.'
)
).not.toBeUndefined();
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,77 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { openWorkspaceSettingPanel } from '@affine-test/kit/utils/setting';
import { openSettingModal } from '@affine-test/kit/utils/setting';
import { clickSideBarCurrentWorkspaceBanner } from '@affine-test/kit/utils/sidebar';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('Create new workspace, then delete it', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await clickSideBarCurrentWorkspaceBanner(page);
await page.getByTestId('new-workspace').click();
await page
.getByTestId('create-workspace-input')
.type('Test Workspace', { delay: 50 });
await page.getByTestId('create-workspace-create-button').click();
await page.waitForTimeout(1000);
await page.waitForSelector('[data-testid="workspace-name"]');
expect(await page.getByTestId('workspace-name').textContent()).toBe(
'Test Workspace'
);
await openSettingModal(page);
await openWorkspaceSettingPanel(page, 'Test Workspace');
await page.getByTestId('delete-workspace-button').click();
const workspaceNameDom = await page.getByTestId('workspace-name');
const currentWorkspaceName = await workspaceNameDom.evaluate(
node => node.textContent
);
await page
.getByTestId('delete-workspace-input')
.type(currentWorkspaceName as string);
const promise = page
.getByTestId('affine-toast')
.waitFor({ state: 'attached' });
await page.getByTestId('delete-workspace-confirm-button').click();
await promise;
await page.reload();
await page.waitForSelector('[data-testid="workspace-name"]');
await page.waitForTimeout(1000);
expect(await page.getByTestId('workspace-name').textContent()).toBe(
'Demo Workspace'
);
await assertCurrentWorkspaceFlavour('local', page);
});
test('Delete last workspace', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const workspaceNameDom = await page.getByTestId('workspace-name');
const currentWorkspaceName = await workspaceNameDom.evaluate(
node => node.textContent
);
await openSettingModal(page);
await openWorkspaceSettingPanel(page, currentWorkspaceName as string);
await page.getByTestId('delete-workspace-button').click();
await page
.getByTestId('delete-workspace-input')
.type(currentWorkspaceName as string);
const promise = page
.getByTestId('affine-toast')
.waitFor({ state: 'attached' });
await page.getByTestId('delete-workspace-confirm-button').click();
await promise;
await page.reload();
await expect(page.getByTestId('new-workspace')).toBeVisible();
await page.getByTestId('new-workspace').click();
await page.type('[data-testid="create-workspace-input"]', 'Test Workspace');
await page.getByTestId('create-workspace-create-button').click();
await page.waitForTimeout(1000);
await page.waitForSelector('[data-testid="workspace-name"]');
expect(await page.getByTestId('workspace-name').textContent()).toBe(
'Test Workspace'
);
});
@@ -0,0 +1,68 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
clickPageMoreActions,
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test.skip('New a page ,then open it and export html', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await page
.getByPlaceholder('Title')
.fill('this is a new page to export html content');
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to export html content',
});
expect(cell).not.toBeUndefined();
await cell.click();
await clickPageMoreActions(page);
const exportParentBtn = page.getByRole('tooltip', {
name: 'Add to favorites Convert to Edgeless Export Delete',
});
await exportParentBtn.click();
const [download] = await Promise.all([
page.waitForEvent('download'),
page.getByRole('button', { name: 'Export to HTML' }).click(),
]);
expect(download.suggestedFilename()).toBe(
'this is a new page to export html content.html'
);
});
test.skip('New a page ,then open it and export markdown', async ({ page }) => {
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await page
.getByPlaceholder('Title')
.fill('this is a new page to export markdown content');
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to export markdown content',
});
expect(cell).not.toBeUndefined();
await cell.click();
await clickPageMoreActions(page);
const exportParentBtn = page.getByRole('tooltip', {
name: 'Add to favorites Convert to Edgeless Export Delete',
});
await exportParentBtn.click();
const [download] = await Promise.all([
page.waitForEvent('download'),
page.getByRole('button', { name: 'Export to Markdown' }).click(),
]);
expect(download.suggestedFilename()).toBe(
'this is a new page to export markdown content.md'
);
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,119 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
clickPageMoreActions,
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { waitForLogMessage } from '@affine-test/kit/utils/utils';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('New a page and open it ,then favorite it', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to favorite',
});
expect(cell).not.toBeUndefined();
await cell.click();
await clickPageMoreActions(page);
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
await favoriteBtn.click();
await assertCurrentWorkspaceFlavour('local', page);
});
test('Export to html, markdown and png', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
{
await clickPageMoreActions(page);
await page.getByTestId('export-menu').click();
const downloadPromise = page.waitForEvent('download');
await page.getByTestId('export-to-markdown').click();
await downloadPromise;
}
await page.waitForTimeout(50);
{
await clickPageMoreActions(page);
await page.getByTestId('export-menu').click();
const downloadPromise = page.waitForEvent('download');
await page.getByTestId('export-to-html').click();
await downloadPromise;
}
// await page.waitForTimeout(50);
// {
// await clickPageMoreActions(page);
// await page.getByTestId('export-menu').click();
// const downloadPromise = page.waitForEvent('download');
// await page.getByTestId('export-to-png').click();
// await downloadPromise;
// }
});
test.skip('Export to pdf', async ({ page }) => {
const CheckedMessage = '[test] beforeprint event emitted';
page.addInitScript(() => {
window.addEventListener('beforeprint', () => {
console.log(CheckedMessage);
});
});
await openHomePage(page);
await waitEditorLoad(page);
{
await clickPageMoreActions(page);
await page.getByTestId('export-menu').click();
await page.getByTestId('export-to-pdf').click();
expect(waitForLogMessage(page, CheckedMessage)).toBeTruthy();
}
});
test('Cancel favorite', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to favorite',
});
expect(cell).not.toBeUndefined();
await cell.click();
await clickPageMoreActions(page);
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
await favoriteBtn.click();
// expect it in favorite list
expect(
page.getByRole('cell', { name: 'this is a new page to favorite' })
).not.toBeUndefined();
// cancel favorite
await page.getByTestId('all-pages').click();
const box = await page
.getByRole('cell', { name: 'this is a new page to favorite' })
.boundingBox();
//hover table record
await page.mouse.move((box?.x ?? 0) + 10, (box?.y ?? 0) + 10);
await page.getByTestId('favorited-icon').click();
// expect it not in favorite list
expect(
page.getByText(
'Tips: Click Add to Favorites/Trash and the page will appear here.'
)
).not.toBeUndefined();
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,119 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
clickPageMoreActions,
createLinkedPage,
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('Show favorite items in sidebar', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
const newPageId = page.url().split('/').reverse()[0];
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to favorite',
});
await expect(cell).toBeVisible();
await cell.click();
await clickPageMoreActions(page);
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
await favoriteBtn.click();
const favoriteListItemInSidebar = page.getByTestId(
'favorite-list-item-' + newPageId
);
expect(await favoriteListItemInSidebar.textContent()).toBe(
'this is a new page to favorite'
);
});
test('Show favorite reference in sidebar', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
// goes to main content
await page.keyboard.press('Enter', { delay: 50 });
await createLinkedPage(page, 'Another page');
const newPageId = page.url().split('/').reverse()[0];
await clickPageMoreActions(page);
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
await favoriteBtn.click();
const favItemTestId = 'favorite-list-item-' + newPageId;
const favoriteListItemInSidebar = page.getByTestId(favItemTestId);
expect(await favoriteListItemInSidebar.textContent()).toBe(
'this is a new page to favorite'
);
const collapseButton = favoriteListItemInSidebar.locator(
'[data-testid="fav-collapsed-button"]'
);
await expect(collapseButton).toBeVisible();
await collapseButton.click();
await expect(
page.locator('[data-type="favorite-list-item"] >> text=Another page')
).toBeVisible();
});
test("Deleted page's reference will not be shown in sidebar", async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
const newPageId = page.url().split('/').reverse()[0];
// goes to main content
await page.keyboard.press('Enter', { delay: 50 });
await createLinkedPage(page, 'Another page');
await clickPageMoreActions(page);
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
await favoriteBtn.click();
// goto "Another page"
await page.locator('.affine-reference-title').click();
// delete the page
await clickPageMoreActions(page);
const deleteBtn = page.getByTestId('editor-option-menu-delete');
await deleteBtn.click();
// confirm delete
await page.locator('button >> text=Delete').click();
const favItemTestId = 'favorite-list-item-' + newPageId;
const favoriteListItemInSidebar = page.getByTestId(favItemTestId);
expect(await favoriteListItemInSidebar.textContent()).toBe(
'this is a new page to favorite'
);
const collapseButton = favoriteListItemInSidebar.locator(
'[data-testid="fav-collapsed-button"]'
);
await expect(collapseButton).not.toBeVisible();
});
@@ -0,0 +1,31 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('click btn new page', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const originPageId = page.url().split('/').reverse()[0];
await newPage(page);
const newPageId = page.url().split('/').reverse()[0];
expect(newPageId).not.toBe(originPageId);
await assertCurrentWorkspaceFlavour('local', page);
});
test('click btn bew page and find it in all pages', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page');
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', { name: 'this is a new page' });
expect(cell).not.toBeUndefined();
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,34 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('click btn bew page and open in tab', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page');
const newPageUrl = page.url();
const newPageId = page.url().split('/').reverse()[0];
await page.getByTestId('all-pages').click();
await page
.getByTestId('more-actions-' + newPageId)
.getByRole('button')
.first()
.click();
const [newTabPage] = await Promise.all([
page.waitForEvent('popup'),
page.getByRole('button', { name: 'Open in new tab' }).click(),
]);
expect(newTabPage.url()).toBe(newPageUrl);
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,56 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('New a page , then delete it in all pages, restore it', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to restore');
const newPageId = page.url().split('/').reverse()[0];
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to restore',
});
expect(cell).not.toBeUndefined();
await page
.getByTestId('more-actions-' + newPageId)
.getByRole('button')
.first()
.click();
const deleteBtn = page.getByTestId('move-to-trash');
await deleteBtn.click();
const confirmTip = page.getByText('Delete page?');
expect(confirmTip).not.toBeUndefined();
await page.getByRole('button', { name: 'Delete' }).click();
await page.getByTestId('trash-page').click();
await page.waitForTimeout(50);
const trashPage = page.url();
// restore it
await page
.getByTestId('more-actions-' + newPageId)
.getByRole('button')
.first()
.click();
// stay in trash page
expect(page.url()).toBe(trashPage);
await page.getByTestId('all-pages').click();
const restoreCell = page.getByRole('cell', {
name: 'this is a new page to restore',
});
expect(restoreCell).not.toBeUndefined();
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,58 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
clickPageMoreActions,
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('New a page ,then open it and show delete modal', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to delete',
});
expect(cell).not.toBeUndefined();
await cell.click();
await clickPageMoreActions(page);
const deleteBtn = page.getByTestId('editor-option-menu-delete');
await deleteBtn.click();
const confirmTip = page.getByText('Delete page?');
expect(confirmTip).not.toBeUndefined();
await assertCurrentWorkspaceFlavour('local', page);
});
test('New a page ,then go to all pages and show delete modal', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
const newPageId = page.url().split('/').reverse()[0];
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to delete',
});
expect(cell).not.toBeUndefined();
await page
.getByTestId('more-actions-' + newPageId)
.getByRole('button')
.first()
.click();
const deleteBtn = page.getByTestId('move-to-trash');
await deleteBtn.click();
const confirmTip = page.getByText('Delete page?');
expect(confirmTip).not.toBeUndefined();
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,43 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import {
getBlockSuiteEditorTitle,
newPage,
waitEditorLoad,
} from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('New a page , then delete it in all pages, finally find it in trash', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
const newPageId = page.url().split('/').reverse()[0];
await page.getByTestId('all-pages').click();
const cell = page.getByRole('cell', {
name: 'this is a new page to delete',
});
expect(cell).not.toBeUndefined();
await page
.getByTestId('more-actions-' + newPageId)
.getByRole('button')
.first()
.click();
const deleteBtn = page.getByTestId('move-to-trash');
await deleteBtn.click();
const confirmTip = page.getByText('Delete page?');
expect(confirmTip).not.toBeUndefined();
await page.getByRole('button', { name: 'Delete' }).click();
await page.getByTestId('trash-page').click();
expect(
page.getByRole('cell', { name: 'this is a new page to delete' })
).not.toBeUndefined();
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,128 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
import {
createWorkspace,
openWorkspaceListModal,
} from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('just one item in the workspace list at first', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const workspaceName = page.getByTestId('workspace-name');
await workspaceName.click();
expect(
page
.locator('div')
.filter({ hasText: 'AFFiNE TestLocal WorkspaceAvailable Offline' })
.nth(3)
).not.toBeNull();
});
test('create one workspace in the workspace list', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const newWorkspaceNameStr = 'New Workspace';
await createWorkspace({ name: newWorkspaceNameStr }, page);
// check new workspace name
const newWorkspaceName = page.getByTestId('workspace-name');
await newWorkspaceName.click();
//check workspace list length
const workspaceCards = await page.$$('data-testid=workspace-card');
expect(workspaceCards.length).toBe(2);
//check page list length
const closeWorkspaceModal = page.getByTestId('close-workspace-modal');
await closeWorkspaceModal.click();
await clickSideBarAllPageButton(page);
await page.waitForTimeout(1000);
const pageList = page.locator('[data-testid=page-list-item]');
const result = await pageList.count();
expect(result).toBe(0);
await page.reload();
await page.waitForTimeout(1000);
const pageList1 = page.locator('[data-testid=page-list-item]');
const result1 = await pageList1.count();
expect(result1).toBe(0);
});
test('create multi workspace in the workspace list', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await createWorkspace({ name: 'New Workspace 2' }, page);
await createWorkspace({ name: 'New Workspace 3' }, page);
// show workspace list
const workspaceName = page.getByTestId('workspace-name');
await workspaceName.click();
{
//check workspace list length
const workspaceCards = await page.$$('data-testid=workspace-card');
expect(workspaceCards.length).toBe(3);
}
await page.reload();
await openWorkspaceListModal(page);
await page.getByTestId('draggable-item').nth(1).click();
await page.waitForTimeout(500);
// @ts-expect-error
const currentId: string = await page.evaluate(() => currentWorkspace.id);
await openWorkspaceListModal(page);
const sourceElement = page.getByTestId('draggable-item').nth(2);
const targetElement = page.getByTestId('draggable-item').nth(1);
const sourceBox = await sourceElement.boundingBox();
const targetBox = await targetElement.boundingBox();
if (!sourceBox || !targetBox) {
throw new Error('sourceBox or targetBox is null');
}
await page.mouse.move(
sourceBox.x + sourceBox.width / 2,
sourceBox.y + sourceBox.height / 2,
{
steps: 5,
}
);
await page.mouse.down();
await page.mouse.move(
targetBox.x + targetBox.width / 2,
targetBox.y + targetBox.height / 2,
{
steps: 5,
}
);
await page.mouse.up();
await page.waitForTimeout(1000);
await page.reload();
await openWorkspaceListModal(page);
await page.waitForTimeout(1000);
// check workspace list length
{
const workspaceCards1 = await page.$$('data-testid=workspace-card');
expect(workspaceCards1.length).toBe(3);
}
const workspaceChangePromise = page.evaluate(() => {
new Promise(resolve => {
window.addEventListener('affine:workspace:change', resolve, {
once: true,
});
});
});
await page.getByTestId('draggable-item').nth(2).click();
await workspaceChangePromise;
// @ts-expect-error
const nextId: string = await page.evaluate(() => currentWorkspace.id);
expect(currentId).toBe(nextId);
});
@@ -0,0 +1,33 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { assertCurrentWorkspaceFlavour } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('preset workspace name', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const workspaceName = page.getByTestId('workspace-name');
await page.waitForTimeout(1000);
expect(await workspaceName.textContent()).toBe('Demo Workspace');
await assertCurrentWorkspaceFlavour('local', page);
});
// test('default workspace avatar', async ({ page }) => {
// const workspaceAvatar = page.getByTestId('workspace-avatar');
// expect(
// await workspaceAvatar.locator('img').getAttribute('src')
// ).not.toBeNull();
// });
test('Open language switch menu', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const editorOptionMenuButton = page.getByTestId('editor-option-menu');
await expect(editorOptionMenuButton).toBeVisible();
await editorOptionMenuButton.click();
const languageMenuButton = page.getByTestId('language-menu-button');
await expect(languageMenuButton).toBeVisible();
const actual = await languageMenuButton.innerText();
expect(actual).toEqual('English');
await assertCurrentWorkspaceFlavour('local', page);
});
@@ -0,0 +1,44 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { createWorkspace } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('Open last workspace when back to affine', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await createWorkspace({ name: 'New Workspace 2' }, page);
await waitEditorLoad(page);
// show workspace list
await page.getByTestId('workspace-name').click();
//check workspace list length
const workspaceCards = await page.$$('data-testid=workspace-card');
expect(workspaceCards.length).toBe(2);
await workspaceCards[1].click();
await openHomePage(page);
const workspaceNameDom = page.getByTestId('workspace-name');
const currentWorkspaceName = await workspaceNameDom.evaluate(
node => node.textContent
);
expect(currentWorkspaceName).toEqual('New Workspace 2');
});
test('Download client tip', async ({ page }) => {
await openHomePage(page);
const downloadClientTipItem = page.locator(
'[data-testid=download-client-tip]'
);
await expect(downloadClientTipItem).toBeVisible();
const closeButton = page.locator(
'[data-testid=download-client-tip-close-button]'
);
await closeButton.click();
await expect(downloadClientTipItem).not.toBeVisible();
await page.goto('http://localhost:8080');
const currentDownloadClientTipItem = page.locator(
'[data-testid=download-client-tip]'
);
await expect(currentDownloadClientTipItem).not.toBeVisible();
});
+176
View File
@@ -0,0 +1,176 @@
import { test } from '@affine-test/kit/playwright';
import { withCtrlOrMeta } from '@affine-test/kit/utils/keyboard';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { newPage, waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect, type Page } from '@playwright/test';
const openQuickSearchByShortcut = async (page: Page) =>
await withCtrlOrMeta(page, () => page.keyboard.press('k', { delay: 50 }));
async function assertTitle(page: Page, text: string) {
const edgeless = page.locator('affine-edgeless-page');
if (!edgeless) {
const locator = page.locator('.affine-default-page-block-title').nth(0);
const actual = await locator.inputValue();
expect(actual).toBe(text);
}
}
async function assertResultList(page: Page, texts: string[]) {
const actual = await page.locator('[cmdk-item]').allInnerTexts();
expect(actual).toEqual(texts);
}
async function titleIsFocused(page: Page) {
const edgeless = page.locator('affine-edgeless-page');
if (!edgeless) {
const title = page.locator('.affine-default-page-block-title');
await expect(title).toBeVisible();
await expect(title).toBeFocused();
}
}
test('Click slider bar button', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
const quickSearchButton = page.locator(
'[data-testid=slider-bar-quick-search-button]'
);
await quickSearchButton.click();
const quickSearch = page.locator('[data-testid=quickSearch]');
await expect(quickSearch).toBeVisible();
});
test('Click arrowDown icon after title', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
const quickSearchButton = page.locator(
'[data-testid=slider-bar-quick-search-button]'
);
await quickSearchButton.click();
const quickSearch = page.locator('[data-testid=quickSearch]');
await expect(quickSearch).toBeVisible();
});
test('Press the shortcut key cmd+k', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
const quickSearch = page.locator('[data-testid=quickSearch]');
await expect(quickSearch).toBeVisible();
});
test('Create a new page without keyword', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
const addNewPage = page.locator('[data-testid=quick-search-add-new-page]');
await addNewPage.click();
await page.waitForTimeout(300);
await assertTitle(page, '');
});
test('Create a new page with keyword', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
await page.keyboard.insertText('test123456');
const addNewPage = page.locator('[data-testid=quick-search-add-new-page]');
await addNewPage.click();
await page.waitForTimeout(300);
await assertTitle(page, 'test123456');
});
test('Enter a keyword to search for', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
await page.keyboard.insertText('test123456');
const actual = await page.locator('[cmdk-input]').inputValue();
expect(actual).toBe('test123456');
});
test('Create a new page and search this page', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
// input title and create new page
await page.keyboard.insertText('test123456');
await page.waitForTimeout(300);
const addNewPage = page.locator('[data-testid=quick-search-add-new-page]');
await addNewPage.click();
await page.waitForTimeout(300);
await assertTitle(page, 'test123456');
await openQuickSearchByShortcut(page);
await page.keyboard.insertText('test123456');
await page.waitForTimeout(300);
await assertResultList(page, ['test123456']);
await page.keyboard.press('Enter');
await page.waitForTimeout(300);
await assertTitle(page, 'test123456');
});
test('Navigate to the 404 page and try to open quick search', async ({
page,
}) => {
await page.goto('http://localhost:8080/404');
const notFoundTip = page.locator('[data-testid=notFound]');
await expect(notFoundTip).toBeVisible();
await openQuickSearchByShortcut(page);
const quickSearch = page.locator('[data-testid=quickSearch]');
await expect(quickSearch).toBeVisible({ visible: false });
});
test('Open quick search on local page', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
const publishedSearchResults = page.locator('[publishedSearchResults]');
await expect(publishedSearchResults).toBeVisible({ visible: false });
});
test('Autofocus input after opening quick search', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
const locator = page.locator('[cmdk-input]');
await expect(locator).toBeVisible();
await expect(locator).toBeFocused();
});
test('Autofocus input after select', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
await page.keyboard.press('ArrowUp');
const locator = page.locator('[cmdk-input]');
await expect(locator).toBeVisible();
await expect(locator).toBeFocused();
});
test('Focus title after creating a new page', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await newPage(page);
await openQuickSearchByShortcut(page);
const addNewPage = page.locator('[data-testid=quick-search-add-new-page]');
await addNewPage.click();
await titleIsFocused(page);
});
test('Not show navigation path if page is not a subpage or current page is not in editor', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await openQuickSearchByShortcut(page);
expect(await page.getByTestId('navigation-path').count()).toBe(0);
});
+22
View File
@@ -0,0 +1,22 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage, webUrl } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('goto not found page', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const currentUrl = page.url();
const invalidUrl = currentUrl.replace('hello-world', 'invalid');
await page.goto(invalidUrl);
await expect(page.getByTestId('notFound')).toBeVisible();
});
test('goto not found workspace', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
const currentUrl = page.url();
await page.goto(new URL('/workspace/invalid/all', webUrl).toString());
await waitEditorLoad(page);
expect(page.url()).toEqual(currentUrl);
});
+89
View File
@@ -0,0 +1,89 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import {
openAboutPanel,
openAppearancePanel,
openSettingModal,
openShortcutsPanel,
} from '@affine-test/kit/utils/setting';
import { createWorkspace } from '@affine-test/kit/utils/workspace';
import { expect } from '@playwright/test';
test('Open settings modal', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await openSettingModal(page);
const modal = await page.getByTestId('setting-modal');
await expect(modal).toBeVisible();
});
test('Change theme', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await openSettingModal(page);
await openAppearancePanel(page);
const root = page.locator('html');
await page.getByTestId('light-theme-trigger').click();
const lightMode = await root.evaluate(element =>
element.getAttribute('data-theme')
);
expect(lightMode).toBe('light');
await page.getByTestId('dark-theme-trigger').click();
const darkMode = await root.evaluate(element =>
element.getAttribute('data-theme')
);
expect(darkMode).toBe('dark');
});
test('Change layout width', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await openSettingModal(page);
await openAppearancePanel(page);
await page.getByTestId('full-width-layout-trigger').click();
const editorWrapper = await page.locator('.editor-wrapper');
const className = await editorWrapper.getAttribute('class');
expect(className).toContain('full-screen');
});
test('Open shortcuts panel', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await openSettingModal(page);
await openShortcutsPanel(page);
const title = await page.getByTestId('keyboard-shortcuts-title');
await expect(title).toBeVisible();
});
test('Open about panel', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await openSettingModal(page);
await openAboutPanel(page);
const title = await page.getByTestId('about-title');
await expect(title).toBeVisible();
});
test('Different workspace should have different name in the setting panel', async ({
page,
}) => {
await openHomePage(page);
await waitEditorLoad(page);
await createWorkspace({ name: 'New Workspace 2' }, page);
await createWorkspace({ name: 'New Workspace 3' }, page);
await openSettingModal(page);
await page.getByTestId('current-workspace-label').click();
expect(await page.getByTestId('workspace-name-input').inputValue()).toBe(
'New Workspace 3'
);
await page.getByText('New Workspace 2').click();
expect(await page.getByTestId('workspace-name-input').inputValue()).toBe(
'New Workspace 2'
);
});
+19
View File
@@ -0,0 +1,19 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('Open shortcuts modal', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await page.locator('[data-testid=help-island]').click();
const shortcutsIcon = page.locator('[data-testid=shortcuts-icon]');
await page.waitForTimeout(1000);
expect(await shortcutsIcon.isVisible()).toEqual(true);
await shortcutsIcon.click();
await page.waitForTimeout(1000);
const shortcutsModal = page.locator('[data-testid=shortcuts-modal]');
await expect(shortcutsModal).toContainText('Page');
});
+12
View File
@@ -0,0 +1,12 @@
import { test } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
test('Create subpage', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await page.getByTestId('app-sidebar-arrow-button-collapse').click();
const sliderBarArea = page.getByTestId('sliderBar-inner');
await expect(sliderBarArea).not.toBeInViewport();
});
+30
View File
@@ -0,0 +1,30 @@
import { resolve } from 'node:path';
import { test, testResultDir } from '@affine-test/kit/playwright';
import { openHomePage } from '@affine-test/kit/utils/load-page';
import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import { expect } from '@playwright/test';
// default could be anything, according to the system
test('default white', async ({ browser }) => {
const context = await browser.newContext({
colorScheme: 'light',
});
const page = await context.newPage();
await openHomePage(page);
await waitEditorLoad(page);
const root = page.locator('html');
const themeMode = await root.evaluate(element =>
element.getAttribute('data-theme')
);
expect(themeMode).toBe('light');
await page.screenshot({
path: resolve(testResultDir, 'affine-light-theme.png'),
});
await page.getByTestId('editor-option-menu').click();
await page.getByTestId('change-theme-dark').click();
await page.waitForTimeout(50);
await page.screenshot({
path: resolve(testResultDir, 'affine-dark-theme.png'),
});
});
+12
View File
@@ -0,0 +1,12 @@
{
"name": "@affine-test/affine-local",
"private": true,
"scripts": {
"e2e": "yarn playwright test"
},
"devDependencies": {
"@affine-test/fixtures": "workspace:*",
"@affine-test/kit": "workspace:*",
"@playwright/test": "^1.35.1"
}
}
+73
View File
@@ -0,0 +1,73 @@
import type {
PlaywrightTestConfig,
PlaywrightWorkerOptions,
} from '@playwright/test';
// import { devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: './e2e',
fullyParallel: true,
timeout: process.env.CI ? 50_000 : 30_000,
use: {
baseURL: 'http://localhost:8080/',
browserName:
(process.env.BROWSER as PlaywrightWorkerOptions['browserName']) ??
'chromium',
permissions: ['clipboard-read', 'clipboard-write'],
viewport: { width: 1440, height: 800 },
actionTimeout: 5 * 1000,
locale: 'en-US',
// Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer
// You can open traces locally(`npx playwright show-trace trace.zip`)
// or in your browser on [Playwright Trace Viewer](https://trace.playwright.dev/).
trace: 'on-first-retry',
// Record video only when retrying a test for the first time.
video: 'on-first-retry',
},
forbidOnly: !!process.env.CI,
workers: 4,
retries: 1,
// 'github' for GitHub Actions CI to generate annotations, plus a concise 'dot'
// default 'list' when running locally
// See https://playwright.dev/docs/test-reporters#github-actions-annotations
reporter: process.env.CI ? 'github' : 'list',
webServer: [
{
command: 'yarn run serve:test-static',
port: 8081,
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
env: {
COVERAGE: process.env.COVERAGE || 'false',
ENABLE_DEBUG_PAGE: '1',
},
},
// Intentionally not building the web, reminds you to run it by yourself.
{
command: 'yarn run start:web-static',
port: 8080,
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
env: {
COVERAGE: process.env.COVERAGE || 'false',
},
},
],
};
if (process.env.CI) {
config.retries = 3;
config.workers = '50%';
}
export default config;
+16
View File
@@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"esModuleInterop": true,
"outDir": "lib"
},
"include": ["e2e"],
"references": [
{
"path": "../kit"
},
{
"path": "../fixtures"
}
]
}