blob: 168248645b078a418dd40ffce8de159c5116352c [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import type {BookmarksFolderNodeElement, SelectFolderAction} from 'chrome://bookmarks/bookmarks.js';
import {ACCOUNT_HEADING_NODE_ID, LOCAL_HEADING_NODE_ID, ROOT_NODE_ID, selectFolder} from 'chrome://bookmarks/bookmarks.js';
import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {microtasksFinished} from 'chrome://webui-test/test_util.js';
import {TestCommandManager} from './test_command_manager.js';
import {TestStore} from './test_store.js';
import {createFolder, createItem, findFolderNode, getAllFoldersOpenState, replaceBody, testTree} from './test_util.js';
suite('<bookmarks-folder-node>', function() {
let rootNode: BookmarksFolderNodeElement;
let store: TestStore;
function getFolderNode(id: string): BookmarksFolderNodeElement|undefined {
return findFolderNode(rootNode, id);
}
setup(function() {
const nodes = testTree(
createFolder(
'1',
[
createFolder(
'2',
[
createFolder('3', []),
createFolder('4', []),
]),
createItem('5'),
]),
createFolder('7', []));
store = new TestStore({
nodes: nodes,
folderOpenState: getAllFoldersOpenState(nodes),
selectedFolder: '1',
});
store.replaceSingleton();
rootNode = document.createElement('bookmarks-folder-node');
rootNode.itemId = ROOT_NODE_ID;
rootNode.depth = -1;
replaceBody(rootNode);
return microtasksFinished();
});
test('selecting and deselecting folders dispatches action', async () => {
const rootFolders =
rootNode.shadowRoot.querySelectorAll('bookmarks-folder-node');
const firstGen = rootFolders[0]!.$['descendants'].querySelectorAll(
'bookmarks-folder-node');
const secondGen =
firstGen[0]!.$['descendants'].querySelectorAll('bookmarks-folder-node');
// Select nested folder.
secondGen[0]!.$['container'].click();
assertTrue(!!store.lastAction);
assertEquals('select-folder', store.lastAction.name);
assertEquals(
secondGen[0]!.itemId, (store.lastAction as SelectFolderAction).id);
// Select folder in a separate subtree.
rootFolders[1]!.$['container'].click();
assertEquals('select-folder', store.lastAction.name);
assertEquals(
rootFolders[1]!.itemId, (store.lastAction as SelectFolderAction).id);
// Doesn't re-select if the folder is already selected.
store.data.selectedFolder = '7';
store.notifyObservers();
await microtasksFinished();
store.resetLastAction();
rootFolders[1]!.$['container'].click();
assertEquals(null, store.lastAction);
});
test('depth calculation', function() {
const rootFolders =
rootNode.shadowRoot.querySelectorAll('bookmarks-folder-node');
const firstGen = rootFolders[0]!.$['descendants'].querySelectorAll(
'bookmarks-folder-node');
const secondGen =
firstGen[0]!.$['descendants'].querySelectorAll('bookmarks-folder-node');
Array.prototype.forEach.call(rootFolders, function(f) {
assertEquals(0, f.depth);
assertEquals('0', f.style.getPropertyValue('--node-depth'));
});
Array.prototype.forEach.call(firstGen, function(f) {
assertEquals(1, f.depth);
assertEquals('1', f.style.getPropertyValue('--node-depth'));
});
Array.prototype.forEach.call(secondGen, function(f) {
assertEquals(2, f.depth);
assertEquals('2', f.style.getPropertyValue('--node-depth'));
});
});
test('doesn\'t highlight selected folder while searching', async () => {
const rootFolders =
rootNode.shadowRoot.querySelectorAll('bookmarks-folder-node');
assertEquals('1', rootFolders[0]!.itemId);
assertTrue(rootFolders[0]!.$.container.hasAttribute('selected'));
store.data.search = {
term: 'test',
inProgress: false,
results: ['3'],
};
store.notifyObservers();
await microtasksFinished();
assertFalse(rootFolders[0]!.$.container.hasAttribute('selected'));
});
test('last visible descendant', async () => {
assertEquals('7', rootNode.getLastVisibleDescendant().itemId);
assertEquals('4', getFolderNode('1')!.getLastVisibleDescendant().itemId);
store.data.folderOpenState.set('2', false);
store.notifyObservers();
await microtasksFinished();
assertEquals('2', getFolderNode('1')!.getLastVisibleDescendant().itemId);
});
test('non-permanent folders are hidden by default', async () => {
store.data.folderOpenState = new Map();
store.notifyObservers();
await microtasksFinished();
assertTrue(getFolderNode('0')!.isOpen);
assertFalse(getFolderNode('1')!.isOpen);
assertFalse(getFolderNode('7')!.isOpen);
});
test(
'local folders are collapsed by default with account and local nodes',
async () => {
// This creates the following structure:
//
// Root node
// -- Account Heading
// ---- Account Bookmarks Bar ('5')
// ------ Folder ('7')
// ------ Folder ('8')
// ---- Account Other Node ('6')
// -- Local Heading
// ---- Bookmarks Bar ('1')
// ------ Folder ('3')
// ------ Folder ('4')
// ---- Other Node ('2')
store = new TestStore({
nodes: testTree(
createFolder(
ACCOUNT_HEADING_NODE_ID,
[
createFolder(
'5',
[
createFolder('7', [], {syncing: true}),
createFolder('8', [], {syncing: true}),
],
{
folderType: chrome.bookmarks.FolderType.BOOKMARKS_BAR,
syncing: true,
}),
createFolder('6', [], {
folderType: chrome.bookmarks.FolderType.OTHER,
syncing: true,
}),
],
{syncing: true}),
createFolder(
LOCAL_HEADING_NODE_ID,
[
createFolder(
'1',
[
createFolder('3', []),
createFolder('4', []),
],
{
folderType: chrome.bookmarks.FolderType.BOOKMARKS_BAR,
}),
createFolder(
'2', [],
{folderType: chrome.bookmarks.FolderType.OTHER}),
],
)),
});
store.replaceSingleton();
replaceBody(rootNode);
await microtasksFinished();
assertTrue(getFolderNode(ROOT_NODE_ID)!.isOpen);
assertTrue(getFolderNode(ACCOUNT_HEADING_NODE_ID)!.isOpen);
assertFalse(getFolderNode('5')!.isOpen);
assertFalse(getFolderNode('6')!.isOpen);
assertFalse(getFolderNode(LOCAL_HEADING_NODE_ID)!.isOpen);
});
test('get node parent', function() {
assertEquals(
getFolderNode(ROOT_NODE_ID), getFolderNode('1')!.getParentFolderNode());
assertEquals(getFolderNode('2'), getFolderNode('4')!.getParentFolderNode());
assertEquals(null, getFolderNode(ROOT_NODE_ID)!.getParentFolderNode());
});
test('next/previous folder nodes', async () => {
function getNextChild(parentId: string, targetId: string, reverse: boolean):
BookmarksFolderNodeElement|null {
return getFolderNode(parentId)!.getNextChild(
reverse, getFolderNode(targetId)!);
}
// Initially open the tree up to two levels.
store.data.folderOpenState.set('1', true);
store.data.folderOpenState.set('2', true);
store.notifyObservers();
await microtasksFinished();
// Forwards.
assertEquals('4', getNextChild('2', '3', false)!.itemId);
assertEquals(null, getNextChild('2', '4', false));
// Backwards.
assertEquals(null, getNextChild('1', '2', true));
assertEquals('3', getNextChild('2', '4', true)!.itemId);
assertEquals('4', getNextChild(ROOT_NODE_ID, '7', true)!.itemId);
// Skips closed folders.
store.data.folderOpenState.set('2', false);
store.notifyObservers();
await microtasksFinished();
assertEquals(null, getNextChild('1', '2', false));
assertEquals('2', getNextChild(ROOT_NODE_ID, '7', true)!.itemId);
});
test('right click opens context menu', function() {
const testCommandManager = new TestCommandManager();
document.body.appendChild(testCommandManager.getCommandManager());
const node = getFolderNode('2')!;
node.$.container.dispatchEvent(new MouseEvent('contextmenu'));
assertDeepEquals(selectFolder('2'), store.lastAction);
testCommandManager.assertMenuOpenForIds(['2']);
});
});