chrome-devtools-frontend
Version:
Chrome DevTools UI
105 lines (82 loc) • 3.86 kB
text/typescript
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {assert} from 'chai';
import type * as Common from '../common/common.js';
// eslint-disable-next-line @devtools/es-modules-import
import * as SDK from './sdk.js';
function findNode(node: SDK.DOMModel.DOMNode, predicate: (node: SDK.DOMModel.DOMNode) => boolean): SDK.DOMModel.DOMNode|
null {
if (predicate(node)) {
return node;
}
const children = node.children();
if (children) {
for (const child of children) {
const result = findNode(child, predicate);
if (result) {
return result;
}
}
}
return null;
}
describe('DOMModel API Test', () => {
it('generates attribute updated event only when attribute is actually changed', async ({inspectedPage, universe}) => {
const primaryTarget = universe.targetManager.primaryPageTarget();
assert.isNotNull(primaryTarget);
const domModel = primaryTarget.model(SDK.DOMModel.DOMModel);
assert.isNotNull(domModel);
await inspectedPage.goToHtml(`
<div id="container">
<div id="node-set-new-value" style="color:red"></div>
<div id="node-set-same-value" style="color:red"></div>
</div>
`);
const documentNode = await domModel.requestDocument();
assert.isNotNull(documentNode);
// Retrieve the subtree to populate the DOMModel cache.
await documentNode.getSubtree(5, true);
const container = findNode(documentNode, n => n.getAttribute('id') === 'container');
assert.isNotNull(container);
const nodeSetNewValue = findNode(documentNode, n => n.getAttribute('id') === 'node-set-new-value');
assert.isNotNull(nodeSetNewValue);
const nodeSetSameValue = findNode(documentNode, n => n.getAttribute('id') === 'node-set-same-value');
assert.isNotNull(nodeSetSameValue);
if (!nodeSetNewValue || !nodeSetSameValue) {
assert.fail('Could not find test nodes');
}
// Verifies that setting a new style attribute value triggers the AttrModified event.
let attrModifiedPromise = domModel.once(SDK.DOMModel.Events.AttrModified);
await inspectedPage.evaluate(() => {
(document.getElementById('node-set-new-value') as HTMLElement).style.setProperty('color', 'blue');
});
let eventData = await attrModifiedPromise;
assert.strictEqual(eventData.node, nodeSetNewValue);
assert.strictEqual(eventData.name, 'style');
assert.strictEqual(nodeSetNewValue.getAttribute('style'), 'color: blue;');
// Verifies that setting the style attribute to the same value does not trigger the AttrModified event.
let attrModifiedFired = false;
const listener =
(event: Common.EventTarget
.EventTargetEvent<SDK.DOMModel.EventTypes[SDK.DOMModel.Events.AttrModified], SDK.DOMModel.EventTypes>):
void => {
if (event.data.node === nodeSetSameValue) {
attrModifiedFired = true;
}
};
domModel.addEventListener(SDK.DOMModel.Events.AttrModified, listener);
await inspectedPage.evaluate(() => {
(document.getElementById('node-set-same-value') as HTMLElement).style.setProperty('color', 'red');
});
// Flushes pending events by triggering a style change on the new value node.
attrModifiedPromise = domModel.once(SDK.DOMModel.Events.AttrModified);
await inspectedPage.evaluate(() => {
(document.getElementById('node-set-new-value') as HTMLElement).style.setProperty('color', 'green');
});
eventData = await attrModifiedPromise;
assert.strictEqual(eventData.node, nodeSetNewValue);
assert.isFalse(attrModifiedFired, 'AttrModified should not have fired for same value');
domModel.removeEventListener(SDK.DOMModel.Events.AttrModified, listener);
});
});