文件
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

109 行
3.9 KiB
TypeScript

import { Page, Locator, ElectronApplication } from '@playwright/test';
import NoteEditorScreen from './NoteEditor/NoteEditorScreen';
import activateMainMenuItem from '../util/activateMainMenuItem';
import Sidebar from './Sidebar';
import GoToAnything from './GoToAnything';
import setFilePickerResponse from '../util/setFilePickerResponse';
import NoteList from './NoteList';
import { expect } from '../util/test';
import ChangeAppLayoutScreen from './ChangeAppLayoutScreen';
import waitForNextWindowMatching from '../util/waitForNextWindowMatching';
import ChatPanel from './ChatPanel';
export default class MainScreen {
public readonly newNoteButton: Locator;
public readonly noteList: NoteList;
public readonly sidebar: Sidebar;
public readonly dialog: Locator;
public readonly noteEditor: NoteEditorScreen;
public readonly goToAnything: GoToAnything;
public readonly changeLayoutScreen: ChangeAppLayoutScreen;
public readonly chatPanel: ChatPanel;
public constructor(private page: Page) {
this.newNoteButton = page.locator('.new-note-button');
this.noteList = new NoteList(page);
this.sidebar = new Sidebar(page, this);
this.dialog = page.locator('.dialog-modal-layer');
this.noteEditor = new NoteEditorScreen(page);
this.goToAnything = new GoToAnything(page, this);
this.changeLayoutScreen = new ChangeAppLayoutScreen(page, this);
this.chatPanel = new ChatPanel(page, this);
}
public async setup() {
await this.waitFor();
const folder = await this.sidebar.createNewFolder('Test');
await folder.waitFor();
return this;
}
public async waitFor() {
await this.noteList.waitFor();
}
// Follows the steps a user would use to create a new note.
public async createNewNote(title: string) {
await this.waitFor();
// The new note button is only visible when a folder is selected -- wait for it explicitly.
await this.newNoteButton.waitFor();
// Create the new note. Retry this -- creating new notes can sometimes fail if done just after
// application startup.
await expect.poll(async () => {
await this.newNoteButton.click();
await expect(this.noteEditor.noteTitleInput).toHaveValue('', { timeout: 4_000 });
await expect(this.noteEditor.noteTitleInput).toHaveJSProperty('placeholder', 'Creating new note...', { timeout: 4_000 });
return true;
}, { timeout: 10_000 }).toBe(true);
// Fill the title
await this.noteEditor.noteTitleInput.click();
await this.noteEditor.noteTitleInput.fill(title);
// Wait for the title to reach the note list, otherwise a later sort can run
// while the note is still "Untitled" and order the list unexpectedly.
if (title !== '') {
await this.noteList.getNoteItemByTitle(title).waitFor();
}
return this.noteEditor;
}
public async openSettings(electronApp: ElectronApplication) {
// Check both labels so this works on MacOS
await activateMainMenuItem(electronApp, /^(Preferences\.\.\.|Options)$/);
}
public async openNewWindow(electronApp: ElectronApplication) {
const pagePromise = waitForNextWindowMatching(/^Joplin -/, electronApp);
await activateMainMenuItem(electronApp, 'Open in new window');
return pagePromise;
}
public async search(text: string) {
const searchBar = this.page.getByPlaceholder('Search...');
await searchBar.fill(text);
}
private async importFromModule_(electronApp: ElectronApplication, moduleName: string, path: string) {
await setFilePickerResponse(electronApp, [path]);
await activateMainMenuItem(electronApp, moduleName, 'Import');
}
public async importHtmlDirectory(electronApp: ElectronApplication, path: string) {
return this.importFromModule_(electronApp, 'HTML - HTML document (Directory)', path);
}
public async importHtmlFile(electronApp: ElectronApplication, path: string) {
return this.importFromModule_(electronApp, 'HTML - HTML document (File)', path);
}
public async pluginPanelLocator(pluginId: string) {
return this.page.locator(
`iframe[id^=${JSON.stringify(`plugin-view-${pluginId}`)}]`,
);
}
}