[TreeOutline] custom renderer support

Adds the basic support for custom renderers to tree nodes.

Bug: chromium:1166669
Change-Id: Iaa271384ea1798c234d131b27cd08ecb8a49623d
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2696651
Commit-Queue: Jack Franklin <jacktfranklin@chromium.org>
Reviewed-by: Tim van der Lippe <tvanderlippe@chromium.org>
This commit is contained in:
Jack Franklin
2021-02-17 11:18:59 +00:00
committed by Commit Bot
parent b265fb501a
commit fdf2a0cecd
8 changed files with 153 additions and 13 deletions
@@ -189,3 +189,13 @@ export async function doubleRaf() {
export async function raf() {
return new Promise(resolve => requestAnimationFrame(resolve));
}
/**
* It's useful to use innerHTML in the tests to have full confidence in the
* renderer output, but LitHtml uses comment nodes to split dynamic from
* static parts of a template, and we don't want our tests full of noise
* from those.
*/
export function stripLitHtmlCommentNodes(text: string) {
return text.replaceAll('<!---->', '');
}
@@ -6,7 +6,7 @@ import * as Platform from '../../../../../front_end/platform/platform.js';
import * as Coordinator from '../../../../../front_end/render_coordinator/render_coordinator.js';
import * as LitHtml from '../../../../../front_end/third_party/lit-html/lit-html.js';
import * as UIComponents from '../../../../../front_end/ui/components/components.js';
import {assertElement, assertShadowRoot, dispatchClickEvent, dispatchKeyDownEvent, getEventPromise, renderElementIntoDOM} from '../../helpers/DOMHelpers.js';
import {assertElement, assertShadowRoot, dispatchClickEvent, dispatchKeyDownEvent, getEventPromise, renderElementIntoDOM, stripLitHtmlCommentNodes} from '../../helpers/DOMHelpers.js';
import {withMutations} from '../../helpers/MutationHelpers.js';
import {assertCurrentFocusedCellIs, emulateUserFocusingCellAt, emulateUserKeyboardNavigation, focusTableCell, getAllRows, getCellByIndexes, getFocusableCell, getHeaderCellForColumnId, getHeaderCells, getValuesOfAllBodyRows, getValuesOfBodyRowByAriaIndex} from './DataGridHelpers.js';
@@ -60,14 +60,6 @@ Object.freeze(columns);
Object.freeze(columnsWithNoneSortable);
Object.freeze(rows);
/**
* It's useful to use innerHTML in the tests to have full confidence in the
* renderer output, but LitHtml uses comment nodes to split dynamic from
* static parts of a template, and we don't want our tests full of noise
* from those.
*/
const stripLitHtmlCommentNodes = (text: string) => text.replaceAll('<!---->', '');
const renderDataGrid = (data: Partial<UIComponents.DataGrid.DataGridData>): UIComponents.DataGrid.DataGrid => {
const component = new UIComponents.DataGrid.DataGrid();
component.data = {
@@ -3,8 +3,9 @@
// found in the LICENSE file.
import * as Coordinator from '../../../../../front_end/render_coordinator/render_coordinator.js';
import * as LitHtml from '../../../../../front_end/third_party/lit-html/lit-html.js';
import * as UIComponents from '../../../../../front_end/ui/components/components.js';
import {assertElement, assertShadowRoot, dispatchClickEvent, dispatchKeyDownEvent, renderElementIntoDOM} from '../../helpers/DOMHelpers.js';
import {assertElement, assertShadowRoot, dispatchClickEvent, dispatchKeyDownEvent, renderElementIntoDOM, stripLitHtmlCommentNodes} from '../../helpers/DOMHelpers.js';
const coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();
const {assert} = chai;
@@ -135,8 +136,7 @@ function treeNodeKeyText(node: HTMLLIElement) {
if (!keyNode) {
throw new Error('Found tree node without a key within it.');
}
// Trim to remove whitespace that made it into the DOM that we don't care about.
return (keyNode.textContent || '').trim();
return keyNode.getAttribute('data-node-key') || '';
}
function getVisibleTreeNodeByText(shadowRoot: ShadowRoot, text: string): HTMLLIElement {
@@ -307,6 +307,36 @@ describe('TreeOutline', () => {
]);
});
it('allows a node to have a custom renderer', async () => {
const tinyTree: UIComponents.TreeOutlineUtils.TreeNode[] = [{
key: 'Offices',
renderer: key => LitHtml.html`<h2 class="top-node">${key.toUpperCase()}</h2>`,
children: () => Promise.resolve([
{
key: 'EMEA',
},
{
key: 'USA',
},
{
key: 'APAC',
},
]),
}];
const {component, shadowRoot} = await renderTreeOutline({
tree: tinyTree,
});
await component.expandRecursively(Number.POSITIVE_INFINITY);
await coordinator.done();
const officeNode = getVisibleTreeNodeByText(shadowRoot, 'Offices');
const key = officeNode.querySelector('[data-node-key]');
assertElement(key, HTMLElement);
const renderedKey = stripLitHtmlCommentNodes(key.innerHTML);
assert.strictEqual(renderedKey, '<h2 class="top-node">OFFICES</h2>');
});
describe('navigating with keyboard', () => {
it('defaults to the first root node as active', async () => {
const {shadowRoot} = await renderTreeOutline({