fix(snapshot): invalidate style sheet upon CSSGroupingRule changes (#27296)
Previously, snapshotter listened to CSSStyleSheet modifications, but one can also modify the list of rules inside CSSGroupingRule. Fixes #27288.
This commit is contained in:
parent
522782cce6
commit
9a5356f93b
|
|
@ -89,6 +89,10 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
|
||||||
private _observer: MutationObserver;
|
private _observer: MutationObserver;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
const invalidateCSSGroupingRule = (rule: CSSGroupingRule) => {
|
||||||
|
if (rule.parentStyleSheet)
|
||||||
|
this._invalidateStyleSheet(rule.parentStyleSheet);
|
||||||
|
};
|
||||||
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'insertRule', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'insertRule', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
||||||
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'deleteRule', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'deleteRule', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
||||||
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'addRule', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'addRule', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
||||||
|
|
@ -96,6 +100,9 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
|
||||||
this._interceptNativeGetter(window.CSSStyleSheet.prototype, 'rules', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
this._interceptNativeGetter(window.CSSStyleSheet.prototype, 'rules', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
||||||
this._interceptNativeGetter(window.CSSStyleSheet.prototype, 'cssRules', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
this._interceptNativeGetter(window.CSSStyleSheet.prototype, 'cssRules', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
||||||
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'replaceSync', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
this._interceptNativeMethod(window.CSSStyleSheet.prototype, 'replaceSync', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
||||||
|
this._interceptNativeMethod(window.CSSGroupingRule.prototype, 'insertRule', invalidateCSSGroupingRule);
|
||||||
|
this._interceptNativeMethod(window.CSSGroupingRule.prototype, 'deleteRule', invalidateCSSGroupingRule);
|
||||||
|
this._interceptNativeGetter(window.CSSGroupingRule.prototype, 'cssRules', invalidateCSSGroupingRule);
|
||||||
this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, 'replace', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, 'replace', (sheet: CSSStyleSheet) => this._invalidateStyleSheet(sheet));
|
||||||
|
|
||||||
this._fakeBase = document.createElement('base');
|
this._fakeBase = document.createElement('base');
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,24 @@ it.describe('snapshots', () => {
|
||||||
expect(distillSnapshot(snapshot2)).toBe('<STYLE>button { color: blue; }</STYLE><BUTTON>Hello</BUTTON>');
|
expect(distillSnapshot(snapshot2)).toBe('<STYLE>button { color: blue; }</STYLE><BUTTON>Hello</BUTTON>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should respect CSSOM change through CSSGroupingRule', async ({ page, toImpl, snapshotter }) => {
|
||||||
|
await page.setContent('<style>@media { button { color: red; } }</style><button>Hello</button>');
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window['rule'] = document.styleSheets[0].cssRules[0];
|
||||||
|
void 0;
|
||||||
|
});
|
||||||
|
const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1');
|
||||||
|
expect(distillSnapshot(snapshot1)).toBe('<STYLE>@media {\n button { color: red; }\n}</STYLE><BUTTON>Hello</BUTTON>');
|
||||||
|
|
||||||
|
await page.evaluate(() => { window['rule'].cssRules[0].style.color = 'blue'; });
|
||||||
|
const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2');
|
||||||
|
expect(distillSnapshot(snapshot2)).toBe('<STYLE>@media {\n button { color: blue; }\n}</STYLE><BUTTON>Hello</BUTTON>');
|
||||||
|
|
||||||
|
await page.evaluate(() => { window['rule'].insertRule('button { color: green; }', 1); });
|
||||||
|
const snapshot3 = await snapshotter.captureSnapshot(toImpl(page), 'call@3', 'snapshot@call@3');
|
||||||
|
expect(distillSnapshot(snapshot3)).toBe('<STYLE>@media {\n button { color: blue; }\n button { color: green; }\n}</STYLE><BUTTON>Hello</BUTTON>');
|
||||||
|
});
|
||||||
|
|
||||||
it('should respect node removal', async ({ page, toImpl, snapshotter }) => {
|
it('should respect node removal', async ({ page, toImpl, snapshotter }) => {
|
||||||
await page.setContent('<div><button id="button1"></button><button id="button2"></button></div>');
|
await page.setContent('<div><button id="button1"></button><button id="button2"></button></div>');
|
||||||
const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1');
|
const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue