Files
notesnook/apps/web/__e2e__/editor.test.ts
2025-09-12 08:28:39 +05:00

471 lines
13 KiB
TypeScript

/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { test, expect } from "@playwright/test";
import { AppModel } from "./models/app.model";
import { getTestId, NOTE, TITLE_ONLY_NOTE } from "./utils";
test("focus mode", async ({ page }) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
await notes.createNote(NOTE);
await notes.editor.enterFocusMode();
expect(await notes.editor.isFocusMode()).toBeTruthy();
expect(
await page.screenshot({ fullPage: true, quality: 100, type: "jpeg" })
).toMatchSnapshot("focus-mode.jpg", { maxDiffPixelRatio: 0.01 });
});
test("full screen in focus mode", async ({ page, headless }) => {
// fullscreen doesn't work in headless mode
if (headless) return;
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
await notes.createNote(NOTE);
await notes.editor.enterFocusMode();
await notes.editor.enterFullscreen();
expect(await notes.editor.isFullscreen()).toBeTruthy();
await notes.editor.exitFullscreen();
expect(await notes.editor.isFullscreen()).toBeFalsy();
});
test("normal mode from focus mode", async ({ page }) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
await notes.createNote(NOTE);
await notes.editor.enterFocusMode();
await notes.editor.exitFocusMode();
expect(await notes.editor.isFocusMode()).toBeFalsy();
expect(
await page.screenshot({ fullPage: true, quality: 100, type: "jpeg" })
).toMatchSnapshot("normal-mode-from-focus-mode.jpg", {
maxDiffPixelRatio: 0.01
});
});
test("creating a new note should clear the editor contents & title", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
await notes.createNote(NOTE);
await notes.newNote();
expect(await notes.editor.isUnloaded()).toBeTruthy();
expect(await notes.editor.getTitle()).toBe("");
expect(await notes.editor.getContent("text")).toBe("");
});
test("creating a new title-only note should add it to the list", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note = await notes.createNote({ title: NOTE.title });
expect(note).toBeDefined();
});
test("opening an empty titled note should empty out editor contents", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
let notes = await app.goToNotes();
await notes.createNote(NOTE);
await notes.createNote(TITLE_ONLY_NOTE);
await notes.newNote();
await app.goto();
notes = await app.goToNotes();
const fullNote = await notes.findNote(NOTE);
await fullNote?.openNote();
const onlyTitle = await notes.findNote(TITLE_ONLY_NOTE);
await onlyTitle?.openNote();
expect(await notes.editor.getContent("text")).toBe("");
expect(await notes.editor.getTitle()).toBe(TITLE_ONLY_NOTE.title);
});
test("focus should not jump to editor while typing in title input", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
await notes.newNote();
await notes.editor.typeTitle("Hello", 200);
expect(await notes.editor.getTitle()).toBe("Hello");
expect(await notes.editor.getContent("text")).toBe("");
});
test("when title format is set to headline, title should be generated from headline until user edits the title", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const settings = await app.goToSettings();
await settings.setTitleFormat("$headline$");
await settings.close();
const notes = await app.goToNotes();
await notes.createNote({ content: "my precious" });
expect(await notes.editor.getTitle()).toBe("my precious");
await notes.editor.setContent(", my precious note");
await notes.editor.waitForSaving();
expect(await notes.editor.getTitle()).toBe("my precious, my precious note");
await notes.editor.setTitle("not precious");
expect(await notes.editor.getTitle()).toBe("not precious");
await notes.editor.setContent(", but...");
await notes.editor.waitForSaving();
expect(await notes.editor.getTitle()).toBe("not precious");
});
test("select all & backspace should clear all content in editor", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note = await notes.createNote(NOTE);
await notes.editor.clear();
await notes.newNote();
await note?.openNote();
expect(await notes.editor.getContent("text")).toBe("");
});
test("editing a note and switching immediately to another note and making an edit shouldn't overlap both notes", async ({
page
}, test) => {
test.setTimeout(45 * 1000);
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note1 = await notes.createNote({
title: "Test note 1",
content: "53ad8e4e40ebebd0f400498d"
});
const note2 = await notes.createNote({
title: "Test note 2",
content: "f054d19e9a2f46eff7b9bb25"
});
for (let i = 0; i < 10; ++i) {
await note1?.openNote();
await notes.editor.setContent(`Test note 1 (${i}) `);
await note2?.openNote();
await notes.editor.setContent(`Test note 2 (${i})`);
}
await notes.editor.waitForSaving();
await notes.newNote();
await note2?.openNote();
expect(await notes.editor.getContent("text")).toMatchSnapshot(
`fast-switch-and-edit-note-2.txt`
);
await note1?.openNote();
expect(await notes.editor.getContent("text")).toMatchSnapshot(
`fast-switch-and-edit-note-1.txt`
);
});
test("editing a note and switching immediately to another note and editing the title shouldn't overlap both notes", async ({
page
}, test) => {
test.setTimeout(45 * 1000);
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note1 = await notes.createNote({
title: "Test note 1",
content: "53ad8e4e40ebebd0f400498d"
});
const note2 = await notes.createNote({
title: "Test note 2",
content: "f054d19e9a2f46eff7b9bb25"
});
for (let i = 0; i < 10; ++i) {
await note1?.openNote();
await notes.editor.typeTitle(`Test note 1 (${i}) `);
await note2?.openNote();
await notes.editor.typeTitle(`Test note 2 (${i})`);
}
await notes.editor.waitForSaving();
await notes.newNote();
await note2?.openNote();
expect(await notes.editor.getTitle()).toMatchSnapshot(
`fast-switch-and-edit-note-title-2.txt`
);
await note1?.openNote();
expect(await notes.editor.getTitle()).toMatchSnapshot(
`fast-switch-and-edit-note-title-1.txt`
);
});
test("editing a note and toggling read-only mode should show updated content", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note = await notes.createNote(NOTE);
await notes.newNote();
await note?.openNote();
await notes.editor.setContent(`An edit I made`);
await note?.properties.readonly();
expect(await note?.properties.isReadonly()).toBeTruthy();
expect(await notes.editor.getContent("text")).toMatchSnapshot(
`readonly-edited-note.txt`
);
});
test("creating a new note and toggling read-only mode should not empty editor content", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note = await notes.createNote(NOTE);
await note?.properties.readonly();
expect(await note?.properties.isReadonly()).toBeTruthy();
expect(await notes.editor.getContent("text")).not.toHaveLength(0);
expect(await notes.editor.getContent("text")).toBe(NOTE.content);
});
test("toggling read-only should hide undo & redo buttons", async ({ page }) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note = await notes.createNote(NOTE);
await notes.editor.undoButton.waitFor({ state: "visible" });
await notes.editor.redoButton.waitFor({ state: "visible" });
await note?.properties.readonly();
expect(await note?.properties.isReadonly()).toBeTruthy();
expect(notes.editor.undoButton).not.toBeVisible();
expect(notes.editor.redoButton).not.toBeVisible();
});
test("#1468 count words separated by newlines", async ({ page }) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
await notes.createNote({
content: "1\n2\n3\na\nb\nc\nd\ne\nali\nwaqar",
title: NOTE.title
});
expect((await notes.editor.getWordCount()) === 10).toBeTruthy();
});
test("disable autosave when note crosses MAX_AUTO_SAVEABLE_WORDS", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const content = "a ".repeat(100);
await notes.createNote({
title: "many words",
content
});
expect(
await app.toasts.waitForToast(
"Auto-save is disabled for large notes. Press Ctrl + S to save."
)
).toBe(true);
await expect(notes.editor.notSavedIcon).toBeVisible();
});
test("when autosave is disabled, pressing ctrl+s should save the note", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const content = "a ".repeat(100);
await notes.createNote({
title: NOTE.title,
content
});
await page.keyboard.press("Control+s");
await expect(notes.editor.savedIcon).toBeVisible();
});
test("when autosave is disabled, switching to another note should save the note", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const content = "a ".repeat(100);
const note1 = await notes.createNote({
title: "Test note 1"
});
const note2 = await notes.createNote({
title: "Test note 2"
});
await note1?.openNote();
await notes.editor.setContent(content);
await note2?.openNote();
await note1?.openNote();
await expect(notes.editor.savedIcon).toBeVisible();
expect(await notes.editor.getContent("text")).toBe(content.trim());
});
test("when autosave is disabled, creating a new note should save the note", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const content = "a ".repeat(100);
const note = await notes.createNote({
title: NOTE.title,
content
});
await notes.newNote();
await note?.openNote();
// await expect(notes.editor.savedIcon).toBeVisible();
expect(await notes.editor.getContent("text")).toBe(content.trim());
});
test("when autosave is disabled, closing the note should save it", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const content = "a ".repeat(100);
const note = await notes.createNote({
title: "Title",
content
});
const noteTab = await notes.editor.findTab((await note!.getId())!);
await noteTab?.close();
await note?.openNote();
await expect(notes.editor.savedIcon).toBeVisible();
expect(await notes.editor.getContent("text")).toBe(content.trim());
});
test("control + alt + right arrow should go to next note", async ({ page }) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note1 = await notes.createNote({
title: "Note 1",
content: "Note 1 content"
});
const note2 = await notes.createNote({
title: "Note 2",
content: "Note 2 content"
});
await note1?.openNote();
await note2?.openNote(true);
await page.keyboard.press("ControlOrMeta+Alt+ArrowRight");
expect(await notes.editor.getTitle()).toBe("Note 1");
expect(await notes.editor.getContent("text")).toBe("Note 1 content");
await page.keyboard.press("ControlOrMeta+Alt+ArrowRight");
expect(await notes.editor.getTitle()).toBe("Note 2");
expect(await notes.editor.getContent("text")).toBe("Note 2 content");
});
test("control + alt + left arrow should go to previous note", async ({
page
}) => {
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note1 = await notes.createNote({
title: "Note 1",
content: "Note 1 content"
});
const note2 = await notes.createNote({
title: "Note 2",
content: "Note 2 content"
});
await note1?.openNote();
await note2?.openNote(true);
await page.keyboard.press("ControlOrMeta+Alt+ArrowLeft");
expect(await notes.editor.getTitle()).toBe("Note 1");
expect(await notes.editor.getContent("text")).toBe("Note 1 content");
await page.keyboard.press("ControlOrMeta+Alt+ArrowLeft");
expect(await notes.editor.getTitle()).toBe("Note 2");
expect(await notes.editor.getContent("text")).toBe("Note 2 content");
});