logseq/e2e-tests/whiteboards.spec.ts

527 lines
18 KiB
TypeScript
Raw Normal View History

2022-09-02 13:21:25 +00:00
import { expect } from '@playwright/test'
import { test } from './fixtures'
2023-06-09 13:56:22 +00:00
import { modKey, renamePage } from './utils'
2022-09-02 13:21:25 +00:00
2022-12-03 08:29:44 +00:00
test('enable whiteboards', async ({ page }) => {
if (await page.$('.nav-header .whiteboard') === null) {
await page.click('#head .toolbar-dots-btn')
await page.click('#head .dropdown-wrapper >> text=Settings')
await page.click('.settings-modal a[data-id=features]')
await page.click('text=Whiteboards >> .. >> .ui__toggle')
await page.waitForTimeout(1000)
await page.keyboard.press('Escape')
}
2022-12-03 08:29:44 +00:00
await expect(page.locator('.nav-header .whiteboard')).toBeVisible()
2022-09-02 13:21:25 +00:00
})
test('should display onboarding tour', async ({ page }) => {
// ensure onboarding tour is going to be triggered locally
await page.evaluate(`window.clearWhiteboardStorage()`)
2022-12-03 08:29:44 +00:00
await page.click('.nav-header .whiteboard')
await expect(page.locator('.cp__whiteboard-welcome')).toBeVisible()
2023-11-14 05:49:58 +00:00
await page.click('.cp__whiteboard-welcome button.skip-welcome')
await expect(page.locator('.cp__whiteboard-welcome')).toBeHidden()
})
test('create new whiteboard', async ({ page }) => {
2022-12-03 08:29:44 +00:00
await page.click('#tl-create-whiteboard')
await expect(page.locator('.logseq-tldraw')).toBeVisible()
2022-09-02 13:21:25 +00:00
})
2022-12-03 08:29:44 +00:00
test('can right click title to show context menu', async ({ page }) => {
await page.click('.whiteboard-page-title', {
button: 'right',
})
2022-11-17 15:02:25 +00:00
2022-12-03 08:29:44 +00:00
await expect(page.locator('#custom-context-menu')).toBeVisible()
2022-11-17 15:02:25 +00:00
2022-12-03 08:29:44 +00:00
await page.keyboard.press('Escape')
2022-11-17 15:02:25 +00:00
2022-12-03 08:29:44 +00:00
await expect(page.locator('#custom-context-menu')).toHaveCount(0)
})
2023-01-16 10:47:52 +00:00
test('newly created whiteboard should have a default title', async ({ page }) => {
2022-12-03 08:29:44 +00:00
await expect(page.locator('.whiteboard-page-title .title')).toContainText(
'Untitled'
)
2023-01-16 10:47:52 +00:00
})
test('set whiteboard title', async ({ page }) => {
const title = 'my-whiteboard'
await page.click('.nav-header .whiteboard')
await page.click('#tl-create-whiteboard')
await page.click('.whiteboard-page-title')
await page.fill('.whiteboard-page-title input', title)
await page.keyboard.press('Enter')
await expect(page.locator('.whiteboard-page-title .title')).toContainText(
title
)
})
test('update whiteboard title', async ({ page }) => {
const title = 'my-whiteboard'
await page.click('.whiteboard-page-title')
await page.fill('.whiteboard-page-title input', title + '-2')
await page.keyboard.press('Enter')
await expect(page.locator('.whiteboard-page-title .title')).toContainText(
title + '-2'
)
})
2022-09-02 13:21:25 +00:00
2022-12-03 08:29:44 +00:00
test('draw a rectangle', async ({ page }) => {
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
2022-09-05 10:24:04 +00:00
await page.keyboard.type('wr')
2022-09-05 10:24:04 +00:00
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 105, bounds.y + 105)
2022-12-03 08:29:44 +00:00
await page.mouse.down()
2022-09-05 10:24:04 +00:00
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 150, bounds.y + 150 )
2022-12-03 08:29:44 +00:00
await page.mouse.up()
await page.keyboard.press('Escape')
2022-09-05 10:24:04 +00:00
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
2022-09-05 10:24:04 +00:00
})
2023-03-09 10:17:21 +00:00
test('undo the rectangle action', async ({ page }) => {
await page.keyboard.press(modKey + '+z', { delay: 100 })
2023-03-08 18:14:00 +00:00
await expect(page.locator('.logseq-tldraw .tl-positioned-svg rect')).toHaveCount(0)
})
test('redo the rectangle action', async ({ page }) => {
await page.waitForTimeout(100)
await page.keyboard.press(modKey + '+Shift+z', { delay: 100 })
await page.keyboard.press('Escape')
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
})
test('clone the rectangle', async ({ page }) => {
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 400, bounds.y + 400)
await page.mouse.move(bounds.x + 120, bounds.y + 120, {steps: 5})
await page.keyboard.down('Alt')
await page.mouse.down()
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 200, bounds.y + 200, {steps: 5})
await page.mouse.up()
await page.keyboard.up('Alt')
await page.waitForTimeout(100)
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
})
2023-05-24 18:24:25 +00:00
test('group the rectangles', async ({ page }) => {
await page.keyboard.press(modKey + '+a')
await page.keyboard.press(modKey + '+g')
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(1)
})
2023-05-24 18:49:07 +00:00
test('delete the group', async ({ page }) => {
2023-05-24 19:27:34 +00:00
await page.keyboard.press(modKey + '+a')
2023-05-24 18:49:07 +00:00
await page.keyboard.press('Delete')
2023-05-24 18:24:25 +00:00
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(0)
2023-05-24 19:27:34 +00:00
// should also delete the grouped shapes
2023-05-24 18:24:25 +00:00
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(0)
})
test('undo the group deletion', async ({ page }) => {
await page.keyboard.press(modKey + '+z')
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(1)
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
})
2023-05-24 18:49:07 +00:00
test('undo the group action', async ({ page }) => {
2023-05-24 18:24:25 +00:00
await page.keyboard.press(modKey + '+z')
await expect(page.locator('.logseq-tldraw .tl-group-container')).toHaveCount(0)
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
})
test('connect rectangles with an arrow', async ({ page }) => {
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
await page.keyboard.type('wc')
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 120, bounds.y + 120)
await page.mouse.down()
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 200, bounds.y + 200, {steps: 5}) // will fail without steps
await page.mouse.up()
await page.keyboard.press('Escape')
await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(1)
})
test('delete the first rectangle', async ({ page }) => {
await page.keyboard.press('Escape', { delay: 100 })
await page.keyboard.press('Escape', { delay: 100 })
await page.click('.logseq-tldraw .tl-box-container:first-of-type')
await page.keyboard.press('Delete')
await page.waitForTimeout(200)
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(0)
})
test('undo the delete action', async ({ page }) => {
await page.keyboard.press(modKey + '+z')
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
await expect(page.locator('.logseq-tldraw .tl-line-container')).toHaveCount(1)
})
2023-05-15 15:55:50 +00:00
test('convert the first rectangle to ellipse', async ({ page }) => {
2023-06-02 18:33:31 +00:00
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
2023-05-15 15:55:50 +00:00
await page.keyboard.press('Escape')
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 220, bounds.y + 220)
await page.mouse.down()
await page.mouse.up()
await page.mouse.move(bounds.x + 520, bounds.y + 520)
2023-05-15 15:55:50 +00:00
await page.click('.tl-context-bar .tl-geometry-tools-pane-anchor')
await page.click('.tl-context-bar .tl-geometry-toolbar [data-tool=ellipse]')
await expect(page.locator('.logseq-tldraw .tl-ellipse-container')).toHaveCount(1)
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(1)
})
2023-05-16 11:05:52 +00:00
test('change the color of the ellipse', async ({ page }) => {
await page.click('.tl-context-bar .tl-color-bg')
await page.click('.tl-context-bar .tl-color-palette .bg-red-500')
await expect(page.locator('.logseq-tldraw .tl-ellipse-container ellipse:last-of-type')).toHaveAttribute('fill', 'var(--ls-wb-background-color-red)')
})
test('undo the color switch', async ({ page }) => {
await page.keyboard.press(modKey + '+z')
await expect(page.locator('.logseq-tldraw .tl-ellipse-container ellipse:last-of-type')).toHaveAttribute('fill', 'var(--ls-wb-background-color-default)')
})
2023-05-16 11:06:40 +00:00
test('undo the shape conversion', async ({ page }) => {
2023-05-15 15:55:50 +00:00
await page.keyboard.press(modKey + '+z')
await page.waitForTimeout(100)
2023-05-15 15:55:50 +00:00
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
await expect(page.locator('.logseq-tldraw .tl-ellipse-container')).toHaveCount(0)
})
2023-04-18 15:15:31 +00:00
test('locked elements should not be removed', async ({ page }) => {
2023-06-02 18:33:31 +00:00
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
2023-04-18 15:15:31 +00:00
await page.keyboard.press('Escape')
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 220, bounds.y + 220)
await page.mouse.down()
await page.mouse.up()
await page.mouse.move(bounds.x + 520, bounds.y + 520)
await page.keyboard.press(`${modKey}+l`, { delay: 100 })
await page.keyboard.press('Delete', { delay: 100 })
await page.keyboard.press(`${modKey}+Shift+l`, { delay: 100 })
2023-04-18 15:15:31 +00:00
await expect(page.locator('.logseq-tldraw .tl-box-container')).toHaveCount(2)
})
test('move arrow to back', async ({ page }) => {
await page.keyboard.press('Escape')
await page.waitForTimeout(1000)
await page.click('.logseq-tldraw .tl-line-container')
await page.keyboard.press('Shift+[')
await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).toHaveClass('tl-line-container')
})
test('move arrow to front', async ({ page }) => {
await page.keyboard.press('Escape')
await page.waitForTimeout(1000)
await page.click('.logseq-tldraw .tl-line-container')
await page.keyboard.press('Shift+]')
await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).not.toHaveClass('tl-line-container')
})
test('undo the move action', async ({ page }) => {
await page.keyboard.press(modKey + '+z')
await page.waitForTimeout(100)
await expect(page.locator('.logseq-tldraw .tl-canvas .tl-layer > div:first-of-type > div:first-of-type')).toHaveClass('tl-line-container')
})
test('cleanup the shapes', async ({ page }) => {
await page.keyboard.press(`${modKey}+a`)
await page.keyboard.press('Delete')
await page.waitForTimeout(100)
await expect(page.locator('[data-type=Shape]')).toHaveCount(0)
})
2023-03-09 10:17:21 +00:00
test('create a block', async ({ page }) => {
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
2023-03-08 18:14:00 +00:00
await page.keyboard.type('ws')
2023-06-02 18:33:31 +00:00
await page.mouse.dblclick(bounds.x + 105, bounds.y + 105)
2023-03-09 10:17:21 +00:00
await page.waitForTimeout(100)
await page.keyboard.type('a')
await page.keyboard.press('Enter')
await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container')).toHaveCount(1)
2023-03-08 18:14:00 +00:00
})
2023-06-14 14:09:14 +00:00
// TODO: Fix the failing test
test.skip('expand the block', async ({ page }) => {
2023-03-09 10:17:21 +00:00
await page.keyboard.press('Escape')
2023-06-12 13:24:53 +00:00
await page.keyboard.press(modKey + '+ArrowDown')
2023-03-09 10:17:21 +00:00
await page.waitForTimeout(100)
await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container .tl-logseq-portal-header')).toHaveCount(1)
})
2023-06-14 14:09:14 +00:00
// TODO: Depends on the previous test
test.skip('undo the expand action', async ({ page }) => {
2023-03-08 18:14:00 +00:00
await page.keyboard.press(modKey + '+z')
2023-03-09 10:17:21 +00:00
await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container .tl-logseq-portal-header')).toHaveCount(0)
})
2024-01-17 19:15:38 +00:00
// TODO: Fix the failing test
test.skip('undo the block action', async ({ page }) => {
2023-03-09 10:17:21 +00:00
await page.keyboard.press(modKey + '+z')
await expect(page.locator('.logseq-tldraw .tl-logseq-portal-container')).toHaveCount(0)
2023-03-08 18:14:00 +00:00
})
2023-03-07 16:50:50 +00:00
test('copy/paste url to create an iFrame shape', async ({ page }) => {
2023-03-07 11:40:36 +00:00
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
await page.keyboard.type('wt')
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 105, bounds.y + 105)
2023-03-07 11:40:36 +00:00
await page.mouse.down()
2023-03-07 17:32:48 +00:00
await page.waitForTimeout(100)
2023-03-07 11:40:36 +00:00
await page.keyboard.type('https://logseq.com')
2023-03-07 17:51:12 +00:00
await page.keyboard.press(modKey + '+a')
await page.keyboard.press(modKey + '+c')
2023-03-07 11:40:36 +00:00
await page.keyboard.press('Escape')
2023-03-07 17:51:12 +00:00
await page.keyboard.press(modKey + '+v')
2023-03-07 11:40:36 +00:00
await expect( page.locator('.logseq-tldraw .tl-iframe-container')).toHaveCount(1)
})
test('copy/paste X status url to create a Post shape', async ({ page }) => {
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
await page.keyboard.type('wt')
await page.mouse.move(bounds.x + 105, bounds.y + 105)
await page.mouse.down()
await page.waitForTimeout(100)
await page.keyboard.type('https://x.com/logseq/status/1605224589046386689')
await page.keyboard.press(modKey + '+a')
await page.keyboard.press(modKey + '+c')
await page.keyboard.press('Escape')
await page.keyboard.press(modKey + '+v')
await expect( page.locator('.logseq-tldraw .tl-tweet-container')).toHaveCount(1)
})
2023-03-07 16:50:50 +00:00
test('copy/paste twitter status url to create a Tweet shape', async ({ page }) => {
2023-03-07 15:38:32 +00:00
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
await page.keyboard.type('wt')
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 105, bounds.y + 105)
2023-03-07 15:38:32 +00:00
await page.mouse.down()
2023-03-07 17:32:48 +00:00
await page.waitForTimeout(100)
2023-03-07 15:38:32 +00:00
await page.keyboard.type('https://twitter.com/logseq/status/1605224589046386689')
2023-03-07 17:51:12 +00:00
await page.keyboard.press(modKey + '+a')
await page.keyboard.press(modKey + '+c')
2023-03-07 15:38:32 +00:00
await page.keyboard.press('Escape')
2023-03-07 17:51:12 +00:00
await page.keyboard.press(modKey + '+v')
2023-03-07 15:38:32 +00:00
await expect( page.locator('.logseq-tldraw .tl-tweet-container')).toHaveCount(2)
2023-03-07 15:38:32 +00:00
})
2023-03-07 16:50:50 +00:00
test('copy/paste youtube video url to create a Youtube shape', async ({ page }) => {
2023-03-07 15:38:32 +00:00
const canvas = await page.waitForSelector('.logseq-tldraw')
const bounds = (await canvas.boundingBox())!
await page.keyboard.type('wt')
2023-06-02 18:33:31 +00:00
await page.mouse.move(bounds.x + 105, bounds.y + 105)
2023-03-07 15:38:32 +00:00
await page.mouse.down()
2023-03-07 17:32:48 +00:00
await page.waitForTimeout(100)
2023-03-07 15:38:32 +00:00
await page.keyboard.type('https://www.youtube.com/watch?v=hz2BacySDXE')
2023-03-07 17:51:12 +00:00
await page.keyboard.press(modKey + '+a')
await page.keyboard.press(modKey + '+c')
2023-03-07 15:38:32 +00:00
await page.keyboard.press('Escape')
2023-03-07 17:51:12 +00:00
await page.keyboard.press(modKey + '+v')
2023-03-07 15:38:32 +00:00
await expect(page.locator('.logseq-tldraw .tl-youtube-container')).toHaveCount(1)
2023-01-04 08:56:52 +00:00
})
2022-12-03 08:29:44 +00:00
test('zoom in', async ({ page }) => {
2023-01-10 08:44:28 +00:00
await page.keyboard.press('Shift+0') // reset zoom
await page.waitForTimeout(1500) // wait for the zoom animation to finish
2023-04-26 09:31:45 +00:00
await page.keyboard.press('Shift+=')
2023-03-09 10:17:21 +00:00
await page.waitForTimeout(1500) // wait for the zoom animation to finish
2022-12-03 08:29:44 +00:00
await expect(page.locator('#tl-zoom')).toContainText('125%')
2022-09-05 10:24:04 +00:00
})
2022-12-03 08:29:44 +00:00
test('zoom out', async ({ page }) => {
2023-01-04 09:27:47 +00:00
await page.keyboard.press('Shift+0')
2023-03-09 10:17:21 +00:00
await page.waitForTimeout(1500) // wait for the zoom animation to finish
2023-04-26 09:31:45 +00:00
await page.keyboard.press('Shift+-')
2023-03-09 10:17:21 +00:00
await page.waitForTimeout(1500) // wait for the zoom animation to finish
await expect(page.locator('#tl-zoom')).toContainText('80%')
2022-09-05 10:24:04 +00:00
})
2022-12-03 08:29:44 +00:00
test('open context menu', async ({ page }) => {
await page.locator('.logseq-tldraw').click({ button: 'right' })
await expect(page.locator('.tl-context-menu')).toBeVisible()
2022-09-02 13:21:25 +00:00
})
2022-12-03 08:29:44 +00:00
test('close context menu on esc', async ({ page }) => {
await page.keyboard.press('Escape')
await expect(page.locator('.tl-context-menu')).toBeHidden()
2022-09-02 13:21:25 +00:00
})
2022-12-03 08:29:44 +00:00
test('quick add another whiteboard', async ({ page }) => {
// create a new board first
await page.click('.nav-header .whiteboard')
await page.click('#tl-create-whiteboard')
await page.click('.whiteboard-page-title')
await page.fill('.whiteboard-page-title input', 'my-whiteboard-3')
await page.keyboard.press('Enter')
2023-01-16 13:55:59 +00:00
2024-01-17 19:15:38 +00:00
await page.waitForTimeout(300)
const canvas = await page.waitForSelector('.logseq-tldraw')
2022-12-03 08:29:44 +00:00
await canvas.dblclick({
position: {
2023-06-02 18:33:31 +00:00
x: 200,
y: 200,
2022-12-03 08:29:44 +00:00
},
})
const quickAdd$ = page.locator('.tl-quick-search')
await expect(quickAdd$).toBeVisible()
await page.fill('.tl-quick-search input', 'my-whiteboard')
await quickAdd$
.locator('.tl-quick-search-option >> text=my-whiteboard-2')
.first()
.click()
await expect(quickAdd$).toBeHidden()
await expect(
page.locator('.tl-logseq-portal-container >> text=my-whiteboard-2')
).toBeVisible()
})
2022-12-03 08:29:44 +00:00
test('go to another board and check reference', async ({ page }) => {
await page
.locator('.tl-logseq-portal-container >> text=my-whiteboard-2')
.click()
await expect(page.locator('.whiteboard-page-title .title')).toContainText(
'my-whiteboard-2'
)
const pageRefCount$ = page.locator('.whiteboard-page-refs-count')
await expect(pageRefCount$.locator('.open-page-ref-link')).toContainText('1')
})
2023-06-08 08:16:41 +00:00
test('Create an embedded whiteboard', async ({ page }) => {
const canvas = await page.waitForSelector('.logseq-tldraw')
await canvas.dblclick({
position: {
2023-06-14 15:34:30 +00:00
x: 110,
y: 110,
2023-06-08 08:16:41 +00:00
},
})
const quickAdd$ = page.locator('.tl-quick-search')
await expect(quickAdd$).toBeVisible()
await page.fill('.tl-quick-search input', 'My embedded whiteboard')
await quickAdd$
.locator('div[data-index="2"] .tl-quick-search-option')
.first()
.click()
await expect(quickAdd$).toBeHidden()
await expect(page.locator('.tl-logseq-portal-header a')).toContainText('My embedded whiteboard')
})
test('New whiteboard should have the correct name', async ({ page }) => {
page.locator('.tl-logseq-portal-header a').click()
await expect(page.locator('.whiteboard-page-title')).toContainText('My embedded whiteboard')
})
test('Create an embedded page', async ({ page }) => {
const canvas = await page.waitForSelector('.logseq-tldraw')
await canvas.dblclick({
position: {
x: 150,
y: 150,
},
})
const quickAdd$ = page.locator('.tl-quick-search')
await expect(quickAdd$).toBeVisible()
await page.fill('.tl-quick-search input', 'My page')
await quickAdd$
.locator('div[data-index="1"] .tl-quick-search-option')
.first()
.click()
await expect(quickAdd$).toBeHidden()
await expect(page.locator('.tl-logseq-portal-header a')).toContainText('My page')
})
test('New page should have the correct name', async ({ page }) => {
page.locator('.tl-logseq-portal-header a').click()
await expect(page.locator('.ls-page-title')).toContainText('My page')
2023-06-09 13:44:54 +00:00
})
2023-06-09 13:46:36 +00:00
test('Renaming a page to an existing whiteboard name should be prohibited', async ({ page }) => {
2023-06-09 13:56:22 +00:00
await renamePage(page, "My embedded whiteboard")
2023-06-09 13:44:54 +00:00
await expect(page.locator('.page-title input')).toHaveValue('My page')
2023-10-16 15:33:08 +00:00
})