|
@@ -2,7 +2,7 @@ import * as fs from 'fs'
|
|
|
import * as path from 'path'
|
|
|
import { test as base, expect, ConsoleMessage, Locator } from '@playwright/test';
|
|
|
import { ElectronApplication, Page, BrowserContext, _electron as electron } from 'playwright'
|
|
|
-import { loadLocalGraph, randomString } from './utils';
|
|
|
+import { loadLocalGraph, openLeftSidebar, randomString } from './utils';
|
|
|
|
|
|
let electronApp: ElectronApplication
|
|
|
let context: BrowserContext
|
|
@@ -12,7 +12,7 @@ let repoName = randomString(10)
|
|
|
let testTmpDir = path.resolve(__dirname, '../tmp')
|
|
|
|
|
|
if (fs.existsSync(testTmpDir)) {
|
|
|
- fs.rmdirSync(testTmpDir, { recursive: true })
|
|
|
+ fs.rmSync(testTmpDir, { recursive: true })
|
|
|
}
|
|
|
|
|
|
export let graphDir = path.resolve(testTmpDir, "e2e-test", repoName)
|
|
@@ -49,6 +49,7 @@ base.beforeAll(async () => {
|
|
|
cwd: "./static",
|
|
|
args: ["electron.js"],
|
|
|
locale: 'en',
|
|
|
+ timeout: 10_000, // should be enough for the app to start
|
|
|
})
|
|
|
context = electronApp.context()
|
|
|
await context.tracing.start({ screenshots: true, snapshots: true });
|
|
@@ -61,6 +62,7 @@ base.beforeAll(async () => {
|
|
|
"appData": app.getPath("appData"),
|
|
|
"userData": app.getPath("userData"),
|
|
|
"appName": app.getName(),
|
|
|
+ "electronVersion": app.getVersion(),
|
|
|
}
|
|
|
})
|
|
|
console.log("Test start with:", info)
|
|
@@ -77,7 +79,6 @@ base.beforeAll(async () => {
|
|
|
})
|
|
|
|
|
|
await page.waitForLoadState('domcontentloaded')
|
|
|
- // await page.waitForFunction(() => window.document.title != "Loading")
|
|
|
// NOTE: The following ensures first start.
|
|
|
// await page.waitForSelector('text=This is a demo graph, changes will not be saved until you open a local folder')
|
|
|
|
|
@@ -92,6 +93,11 @@ base.beforeAll(async () => {
|
|
|
})
|
|
|
|
|
|
await loadLocalGraph(page, graphDir);
|
|
|
+
|
|
|
+ // render app
|
|
|
+ await page.waitForFunction('window.document.title !== "Loading"')
|
|
|
+ expect(await page.title()).toMatch(/^Logseq.*?/)
|
|
|
+ await openLeftSidebar(page)
|
|
|
})
|
|
|
|
|
|
base.beforeEach(async () => {
|
|
@@ -118,7 +124,7 @@ interface Block {
|
|
|
* Must type input some text into an **empty** block.
|
|
|
* **DO NOT USE** this if there's auto-complete
|
|
|
*/
|
|
|
- mustType(value: string, options?: { delay?: number }): Promise<void>;
|
|
|
+ mustType(value: string, options?: { delay?: number, toBe?: string }): Promise<void>;
|
|
|
/**
|
|
|
* Press Enter and go to next block, require cursor to be in current block(editing mode).
|
|
|
* When cursor is not at the end of block, trailing text will be moved to the next block.
|
|
@@ -136,6 +142,10 @@ interface Block {
|
|
|
waitForSelectedBlocks(total: number): Promise<void>;
|
|
|
/** Escape editing mode, modal popup and selection. */
|
|
|
escapeEditing(): Promise<void>;
|
|
|
+ /** Find current selectionStart, i.e. text cursor position. */
|
|
|
+ selectionStart(): Promise<number>;
|
|
|
+ /** Find current selectionEnd. */
|
|
|
+ selectionEnd(): Promise<number>;
|
|
|
}
|
|
|
|
|
|
// hijack electron app into the test context
|
|
@@ -156,12 +166,13 @@ export const test = base.extend<{ page: Page, block: Block, context: BrowserCont
|
|
|
await locator.fill(value)
|
|
|
await expect(locator).toHaveText(value, { timeout: 1000 })
|
|
|
},
|
|
|
- mustType: async (value: string, options?: { delay?: number }) => {
|
|
|
+ mustType: async (value: string, options?: { delay?: number, toBe?: string }) => {
|
|
|
const locator: Locator = page.locator('textarea >> nth=0')
|
|
|
await locator.waitFor({ timeout: 1000 })
|
|
|
- const { delay = 100 } = options || {};
|
|
|
+ const { delay = 50 } = options || {};
|
|
|
+ const { toBe = value } = options || {};
|
|
|
await locator.type(value, { delay })
|
|
|
- await expect(locator).toHaveText(value, { timeout: 1000 })
|
|
|
+ await expect(locator).toHaveText(toBe, { timeout: 1000 })
|
|
|
},
|
|
|
enterNext: async (): Promise<Locator> => {
|
|
|
let blockCount = await page.locator('.page-blocks-inner .ls-block').count()
|
|
@@ -191,6 +202,7 @@ export const test = base.extend<{ page: Page, block: Block, context: BrowserCont
|
|
|
waitForBlocks: async (total: number): Promise<void> => {
|
|
|
// NOTE: `nth=` counts from 0.
|
|
|
await page.waitForSelector(`.ls-block >> nth=${total - 1}`, { timeout: 1000 })
|
|
|
+ await page.waitForSelector(`.ls-block >> nth=${total}`, { state: 'detached', timeout: 1000 })
|
|
|
},
|
|
|
waitForSelectedBlocks: async (total: number): Promise<void> => {
|
|
|
// NOTE: `nth=` counts from 0.
|
|
@@ -199,6 +211,18 @@ export const test = base.extend<{ page: Page, block: Block, context: BrowserCont
|
|
|
escapeEditing: async (): Promise<void> => {
|
|
|
await page.keyboard.press('Escape')
|
|
|
await page.keyboard.press('Escape')
|
|
|
+ },
|
|
|
+ selectionStart: async (): Promise<number> => {
|
|
|
+ return await page.locator('textarea >> nth=0').evaluate(node => {
|
|
|
+ const elem = <HTMLTextAreaElement>node
|
|
|
+ return elem.selectionStart
|
|
|
+ })
|
|
|
+ },
|
|
|
+ selectionEnd: async (): Promise<number> => {
|
|
|
+ return await page.locator('textarea >> nth=0').evaluate(node => {
|
|
|
+ const elem = <HTMLTextAreaElement>node
|
|
|
+ return elem.selectionEnd
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
use(block)
|