diff --git a/src/browser/commands.js b/src/browser/commands.js index 9ba41a45..900e1ae7 100644 --- a/src/browser/commands.js +++ b/src/browser/commands.js @@ -30,6 +30,7 @@ export async function focusElem(elem) { export async function hoverAt(x, y) { await sendMouse({ type: 'move', position: [x, y] }); + if (window.d2lTest) window.d2lTest.hovering = true; } export async function hoverElem(elem) { diff --git a/src/browser/vdiff.js b/src/browser/vdiff.js index e50b9d47..718bb886 100644 --- a/src/browser/vdiff.js +++ b/src/browser/vdiff.js @@ -17,6 +17,12 @@ mocha.setup({ /* eslint-enable */ async function ScreenshotAndCompare(opts) { + + if (window.d2lTest) { + document.documentElement.classList.add('screenshot'); + inlineStyles(this.elem); + } + const name = this.test.fullTitle(); const rect = this.elem.getBoundingClientRect(); const slowDuration = this.test.slow(); @@ -25,7 +31,46 @@ async function ScreenshotAndCompare(opts) { this.test.timeout(0); result = await executeServerCommand('brightspace-visual-diff-compare-resize', { name }); } + + if (window.d2lTest) document.documentElement.classList.remove('screenshot'); + if (!result.pass) { expect.fail(result.message); } } + +const disallowedProps = ['width', 'inline-size']; +let count = 0; + +function inlineStyles(elem) { + // headed chrome takes screenshots by first moving the element and locking it down, + // which breaks the hover state. So, copy current styles inline before screenshot + if (window.d2lTest.hovering && window.chrome) { + count += 1; + document.documentElement.classList.add('screenshot'); + elem.classList.add(`__d2lTestHovering-${count}`); + + [...elem.children, ...elem.shadowRoot?.children ?? []].forEach(child => inlineStyles(child)); + + const computedStyle = getComputedStyle(elem); + [...computedStyle].forEach(prop => { + if (!disallowedProps.includes(prop)) { + elem.style[prop] = computedStyle.getPropertyValue(prop); + } + }); + + ['before', 'after'].forEach(pseudoEl => { + const computedStyle = getComputedStyle(elem, `::${pseudoEl}`); + if (computedStyle.content !== 'none') { + const sheet = new CSSStyleSheet(); + [...computedStyle].forEach(prop => { + if (!disallowedProps.includes(prop)) { + const value = computedStyle.getPropertyValue(prop); + sheet.insertRule(`.__d2lTestHovering-${count}::${pseudoEl} { ${prop}: ${value} !important; }`); + } + }); + elem.getRootNode().adoptedStyleSheets.push(sheet); + } + }); + } +} diff --git a/src/server/pause.js b/src/server/pause.js index 25fe05ad..40e8643a 100644 --- a/src/server/pause.js +++ b/src/server/pause.js @@ -3,6 +3,10 @@ test.pause = new Promise(r => test.start = r); const controls = `