mirror of
https://github.com/jlengrand/open-wc.git
synced 2026-03-10 08:31:19 +00:00
feat(semantic-dom-diff): add support for snapshot testing
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -32,3 +32,6 @@ dist
|
||||
build-stats.json
|
||||
stats.html
|
||||
.rpt2_cache
|
||||
|
||||
##
|
||||
packages/**/__snapshots__
|
||||
13
__snapshots__/BDD.md
Normal file
13
__snapshots__/BDD.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# `BDD`
|
||||
|
||||
#### `uses chai dom equals plugin snapshot`
|
||||
|
||||
```html
|
||||
<div>
|
||||
<h1>
|
||||
Hey
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
51
__snapshots__/component-a.md
Normal file
51
__snapshots__/component-a.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# `component-a`
|
||||
|
||||
## `success states`
|
||||
|
||||
#### `matches a string snapshot`
|
||||
|
||||
```html
|
||||
<div>
|
||||
A
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
#### `matches a dom element snapshot`
|
||||
|
||||
```html
|
||||
<div>
|
||||
B
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
#### `matches a dom element snapshot, using .dom`
|
||||
|
||||
```html
|
||||
<div>
|
||||
C
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
## `error states`
|
||||
|
||||
#### `matches a lightdom snapshot`
|
||||
|
||||
```html
|
||||
<span>
|
||||
A
|
||||
</span>
|
||||
|
||||
```
|
||||
|
||||
#### `matches shadow dom snapshot`
|
||||
|
||||
```html
|
||||
<span>
|
||||
B
|
||||
</span>
|
||||
|
||||
```
|
||||
|
||||
24
__snapshots__/component-b.md
Normal file
24
__snapshots__/component-b.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# `component-b`
|
||||
|
||||
## `success states`
|
||||
|
||||
#### `can ignore attributes`
|
||||
|
||||
```html
|
||||
<div>
|
||||
A
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
## `error states`
|
||||
|
||||
#### `can ignore tags`
|
||||
|
||||
```html
|
||||
<div>
|
||||
A
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
"site:start": "npm run vuepress:start",
|
||||
"test": "karma start --coverage",
|
||||
"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:ci": "lerna run test:ci",
|
||||
"test:legacy": "karma start --legacy --coverage",
|
||||
"test:bs": "karma start karma.bs.conf.js --legacy --coverage",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @ts-nocheck
|
||||
|
||||
const resolve = require('rollup-plugin-node-resolve');
|
||||
const { terser } = require('rollup-plugin-terser');
|
||||
const babel = require('rollup-plugin-babel');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @ts-nocheck
|
||||
|
||||
const resolve = require('rollup-plugin-node-resolve');
|
||||
const { terser } = require('rollup-plugin-terser');
|
||||
const babel = require('rollup-plugin-babel');
|
||||
|
||||
@@ -2,72 +2,7 @@
|
||||
|
||||
[//]: # (AUTO INSERT HEADER PREPUBLISH)
|
||||
|
||||
`chai-dom-test` enables you to easily test the rendered dom of test fixture against a snapshot. It integrates [semantic-dom-diff](https://www.npmjs.com/package/@open-wc/semantic-dom-diff) with chai.
|
||||
|
||||
## Manual Setup
|
||||
|
||||
Add the following after chai is loaded
|
||||
|
||||
```js
|
||||
import { chai } from '@bundled-es-modules/chai';
|
||||
import { chaiDomEquals } from '@open-wc/chai-dom-equals';
|
||||
|
||||
chai.use(chaiDomEquals);
|
||||
```
|
||||
|
||||
## Test dom of an element
|
||||
```js
|
||||
it('has the following dom', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).dom.to.equal('<div><h1>Hey</h1></div>');
|
||||
});
|
||||
```
|
||||
|
||||
## Test shadow dom of an element
|
||||
```js
|
||||
it('has the following shadow dom', async () => {
|
||||
const tag = defineCE(class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.shadowRoot.innerHTML = '<p> shadow content</p> <!-- comment --> <slot></slot>';
|
||||
}
|
||||
});
|
||||
const el = await fixture(`<${tag}></${tag}>`);
|
||||
expect(el).shadowDom.to.equal('<p>shadow content</p><slot>');
|
||||
});
|
||||
```
|
||||
|
||||
## Literal matching
|
||||
By default dom is diffed 'semantically'. Differences in whitespace, newlines, attributes/class order are ignored and style, script and comment nodes are removed.
|
||||
|
||||
If you want to match literally instead you can use some of the provided utilities to handle diffing on browsers with the shadow dom polyfill:
|
||||
|
||||
```javascript
|
||||
import { getOuterHtml, getCleanedShadowDom } from '@open-wc/chai-dom-equals';
|
||||
|
||||
it('literally equals', () => {
|
||||
const tag = defineCE(class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.shadowRoot.innerHTML = '<p> shadow content</p> <!-- comment --> <slot></slot>';
|
||||
}
|
||||
});
|
||||
const el = await fixture(`<${tag}></${tag}>`);
|
||||
const outerHTML = getOuterHtml(el);
|
||||
const innerHTML = getCleanedShadowDom(el);
|
||||
|
||||
expect(outerHTML).to.equal(`<${tag}></${tag}>`);
|
||||
expect(innerHTML).to.equal('<p> shadow content</p> <!-- comment --> <slot></slot>');
|
||||
});
|
||||
```
|
||||
> Note: this package is deprecated, usage `@open-wc/semantic-dom-diff` which exposes a chai plugin now.
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="../../../mocha/mocha.css" rel="stylesheet" />
|
||||
<script src="../../../mocha/mocha.js"></script>
|
||||
<script src="../../../@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script>
|
||||
mocha.setup('bdd');
|
||||
</script>
|
||||
|
||||
<script type="module">
|
||||
import './chai-dom-equals.test.js';
|
||||
|
||||
mocha.checkLeaks();
|
||||
mocha.run();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2,6 +2,8 @@
|
||||
"scripts": {
|
||||
"test": "karma start --coverage",
|
||||
"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",
|
||||
"test:legacy:watch": "karma start --legacy --auto-watch=true --single-run=false"
|
||||
},
|
||||
|
||||
@@ -6,123 +6,251 @@
|
||||
```bash
|
||||
yarn add @open-wc/semantic-dom-diff --dev
|
||||
```
|
||||
`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
|
||||
- tags and attributes are printed on individual lines
|
||||
- comments are removed
|
||||
- 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.
|
||||
|
||||
<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:
|
||||
|
||||
## Basic usage
|
||||
```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
|
||||
### Snapshot testing
|
||||
The most powerful feature of `semantic-dom-diff` is the ability to test and manage snapshots of your web components.
|
||||
|
||||
> 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).
|
||||
|
||||
#### Setting up a snapshot
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
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
|
||||
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']
|
||||
});
|
||||
|
||||
expect(el).dom.to.equalSnapshot({
|
||||
ignoreAttributes: ['my-random-attribute']
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**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';
|
||||
it('renders correctly', async () => {
|
||||
const el = await fixture(`
|
||||
<input id="customInput${Math.random()}">
|
||||
`);
|
||||
|
||||
const leftTree = getDiffableHTML(`
|
||||
<div>
|
||||
<input id="someRandomlyGeneratedId">
|
||||
</div>
|
||||
`, { ignoreAttributes: [{ tags: ['input'], attributs: ['id'] }] });
|
||||
// ignore id attributes on input elements
|
||||
expect(el).dom.to.equal('<div>Hey</div>', {
|
||||
ignoreAttributes: [
|
||||
{ tags: ['input'], attributs: ['id'] }
|
||||
]
|
||||
});
|
||||
|
||||
const rightTree = getDiffableHTML(`
|
||||
<div>
|
||||
<input>
|
||||
</div>
|
||||
`);
|
||||
|
||||
// this test will pass, the id attribute is ignored
|
||||
expect(leftTree).to.equal(rightTree);
|
||||
expect(el).dom.to.equalSnapshot({
|
||||
ignoreAttributes: [
|
||||
{ tags: ['input'], attributs: ['id'] }
|
||||
]
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Ignoring a tag
|
||||
Similarly you can tell the diff to ignore certain tags entirely:
|
||||
**Ignoring tags**
|
||||
|
||||
You can tell the diff to ignore certain tags entirely:
|
||||
|
||||
```javascript
|
||||
import { getDiffableHTML } from '@open-wc/semantic-dom-diff';
|
||||
it('renders correctly', async () => {
|
||||
const el = await fixture(`
|
||||
<div>
|
||||
<my-custom-element></my-custom-element>
|
||||
foo
|
||||
</div>
|
||||
`);
|
||||
|
||||
const leftTree = getDiffableHTML(`
|
||||
<div>
|
||||
<my-custom-element><my-custom-element>
|
||||
foo
|
||||
</div>
|
||||
`, { ignoreTags: ['my-custom-element'] });
|
||||
// ignore id attributes on input elements
|
||||
expect(el).dom.to.equal('<div>Hey</div>', {
|
||||
ignoreTags: ['my-custom-element']
|
||||
});
|
||||
|
||||
const rightTree = getDiffableHTML(`
|
||||
<div>
|
||||
foo
|
||||
</div>
|
||||
`);
|
||||
|
||||
// this test will pass, the tag is ignored completely
|
||||
expect(leftTree).to.equal(rightTree);
|
||||
expect(el).dom.to.equalSnapshot({
|
||||
ignoreTags: ['my-custom-element']
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Ignoring children
|
||||
**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.
|
||||
|
||||
We can ignore just it's light dom:
|
||||
|
||||
```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']
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
<script>
|
||||
|
||||
112
packages/semantic-dom-diff/chai-dom-diff.js
Normal file
112
packages/semantic-dom-diff/chai-dom-diff.js
Normal file
@@ -0,0 +1,112 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { getDiffableHTML } from './get-diffable-html.js';
|
||||
import { getOuterHtml, getCleanedShadowDom, snapshotPath } from './src/utils.js';
|
||||
|
||||
/**
|
||||
* @param {any} chai
|
||||
* @param {any} utils
|
||||
*/
|
||||
export const chaiDomDiff = (chai, utils) => {
|
||||
/**
|
||||
* can not be an arrow function as it gets rebound by chai
|
||||
*/
|
||||
chai.Assertion.addProperty('lightDom', function lightDom() {
|
||||
new chai.Assertion(this._obj.nodeType).to.equal(1);
|
||||
utils.flag(this, 'lightDom', true);
|
||||
});
|
||||
|
||||
/**
|
||||
* can not be an arrow function as it gets rebound by chai
|
||||
*/
|
||||
chai.Assertion.addProperty('shadowDom', function shadowDom() {
|
||||
new chai.Assertion(this._obj.nodeType).to.equal(1);
|
||||
utils.flag(this, 'shadowDom', true);
|
||||
});
|
||||
|
||||
/**
|
||||
* can not be an arrow function as it gets rebound by chai
|
||||
*/
|
||||
chai.Assertion.addProperty('dom', function dom() {
|
||||
new chai.Assertion(this._obj.nodeType).to.equal(1);
|
||||
utils.flag(this, 'dom', true);
|
||||
});
|
||||
|
||||
const domEquals = _super =>
|
||||
function handleDom(value, ...args) {
|
||||
if (utils.flag(this, 'shadowDom')) {
|
||||
const expectedHTML = getDiffableHTML(value, args[0]);
|
||||
const actualHTML = getDiffableHTML(getCleanedShadowDom(this._obj), args[0]);
|
||||
|
||||
// use chai's built-in string comparison, log the updated snapshot on error
|
||||
new chai.Assertion(actualHTML).to.equal(expectedHTML);
|
||||
} else if (utils.flag(this, 'lightDom')) {
|
||||
const expectedHTML = getDiffableHTML(value, args[0]);
|
||||
const actualHTML = getDiffableHTML(this._obj.innerHTML, args[0]);
|
||||
|
||||
// use chai's built-in string comparison, log the updated snapshot on error
|
||||
new chai.Assertion(actualHTML).to.equal(expectedHTML);
|
||||
} else if (utils.flag(this, 'dom')) {
|
||||
const expectedHTML = getDiffableHTML(value, args[0]);
|
||||
const actualHTML = getDiffableHTML(getOuterHtml(this._obj), args[0]);
|
||||
|
||||
// use chai's built-in string comparison, log the updated snapshot on error
|
||||
new chai.Assertion(actualHTML).to.equal(expectedHTML);
|
||||
} else {
|
||||
_super.apply(this, [value, ...args]);
|
||||
}
|
||||
};
|
||||
|
||||
chai.Assertion.overwriteMethod('equals', domEquals);
|
||||
chai.Assertion.overwriteMethod('equal', domEquals);
|
||||
chai.Assertion.overwriteMethod('eq', domEquals);
|
||||
|
||||
const context = window.__mocha_context__;
|
||||
const snapshotState = window.__snapshot__;
|
||||
|
||||
function equalSnapshot(options) {
|
||||
const object = chai.util.flag(this, 'object');
|
||||
const { index } = context;
|
||||
context.index += 1;
|
||||
let dom;
|
||||
let path;
|
||||
|
||||
if (utils.flag(this, 'shadowDom')) {
|
||||
dom = getCleanedShadowDom(object);
|
||||
} else if (utils.flag(this, 'lightDom')) {
|
||||
dom = object.innerHTML;
|
||||
} else {
|
||||
dom = object;
|
||||
}
|
||||
const html = getDiffableHTML(dom, options);
|
||||
|
||||
if (context.runnable.type === 'hook') {
|
||||
path = snapshotPath(context.runnable.ctx.currentTest);
|
||||
} else {
|
||||
path = snapshotPath(context.runnable);
|
||||
}
|
||||
|
||||
if (snapshotState.update) {
|
||||
snapshotState.set(path, index, html, 'html');
|
||||
} else {
|
||||
const snapshot = snapshotState.get(path, index);
|
||||
|
||||
if (!snapshot) {
|
||||
snapshotState.set(path, index, html, 'html');
|
||||
} else if (!snapshotState.match(html, getDiffableHTML(snapshot.code, options))) {
|
||||
/* istanbul ignore next */
|
||||
throw new chai.AssertionError(
|
||||
`Received value does not match stored snapshot ${index}`,
|
||||
{
|
||||
actual: html,
|
||||
expected: snapshot.code,
|
||||
showDiff: true,
|
||||
},
|
||||
chai.util.flag(this, 'ssfi'),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.addMethod(chai.Assertion.prototype, 'equalSnapshot', equalSnapshot);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
const DEFAULT_IGNORE_CHILDREN = ['script', 'style', 'svg'];
|
||||
const DEFAULT_IGNORE_TAGS = ['script', 'style', 'svg'];
|
||||
const VOID_ELEMENTS = [
|
||||
'area',
|
||||
'base',
|
||||
@@ -52,7 +52,7 @@ const VOID_ELEMENTS = [
|
||||
* // use regular string comparison to spot the differences
|
||||
* expect(htmlA).to.equal(htmlB);
|
||||
*
|
||||
* @param {string} html
|
||||
* @param {Node | string} html
|
||||
* @param {DiffOptions} [options]
|
||||
* @returns {string} html restructured in a diffable format
|
||||
*/
|
||||
@@ -63,8 +63,8 @@ export function getDiffableHTML(html, options = {}) {
|
||||
const ignoreAttributesForTags = /** @type {IgnoreAttributesForTags[]} */ (options.ignoreAttributes
|
||||
? options.ignoreAttributes.filter(e => typeof e !== 'string')
|
||||
: []);
|
||||
const ignoreTags = options.ignoreTags || [];
|
||||
const ignoreChildren = [...(options.ignoreChildren || []), ...DEFAULT_IGNORE_CHILDREN];
|
||||
const ignoreTags = [...(options.ignoreTags || []), ...DEFAULT_IGNORE_TAGS];
|
||||
const ignoreChildren = options.ignoreChildren || [];
|
||||
|
||||
let text = '';
|
||||
let depth = -1;
|
||||
@@ -199,8 +199,18 @@ export function getDiffableHTML(html, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
container,
|
||||
|
||||
@@ -5,3 +5,5 @@ export {
|
||||
// backwards compatible export
|
||||
getDiffableHTML as getDiffableSemanticHTML,
|
||||
};
|
||||
|
||||
export { chaiDomDiff } from './chai-dom-diff';
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
"scripts": {
|
||||
"test": "karma start --coverage",
|
||||
"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",
|
||||
"test:legacy:watch": "karma start --legacy --auto-watch=true --single-run=false",
|
||||
"test:bs": "karma start karma.bs.conf.js --legacy --coverage",
|
||||
@@ -31,6 +33,7 @@
|
||||
"@open-wc/testing-karma": "^1.0.2",
|
||||
"@open-wc/testing-karma-bs": "^1.0.2",
|
||||
"@open-wc/testing-wallaby": "^0.1.12",
|
||||
"@open-wc/testing-helpers": "^0.8.5",
|
||||
"mocha": "^5.0.0",
|
||||
"webpack-merge": "^4.1.5"
|
||||
}
|
||||
|
||||
56
packages/semantic-dom-diff/src/utils.js
Normal file
56
packages/semantic-dom-diff/src/utils.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// @ts-nocheck
|
||||
|
||||
/**
|
||||
* el.outerHTML is not polyfilled so we need to recreate the tag + attributes and
|
||||
* combine it with el.innerHTML.
|
||||
*
|
||||
* @param {Element} el Element you want to get the out Html from
|
||||
* @returns {String} outer html
|
||||
*/
|
||||
export const getOuterHtml = el => {
|
||||
/* istanbul ignore next */
|
||||
if (window.ShadyCSS && window.ShadyCSS.nativeShadow === false) {
|
||||
const tagName = el.tagName.toLowerCase();
|
||||
let attributes = ' ';
|
||||
Array.prototype.slice.call(el.attributes).forEach(item => {
|
||||
attributes += `${item.name}="${item.value}" `;
|
||||
});
|
||||
// removes last ' ' or if there are no attributes makes it to equal ''
|
||||
attributes = attributes.slice(0, -1);
|
||||
return `<${tagName}${attributes}>${el.innerHTML}</${tagName}>`;
|
||||
}
|
||||
return el.outerHTML;
|
||||
};
|
||||
|
||||
/**
|
||||
* For comparision we do not need the style scoping classes on polyfilled browsers
|
||||
* Rather naive approach for now - probably need to improve once we have failing cases.
|
||||
*
|
||||
* @param {Element} el Element you want to get the cleaned shadow dom
|
||||
* @returns {String} cleaned shadow dom
|
||||
*/
|
||||
export const getCleanedShadowDom = el => {
|
||||
/* istanbul ignore next */
|
||||
if (window.ShadyCSS && window.ShadyCSS.nativeShadow === false) {
|
||||
const tagName = el.tagName.toLowerCase();
|
||||
const regexTagName = new RegExp(tagName, 'g');
|
||||
let domString = el.shadowRoot.innerHTML;
|
||||
domString = domString.replace(/style-scope/g, ''); // remove style-scope class
|
||||
domString = domString.replace(regexTagName, ''); // remove scoped class name
|
||||
domString = domString.replace(/(class=".*?)(\s)*"/g, '$1"'); // remove trailing spaces in class=" "
|
||||
domString = domString.replace(/ class="\w?"/g, ''); // remove empty class attributes
|
||||
return domString;
|
||||
}
|
||||
return el.shadowRoot.innerHTML;
|
||||
};
|
||||
|
||||
export function snapshotPath(rootNode) {
|
||||
const path = [];
|
||||
let node = rootNode;
|
||||
|
||||
while (node && node.parent) {
|
||||
path.push(node.title);
|
||||
node = node.parent;
|
||||
}
|
||||
return path.reverse();
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
/* istanbul ignore next */
|
||||
// do manual setup and not use testing to not have circle dependencies
|
||||
import { chai } from '@bundled-es-modules/chai';
|
||||
import { cachedWrappers } from '@open-wc/testing-helpers/index-no-side-effects.js';
|
||||
import { chaiDomEquals } from '../chai-dom-equals.js';
|
||||
import { chaiDomDiff } from '../chai-dom-diff.js';
|
||||
|
||||
// register-cleanup
|
||||
if (afterEach) {
|
||||
@@ -16,4 +17,4 @@ if (afterEach) {
|
||||
}
|
||||
|
||||
// register-plugins
|
||||
chai.use(chaiDomEquals);
|
||||
chai.use(chaiDomDiff);
|
||||
@@ -0,0 +1,68 @@
|
||||
import { expect } from '@bundled-es-modules/chai';
|
||||
import './bdd-setup.js';
|
||||
|
||||
customElements.define(
|
||||
'snapshotted-element',
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.shadowRoot.innerHTML = '<span>B</span>';
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
describe('component-a', () => {
|
||||
describe('success states', () => {
|
||||
it('matches a string snapshot', () => {
|
||||
expect('<div>A</div>').to.equalSnapshot();
|
||||
});
|
||||
|
||||
it('matches a dom element snapshot', () => {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = 'B';
|
||||
expect(div).to.equalSnapshot();
|
||||
});
|
||||
|
||||
it('matches a dom element snapshot, using .dom', () => {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = 'C';
|
||||
expect(div).dom.to.equalSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('error states', () => {
|
||||
it('matches a lightdom snapshot', () => {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = '<span>A</span>';
|
||||
expect(div).lightDom.to.equalSnapshot();
|
||||
});
|
||||
|
||||
it('matches shadow dom snapshot', () => {
|
||||
const myElement = document.createElement('snapshotted-element');
|
||||
document.body.appendChild(myElement);
|
||||
expect(myElement).shadowDom.to.equalSnapshot();
|
||||
myElement.parentElement.removeChild(myElement);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('component-b', () => {
|
||||
describe('success states', () => {
|
||||
it('can ignore attributes', () => {
|
||||
expect(`<div random-attribute="${Math.random()}">A</div>`).to.equalSnapshot({
|
||||
ignoreAttributes: ['random-attribute'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('error states', () => {
|
||||
it('can ignore tags', () => {
|
||||
expect(`<div>A</div><span>B</span>`).to.equalSnapshot({ ignoreTags: ['span'] });
|
||||
});
|
||||
});
|
||||
});
|
||||
47
packages/semantic-dom-diff/test/chai-dom-equals.test.js
Normal file
47
packages/semantic-dom-diff/test/chai-dom-equals.test.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { expect } from '@bundled-es-modules/chai';
|
||||
import './bdd-setup.js';
|
||||
import { fixture, defineCE } from '@open-wc/testing-helpers';
|
||||
|
||||
describe('dom', () => {
|
||||
it('can compare dom nodes', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).dom.to.equal('<div><h1>Hey</h1></div>');
|
||||
});
|
||||
|
||||
it('passes along provided configuration', async () => {
|
||||
const el = await fixture('<div foo="bar"></div>');
|
||||
expect(el).dom.to.equal('<div></div>', { ignoreAttributes: ['foo'] });
|
||||
});
|
||||
});
|
||||
|
||||
describe('lightDom', () => {
|
||||
it('can compare lightDom nodes', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).lightDom.to.equal('<h1>Hey</h1>');
|
||||
});
|
||||
|
||||
it('passes along provided configuration', async () => {
|
||||
const el = await fixture('<div><p foo="bar">foo</p></div>');
|
||||
expect(el).lightDom.to.equal('<p>foo</p>', { ignoreAttributes: ['foo'] });
|
||||
});
|
||||
});
|
||||
|
||||
describe('shadowDom', () => {
|
||||
it('can compare shadow dom nodes', async () => {
|
||||
const tag = defineCE(
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.shadowRoot.innerHTML = '<p> shadow content</p> <!-- comment --> <slot></slot>';
|
||||
}
|
||||
},
|
||||
);
|
||||
const el = await fixture(`<${tag}><span> light content </span></${tag}>`);
|
||||
expect(el).dom.to.equal(`<${tag}><span>light content</span></${tag}>`);
|
||||
expect(el).shadowDom.to.equal('<p>shadow content</p><slot>');
|
||||
});
|
||||
});
|
||||
@@ -387,7 +387,7 @@ describe('getDiffableHTML()', () => {
|
||||
});
|
||||
|
||||
describe('non-HTML elements', () => {
|
||||
it('does not sprint script content, but preserves attributes', () => {
|
||||
it('does not print script tags', () => {
|
||||
const html = getDiffableHTML(`
|
||||
<div>pre</div>
|
||||
<script>
|
||||
@@ -397,23 +397,11 @@ describe('getDiffableHTML()', () => {
|
||||
<div>post</div>
|
||||
`);
|
||||
expect(html).to.equal(
|
||||
'<div>\n' +
|
||||
' pre\n' +
|
||||
'</div>\n' +
|
||||
'<script>\n' +
|
||||
'</script>\n' +
|
||||
'<script\n' +
|
||||
' src="./foo.js"\n' +
|
||||
' type="module"\n' +
|
||||
'>\n' +
|
||||
'</script>\n' +
|
||||
'<div>\n' +
|
||||
' post\n' +
|
||||
'</div>\n',
|
||||
'<div>\n' + ' pre\n' + '</div>\n' + '<div>\n' + ' post\n' + '</div>\n',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not sprint style content, but preserves attributes', () => {
|
||||
it('does not print styles', () => {
|
||||
const html = getDiffableHTML(`
|
||||
<div>pre</div>
|
||||
<style scope="foo">
|
||||
@@ -422,18 +410,11 @@ describe('getDiffableHTML()', () => {
|
||||
<div>post</div>
|
||||
`);
|
||||
expect(html).to.equal(
|
||||
'<div>\n' +
|
||||
' pre\n' +
|
||||
'</div>\n' +
|
||||
'<style scope="foo">\n' +
|
||||
'</style>\n' +
|
||||
'<div>\n' +
|
||||
' post\n' +
|
||||
'</div>\n',
|
||||
'<div>\n' + ' pre\n' + '</div>\n' + '<div>\n' + ' post\n' + '</div>\n',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not sprint svg content, but preserves attributes', () => {
|
||||
it('does not print svg', () => {
|
||||
const html = getDiffableHTML(`
|
||||
<div>pre</div>
|
||||
<svg height="80" width="300" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
@@ -449,18 +430,7 @@ describe('getDiffableHTML()', () => {
|
||||
<div>post</div>
|
||||
`);
|
||||
expect(html).to.equal(
|
||||
'<div>\n' +
|
||||
' pre\n' +
|
||||
'</div>\n' +
|
||||
'<svg\n' +
|
||||
' height="80"\n' +
|
||||
' width="300"\n' +
|
||||
' xmlns:xlink="http://www.w3.org/1999/xlink"\n' +
|
||||
'>\n' +
|
||||
'</svg>\n' +
|
||||
'<div>\n' +
|
||||
' post\n' +
|
||||
'</div>\n',
|
||||
'<div>\n' + ' pre\n' + '</div>\n' + '<div>\n' + ' post\n' + '</div>\n',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -783,4 +753,26 @@ describe('getDiffableHTML()', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('dom node as input', () => {
|
||||
const node = document.createElement('div');
|
||||
node.setAttribute('id', 'foo');
|
||||
node.innerHTML = `
|
||||
<span>A</span>
|
||||
<span>B</span>
|
||||
`;
|
||||
|
||||
const html = getDiffableHTML(node);
|
||||
|
||||
expect(html).to.equal(
|
||||
'<div id="foo">\n' +
|
||||
' <span>\n' +
|
||||
' A\n' +
|
||||
' </span>\n' +
|
||||
' <span>\n' +
|
||||
' B\n' +
|
||||
' </span>\n' +
|
||||
'</div>\n',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import './bdd-setup.js';
|
||||
import { expect } from '@bundled-es-modules/chai';
|
||||
import { fixture, defineCE } from '@open-wc/testing-helpers';
|
||||
import { getOuterHtml, getCleanedShadowDom } from '../index.js';
|
||||
import '../bdd-setup.js';
|
||||
import { getOuterHtml, getCleanedShadowDom } from '../../src/utils.js';
|
||||
|
||||
describe('getOuterHtml', () => {
|
||||
it('support el.outerHTML also on polyfilled browsers', async () => {
|
||||
@@ -150,75 +150,3 @@ describe('getCleanedShadowDom', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dom', () => {
|
||||
it('can compare dom nodes', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).dom.to.equal('<div><h1>Hey</h1></div>');
|
||||
});
|
||||
|
||||
it('passes along provided configuration', async () => {
|
||||
const el = await fixture('<div foo="bar"></div>');
|
||||
expect(el).dom.to.equal('<div></div>', { ignoreAttributes: ['foo'] });
|
||||
});
|
||||
|
||||
it('handles .semantically as backwards compatibility', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).dom.to.semantically.equal('<div><h1>Hey</h1></div>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lightDom', () => {
|
||||
it('can compare lightDom nodes', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).lightDom.to.equal('<h1>Hey</h1>');
|
||||
});
|
||||
|
||||
it('passes along provided configuration', async () => {
|
||||
const el = await fixture('<div><p foo="bar">foo</p></div>');
|
||||
expect(el).lightDom.to.equal('<p>foo</p>', { ignoreAttributes: ['foo'] });
|
||||
});
|
||||
|
||||
it('handles .semantically as backwards compatibility', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).lightDom.to.semantically.equal('<h1>Hey</h1>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('shadowDom', () => {
|
||||
it('can compare shadow dom nodes', async () => {
|
||||
const tag = defineCE(
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.shadowRoot.innerHTML = '<p> shadow content</p> <!-- comment --> <slot></slot>';
|
||||
}
|
||||
},
|
||||
);
|
||||
const el = await fixture(`<${tag}><span> light content </span></${tag}>`);
|
||||
expect(el).dom.to.equal(`<${tag}><span>light content</span></${tag}>`);
|
||||
expect(el).shadowDom.to.equal('<p>shadow content</p><slot>');
|
||||
});
|
||||
|
||||
it('supports .semantically as backwards compatibility', async () => {
|
||||
const tag = defineCE(
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.shadowRoot.innerHTML = '<p> shadow content</p> <!-- comment --> <slot></slot>';
|
||||
}
|
||||
},
|
||||
);
|
||||
const el = await fixture(`<${tag}><span> light content </span></${tag}>`);
|
||||
expect(el).dom.to.semantically.equal(`<${tag}><span>light content</span></${tag}>`);
|
||||
expect(el).shadowDom.to.semantically.equal('<p>shadow content</p><slot>');
|
||||
});
|
||||
});
|
||||
@@ -43,6 +43,8 @@ Commands explained:
|
||||
- `test:watch`: does a single test run, and then re-runs on file changes. coverage is not analyzed for performance. in watch mode you can also debug in the browser, which is very convenient. visit http://localhost:9876/debug.html
|
||||
- `test:legacy`: like `test`, except that it compiles your code to es5 and adds [babel](https://babeljs.io/docs/en/babel-polyfill) and [web component](https://github.com/webcomponents/webcomponentsjs) polyfills for maximum compatibility.
|
||||
- `test:legacy:watch`: like `test:watch`, adding the same mentioned polyfills
|
||||
- `test:update-snapshots`: updates any snapshots files from `@open-wc/semantic-dom-diff`. Use this when your component's rendered HTML changed.
|
||||
- `test:prune-snapshots`: prunes any used snapshots files from `@open-wc/semantic-dom-diff`.
|
||||
|
||||
### Testing single files or folders
|
||||
By default karma runs all your test files. To test a single file or folder, use the `--grep` flag. (If you did a manual setup, makes sure your config handles this flag).
|
||||
@@ -168,7 +170,9 @@ npm i --save @open-wc/testing-karma webpack-merge karma
|
||||
```json
|
||||
"scripts": {
|
||||
"test": "karma start --coverage",
|
||||
"test:watch": "karma start --auto-watch=true --single-run=false"
|
||||
"test:watch": "karma start --auto-watch=true --single-run=false",
|
||||
"test:update-snapshots": "karma start --update-snapshots",
|
||||
"test:prune-snapshots": "karma start --prune-snapshots"
|
||||
},
|
||||
```
|
||||
- If you want to run tests on legacy browsers as well, add these scripts:
|
||||
@@ -176,6 +180,8 @@ npm i --save @open-wc/testing-karma webpack-merge karma
|
||||
"scripts": {
|
||||
"test": "karma start --coverage",
|
||||
"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",
|
||||
"test:legacy:watch": "karma start --legacy --auto-watch=true --single-run=false"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,8 @@ const path = require('path');
|
||||
|
||||
const coverage = process.argv.find(arg => arg.includes('coverage'));
|
||||
const legacy = process.argv.find(arg => arg.includes('legacy'));
|
||||
const updateSnapshots = process.argv.find(arg => arg.includes('update-snapshots'));
|
||||
const pruneSnapshots = process.argv.find(arg => arg.includes('prune-snapshots'));
|
||||
|
||||
/**
|
||||
* Creates a basic karma configuration file.
|
||||
@@ -13,6 +15,7 @@ module.exports = config => ({
|
||||
|
||||
files: legacy
|
||||
? [
|
||||
{ pattern: '__snapshots__/**/*.md' },
|
||||
{ pattern: require.resolve('@babel/polyfill/dist/polyfill.min.js'), watched: false },
|
||||
{
|
||||
pattern: require.resolve('@webcomponents/webcomponentsjs/custom-elements-es5-adapter'),
|
||||
@@ -23,7 +26,7 @@ module.exports = config => ({
|
||||
watched: false,
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
: ['__snapshots__/**/*.md'],
|
||||
|
||||
customLaunchers: {
|
||||
ChromeHeadlessNoSandbox: {
|
||||
@@ -42,13 +45,15 @@ module.exports = config => ({
|
||||
require.resolve('karma-sourcemap-loader'),
|
||||
require.resolve('karma-coverage-istanbul-reporter'),
|
||||
require.resolve('karma-static'),
|
||||
require.resolve('karma-snapshot'),
|
||||
require.resolve('karma-mocha-snapshot'),
|
||||
require.resolve('karma-chrome-launcher'),
|
||||
|
||||
// fallback: resolve any karma- plugins
|
||||
'karma-*',
|
||||
],
|
||||
|
||||
frameworks: ['mocha', 'source-map-support', 'webpack'],
|
||||
frameworks: ['mocha', 'snapshot', 'mocha-snapshot', 'source-map-support', 'webpack'],
|
||||
|
||||
middleware: ['static'],
|
||||
|
||||
@@ -57,6 +62,7 @@ module.exports = config => ({
|
||||
},
|
||||
|
||||
preprocessors: {
|
||||
'**/__snapshots__/**/*.md': ['snapshot'],
|
||||
'**/*.test.js': ['webpack', 'sourcemap'],
|
||||
'**/*.spec.js': ['webpack', 'sourcemap'],
|
||||
},
|
||||
@@ -110,6 +116,14 @@ module.exports = config => ({
|
||||
},
|
||||
},
|
||||
|
||||
snapshot: {
|
||||
update: updateSnapshots,
|
||||
prune: pruneSnapshots,
|
||||
pathResolver(basePath, suiteName) {
|
||||
return path.join(basePath, '__snapshots__', `${suiteName}.md`);
|
||||
},
|
||||
},
|
||||
|
||||
webpack: {
|
||||
devtool: 'inline-cheap-module-source-map',
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
"scripts": {
|
||||
"test": "karma start demo/karma.conf.js --coverage",
|
||||
"test:watch": "karma start demo/karma.conf.js --auto-watch=true --single-run=false",
|
||||
"test:update-snapshots": "karma start demo/karma.conf.js --update-snapshots",
|
||||
"test:prune-snapshots": "karma start demo/karma.conf.js --prune-snapshots",
|
||||
"test:legacy": "karma start demo/karma.conf.js --legacy --coverage",
|
||||
"test:bs": "karma start demo/karma.bs.conf.js --legacy --coverage",
|
||||
"prepublishOnly": "../../scripts/insert-header.js"
|
||||
@@ -40,6 +42,8 @@
|
||||
"karma-coverage-istanbul-reporter": "^2.0.0",
|
||||
"karma-mocha": "^1.0.0",
|
||||
"karma-mocha-reporter": "^2.0.0",
|
||||
"karma-mocha-snapshot": "^0.2.1",
|
||||
"karma-snapshot": "^0.6.0",
|
||||
"karma-source-map-support": "^1.3.0",
|
||||
"karma-sourcemap-loader": "^0.3.0",
|
||||
"karma-static": "^1.0.1",
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
"scripts": {
|
||||
"test": "karma start --coverage",
|
||||
"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",
|
||||
"test:legacy:watch": "karma start --legacy --auto-watch=true --single-run=false",
|
||||
"test:bs": "karma start karma.bs.conf.js --legacy --coverage",
|
||||
@@ -29,6 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@bundled-es-modules/chai": "^4.2.0",
|
||||
"@open-wc/semantic-dom-diff": "^0.9.7",
|
||||
"@open-wc/chai-dom-equals": "^0.10.11",
|
||||
"@open-wc/testing-helpers": "^0.8.5",
|
||||
"@types/chai": "^4.1.7",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { chai } from '@bundled-es-modules/chai';
|
||||
import { chaiDomEquals } from '@open-wc/chai-dom-equals';
|
||||
import { chaiDomDiff } from '@open-wc/semantic-dom-diff';
|
||||
|
||||
chai.use(chaiDomEquals);
|
||||
chai.use(chaiDomDiff);
|
||||
|
||||
@@ -14,4 +14,9 @@ describe('BDD', () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).dom.to.equal('<div><h1>Hey</h1></div>');
|
||||
});
|
||||
|
||||
it('uses chai dom equals plugin snapshot', async () => {
|
||||
const el = await fixture(`<div><!-- comment --><h1>${'Hey'} </h1> </div>`);
|
||||
expect(el).dom.to.equalSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user