@wildpeaks/snapshot-dom
Advanced tools
Comparing version 2.0.0-rc2 to 2.0.0-rc3
{ | ||
"name": "@wildpeaks/snapshot-dom", | ||
"version": "2.0.0-rc2", | ||
"version": "2.0.0-rc3", | ||
"description": "Converts a DOM element to a JSON tree", | ||
@@ -5,0 +5,0 @@ "author": "Cecile Muller", |
229
README.md
# Snapshot | ||
Converts an HTMLElement to a JSON tree, useful for automated DOM tests. | ||
**Converts an HTMLElement to a JSON tree, useful for automated DOM tests.** | ||
@@ -9,38 +9,205 @@ Install: | ||
Usage: | ||
--- | ||
## Create a snapshot | ||
The package provides a function to generate a JSON snapshot of the a DOM element: | ||
- in **Node**: `toJSON` | ||
- in **Browser**: `window.snapshotToJSON` | ||
Using **jsDOM**: | ||
````js | ||
document.body.innerHTML = '<div class="class1"><div class="class2"></div><p>Hello World</p></div>'; | ||
const {toJSON} = require("@wildpeaks/snapshot-dom"); | ||
const html = `<article class="class1 class2"><p>Hello</p><p>World</p></article>`; | ||
assert.deepStrictEqual( | ||
snapshot.toJSON(document.body), | ||
{ | ||
tagName: 'body', | ||
childNodes: [ | ||
{ | ||
tagName: 'div', | ||
attributes: { | ||
class: 'class1' | ||
const {window} = new JSDOM(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`); | ||
const snapshot = toJSON(window.document.body); | ||
```` | ||
Using **Puppeteer**: | ||
````js | ||
const script = require.resolve("@wildpeaks/snapshot-dom/lib/browser.js"); | ||
const html = `<article class="class1 class2"><p>Hello</p><p>World</p></article>`; | ||
let snapshot; | ||
const browser = await puppeteer.launch(); | ||
try { | ||
const page = await browser.newPage(); | ||
await page.setContent(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`, {waitUntil: "load"}); | ||
await page.addScriptTag({path: script}); | ||
snapshot = await page.evaluate(() => window.snapshotToJSON(document.body)); | ||
} finally { | ||
await browser.close(); | ||
} | ||
```` | ||
In both examples, `snapshot` contains: | ||
```` | ||
{ | ||
tagName: "body", | ||
childNodes: [ | ||
{ | ||
tagName: "article", | ||
attributes: { | ||
class: "class1 class2" | ||
}, | ||
childNodes: [ | ||
{ | ||
tagName: "p", | ||
childNodes: [ | ||
{ | ||
nodeName: "#text", | ||
nodeValue: "Hello" | ||
} | ||
] | ||
}, | ||
childNodes: [ | ||
{ | ||
tagName: 'div', | ||
attributes: { | ||
class: 'class2' | ||
{ | ||
tagName: "p", | ||
childNodes: [ | ||
{ | ||
nodeName: "#text", | ||
nodeValue: "World" | ||
} | ||
}, | ||
{ | ||
tagName: 'p', | ||
childNodes: [ | ||
{ | ||
nodeName: '#text', | ||
nodeValue: 'Hello World' | ||
} | ||
] | ||
} | ||
] | ||
] | ||
} | ||
] | ||
} | ||
] | ||
} | ||
```` | ||
--- | ||
## Remove empty values | ||
The package provides a transform function to remove empty values: | ||
- in **Node**: `removeEmptyAttributes` | ||
- in **Browser**: `window.snapshotRemoveEmptyAttributes` | ||
Using **jsDOM**: | ||
````js | ||
const {toJSON} = require("@wildpeaks/snapshot-dom"); | ||
const {removeEmptyAttributes} = require("@wildpeaks/snapshot-dom/removeEmptyAttributes"); | ||
const html = `<img param1 param2="" param3="hello" />`; | ||
const {window} = new JSDOM(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`); | ||
const snapshot = toJSON(window.document.body); | ||
removeEmptyAttributes(snapshot); | ||
```` | ||
Using **Puppeteer**: | ||
````js | ||
const script1 = require.resolve("@wildpeaks/snapshot-dom/lib/browser.js"); | ||
const script2 = require.resolve("@wildpeaks/snapshot-dom/removeEmptyAttributes/browser.js"); | ||
const html = `<img param1 param2="" param3="hello" />`; | ||
let snapshot; | ||
const browser = await puppeteer.launch(); | ||
try { | ||
const page = await browser.newPage(); | ||
await page.setContent(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`, {waitUntil: "load"}); | ||
await page.addScriptTag({path: script1}); | ||
await page.addScriptTag({path: script2}); | ||
snapshot = await page.evaluate(() => { | ||
let snapshot_ = window.snapshotToJSON(document.body); | ||
snapshot_ = window.snapshotRemoveEmptyAttributes(snapshot_); | ||
return snapshot_; | ||
}); | ||
} finally { | ||
await browser.close(); | ||
} | ||
```` | ||
In both examples, `snapshot` contains: | ||
```` | ||
{ | ||
tagName: "body", | ||
childNodes: [ | ||
{ | ||
tagName: "img", | ||
attributes: { | ||
param3: "hello" | ||
} | ||
] | ||
} | ||
); | ||
} | ||
] | ||
} | ||
```` | ||
Note that `param1` and `param2` aren't in the tree because of the transform. | ||
--- | ||
## Sort values | ||
The package provides a transform function to sort values in space-separated attributes like `class`: | ||
- in **Node**: `sortAttributes` | ||
- in **Browser**: `window.snapshotSortAttributes` | ||
Using **jsDOM**: | ||
````js | ||
const {toJSON} = require("@wildpeaks/snapshot-dom"); | ||
const {sortAttributes} = require("@wildpeaks/snapshot-dom/sortAttributes"); | ||
const html = `<article data-param1="sorted2 sorted1 sorted3" data-param2="unsorted2 unsorted1 unsorted3"></article>`; | ||
const {window} = new JSDOM(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`); | ||
const snapshot = toJSON(window.document.body); | ||
sortAttributes(snapshot, ["data-param1"]); | ||
```` | ||
Using **Puppeteer**: | ||
````js | ||
const script1 = require.resolve("@wildpeaks/snapshot-dom/lib/browser.js"); | ||
const script2 = require.resolve("@wildpeaks/snapshot-dom/sortAttributes/browser.js"); | ||
const html = `<article data-param1="sorted2 sorted1 sorted3" data-param2="unsorted2 unsorted1 unsorted3"></article>`; | ||
let snapshot; | ||
const browser = await puppeteer.launch(); | ||
try { | ||
const page = await browser.newPage(); | ||
await page.setContent(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`, {waitUntil: "load"}); | ||
await page.addScriptTag({path: script1}); | ||
await page.addScriptTag({path: script2}); | ||
snapshot = await page.evaluate(() => { | ||
let snapshot_ = window.snapshotToJSON(document.body); | ||
snapshot_ = window.snapshotSortAttributes(snapshot_, ["data-param1"]); | ||
return snapshot_; | ||
}); | ||
} finally { | ||
await browser.close(); | ||
} | ||
```` | ||
In both examples, `snapshot` contains: | ||
```` | ||
{ | ||
tagName: "body", | ||
childNodes: [ | ||
{ | ||
tagName: "article", | ||
attributes: { | ||
"data-param1": "sorted1 sorted2 sorted3", | ||
"data-param2": "unsorted2 unsorted1 unsorted3" | ||
} | ||
} | ||
] | ||
} | ||
```` | ||
Note how values in `data-param1` are sorted whereas they remain unsorted in `data-param2`. | ||
Also note that, because it rewrites the value, it trims and condenses consecutive whitespace. | ||
--- | ||
## Migration from v1 to v2 | ||
**The second parameter has been removed**: use function `removeEmptyAttributes` to get | ||
the same result as the parameter that was removed. |
@@ -1,1 +0,1 @@ | ||
"use strict";window.snapshotRemoveEmptyAttributes=function t(e){if("object"==typeof e&&null!==e&&(Array.isArray(e.childNodes)&&(e.childNodes=e.childNodes.map(t)),e&&e.attributes)){const t=[];for(const s in e.attributes)e.attributes[s]||t.push(s);t.forEach(t=>delete e.attributes[t])}return e}; | ||
"use strict";window.snapshotRemoveEmptyAttributes=function t(e){if("object"==typeof e&&null!==e&&(Array.isArray(e.childNodes)&&e.childNodes.forEach(t),e.attributes)){const t=[];for(const s in e.attributes)e.attributes[s]||t.push(s);t.forEach(t=>delete e.attributes[t])}}; |
@@ -1,1 +0,1 @@ | ||
"use strict";function removeEmptyAttributes(t){if("object"==typeof t&&null!==t&&(Array.isArray(t.childNodes)&&(t.childNodes=t.childNodes.map(removeEmptyAttributes)),t&&t.attributes)){const e=[];for(const r in t.attributes)t.attributes[r]||e.push(r);e.forEach(e=>delete t.attributes[e])}return t}module.exports.removeEmptyAttributes=removeEmptyAttributes; | ||
"use strict";function removeEmptyAttributes(t){if("object"==typeof t&&null!==t&&(Array.isArray(t.childNodes)&&t.childNodes.forEach(removeEmptyAttributes),t.attributes)){const e=[];for(const r in t.attributes)t.attributes[r]||e.push(r);e.forEach(e=>delete t.attributes[e])}}module.exports.removeEmptyAttributes=removeEmptyAttributes; |
@@ -1,1 +0,1 @@ | ||
"use strict";window.snapshotSortAttributes=function t(r,i){if("object"==typeof r&&null!==r&&Array.isArray(i)&&(Array.isArray(r.childNodes)&&(r.childNodes=r.childNodes.map(r=>t(r,i))),r&&r.attributes))for(const t in r.attributes)i.includes(t)&&(r.attributes[t]="string"==typeof(s=r.attributes[t])?s.trim().replace(/[\s]+/g," ").split(" ").sort().join(" "):s);var s;return r}; | ||
"use strict";window.snapshotSortAttributes=function t(r,i){if("object"==typeof r&&null!==r&&Array.isArray(i)&&(Array.isArray(r.childNodes)&&r.childNodes.forEach(r=>t(r,i)),r&&r.attributes))for(const t in r.attributes)i.includes(t)&&(r.attributes[t]="string"==typeof(s=r.attributes[t])?s.trim().replace(/[\s]+/g," ").split(" ").sort().join(" "):s);var s}; |
@@ -1,1 +0,1 @@ | ||
"use strict";function sortAttributeValue(t){return"string"==typeof t?t.trim().replace(/[\s]+/g," ").split(" ").sort().join(" "):t}function sortAttributes(t,r){if("object"==typeof t&&null!==t&&Array.isArray(r)&&(Array.isArray(t.childNodes)&&(t.childNodes=t.childNodes.map(t=>sortAttributes(t,r))),t&&t.attributes))for(const s in t.attributes)r.includes(s)&&(t.attributes[s]=sortAttributeValue(t.attributes[s]));return t}module.exports.sortAttributes=sortAttributes; | ||
"use strict";function sortAttributeValue(t){return"string"==typeof t?t.trim().replace(/[\s]+/g," ").split(" ").sort().join(" "):t}function sortAttributes(t,r){if("object"==typeof t&&null!==t&&Array.isArray(r)&&(Array.isArray(t.childNodes)&&t.childNodes.forEach(t=>sortAttributes(t,r)),t&&t.attributes))for(const s in t.attributes)r.includes(s)&&(t.attributes[s]=sortAttributeValue(t.attributes[s]))}module.exports.sortAttributes=sortAttributes; |
8375
213