Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@open-wc/semantic-dom-diff

Package Overview
Dependencies
Maintainers
2
Versions
129
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@open-wc/semantic-dom-diff - npm Package Compare versions

Comparing version 0.9.7 to 0.10.0

11

CHANGELOG.md

@@ -6,2 +6,13 @@ # Change Log

# [0.10.0](https://github.com/open-wc/open-wc/compare/@open-wc/semantic-dom-diff@0.9.7...@open-wc/semantic-dom-diff@0.10.0) (2019-04-08)
### Features
* **semantic-dom-diff:** add support for snapshot testing ([f7a675a](https://github.com/open-wc/open-wc/commit/f7a675a))
## [0.9.7](https://github.com/open-wc/open-wc/compare/@open-wc/semantic-dom-diff@0.9.6...@open-wc/semantic-dom-diff@0.9.7) (2019-04-06)

@@ -8,0 +19,0 @@

22

get-diffable-html.js

@@ -1,2 +0,2 @@

const DEFAULT_IGNORE_CHILDREN = ['script', 'style', 'svg'];
const DEFAULT_IGNORE_TAGS = ['script', 'style', 'svg'];
const VOID_ELEMENTS = [

@@ -55,3 +55,3 @@ 'area',

*
* @param {string} html
* @param {Node | string} html
* @param {DiffOptions} [options]

@@ -67,4 +67,4 @@ * @returns {string} html restructured in a diffable format

: []);
const ignoreTags = options.ignoreTags || [];
const ignoreChildren = [...(options.ignoreChildren || []), ...DEFAULT_IGNORE_CHILDREN];
const ignoreTags = [...(options.ignoreTags || []), ...DEFAULT_IGNORE_TAGS];
const ignoreChildren = options.ignoreChildren || [];

@@ -204,5 +204,15 @@ let text = '';

const container = document.createElement('diff-container');
container.innerHTML = html;
let container;
if (typeof html === 'string') {
container = document.createElement('diff-container');
container.innerHTML = html;
depth = -1;
} else if (html instanceof Node) {
container = html;
depth = 0;
} else {
throw new Error(`Cannot create diffable HTML from: ${html}`);
}
const walker = document.createTreeWalker(

@@ -209,0 +219,0 @@ container,

@@ -8,1 +8,3 @@ import { getDiffableHTML } from './get-diffable-html.js';

};
export { chaiDomDiff } from './chai-dom-diff';
{
"name": "@open-wc/semantic-dom-diff",
"version": "0.9.7",
"version": "0.10.0",
"description": "To compare dom and shadow dom trees. Part of open-wc recommendations",

@@ -24,2 +24,4 @@ "author": "open-wc",

"test:watch": "karma start --auto-watch=true --single-run=false",
"test:update-snapshots": "karma start --update-snapshots",
"test:prune-snapshots": "karma start --prune-snapshots",
"test:legacy": "karma start --legacy --coverage",

@@ -32,4 +34,5 @@ "test:legacy:watch": "karma start --legacy --auto-watch=true --single-run=false",

"@bundled-es-modules/chai": "^4.2.0",
"@open-wc/testing-karma": "^1.0.2",
"@open-wc/testing-karma-bs": "^1.0.2",
"@open-wc/testing-helpers": "^0.8.6",
"@open-wc/testing-karma": "^1.1.0",
"@open-wc/testing-karma-bs": "^1.0.3",
"@open-wc/testing-wallaby": "^0.1.12",

@@ -39,3 +42,3 @@ "mocha": "^5.0.0",

},
"gitHead": "5b8ec8d320bb2a171c323702204ce0a47d42fb54"
"gitHead": "87937f313855458c9cb34d72e68bfc4817fd0d93"
}

@@ -15,3 +15,3 @@ # Semantic Dom Diff

```
`semantic-dom-diff` exports a function which takes a string of HTML and returns a string of HTML, restructuring it so that it can be easily compared:
`semantic-dom-diff` allows diffing chunks of dom or HTML for semanticaly equality:
- whitespace and newlines are normalized

@@ -21,87 +21,214 @@ - tags and attributes are printed on individual lines

- style, script and svg contents are removed
- tags, attributes or element's light dom can be ignored through configuration
Additional options can be configured.
## Chai plugin
While `semantic-dom-diff` can be used standalone (see below) you will most commonly use this through our chai plugin.
## Basic usage
<details>
<summary>Registering the plugin</summary>
> If you are using `@open-wc/testing` this is already done for you.
```javascript
import { chai } from '@bundled-es-modules/chai';
import { chaiDomDiff } from '@open-wc/semantic-dom-diff';
chai.use(chaiDomDiff);
```
</details>
### Setting up your dom for diffing
You can set up our chai plugin to diff different types of DOM:
```javascript
import { getDiffableHTML } from '@open-wc/semantic-dom-diff';
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
const leftTree = getDiffableHTML(`
<div>foo</div>
`);
const rightTree = getDiffableHTML(`
<div>bar</div>
`);
connectedCallback() {
this.shadowRoot.innerHTML = '<p> shadow content </p>';
}
}
// use any string comparison tool, for example chai:
expect(leftTree).to.equal(rightTree);
customElements.define('my-element', MyElement);
it('my test', async () => {
const el = await fixture(`
<my-element>
<div> light dom content </div>
</my-element>
`);
expect(el).dom // dom is <my-element><div>light dom content</div></my-element>
expect(el).lightDom // dom is <div>light dom content</div>
expect(el).shadowDom // dom is <p>shadow content</p>
});
```
## Ignoring tags and attributes
When working with libraries or custom elements there might be parts of the rendered HTML which is random or otherwise outside of your control. In those cases, you might want to ignore certain attributes or tags entirely. This is possible by passing an options object.
### Manual diffing
You can use the chai plugin to manually diff chunks of dom. The dom is diffed semantically: whitespace, newlines etc. are normalized.
### Ignoring an attribute
```javascript
import { getDiffableHTML } from '@open-wc/semantic-dom-diff';
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
const leftTree = getDiffableHTML(`
<div data-my-attribute="someRandomlyGeneratedDataInAnAttribute">
foo
</div>
`, { ignoreAttributes: ['data-my-attribute'] });
connectedCallback() {
this.shadowRoot.innerHTML = '<p> shadow content </p>';
}
}
const rightTree = getDiffableHTML(`
<div>
foo
</div>
`);
customElements.define('my-element', MyElement);
// this test will pass, the attribute is ignored
expect(leftTree).to.equal(rightTree);
it('my test', async () => {
const el = await fixture(`
<my-element>
<div> light dom content </div>
</my-element>
`);
expect(el).dom.to.equal('<my-element><div>light dom content</div></my-element>');
expect(el).lightDom.to.equal('<div>light dom content</div>');
expect(el).shadowDom.to.equal('<p>shadow content</p>');
});
```
### Ignoring an attribute only for certain tags
Randomly generated ids are often used, throwing off your diffs. You can ignore attributes on specific tags:
```javascript
import { getDiffableHTML } from '@open-wc/semantic-dom-diff';
### Snapshot testing
The most powerful feature of `semantic-dom-diff` is the ability to test and manage snapshots of your web components.
const leftTree = getDiffableHTML(`
<div>
<input id="someRandomlyGeneratedId">
</div>
`, { ignoreAttributes: [{ tags: ['input'], attributs: ['id'] }] });
> If you are not using `@open-wc/testing-karma`, you need to manually install [karma-snapshot](https://www.npmjs.com/package/karma-snapshot) and [karma-mocha-snapshot](https://www.npmjs.com/package/karma-mocha-snapshot).
const rightTree = getDiffableHTML(`
<div>
<input>
</div>
`);
#### Setting up a snapshot
// this test will pass, the id attribute is ignored
expect(leftTree).to.equal(rightTree);
Snapshots are created by setting up your component in a specific state, and then calling `.to.equalSnapshot()`. You can use `.dom`, `.lightDom` or `.shadowDom` to set up the dom of your element:
```js
import { fixture } from '@open-wc/testing';
describe('my-message', () => {
it('renders message foo correctly', () => {
const element = await fixture(`
<my-message message="Foo"></my-element>
`);
expect(element).shadowDom.to.equalSnapshot();
});
it('renders message bar correctly', () => {
const element = await fixture(`
<my-message message="Bar"></my-element>
`);
expect(element).shadowDom.to.equalSnapshot();
});
it('renders a capitalized message correctly', () => {
const element = await fixture(`
<my-message message="Bar" capitalized></my-element>
`);
expect(element).shadowDom.to.equalSnapshot();
});
it('allows rendering a message from a slot', () => {
const element = await fixture(`
<my-message capitalized>Bar</my-element>
`);
expect(element).lightDom.to.equalSnapshot();
});
});
```
### Ignoring a tag
Similarly you can tell the diff to ignore certain tags entirely:
Snapshots are stored in the `__snapshots__` folder in your project, using the most top level `describe` as the name for your snapshots file.
#### Updating a snapshot
> If you are not using the standard `@open-wc/testing-karma` configuration, see the documentation of `karma-snapshot` how to pass the update/prune flags.
When your tests run for the first time the snapshot files are generated. On subsequent test runs your element is compared with the stored snapshots. If the element and the snapshots differ the test fails.
If the difference was an intended change, you can update the snapshots by passing the `--update-snapshots` flag.
#### Cleaning up unused snapshots
After refactoring there might be leftover snapshot files which are unused. You can run karma with the `--prune-snapshots` flag to clean these up.
**Ignoring tags and attributes**
When working with libraries or custom elements there might be parts of the rendered dom which is random or otherwise outside of your control. In those cases, you might want to ignore certain attributes or tags entirely. This is possible by passing an options object.
```javascript
import { getDiffableHTML } from '@open-wc/semantic-dom-diff';
it('renders correctly', async () => {
const el = await fixture(`
<div my-random-attribute="${Math.random()}">
Hey
</div>
`);
expect(el).dom.to.equal('<div>Hey</div>', {
ignoreAttributes: ['my-random-attribute']
});
const leftTree = getDiffableHTML(`
<div>
<my-custom-element><my-custom-element>
foo
</div>
`, { ignoreTags: ['my-custom-element'] });
expect(el).dom.to.equalSnapshot({
ignoreAttributes: ['my-random-attribute']
});
});
```
const rightTree = getDiffableHTML(`
<div>
foo
</div>
`);
**Ignoring an attribute only for certain tags**
// this test will pass, the tag is ignored completely
expect(leftTree).to.equal(rightTree);
Randomly generated ids are often used, throwing off your diffs. You can ignore attributes on specific tags:
```javascript
it('renders correctly', async () => {
const el = await fixture(`
<input id="customInput${Math.random()}">
`);
// ignore id attributes on input elements
expect(el).dom.to.equal('<div>Hey</div>', {
ignoreAttributes: [
{ tags: ['input'], attributs: ['id'] }
]
});
expect(el).dom.to.equalSnapshot({
ignoreAttributes: [
{ tags: ['input'], attributs: ['id'] }
]
});
});
```
### Ignoring children
**Ignoring tags**
You can tell the diff to ignore certain tags entirely:
```javascript
it('renders correctly', async () => {
const el = await fixture(`
<div>
<my-custom-element></my-custom-element>
foo
</div>
`);
// ignore id attributes on input elements
expect(el).dom.to.equal('<div>Hey</div>', {
ignoreTags: ['my-custom-element']
});
expect(el).dom.to.equalSnapshot({
ignoreTags: ['my-custom-element']
});
});
```
**Ignoring children**
When working with web components you may find that they sometimes render to their light dom, for example to meet some accessibility requirements. We don't want to ignore the tag completely, as we would then not be able to test if we did render the tag.

@@ -112,24 +239,25 @@

```javascript
import { getDiffableHTML } from '@open-wc/semantic-dom-diff';
it('renders correctly', async () => {
const el = await fixture(`
<div>
<my-custom-input id="myInput">
<input id="inputRenderedInLightDom">
Some text rendered in the light dom
</my-custom-input>
foo
</div>
`);
const leftTree = getDiffableHTML(`
<div>
<my-custom-input id="myInput">
<input id="inputRenderedInLightDom">
Some text rendered in the light dom
</my-custom-input>
foo
</div>
`, { ignoreChildren: ['my-custom-element'] });
// ignore id attributes on input elements
expect(el).dom.to.equal(`
<div>
<my-custom-input id="myInput"></my-custom-input>
foo
</div>
`, { ignoreChildren: ['my-custom-element'] });
const rightTree = getDiffableHTML(`
<div>
<my-custom-input id="myInput"></my-custom-input>
foo
</div>
`);
// this test will pass, the light dom of my-custom-input is ignored, but we can still test
// to see if the tag is placed properly
expect(leftTree).to.equal(rightTree);
expect(el).dom.to.equalSnapshot({
ignoreChildren: ['my-custom-element']
});
});
```

@@ -136,0 +264,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc