chrome-devtools-frontend
Version:
Chrome DevTools UI
344 lines (284 loc) • 15 kB
text/typescript
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import './dom_extension.js';
import {renderElementIntoDOM} from '../../testing/DOMHelpers.js';
function createSlot(parent: HTMLElement, name?: string) {
const slot = parent.createChild('slot');
if (name) {
slot.name = name;
}
return slot;
}
function createChild(parent: HTMLElement, tagName: keyof HTMLElementTagNameMap, name?: string, text = '') {
const child = parent.createChild(tagName, name);
if (name) {
child.slot = name;
}
child.textContent = text;
return child;
}
function traverseNextNode(parent: HTMLElement, stayWithin: HTMLElement): HTMLElement {
return parent.traverseNextNode(stayWithin) as HTMLElement;
}
describe('DataGrid', () => {
it('Traverse Node with Children', () => {
const component1 = document.createElement('div');
component1.classList.add('component1');
createChild(component1, 'div', 'component1-content', 'text 1');
createChild(component1, 'div', 'component2-content', 'text 2');
createChild(component1, 'span', undefined, 'text 3');
createChild(component1, 'span', 'component1-content', 'text 4');
// Now we have:
/*
* <div class="component1">
* <div class="component1-content" slot="component1-content">text 1</div>
* <div class="component2-content" slot="component2-content">text 2</div>
* <span>text 3</span><span class="component1-content" slot="component1-content">text 4</span>
* </div>
*/
let node: HTMLElement = component1;
assert.isNull(node.nodeValue, 'root node value is incorrect');
assert.strictEqual(node.nodeName, 'DIV', 'root node name is incorrect');
assert.strictEqual(node.className, 'component1', 'root node class is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV', 'first child node name is incorrect');
assert.strictEqual(node.className, 'component1-content', 'first child class is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeValue, 'text 1', 'second child node value is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV', 'second child node name is incorrect');
assert.strictEqual(node.className, 'component2-content', 'second child class is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeValue, 'text 2', 'second child node value is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'SPAN', 'third child node name is incorrect');
assert.strictEqual(node.className, '', 'third child class is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeValue, 'text 3', 'third child node value is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'SPAN', 'forth child node name is incorrect');
assert.strictEqual(node.className, 'component1-content', 'forth child class is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeValue, 'text 4', 'forth child node value is incorrect');
});
it('Traverse Node with Shadows', () => {
const component1 = document.createElement('div');
component1.classList.add('component1');
const shadow1 = component1.attachShadow({mode: 'open'});
const shadow1Content = document.createElement('div');
shadow1Content.classList.add('shadow-component1');
shadow1.appendChild(shadow1Content);
const component2 = shadow1Content.createChild('div', 'component2');
const shadow2 = component2.attachShadow({mode: 'open'});
const shadow2Content = document.createElement('div');
shadow2Content.classList.add('shadow-component1');
shadow2.appendChild(shadow2Content);
const midDiv = createChild(shadow2Content, 'div', 'mid-div');
createChild(midDiv, 'div', undefined, 'component2-text');
// Now we have:
/*
* <div class="component1"></div>
* <div class="shadow-component1"><div class="component2"></div></div>
* <div class="shadow-component1"><div class="mid-div" slot="mid-div"><div>component2-text</div></div></div>
*/
let node: HTMLElement = component1;
assert.strictEqual(node.nodeName, 'DIV', 'root node name is incorrect');
assert.strictEqual(node.className, 'component1', 'root node class is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, '#document-fragment', 'first document fragment node name is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV', 'first document fragment child node name is incorrect');
assert.strictEqual(node.className, 'shadow-component1', 'first document fragment child node name is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, 'component2');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, '#document-fragment');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, 'shadow-component1');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, 'mid-div');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, '');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, '#text');
assert.strictEqual(node.nodeValue, 'component2-text');
});
it('Traverse Node with Slots', () => {
const component1 = document.createElement('div');
component1.classList.add('component1');
const shadow1 = component1.attachShadow({mode: 'open'});
const shadow1Content = document.createElement('div');
shadow1Content.classList.add('shadow-component1');
shadow1.appendChild(shadow1Content);
createSlot(shadow1Content, 'component1-content');
createSlot(shadow1Content);
const component2 = shadow1Content.createChild('div', 'component2');
const shadow2 = component2.attachShadow({mode: 'open'});
createSlot(component2, 'component2-content');
createChild(component2, 'div', 'component2-content', 'component2 light dom text');
const shadow2Content = document.createElement('div');
shadow2Content.classList.add('shadow-component1');
shadow2.appendChild(shadow2Content);
const midDiv = createChild(shadow2Content, 'div', 'mid-div');
createChild(midDiv, 'div', undefined, 'component2-text');
createSlot(midDiv);
createSlot(midDiv, 'component2-content');
// Now we have:
/*
* <div class="component1"></div>
* <div class="shadow-component1">
* <slot name="component1-content"></slot>
* <slot></slot>
* <div class="component2">
* <slot name="component2-content"></slot>
* <div class="component2-content" slot="component2-content">component2 light dom text</div>
* </div>
* </div>
* <div class="shadow-component1">
* <div class="mid-div" slot="mid-div">
* <div>component2-text</div>
* <slot></slot>
* <slot name="component2-content"></slot>
* </div>
* </div>
*/
let node: HTMLElement = component1;
assert.strictEqual(node.nodeName, 'DIV', 'root node name is incorrect');
assert.strictEqual(node.className, 'component1', 'root node class is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, '#document-fragment', 'first document fragment node name is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV', 'first document fragment child node name is incorrect');
assert.strictEqual(node.className, 'shadow-component1', 'first document fragment child node name is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'SLOT', 'first slot node name is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'SLOT', 'second slot node name is incorrect');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, 'component2');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, '#document-fragment');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, 'shadow-component1');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, 'mid-div');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, '');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeValue, 'component2-text');
assert.strictEqual(node.nodeName, '#text');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'SLOT');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'SLOT');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'SLOT');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeName, 'DIV');
assert.strictEqual(node.className, 'component2-content');
node = traverseNextNode(node, component1);
assert.strictEqual(node.nodeValue, 'component2 light dom text');
assert.strictEqual(node.nodeName, '#text');
});
});
describe('Node.prototype.deepInnerText', () => {
it('gets text from a simple element', () => {
const element = document.createElement('div');
element.textContent = 'Simple text';
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), 'Simple text');
});
it('gets text from an element with multiple children', () => {
const element = document.createElement('div');
element.createChild('p').textContent = 'First child';
element.createChild('span').textContent = 'Second child';
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), element.innerText);
assert.strictEqual(element.deepInnerText(), 'First child\n\nSecond child');
});
it('gets text from an element with nested children', () => {
const element = document.createElement('div');
element.appendChild(document.createTextNode(' Outer text. '));
const childDiv = element.createChild('div');
childDiv.textContent = ' Child text. '; // innerText of childDiv would be "Child text. Grandchild text."
const grandchildSpan = childDiv.createChild('span');
grandchildSpan.textContent = 'Grandchild text.';
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), element.innerText);
assert.strictEqual(element.deepInnerText(), 'Outer text.\nChild text. Grandchild text.');
});
it('gets text from an element with a shadow DOM', () => {
const element = document.createElement('div');
const shadow = element.attachShadow({mode: 'open'});
shadow.createChild('p').textContent = 'Shadow text';
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), 'Shadow text');
});
it('gets text from an element with a shadow DOM and slotted content', () => {
const element = document.createElement('div');
element.createChild('span').textContent = 'Slotted content';
const shadow = element.attachShadow({mode: 'open'});
shadow.appendChild(document.createTextNode('Shadow text before slot. '));
shadow.createChild('slot');
shadow.createChild('p').textContent = 'Shadow text after slot.';
renderElementIntoDOM(element);
const expectedText = 'Shadow text before slot.\nSlotted content\nShadow text after slot.';
assert.strictEqual(element.deepInnerText(), expectedText);
});
it('gets text from an element with multiple shadow DOMs and regular siblings', () => {
const element = document.createElement('div');
element.appendChild(document.createTextNode('Light DOM text before shadow 1. '));
const shadow1 = element.createChild('div').attachShadow({mode: 'open'});
const shadow1Paragraph1 = shadow1.createChild('p');
shadow1Paragraph1.createChild('span').textContent = 'Shadow 1';
shadow1Paragraph1.createChild('span').textContent = '(1)';
const shadow1Paragraph2 = shadow1.createChild('p');
shadow1Paragraph2.createChild('span').textContent = 'Shadow 1';
shadow1Paragraph2.createChild('span').textContent = '(2)';
element.appendChild(document.createTextNode(' Light DOM text between shadows. '));
const shadow2 = element.createChild('div').attachShadow({mode: 'open'});
shadow2.createChild('span').textContent = 'Shadow 2 text.';
element.appendChild(document.createTextNode(' Light DOM text after shadow 2.'));
renderElementIntoDOM(element);
const expectedText =
'Light DOM text before shadow 1.\nShadow 1(1)\nShadow 1(2)\nLight DOM text between shadows.\nShadow 2 text.\nLight DOM text after shadow 2.';
assert.strictEqual(element.deepInnerText(), expectedText);
});
it('returns empty string for an element with no text content', () => {
const element = document.createElement('div');
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), '');
});
it('ignores text content within SCRIPT tags', () => {
const element = document.createElement('div');
element.innerHTML = 'Visible text<script>console.log("script text")</script>';
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), 'Visible text');
});
it('ignores text content within STYLE tags', () => {
const element = document.createElement('div');
element.innerHTML = 'Visible text<style>body { color: red; }</style>';
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), 'Visible text');
});
it('gets text when called directly on a TextNode', () => {
const textNode = document.createTextNode('Direct text node content');
assert.strictEqual(textNode.deepInnerText(), 'Direct text node content');
});
it('handles elements that only contain other elements which produce text', () => {
const element = document.createElement('div');
const child = element.createChild('p');
child.textContent = 'Paragraph text';
renderElementIntoDOM(element);
assert.strictEqual(element.deepInnerText(), 'Paragraph text');
});
});