@applitools/dom-snapshot 4.15.1 → 4.15.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +44 -0
- package/dist/browser/cssom/createAstFromCssom.d.ts +1 -1
- package/dist/browser/cssom/createAstFromDeclaration.d.ts +1 -1
- package/dist/browser/cssom/styleSheetToCssText.d.ts +1 -1
- package/dist/pollResult.js +1 -1
- package/dist/pollResultCjs.js +1 -1
- package/dist/pollResultEs.js +1 -1
- package/dist/processPage.js +3 -3
- package/dist/processPage.js.map +1 -1
- package/dist/processPagePoll.js +3 -3
- package/dist/processPagePoll.js.map +1 -1
- package/dist/processPagePollCjs.js +3 -3
- package/dist/processPagePollCjs.js.map +1 -1
- package/dist/processPagePollEs.js +3 -3
- package/dist/processPagePollEs.js.map +1 -1
- package/index.js +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,36 @@
|
|
|
9
9
|
- fix style programmatic generated fallback
|
|
10
10
|
- performance boost
|
|
11
11
|
|
|
12
|
+
## [4.15.3](https://github.com/Applitools-Dev/sdk/compare/js/dom-snapshot@4.15.2...js/dom-snapshot@4.15.3) (2025-12-07)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* capture JavaScript-modified CSS selectors in nested [@layer](https://github.com/layer) rules ([#3391](https://github.com/Applitools-Dev/sdk/issues/3391)) ([b3bceb5](https://github.com/Applitools-Dev/sdk/commit/b3bceb5bfe894f3548173d23942e09d0e04b7e04))
|
|
18
|
+
|
|
19
|
+
## [4.15.2](https://github.com/Applitools-Dev/sdk/compare/js/dom-snapshot@4.15.1...js/dom-snapshot@4.15.2) (2025-12-01)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* handle CSS variables in Shadow DOM adopted stylesheets | FLD-3790 ([#3381](https://github.com/Applitools-Dev/sdk/issues/3381)) ([b2bfca3](https://github.com/Applitools-Dev/sdk/commit/b2bfca3cd706cd996d78d51c6242148fbb8ce741))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* @applitools/utils bumped to 1.14.1
|
|
30
|
+
#### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* setup script compatibility with ESM | AD-11756 ([#3363](https://github.com/Applitools-Dev/sdk/issues/3363)) ([d1222f4](https://github.com/Applitools-Dev/sdk/commit/d1222f40a74ab62782bebeeb0cf899aac3f3d3b6))
|
|
33
|
+
* @applitools/logger bumped to 2.2.7
|
|
34
|
+
|
|
35
|
+
* @applitools/driver bumped to 1.24.3
|
|
36
|
+
|
|
37
|
+
* @applitools/spec-driver-webdriver bumped to 1.5.3
|
|
38
|
+
|
|
39
|
+
* @applitools/spec-driver-puppeteer bumped to 1.6.9
|
|
40
|
+
|
|
41
|
+
|
|
12
42
|
## [4.15.1](https://github.com/Applitools-Dev/sdk/compare/js/dom-snapshot@4.15.0...js/dom-snapshot@4.15.1) (2025-11-19)
|
|
13
43
|
|
|
14
44
|
|
package/README.md
CHANGED
|
@@ -101,6 +101,50 @@ This approach:
|
|
|
101
101
|
- Build system remains consistent across all outputs
|
|
102
102
|
- Consumer packages unaffected during migration
|
|
103
103
|
|
|
104
|
+
### CSS Merging Design Principles
|
|
105
|
+
|
|
106
|
+
The DOM snapshot captures CSS from two sources to ensure **cross-browser re-renderability**:
|
|
107
|
+
|
|
108
|
+
1. **textContent** - Raw CSS as written in `<style>` tags (source code)
|
|
109
|
+
2. **CSSOM** - Browser's runtime CSS Object Model (computed state)
|
|
110
|
+
|
|
111
|
+
#### Why Merge Both Sources?
|
|
112
|
+
|
|
113
|
+
Different browsers have varying CSS support levels. By merging both sources, we ensure:
|
|
114
|
+
- ✅ **Browser-specific syntax is preserved** (e.g., `-webkit-appearance`, vendor prefixes)
|
|
115
|
+
- ✅ **Unsupported CSS features are captured** (e.g., CSS nesting in older browsers)
|
|
116
|
+
- ✅ **Runtime modifications are included** (e.g., JavaScript-modified styles)
|
|
117
|
+
- ✅ **Snapshots render correctly across browsers** with different CSS capabilities
|
|
118
|
+
|
|
119
|
+
#### Design Trade-off: Re-renderability vs Runtime State
|
|
120
|
+
|
|
121
|
+
When CSS exists in textContent but not in CSSOM, we **cannot distinguish** between:
|
|
122
|
+
|
|
123
|
+
1. **Browser limitation** - CSSOM doesn't support the syntax (e.g., vendor prefixes, new CSS features)
|
|
124
|
+
- ✅ **Should preserve** for cross-browser re-renderability
|
|
125
|
+
|
|
126
|
+
2. **JavaScript removal** - JavaScript explicitly deleted the CSS at runtime
|
|
127
|
+
- ❌ **Ideally wouldn't preserve** since it was intentionally removed
|
|
128
|
+
|
|
129
|
+
**Our Choice: Prioritize Re-renderability**
|
|
130
|
+
|
|
131
|
+
We choose to **preserve textContent when CSSOM is missing**, accepting the trade-off that we might include CSS that JavaScript intentionally removed. This decision:
|
|
132
|
+
|
|
133
|
+
- ✅ Maximizes cross-browser compatibility
|
|
134
|
+
- ✅ Ensures vendor-specific CSS works where supported
|
|
135
|
+
- ✅ Captures emerging CSS features not yet in CSSOM
|
|
136
|
+
- ❌ May include runtime-deleted CSS (unavoidable without JS tracking)
|
|
137
|
+
|
|
138
|
+
This is consistent with how we handle vendor prefixes and other browser-specific CSS throughout the package.
|
|
139
|
+
|
|
140
|
+
#### Implementation Details
|
|
141
|
+
|
|
142
|
+
See `src/browser/cssom/mergeRules.ts` for the merging algorithm, which:
|
|
143
|
+
- Recursively merges CSS rules from textContent and CSSOM
|
|
144
|
+
- Preserves nested rules (CSS nesting with `&`) from either source
|
|
145
|
+
- Handles style property conflicts by preferring CSSOM values
|
|
146
|
+
- Maintains both vendor-prefixed and normalized property versions
|
|
147
|
+
|
|
104
148
|
## Installing
|
|
105
149
|
|
|
106
150
|
```sh
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Logger } from '../logger';
|
|
2
|
-
declare function createAstFromCssom(cssomRules: CSSRuleList, logger: Logger): any[];
|
|
2
|
+
declare function createAstFromCssom(cssomRules: CSSRuleList, logger: Logger, shadowRoot?: Document): any[];
|
|
3
3
|
export default createAstFromCssom;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare function createAstFromDeclaration(cssomDeclaration: CSSStyleDeclaration): any[];
|
|
1
|
+
declare function createAstFromDeclaration(cssomDeclaration: CSSStyleDeclaration, shadowRoot?: Document, selector?: string): any[];
|
|
2
2
|
export default createAstFromDeclaration;
|
package/dist/pollResult.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* @applitools/dom-snapshot@4.15.
|
|
1
|
+
/* @applitools/dom-snapshot@4.15.3 */
|
|
2
2
|
function __pollResult() {
|
|
3
3
|
var pollResult=function(){"use strict";return function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=function(t){return function(){var t={};function e(t,e=0){const n=t.charCodeAt(e);return n>=55296&&n<56320?1024*(n-55296)+(t.charCodeAt(e+1)-56320)+65536:56320<=n&&n<=57343?-1:n}var n=function(t,n){const r=[];let o=0;for(let c=0;c<t.length;++c){const u=e(t,c);let a=0;u>0&&(a=u<128?1:u<2048?2:u<65536?3:u<2097152?4:u<67108864?5:6),o+a>n?(r.push(c),o=a):o+=a}return r};const r=function(t){return t&&t.__esModule?t:{default:t}}(n),o="WIP",c="SUCCESS",u="SUCCESS_CHUNKED",a="ERROR";var s=function(t,e,n={}){const s=function(t,{chunkByteLength:e=0}={}){if(t){if(t.value){if(e){if(!t.chunks)try{const n=JSON.stringify(t.value);t.chunks=(0,r.default)(n,e),t.chunks.length>0&&(t.from=0,t.value=n)}catch(t){return{status:a,error:t.message}}if(t.from>=0)return{status:u,value:t.value.substring(t.from,t.from=t.chunks.shift()),done:!t.from}}return{status:c,value:t.value}}return t.error?{status:a,error:t.error}:{status:o}}return{status:a,error:"unexpected poll request received - cannot find state of current operation"}}((t=t||{})[e],n);return(s.status===c||s.status===a||s.status===u&&s.done)&&delete t[e],s};const i=s;var l=function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(t,"__esModule",{value:!0}),t.isAccessibleFrame=t.isInlineFrame=t.absolutizeUrl=p=t.poll=t.pollify=t.chunkify=void 0;const f=l(n);t.chunkify=f.default;const d=l((function(t,e,n){return r=>function(...o){return e[n]||(e[n]={},Promise.resolve().then((()=>t(...o))).then((t=>e[n].value=t)).catch((t=>e[n].error=t.message+"\nStack:"+t.stack))),i(e,n,r)}}));t.pollify=d.default;const h=l(s);var p=t.poll=h.default;const m=l((function(t,e){if(function(t){try{return new URL(t),!0}catch(t){return!1}}(t))return t;let n=!0;try{n=t!==decodeURI(t)}catch(t){n=!0}try{const r=new URL(t,e).href;return n?r:decodeURI(r)}catch(e){return n?t:decodeURI(t)}}));t.absolutizeUrl=m.default;const v=l((function(t){return t.contentDocument&&t.contentDocument.location&&!/^https?:$/.test(t.contentDocument.location.protocol)}));t.isInlineFrame=v.default;const y=l((function(t){try{const e=t.contentDocument;return Boolean(e&&e.defaultView&&e.defaultView.frameElement)}catch(t){return!1}}));return t.isAccessibleFrame=y.default,function(t){try{return JSON.stringify(p(window.__EYES__APPLITOOLS__,"domSnapshotResult",t))}catch(t){return JSON.stringify({status:"ERROR",error:t.message})}}}()},r=!0;try{var o=window.__applitools_sandbox;o||((o=document.createElement("iframe")).setAttribute("data-applitools-sandbox",""),o.setAttribute("data-applitools-skip",""),document.head.appendChild(o),window.__applitools_sandbox=o);var c=window.crypto.getRandomValues(new Uint32Array(1))[0],u=o.contentDocument.createElement("script");u.textContent="window['ctor-".concat(c,"'] = ").concat(n.toString(),";"),o.contentDocument.head.appendChild(u);var a=o.contentWindow["ctor-".concat(c)];if("function"!=typeof a)throw new Error("Sandbox failed to extract function");return r=!1,a(document).apply(void 0,t)}catch(e){try{return n(document).apply(void 0,t)}catch(t){throw r?t:e}}}}();
|
|
4
4
|
//# sourceMappingURL=pollResult.js.map
|
package/dist/pollResultCjs.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/* @applitools/dom-snapshot@4.15.
|
|
1
|
+
/* @applitools/dom-snapshot@4.15.3 */
|
|
2
2
|
"use strict";module.exports=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=function(t){return function(){var t={};function e(t,e=0){const n=t.charCodeAt(e);return n>=55296&&n<56320?1024*(n-55296)+(t.charCodeAt(e+1)-56320)+65536:56320<=n&&n<=57343?-1:n}var n=function(t,n){const r=[];let o=0;for(let c=0;c<t.length;++c){const u=e(t,c);let a=0;u>0&&(a=u<128?1:u<2048?2:u<65536?3:u<2097152?4:u<67108864?5:6),o+a>n?(r.push(c),o=a):o+=a}return r};const r=function(t){return t&&t.__esModule?t:{default:t}}(n),o="WIP",c="SUCCESS",u="SUCCESS_CHUNKED",a="ERROR";var s=function(t,e,n={}){const s=function(t,{chunkByteLength:e=0}={}){if(t){if(t.value){if(e){if(!t.chunks)try{const n=JSON.stringify(t.value);t.chunks=(0,r.default)(n,e),t.chunks.length>0&&(t.from=0,t.value=n)}catch(t){return{status:a,error:t.message}}if(t.from>=0)return{status:u,value:t.value.substring(t.from,t.from=t.chunks.shift()),done:!t.from}}return{status:c,value:t.value}}return t.error?{status:a,error:t.error}:{status:o}}return{status:a,error:"unexpected poll request received - cannot find state of current operation"}}((t=t||{})[e],n);return(s.status===c||s.status===a||s.status===u&&s.done)&&delete t[e],s};const i=s;var l=function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(t,"__esModule",{value:!0}),t.isAccessibleFrame=t.isInlineFrame=t.absolutizeUrl=p=t.poll=t.pollify=t.chunkify=void 0;const f=l(n);t.chunkify=f.default;const d=l((function(t,e,n){return r=>function(...o){return e[n]||(e[n]={},Promise.resolve().then((()=>t(...o))).then((t=>e[n].value=t)).catch((t=>e[n].error=t.message+"\nStack:"+t.stack))),i(e,n,r)}}));t.pollify=d.default;const h=l(s);var p=t.poll=h.default;const m=l((function(t,e){if(function(t){try{return new URL(t),!0}catch(t){return!1}}(t))return t;let n=!0;try{n=t!==decodeURI(t)}catch(t){n=!0}try{const r=new URL(t,e).href;return n?r:decodeURI(r)}catch(e){return n?t:decodeURI(t)}}));t.absolutizeUrl=m.default;const v=l((function(t){return t.contentDocument&&t.contentDocument.location&&!/^https?:$/.test(t.contentDocument.location.protocol)}));t.isInlineFrame=v.default;const y=l((function(t){try{const e=t.contentDocument;return Boolean(e&&e.defaultView&&e.defaultView.frameElement)}catch(t){return!1}}));return t.isAccessibleFrame=y.default,function(t){try{return JSON.stringify(p(window.__EYES__APPLITOOLS__,"domSnapshotResult",t))}catch(t){return JSON.stringify({status:"ERROR",error:t.message})}}}()},r=!0;try{var o=window.__applitools_sandbox;o||((o=document.createElement("iframe")).setAttribute("data-applitools-sandbox",""),o.setAttribute("data-applitools-skip",""),document.head.appendChild(o),window.__applitools_sandbox=o);var c=window.crypto.getRandomValues(new Uint32Array(1))[0],u=o.contentDocument.createElement("script");u.textContent="window['ctor-".concat(c,"'] = ").concat(n.toString(),";"),o.contentDocument.head.appendChild(u);var a=o.contentWindow["ctor-".concat(c)];if("function"!=typeof a)throw new Error("Sandbox failed to extract function");return r=!1,a(document).apply(void 0,t)}catch(e){try{return n(document).apply(void 0,t)}catch(t){throw r?t:e}}};
|
|
3
3
|
//# sourceMappingURL=pollResultCjs.js.map
|
package/dist/pollResultEs.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/* @applitools/dom-snapshot@4.15.
|
|
1
|
+
/* @applitools/dom-snapshot@4.15.3 */
|
|
2
2
|
function t(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n=function(t){return function(){var t={};function e(t,e=0){const n=t.charCodeAt(e);return n>=55296&&n<56320?1024*(n-55296)+(t.charCodeAt(e+1)-56320)+65536:56320<=n&&n<=57343?-1:n}var n=function(t,n){const r=[];let o=0;for(let c=0;c<t.length;++c){const u=e(t,c);let a=0;u>0&&(a=u<128?1:u<2048?2:u<65536?3:u<2097152?4:u<67108864?5:6),o+a>n?(r.push(c),o=a):o+=a}return r};const r=function(t){return t&&t.__esModule?t:{default:t}}(n),o="WIP",c="SUCCESS",u="SUCCESS_CHUNKED",a="ERROR";var s=function(t,e,n={}){const s=function(t,{chunkByteLength:e=0}={}){if(t){if(t.value){if(e){if(!t.chunks)try{const n=JSON.stringify(t.value);t.chunks=(0,r.default)(n,e),t.chunks.length>0&&(t.from=0,t.value=n)}catch(t){return{status:a,error:t.message}}if(t.from>=0)return{status:u,value:t.value.substring(t.from,t.from=t.chunks.shift()),done:!t.from}}return{status:c,value:t.value}}return t.error?{status:a,error:t.error}:{status:o}}return{status:a,error:"unexpected poll request received - cannot find state of current operation"}}((t=t||{})[e],n);return(s.status===c||s.status===a||s.status===u&&s.done)&&delete t[e],s};const i=s;var l=function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(t,"__esModule",{value:!0}),t.isAccessibleFrame=t.isInlineFrame=t.absolutizeUrl=p=t.poll=t.pollify=t.chunkify=void 0;const f=l(n);t.chunkify=f.default;const d=l((function(t,e,n){return r=>function(...o){return e[n]||(e[n]={},Promise.resolve().then((()=>t(...o))).then((t=>e[n].value=t)).catch((t=>e[n].error=t.message+"\nStack:"+t.stack))),i(e,n,r)}}));t.pollify=d.default;const h=l(s);var p=t.poll=h.default;const m=l((function(t,e){if(function(t){try{return new URL(t),!0}catch(t){return!1}}(t))return t;let n=!0;try{n=t!==decodeURI(t)}catch(t){n=!0}try{const r=new URL(t,e).href;return n?r:decodeURI(r)}catch(e){return n?t:decodeURI(t)}}));t.absolutizeUrl=m.default;const v=l((function(t){return t.contentDocument&&t.contentDocument.location&&!/^https?:$/.test(t.contentDocument.location.protocol)}));t.isInlineFrame=v.default;const y=l((function(t){try{const e=t.contentDocument;return Boolean(e&&e.defaultView&&e.defaultView.frameElement)}catch(t){return!1}}));return t.isAccessibleFrame=y.default,function(t){try{return JSON.stringify(p(window.__EYES__APPLITOOLS__,"domSnapshotResult",t))}catch(t){return JSON.stringify({status:"ERROR",error:t.message})}}}()},r=!0;try{var o=window.__applitools_sandbox;o||((o=document.createElement("iframe")).setAttribute("data-applitools-sandbox",""),o.setAttribute("data-applitools-skip",""),document.head.appendChild(o),window.__applitools_sandbox=o);var c=window.crypto.getRandomValues(new Uint32Array(1))[0],u=o.contentDocument.createElement("script");u.textContent="window['ctor-".concat(c,"'] = ").concat(n.toString(),";"),o.contentDocument.head.appendChild(u);var a=o.contentWindow["ctor-".concat(c)];if("function"!=typeof a)throw new Error("Sandbox failed to extract function");return r=!1,a(document).apply(void 0,t)}catch(e){try{return n(document).apply(void 0,t)}catch(t){throw r?t:e}}}export{t as default};
|
|
3
3
|
//# sourceMappingURL=pollResultEs.js.map
|