一些检查失败了
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
328 行
12 KiB
TypeScript
328 行
12 KiB
TypeScript
import { test, expect } from './util/test';
|
|
import MainScreen from './models/MainScreen';
|
|
import { Second } from '@joplin/utils/time';
|
|
|
|
test.describe('sidebar', () => {
|
|
test('should be able to create new folders', async ({ mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
const title = `Test folder ${i}`;
|
|
await sidebar.createNewFolder(title);
|
|
await expect(sidebar.container.getByText(title)).toBeAttached();
|
|
}
|
|
|
|
// The first folder should still be visible
|
|
await expect(sidebar.container.getByText('Test folder 0')).toBeAttached();
|
|
});
|
|
|
|
test('should allow changing the focused folder with the arrow keys', async ({ electronApp, mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const folderAHeader = await sidebar.createNewFolder('Folder A');
|
|
await expect(folderAHeader).toBeVisible();
|
|
|
|
const folderBHeader = await sidebar.createNewFolder('Folder B');
|
|
await expect(folderBHeader).toBeVisible();
|
|
await folderBHeader.click();
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
|
|
await folderBHeader.click();
|
|
await mainWindow.keyboard.press('ArrowUp');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder A');
|
|
await mainWindow.keyboard.press('ArrowDown');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder B');
|
|
await mainWindow.keyboard.press('ArrowUp');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder A');
|
|
await mainWindow.keyboard.press('ArrowUp');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('All notes');
|
|
await mainWindow.keyboard.press('ArrowUp');
|
|
await expect(mainWindow.locator(':focus')).toHaveText(/NOTEBOOKS/i);
|
|
await mainWindow.keyboard.press('ArrowDown');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('All notes');
|
|
});
|
|
|
|
// Regression test for https://github.com/laurent22/joplin/issues/15029
|
|
test('should remain focused when navigating with the arrow keys', async ({ electronApp, mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
// Build the folder hierarchy: Navigating upwards through the list
|
|
// should transition from a notebook with more notes to a notebook with
|
|
// fewer notes.
|
|
const folderAHeader = await sidebar.createNewFolder('Folder A');
|
|
await mainScreen.createNewNote('Test');
|
|
await expect(folderAHeader).toBeVisible();
|
|
const folderBHeader = await sidebar.createNewFolder('Folder B');
|
|
await mainScreen.createNewNote('Test 2');
|
|
await mainScreen.createNewNote('Test 3');
|
|
const folderCHeader = await sidebar.createNewFolder('Folder C');
|
|
const folderDHeader = await sidebar.createNewFolder('Folder D');
|
|
|
|
await folderBHeader.dragTo(folderAHeader);
|
|
await folderCHeader.dragTo(folderAHeader);
|
|
|
|
// Should have the correct initial state
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
await sidebar.expectToHaveDepths([
|
|
[folderAHeader, 2],
|
|
[folderBHeader, 3],
|
|
[folderCHeader, 3],
|
|
[folderDHeader, 2],
|
|
]);
|
|
|
|
const assertFocused = async (title: RegExp) => {
|
|
await expect(mainWindow.locator(':focus')).toHaveText(title);
|
|
// Pause to help check that focus is stable. This is present to help this test more reliably detect
|
|
// timing-related issues.
|
|
await mainWindow.waitForTimeout(Second);
|
|
await expect(mainWindow.locator(':focus')).toHaveText(title);
|
|
};
|
|
|
|
await folderDHeader.click();
|
|
|
|
// Focus should remain on the correct folder header while navigating
|
|
await mainWindow.keyboard.press('ArrowUp');
|
|
await assertFocused(/^Folder C/);
|
|
await mainWindow.keyboard.press('ArrowUp');
|
|
await assertFocused(/^Folder B/);
|
|
await mainWindow.keyboard.press('ArrowUp');
|
|
await assertFocused(/^Folder A/);
|
|
});
|
|
|
|
test('should allow changing the focused folder by pressing the first character of the title', async ({ electronApp, mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const folderAHeader = await sidebar.createNewFolder('1-Test A');
|
|
await expect(folderAHeader).toBeVisible();
|
|
|
|
const folderBHeader = await sidebar.createNewFolder('Folder b');
|
|
await expect(folderBHeader).toBeVisible();
|
|
await folderBHeader.click();
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
|
|
await folderBHeader.click();
|
|
await mainWindow.keyboard.type('1');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('1-Test A');
|
|
await mainWindow.keyboard.type('F');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder b');
|
|
await mainWindow.keyboard.type('A');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('All notes');
|
|
|
|
// Should be case-insensitive
|
|
await mainWindow.keyboard.type('f');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder b');
|
|
});
|
|
|
|
test('left/right arrow keys should expand/collapse notebooks', async ({ electronApp, mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
// Build the folder hierarchy
|
|
const folderAHeader = await sidebar.createNewFolder('Folder A');
|
|
await expect(folderAHeader).toBeVisible();
|
|
const folderBHeader = await sidebar.createNewFolder('Folder B');
|
|
const folderCHeader = await sidebar.createNewFolder('Folder C');
|
|
const folderDHeader = await sidebar.createNewFolder('Folder D');
|
|
await folderBHeader.dragTo(folderAHeader);
|
|
await folderCHeader.dragTo(folderAHeader);
|
|
await folderDHeader.dragTo(folderCHeader);
|
|
|
|
// Folders should have correct initial levels
|
|
await sidebar.expectToHaveDepths([
|
|
[folderAHeader, 2],
|
|
[folderBHeader, 3],
|
|
[folderCHeader, 3],
|
|
[folderDHeader, 4],
|
|
]);
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
await folderBHeader.click();
|
|
|
|
// Pressing [left] on a folder with no children should jump to its parent
|
|
await mainWindow.keyboard.press('ArrowLeft');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder A');
|
|
|
|
// Pressing [left] again should collapse the folder
|
|
await expect(folderAHeader).toHaveJSProperty('ariaExpanded', 'true');
|
|
await mainWindow.keyboard.press('ArrowLeft');
|
|
await expect(folderAHeader).toHaveJSProperty('ariaExpanded', 'false');
|
|
// Should still be focused
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder A');
|
|
|
|
// Pressing [right] on a collapsed folder should expand it
|
|
await mainWindow.keyboard.press('ArrowRight');
|
|
await expect(folderAHeader).toHaveJSProperty('ariaExpanded', 'true');
|
|
// Pressing [right] again should move to the next item
|
|
await mainWindow.keyboard.press('ArrowRight');
|
|
await expect(mainWindow.locator(':focus')).toHaveText('Folder B');
|
|
});
|
|
|
|
test('should allow changing the parent of a folder by drag-and-drop', async ({ electronApp, mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const parentFolderHeader = await sidebar.createNewFolder('Parent folder');
|
|
await expect(parentFolderHeader).toBeVisible();
|
|
|
|
const childFolderHeader = await sidebar.createNewFolder('Child folder');
|
|
await expect(childFolderHeader).toBeVisible();
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
|
|
await expect(childFolderHeader).toBeVisible();
|
|
await childFolderHeader.dragTo(parentFolderHeader);
|
|
|
|
// Verify that it's now a child folder -- expand and collapse the parent
|
|
await expect(parentFolderHeader).toHaveJSProperty('ariaExpanded', 'true');
|
|
const toggleButton = parentFolderHeader.getByRole('button', { name: /^(Expand|Collapse)/ });
|
|
await toggleButton.click();
|
|
|
|
// Should be collapsed
|
|
await expect(childFolderHeader).not.toBeAttached();
|
|
await expect(parentFolderHeader).toHaveJSProperty('ariaExpanded', 'false');
|
|
|
|
await toggleButton.click();
|
|
|
|
// Should be possible to move back to the root
|
|
const rootFolderHeader = sidebar.container.getByText('Notebooks');
|
|
await childFolderHeader.dragTo(rootFolderHeader);
|
|
await expect(toggleButton).not.toBeVisible();
|
|
});
|
|
|
|
test('all notes section should list all notes', async ({ electronApp, mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const testFolderA = await sidebar.createNewFolder('Folder A');
|
|
await expect(testFolderA).toBeAttached();
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
|
|
await mainScreen.createNewNote('A note in Folder A');
|
|
await expect(mainWindow.getByText('A note in Folder A')).toBeAttached();
|
|
await mainScreen.createNewNote('Another note in Folder A');
|
|
|
|
const testFolderB = await sidebar.createNewFolder('Folder B');
|
|
await expect(testFolderB).toBeAttached();
|
|
|
|
await mainScreen.createNewNote('A note in Folder B');
|
|
|
|
const allNotesButton = sidebar.container.getByText('All notes');
|
|
await allNotesButton.click();
|
|
|
|
await expect(mainWindow.getByText('A note in Folder A')).toBeAttached();
|
|
await expect(mainWindow.getByText('Another note in Folder A')).toBeAttached();
|
|
await expect(mainWindow.getByText('A note in Folder B')).toBeAttached();
|
|
});
|
|
|
|
test('double-clicking should collapse/expand folders in the sidebar', async ({ mainWindow }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const testFolderA = await sidebar.createNewFolder('Folder A');
|
|
const testFolderB = await sidebar.createNewFolder('Folder B');
|
|
|
|
// Convert folder B to a subfolder
|
|
await testFolderB.dragTo(testFolderA);
|
|
|
|
await expect(testFolderB).toBeVisible();
|
|
|
|
// Collapse
|
|
await testFolderA.dblclick();
|
|
await expect(testFolderB).not.toBeVisible();
|
|
|
|
// Expand
|
|
await testFolderA.dblclick();
|
|
await expect(testFolderB).toBeVisible();
|
|
});
|
|
|
|
test('should be possible to select, then deselect, multiple folders with cmd-click', async ({ mainWindow, electronApp }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const folderA = await sidebar.createNewFolder('Folder A');
|
|
const folderB = await sidebar.createNewFolder('Folder B');
|
|
const folderC = await sidebar.createNewFolder('Folder C');
|
|
const folderD = await sidebar.createNewFolder('Folder D');
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
|
|
await folderA.click();
|
|
await folderB.click({ modifiers: ['ControlOrMeta'] });
|
|
await folderC.click({ modifiers: ['ControlOrMeta'] });
|
|
|
|
await expect(folderA).toBeSelected();
|
|
await expect(folderB).toBeSelected();
|
|
await expect(folderC).toBeSelected();
|
|
await expect(folderD).toHaveJSProperty('ariaSelected', 'false');
|
|
|
|
// Should be able to deselect up to two folders
|
|
await folderA.click({ modifiers: ['ControlOrMeta'] });
|
|
await expect(folderA).toHaveJSProperty('ariaSelected', 'false');
|
|
await folderB.click({ modifiers: ['ControlOrMeta'] });
|
|
await expect(folderB).toHaveJSProperty('ariaSelected', 'false');
|
|
// Should not be possible to deselect the last folder
|
|
await folderC.click({ modifiers: ['ControlOrMeta'] });
|
|
await expect(folderC).toBeSelected();
|
|
});
|
|
|
|
test('should be possible to move multiple folders at once with drag and drop', async ({ mainWindow, electronApp }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const folderA = await sidebar.createNewFolder('Folder A');
|
|
const folderB = await sidebar.createNewFolder('Folder B');
|
|
const folderC = await sidebar.createNewFolder('Folder C');
|
|
const folderD = await sidebar.createNewFolder('Folder D');
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
|
|
await folderB.click();
|
|
await folderC.click({ modifiers: ['ControlOrMeta'] });
|
|
|
|
await expect(folderB).toBeSelected();
|
|
await expect(folderC).toBeSelected();
|
|
|
|
await folderB.dragTo(folderA);
|
|
|
|
// Should have made folder B **and folder C** subfolders of testFolderA
|
|
await sidebar.expectToHaveDepths([
|
|
[folderA, 2],
|
|
[folderB, 3],
|
|
[folderC, 3],
|
|
[folderD, 2],
|
|
]);
|
|
});
|
|
|
|
test('should not move selected folders when dragging an unselected folder', async ({ mainWindow, electronApp }) => {
|
|
const mainScreen = await new MainScreen(mainWindow).setup();
|
|
const sidebar = mainScreen.sidebar;
|
|
|
|
const testFolderA = await sidebar.createNewFolder('Folder A');
|
|
const testFolderB = await sidebar.createNewFolder('Folder B');
|
|
const testFolderC = await sidebar.createNewFolder('Folder C');
|
|
|
|
await sidebar.forceUpdateSorting(electronApp);
|
|
|
|
await testFolderB.click();
|
|
await testFolderC.click({ modifiers: ['ControlOrMeta'] });
|
|
|
|
await expect(testFolderB).toBeSelected();
|
|
await expect(testFolderC).toBeSelected();
|
|
|
|
await testFolderA.dragTo(testFolderB);
|
|
|
|
await sidebar.expectToHaveDepths([
|
|
[testFolderB, 2],
|
|
[testFolderA, 3],
|
|
[testFolderC, 2],
|
|
]);
|
|
});
|
|
});
|