import {multiline} from '../../support/test-utils'; import type {StyleExpectations} from '../globals'; async function expectStyles(styles: StyleExpectations) { await expectPageStyles(expect, styles); } describe('Style override', () => { it('should override user agent style', async () => { await loadTestPage({ '/': multiline( '', '', '', '', '', ' Text', ' Link', '', '', ), }); await expectStyles([ ['document', 'background-color', 'rgb(24, 26, 27)'], ['document', 'color', 'rgb(232, 230, 227)'], ['body', 'background-color', 'rgb(24, 26, 27)'], ['body', 'color', 'rgb(232, 230, 227)'], ['a', 'color', 'rgb(51, 145, 255)'], ]); }); it('should override static style', async () => { await loadTestPage({ '/': multiline( '', '', '', ' ', '', '', '

Style override!

', '', '', ), }); await expectStyles([ ['document', 'background-color', 'rgb(24, 26, 27)'], ['body', 'background-color', 'rgb(96, 104, 108)'], ['body', 'color', 'rgb(232, 230, 227)'], ['h1', 'color', 'rgb(232, 230, 227)'], ['h1 strong', 'color', 'rgb(255, 26, 26)'], ]); }); it('should restore override', async () => { await loadTestPage({ '/': multiline( '', '', '', '', '', '

Style override!

', '', '', ), }); await pageUtils.evaluateScript(() => { const styleElement = document.createElement('style'); styleElement.classList.add('testcase-style'); document.head.append(styleElement); styleElement.sheet!.insertRule('h1 { color: gray }'); styleElement.sheet!.insertRule('strong { color: red }'); }); await expectStyles([ ['h1', 'color', 'rgb(152, 143, 129)'], ['h1 strong', 'color', 'rgb(255, 26, 26)'], ]); await expect(pageUtils.evaluateScript(async () => { const style = document.querySelector('.testcase-style')!; style.nextSibling!.remove(); await new Promise((resolve) => setTimeout(resolve)); return (style.nextSibling as HTMLStyleElement).classList.contains('darkreader--sync'); })).resolves.toBe(true); }); it('should move override', async () => { await loadTestPage({ '/': multiline( '', '', '', '', '', '

Some test foor...... Moving styles!

', '', '', ), }); await pageUtils.evaluateScript(() => { const styleElement = document.createElement('style'); styleElement.classList.add('testcase-style'); document.head.append(styleElement); styleElement.sheet!.insertRule('h1 { color: gray } '); styleElement.sheet!.insertRule('strong { color: red } '); }); await expect(pageUtils.evaluateScript(async () => { const style = document.querySelector('.testcase-style')!; document.body.append(style); await new Promise((resolve) => setTimeout(resolve)); return (style.nextSibling as HTMLStyleElement).classList.contains('darkreader--sync'); })).resolves.toBe(true); }); it('should remove override', async () => { await loadTestPage({ '/': multiline( '', '', '', '', '', '

Some test foor...... Oh uhm removing styles :(!

', '', '', ), }); await pageUtils.evaluateScript(() => { const styleElement = document.createElement('style'); styleElement.classList.add('testcase-style'); document.head.append(styleElement); styleElement.sheet!.insertRule('h1 { color: gray }'); styleElement.sheet!.insertRule('strong { color: red }'); }); await expect(pageUtils.evaluateScript(async () => { const style = document.querySelector('.testcase-style')!; const sibling = style.nextSibling!; style.remove(); await new Promise((resolve) => setTimeout(resolve)); return sibling.isConnected && !((sibling as HTMLStyleElement).classList.contains('darkreader--sync')); })).resolves.toBe(false); }); it('should react to updated style', async () => { if (product === 'firefox') { expect(true); return; } await loadTestPage({ '/': multiline( '', '', '', '', '', '

Some test foor...... Oh uhm a pink background

', '', '', ), }); await pageUtils.evaluateScript(() => { const styleElement = document.createElement('style'); styleElement.classList.add('testcase-style'); document.head.append(styleElement); styleElement.sheet!.insertRule('h1 { color: gray }'); styleElement.sheet!.insertRule('strong { color: red }'); }); await expect(pageUtils.evaluateScript(async () => { const style = document.querySelector('.testcase-style')!; (style as HTMLStyleElement).sheet!.insertRule('html { background-color: pink }'); await new Promise((resolve) => setTimeout(resolve)); return (style.nextSibling as HTMLStyleElement).sheet!.cssRules[0].cssText; })).resolves.toBe('html { background-color: var(--darkreader-background-ffc0cb, #590010); }'); }); it('should react to a new style', async () => { await loadTestPage({ '/': multiline( '', '', '', '', '', '

Some test foor...... Oh uhm what?!

', '', '', ), }); await expect(pageUtils.evaluateScript(async () => { const styleElement = document.createElement('style'); styleElement.classList.add('testcase-style'); document.head.append(styleElement); styleElement.sheet!.insertRule('h1 { color: pink }'); styleElement.sheet!.insertRule('strong { color: orange }'); await new Promise((resolve) => setTimeout(resolve)); return (styleElement.nextSibling as HTMLStyleElement).sheet!.cssRules.length === 2 && (styleElement.nextSibling as HTMLStyleElement).classList.contains('darkreader--sync'); })).resolves.toBe(true); }); it('should handle defined custom elements', async () => { if (product === 'firefox') { return; } await loadTestPage({ '/': multiline( '', '', '', '', '', '', '', '', '', ), }); pageUtils.evaluateScript(async () => { class CustomElement extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({mode: 'open'}); const style = document.createElement('style'); style.textContent = 'p { color: pink }'; const paragraph = document.createElement('p'); paragraph.textContent = 'Some text content that should be pink.'; shadowRoot.append(style); shadowRoot.append(paragraph); } } customElements.define('custom-element', CustomElement); }); await expectStyles([ [['custom-element', 'p'], 'color', 'rgb(255, 160, 177)'], ]); }); });