2025-01-12 18:05:24 +02:00
|
|
|
import { expect, Locator, Page } from "@playwright/test";
|
|
|
|
import type { BrowserContext } from "@playwright/test";
|
|
|
|
|
|
|
|
interface GotoOpts {
|
2025-01-17 23:13:55 +02:00
|
|
|
url?: string;
|
2025-01-12 18:05:24 +02:00
|
|
|
isMobile?: boolean;
|
|
|
|
}
|
2025-01-11 00:13:46 +02:00
|
|
|
|
2025-01-13 17:42:21 +02:00
|
|
|
const BASE_URL = "http://127.0.0.1:8082";
|
|
|
|
|
2025-01-11 00:13:46 +02:00
|
|
|
export default class App {
|
|
|
|
readonly page: Page;
|
2025-01-12 18:05:24 +02:00
|
|
|
readonly context: BrowserContext;
|
2025-01-11 00:13:46 +02:00
|
|
|
|
|
|
|
readonly tabBar: Locator;
|
|
|
|
readonly noteTree: Locator;
|
2025-01-17 20:15:48 +02:00
|
|
|
readonly launcherBar: Locator;
|
2025-01-11 12:48:59 +02:00
|
|
|
readonly currentNoteSplit: Locator;
|
2025-01-11 13:36:56 +02:00
|
|
|
readonly sidebar: Locator;
|
2025-01-11 00:13:46 +02:00
|
|
|
|
2025-01-12 18:05:24 +02:00
|
|
|
constructor(page: Page, context: BrowserContext) {
|
2025-01-11 00:13:46 +02:00
|
|
|
this.page = page;
|
2025-01-12 18:05:24 +02:00
|
|
|
this.context = context;
|
|
|
|
|
2025-01-11 00:13:46 +02:00
|
|
|
this.tabBar = page.locator(".tab-row-widget-container");
|
|
|
|
this.noteTree = page.locator(".tree-wrapper");
|
2025-01-17 20:15:48 +02:00
|
|
|
this.launcherBar = page.locator("#launcher-container");
|
2025-03-02 20:47:57 +01:00
|
|
|
this.currentNoteSplit = page.locator(".note-split:not(.hidden-ext)");
|
2025-01-11 13:36:56 +02:00
|
|
|
this.sidebar = page.locator("#right-pane");
|
2025-01-11 00:13:46 +02:00
|
|
|
}
|
|
|
|
|
2025-01-17 23:13:55 +02:00
|
|
|
async goto({ url, isMobile }: GotoOpts = {}) {
|
2025-01-12 18:05:24 +02:00
|
|
|
await this.context.addCookies([
|
|
|
|
{
|
2025-01-13 17:42:21 +02:00
|
|
|
url: BASE_URL,
|
2025-01-12 18:05:24 +02:00
|
|
|
name: "trilium-device",
|
2025-01-17 23:13:55 +02:00
|
|
|
value: isMobile ? "mobile" : "desktop"
|
2025-01-12 18:05:24 +02:00
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
2025-01-17 23:13:55 +02:00
|
|
|
if (!url) {
|
|
|
|
url = "/";
|
|
|
|
}
|
|
|
|
|
2025-03-07 20:34:01 +02:00
|
|
|
await this.page.goto(url, { waitUntil: "networkidle", timeout: 30_000 });
|
2025-01-11 00:13:46 +02:00
|
|
|
|
|
|
|
// Wait for the page to load.
|
2025-01-17 23:13:55 +02:00
|
|
|
if (url === "/") {
|
2025-03-02 20:47:57 +01:00
|
|
|
await expect(this.page.locator(".tree")).toContainText("Trilium Integration Test");
|
2025-01-17 23:13:55 +02:00
|
|
|
await this.closeAllTabs();
|
|
|
|
}
|
2025-01-11 00:13:46 +02:00
|
|
|
}
|
|
|
|
|
2025-01-11 12:48:59 +02:00
|
|
|
async goToNoteInNewTab(noteTitle: string) {
|
|
|
|
const autocomplete = this.currentNoteSplit.locator(".note-autocomplete");
|
|
|
|
await autocomplete.fill(noteTitle);
|
|
|
|
await autocomplete.press("ArrowDown");
|
|
|
|
await autocomplete.press("Enter");
|
|
|
|
}
|
|
|
|
|
2025-01-12 17:28:41 +02:00
|
|
|
async goToSettings() {
|
|
|
|
await this.page.locator(".launcher-button.bx-cog").click();
|
|
|
|
}
|
|
|
|
|
2025-01-11 00:13:46 +02:00
|
|
|
getTab(tabIndex: number) {
|
|
|
|
return this.tabBar.locator(".note-tab-wrapper").nth(tabIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
getActiveTab() {
|
|
|
|
return this.tabBar.locator(".note-tab[active]");
|
|
|
|
}
|
|
|
|
|
2025-01-13 17:21:50 +02:00
|
|
|
/**
|
|
|
|
* Closes all the tabs in the client by issuing a command.
|
|
|
|
*/
|
2025-01-11 00:13:46 +02:00
|
|
|
async closeAllTabs() {
|
2025-01-13 17:21:50 +02:00
|
|
|
await this.triggerCommand("closeAllTabs");
|
2025-01-11 00:13:46 +02:00
|
|
|
}
|
|
|
|
|
2025-01-13 17:21:50 +02:00
|
|
|
/**
|
|
|
|
* Adds a new tab by cliking on the + button near the tab bar.
|
|
|
|
*/
|
2025-01-11 00:13:46 +02:00
|
|
|
async addNewTab() {
|
|
|
|
await this.page.locator('[data-trigger-command="openNewTab"]').click();
|
|
|
|
}
|
|
|
|
|
2025-01-13 17:21:50 +02:00
|
|
|
/**
|
|
|
|
* Looks for a given title in the note tree and clicks on it. Useful for selecting option pages in settings in a similar fashion as the user.
|
|
|
|
* @param title the title of the note to click, as displayed in the note tree.
|
|
|
|
*/
|
2025-01-11 00:13:46 +02:00
|
|
|
async clickNoteOnNoteTreeByTitle(title: string) {
|
2025-01-13 17:21:50 +02:00
|
|
|
await this.noteTree.getByText(title).click();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Executes any Trilium command on the client.
|
|
|
|
* @param command the command to send.
|
|
|
|
*/
|
|
|
|
async triggerCommand(command: string) {
|
|
|
|
await this.page.evaluate(async (command: string) => {
|
|
|
|
await (window as any).glob.appContext.triggerCommand(command);
|
|
|
|
}, command);
|
2025-01-11 00:13:46 +02:00
|
|
|
}
|
|
|
|
|
2025-01-13 17:42:21 +02:00
|
|
|
async setOption(key: string, value: string) {
|
|
|
|
const csrfToken = await this.page.evaluate(() => {
|
|
|
|
return (window as any).glob.csrfToken;
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(csrfToken).toBeTruthy();
|
2025-03-02 20:47:57 +01:00
|
|
|
await expect(
|
|
|
|
await this.page.request.put(`${BASE_URL}/api/options/${key}/${value}`, {
|
|
|
|
headers: {
|
|
|
|
"x-csrf-token": csrfToken
|
|
|
|
}
|
|
|
|
})
|
|
|
|
).toBeOK();
|
2025-01-13 17:42:21 +02:00
|
|
|
}
|
2025-01-11 00:13:46 +02:00
|
|
|
}
|