mirror of
https://github.com/abort-retry-ignore/joplock.git
synced 2026-05-23 12:58:44 +00:00
177 lines
6.6 KiB
JavaScript
177 lines
6.6 KiB
JavaScript
'use strict';
|
|
|
|
const { expect } = require('@playwright/test');
|
|
|
|
const DEV_EMAIL = process.env.PLAYWRIGHT_EMAIL || 'admin@localhost';
|
|
const DEV_PASSWORD = process.env.PLAYWRIGHT_PASSWORD || 'admin';
|
|
|
|
const slug = prefix => `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
const desktopEditor = page => page.locator('#editor-panel #note-editor-form');
|
|
const mobileEditor = page => page.locator('#mobile-editor-body #note-editor-form');
|
|
|
|
async function login(page) {
|
|
await page.goto('/login');
|
|
await expect(page.getByRole('heading', { name: 'Joplock' })).toBeVisible();
|
|
await page.getByPlaceholder('Email').fill(DEV_EMAIL);
|
|
await page.locator('#login-password').fill(DEV_PASSWORD);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
await page.waitForURL(/\/$/);
|
|
await expect(page.locator('body.app-shell')).toBeVisible();
|
|
}
|
|
|
|
function acceptDialogs(page) {
|
|
page.on('dialog', dialog => dialog.accept());
|
|
}
|
|
|
|
async function waitForSaved(page) {
|
|
await expect(page.locator('#editor-panel #autosave-status .autosave-ok, #mobile-editor-body #autosave-status .autosave-ok').first()).toHaveText('Saved', { timeout: 10000 });
|
|
const mobileSaved = page.locator('#mobile-editor-status .autosave-ok');
|
|
if (await mobileSaved.count()) {
|
|
await expect(mobileSaved).toHaveText('Saved', { timeout: 10000 });
|
|
}
|
|
}
|
|
|
|
async function setNoteBody(page, body) {
|
|
const cmContent = page.locator('#editor-panel .cm-content, #mobile-editor-body .cm-content').first();
|
|
if (await cmContent.count()) {
|
|
await cmContent.click();
|
|
await page.keyboard.press('Control+A');
|
|
await page.keyboard.press('Delete');
|
|
await page.keyboard.type(body);
|
|
return;
|
|
}
|
|
const textarea = page.locator('#editor-panel #note-body, #mobile-editor-body #note-body').first();
|
|
await expect(textarea).toHaveCount(1);
|
|
await textarea.evaluate((el, value) => {
|
|
el.value = value;
|
|
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
}, body);
|
|
}
|
|
|
|
async function setNoteTitle(page, title) {
|
|
const hiddenInput = page.locator('#editor-panel .editor-title-hidden, #mobile-editor-body .editor-title-hidden').first();
|
|
await expect(hiddenInput).toHaveCount(1);
|
|
await hiddenInput.evaluate((el, value) => {
|
|
el.value = value;
|
|
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
}, title);
|
|
const titleDiv = page.locator('#editor-panel .editor-title, #mobile-editor-body .editor-title').first();
|
|
if (await titleDiv.count()) {
|
|
await titleDiv.evaluate((el, value) => {
|
|
el.textContent = value;
|
|
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
}, title);
|
|
}
|
|
}
|
|
|
|
async function createNotebook(page, title) {
|
|
await page.getByRole('button', { name: '+ Notebook' }).click();
|
|
await expect(page.locator('#new-folder-modal')).toBeVisible();
|
|
await page.locator('#new-folder-title').fill(title);
|
|
await page.locator('#new-folder-modal-form').evaluate(form => form.requestSubmit());
|
|
await expect(page.locator('#new-folder-modal')).toBeHidden();
|
|
await expect(page.locator('.nav-folder-title', { hasText: title })).toBeVisible();
|
|
}
|
|
|
|
async function deleteNotebook(page, folderName) {
|
|
const folderTitle = page.locator('.nav-folder-title', { hasText: folderName }).first();
|
|
await expect(folderTitle).toBeVisible();
|
|
const row = folderTitle.locator('xpath=ancestor::div[contains(@class,"nav-folder-row")]').first();
|
|
await row.click({ button: 'right' });
|
|
await expect(page.locator('#folder-context-menu')).toBeVisible();
|
|
await page.getByRole('button', { name: 'Delete notebook' }).click();
|
|
await expect(page.locator('.nav-folder-title', { hasText: folderName })).toHaveCount(0, { timeout: 15000 });
|
|
}
|
|
|
|
async function createDesktopNote(page, folderName) {
|
|
const button = page.locator(`.nav-folder[data-folder-title="${folderName}"] .nav-folder-add`).first();
|
|
await expect(button).toBeVisible();
|
|
await button.click();
|
|
await expect(desktopEditor(page)).toBeVisible();
|
|
}
|
|
|
|
async function openDesktopNote(page, noteTitle) {
|
|
await page.getByRole('button', { name: noteTitle, exact: true }).click();
|
|
await expect(desktopEditor(page)).toBeVisible();
|
|
await expect(page.locator('#editor-panel .editor-title')).toContainText(noteTitle);
|
|
}
|
|
|
|
async function searchDesktop(page, query) {
|
|
const search = page.locator('#nav-search');
|
|
await search.fill(query);
|
|
await search.press('Enter');
|
|
await expect(page.locator('.nav-folder-title', { hasText: 'Search Results' })).toBeVisible();
|
|
}
|
|
|
|
async function openSettings(page) {
|
|
await page.goto('/settings');
|
|
await page.waitForURL(/\/settings/);
|
|
await expect(page.getByRole('heading', { name: 'Joplock Settings' })).toBeVisible();
|
|
}
|
|
|
|
async function ensureMobileFoldersScreen(page) {
|
|
await expect(page.locator('#mobile-app[aria-hidden="false"]')).toBeVisible();
|
|
if (await page.locator('#mobile-editor-screen.mobile-screen-active').count()) {
|
|
await page.locator('#mobile-editor-back').click();
|
|
}
|
|
if (await page.locator('#mobile-notes-screen.mobile-screen-active').count()) {
|
|
await page.locator('#mobile-notes-screen .mobile-back-btn').click();
|
|
}
|
|
await expect(page.locator('#mobile-folders-screen.mobile-screen-active')).toBeVisible();
|
|
}
|
|
|
|
async function setUiMode(page, mode) {
|
|
const result = await page.evaluate(async value => {
|
|
const res = await fetch('/api/web/settings', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'same-origin',
|
|
body: JSON.stringify({ uiMode: value }),
|
|
});
|
|
return res.status;
|
|
}, mode);
|
|
if (result !== 204) throw new Error(`setUiMode failed: ${result}`);
|
|
}
|
|
|
|
async function logout(page) {
|
|
await page.goto('/logout');
|
|
await expect(page.locator('#logout-login-link')).toBeVisible({ timeout: 15000 });
|
|
await page.locator('#logout-login-link').click();
|
|
await page.waitForURL(/\/login\?loggedOut=1/);
|
|
await expect(page.getByRole('button', { name: 'Login' })).toBeVisible();
|
|
}
|
|
|
|
async function openMobileFolder(page, folderName) {
|
|
await expect(page.locator('#mobile-app[aria-hidden="false"]')).toBeVisible();
|
|
const row = page.locator('#mobile-folders-body .mobile-folder-row', { hasText: folderName }).first();
|
|
await expect(row).toBeVisible();
|
|
await row.click();
|
|
await expect(page.locator('#mobile-notes-screen.mobile-screen-active')).toBeVisible();
|
|
await expect(page.locator('#mobile-notes-title')).toContainText(folderName);
|
|
}
|
|
|
|
async function openMobileNote(page, noteTitle) {
|
|
await page.getByRole('button', { name: new RegExp(noteTitle) }).click();
|
|
await expect(page.locator('#mobile-editor-screen.mobile-screen-active')).toBeVisible();
|
|
await expect(mobileEditor(page)).toBeVisible();
|
|
}
|
|
|
|
module.exports = {
|
|
acceptDialogs,
|
|
createDesktopNote,
|
|
createNotebook,
|
|
deleteNotebook,
|
|
login,
|
|
logout,
|
|
ensureMobileFoldersScreen,
|
|
openDesktopNote,
|
|
openMobileFolder,
|
|
openMobileNote,
|
|
openSettings,
|
|
searchDesktop,
|
|
setNoteBody,
|
|
setNoteTitle,
|
|
setUiMode,
|
|
slug,
|
|
waitForSaved,
|
|
};
|