mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-22 19:53:48 +08:00
refactor: move test utils to package (#3206)
This commit is contained in:
@@ -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);
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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'
|
||||
);
|
||||
});
|
||||
@@ -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');
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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'),
|
||||
});
|
||||
});
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["e2e"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../kit"
|
||||
},
|
||||
{
|
||||
"path": "../fixtures"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user