mirror of
https://github.com/jlengrand/open-wc.git
synced 2026-03-10 08:31:19 +00:00
242 lines
7.8 KiB
JavaScript
242 lines
7.8 KiB
JavaScript
/* eslint-disable no-param-reassign */
|
|
|
|
import { getDiffableHTML, isDiffOptions } from './get-diffable-html.js';
|
|
import { getOuterHtml, getCleanedShadowDom, snapshotPath } from './src/utils.js';
|
|
|
|
/** @typedef {import('./get-diffable-html.js').DiffOptions} DiffOptions */
|
|
|
|
function disambiguateArgs(...args) {
|
|
switch (args.length) {
|
|
// equal<T>(actual: T, expected: T, message?: string, options?: DiffOptions): void;
|
|
case 2: {
|
|
const [message, options] = args;
|
|
return { message, options };
|
|
}
|
|
|
|
// equal<T>(actual: T, expected: T, message?: string): void;
|
|
// equal<T>(actual: T, expected: T, options?: DiffOptions): void;
|
|
case 1: {
|
|
const [first] = args;
|
|
return isDiffOptions(first) ? { options: first } : { message: first };
|
|
}
|
|
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @type {Chai.ChaiPlugin}
|
|
*/
|
|
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 getDomHtml = el => getOuterHtml(el);
|
|
const getLightDomHtml = el => el.innerHTML;
|
|
const getShadowDomHtml = el => getCleanedShadowDom(el);
|
|
|
|
/**
|
|
* Base HTML assertion for `assert` interface.
|
|
* @param {string | Node} actual
|
|
* @param {string | Node} expected
|
|
* @param {boolean} negate
|
|
* @param {[string]|[DiffOptions]|[string, DiffOptions]} rest
|
|
*/
|
|
const assertHtmlEquals = (actual, expected, negate, ...rest) => {
|
|
const { message, options } = disambiguateArgs(...rest);
|
|
// use chai's built-in string comparison, log the updated snapshot on error
|
|
const assertion = new chai.Assertion(getDiffableHTML(actual, options), message);
|
|
const expectedDiffableHTML = getDiffableHTML(expected, options);
|
|
|
|
if (negate) {
|
|
assertion.not.equal(expectedDiffableHTML, message);
|
|
} else {
|
|
assertion.equal(expectedDiffableHTML, message);
|
|
}
|
|
};
|
|
|
|
/** DOM assertion for `should` and `expect` interfaces. */
|
|
const domEquals = _super =>
|
|
/**
|
|
* @this {Chai.AssertionStatic}
|
|
*/
|
|
function handleDom(value, ...args) {
|
|
if (
|
|
utils.flag(this, 'lightDom') ||
|
|
utils.flag(this, 'shadowDom') ||
|
|
utils.flag(this, 'dom')
|
|
) {
|
|
let html;
|
|
if (utils.flag(this, 'lightDom')) {
|
|
html = getLightDomHtml(this._obj);
|
|
} else if (utils.flag(this, 'shadowDom')) {
|
|
html = getShadowDomHtml(this._obj);
|
|
} else {
|
|
html = getDomHtml(this._obj);
|
|
}
|
|
|
|
assertHtmlEquals(html, value, utils.flag(this, 'negate'), args[0]);
|
|
} 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__;
|
|
|
|
/**
|
|
* Base HTML snapshot assertion for `assert` interface.
|
|
* @this {Chai.AssertionStatic}
|
|
* @param {string|Node} actual
|
|
* @param {boolean} negate
|
|
* @param {[string]|[DiffOptions]|[string, DiffOptions]} rest
|
|
*/
|
|
function assertHtmlEqualsSnapshot(actual, negate, ...rest) {
|
|
const { message, options } = disambiguateArgs(...rest);
|
|
const { index } = context;
|
|
context.index += 1;
|
|
let path;
|
|
|
|
const html = getDiffableHTML(actual, 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 {
|
|
const isMatch = snapshotState.match(html, getDiffableHTML(snapshot.code, options));
|
|
if ((isMatch && negate) || (!isMatch && !negate)) {
|
|
/* istanbul ignore next */
|
|
throw new chai.AssertionError(
|
|
message || `Received value does not match stored snapshot ${index}`,
|
|
{
|
|
actual: html,
|
|
expected: snapshot.code,
|
|
showDiff: true,
|
|
},
|
|
chai.util.flag(this, 'ssfi'),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Snapshot assertion for `should` and `expect` interfaces.
|
|
* @this {Chai.AssertionStatic}
|
|
*/
|
|
function equalSnapshot(options) {
|
|
const el = chai.util.flag(this, 'object');
|
|
let html;
|
|
if (utils.flag(this, 'shadowDom')) {
|
|
html = getShadowDomHtml(el);
|
|
} else if (utils.flag(this, 'lightDom')) {
|
|
html = getLightDomHtml(el);
|
|
} else {
|
|
html = el;
|
|
}
|
|
return assertHtmlEqualsSnapshot.call(this, html, utils.flag(this, 'negate'), options);
|
|
}
|
|
|
|
utils.addMethod(chai.Assertion.prototype, 'equalSnapshot', equalSnapshot);
|
|
utils.addMethod(chai.Assertion.prototype, 'notEqualSnapshot', equalSnapshot);
|
|
|
|
utils.addMethod(chai.assert, 'equalSnapshot', assertHtmlEqualsSnapshot);
|
|
utils.addMethod(chai.assert, 'notEqualSnapshot', assertHtmlEqualsSnapshot);
|
|
|
|
/** @type {Chai.Assert['dom']} */
|
|
chai.assert.dom = {
|
|
equal(actualEl, expectedHTML, ...rest) {
|
|
const negate = false;
|
|
return assertHtmlEquals.call(this, getDomHtml(actualEl), expectedHTML, negate, ...rest);
|
|
},
|
|
notEqual(actualEl, expectedHTML, ...rest) {
|
|
const negate = true;
|
|
return assertHtmlEquals.call(this, getDomHtml(actualEl), expectedHTML, negate, ...rest);
|
|
},
|
|
equalSnapshot(actualEl, ...rest) {
|
|
const negate = false;
|
|
return assertHtmlEqualsSnapshot.call(this, actualEl, negate, ...rest);
|
|
},
|
|
notEqualSnapshot(actualEl, ...rest) {
|
|
const negate = true;
|
|
return assertHtmlEqualsSnapshot.call(this, actualEl, negate, ...rest);
|
|
},
|
|
};
|
|
|
|
/** @type {Chai.Assert['lightDom']} */
|
|
chai.assert.lightDom = {
|
|
equal(actualEl, expectedHTML, ...rest) {
|
|
const negate = false;
|
|
return assertHtmlEquals.call(this, getLightDomHtml(actualEl), expectedHTML, negate, ...rest);
|
|
},
|
|
notEqual(actualEl, expectedHTML, ...rest) {
|
|
const negate = true;
|
|
return assertHtmlEquals.call(this, getLightDomHtml(actualEl), expectedHTML, negate, ...rest);
|
|
},
|
|
equalSnapshot(actualEl, ...rest) {
|
|
const negate = false;
|
|
return assertHtmlEqualsSnapshot.call(this, getLightDomHtml(actualEl), negate, ...rest);
|
|
},
|
|
notEqualSnapshot(actualEl, ...rest) {
|
|
const negate = true;
|
|
return assertHtmlEqualsSnapshot.call(this, getLightDomHtml(actualEl), negate, ...rest);
|
|
},
|
|
};
|
|
|
|
/** @type {Chai.Assert['shadowDom']} */
|
|
chai.assert.shadowDom = {
|
|
equal(actualEl, expectedHTML, ...rest) {
|
|
const negate = false;
|
|
return assertHtmlEquals.call(this, getShadowDomHtml(actualEl), expectedHTML, negate, ...rest);
|
|
},
|
|
notEqual(actualEl, expectedHTML, ...rest) {
|
|
const negate = true;
|
|
return assertHtmlEquals.call(this, getShadowDomHtml(actualEl), expectedHTML, negate, ...rest);
|
|
},
|
|
equalSnapshot(actualEl, ...rest) {
|
|
const negate = false;
|
|
return assertHtmlEqualsSnapshot.call(this, getShadowDomHtml(actualEl), negate, ...rest);
|
|
},
|
|
notEqualSnapshot(actualEl, ...rest) {
|
|
const negate = true;
|
|
return assertHtmlEqualsSnapshot.call(this, getShadowDomHtml(actualEl), negate, ...rest);
|
|
},
|
|
};
|
|
};
|