eslint-plugin-ecmascript-compat
Version:
ESLint plugin for checking JavaScript code compatibility with target browsers and Node.js versions
244 lines (219 loc) • 6.02 kB
JavaScript
/* eslint-disable camelcase */
const assert = require('node:assert');
const { it } = require('node:test');
const { unsupportedFeatures } = require('./compatibility');
const features = require('./features');
it('supports feature in version introduced', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
chrome: { version_added: '73' },
},
},
},
],
};
const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
assert.deepStrictEqual(unsupported, []);
});
it('supports feature in version later than introduced, treating versions as numbers', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
safari: { version_added: '9' },
},
},
},
],
};
const unsupported = unsupportedFeatures(
[feature],
[{ name: 'safari', version: '14.0' }]
);
assert.deepStrictEqual(unsupported, []);
});
it('doesnt support feature in version before introduced', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
chrome: { version_added: '73' },
},
},
},
],
};
const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '72' }]);
assert.strictEqual(unsupported[0], feature);
});
it('supports feature supported by family in unknown version', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
chrome: { version_added: true },
},
},
},
],
};
const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
assert.deepStrictEqual(unsupported, []);
});
it('doesnt support feature not supported in any version of family', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
chrome: { version_added: false },
},
},
},
],
};
const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
assert.strictEqual(unsupported[0], feature);
});
it('supports feature with unknown support by family', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
chrome: { version_added: null },
},
},
},
],
};
const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
assert.deepStrictEqual(unsupported, []);
});
it('supports feature with omitted support entry for mobile target', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
chrome: { version_added: '73' },
},
},
},
],
};
const unsupported = unsupportedFeatures(
[feature],
[{ name: 'chrome_android', version: '73' }]
);
assert.deepStrictEqual(unsupported, []);
});
it('doesnt support feature supported by one target but not another', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
chrome: { version_added: '60' },
firefox: { version_added: '55' },
},
},
},
],
};
const unsupported = unsupportedFeatures(
[feature],
[
{ name: 'chrome', version: '73' },
{ name: 'firefox', version: '50' },
]
);
assert.strictEqual(unsupported[0], feature);
});
it('uses primary support record where multiple ones exist', () => {
const feature = {
compatFeatures: [
{
__compat: {
support: {
nodejs: [
{ version_added: '7.0.0' },
{
version_added: '6.5.0',
flags: [
{
type: 'runtime_flag',
name: '--harmony',
},
],
},
],
},
},
},
],
};
const primaryUnsupported = unsupportedFeatures(
[feature],
[{ name: 'nodejs', version: '7.0.0' }]
);
assert.deepStrictEqual(primaryUnsupported, []);
const secondaryUnsupported = unsupportedFeatures(
[feature],
[{ name: 'nodejs', version: '6.7.0' }]
);
assert.deepStrictEqual(secondaryUnsupported[0], feature);
});
it('explains what the problem is when compat feature not found in MDN data', () => {
const feature = {
ruleConfig: {
definition: {
meta: {
docs: { description: 'some rule' },
},
},
},
compatFeatures: [
// Unsupported compatFeature first, to test that validation does not short-circuit
{
__compat: {
support: {
chrome: { version_added: '72' },
},
},
},
// Typically when wrong path to compatData node used
undefined,
],
};
assert.throws(
() => unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]),
{ message: "Sparse compatFeatures for rule 'some rule': object,undefined" }
);
});
it('can rely on all the versions in the compatibility data used being semver or partial semver', () => {
// We rely on this to avoid having to deal with ranged versions, for simplicity.
// https://github.com/mdn/browser-compat-data/blob/main/schemas/compat-data-schema.md#ranged-versions
for (const esFeature of features) {
for (const compatFeature of esFeature.compatFeatures) {
// eslint-disable-next-line no-underscore-dangle
for (const supportStatement of Object.values(compatFeature.__compat.support)) {
const simpleSupportStatement = Array.isArray(supportStatement)
? supportStatement[0]
: supportStatement;
if (simpleSupportStatement.version_added !== false) {
assert.match(
simpleSupportStatement.version_added,
/\d+(?<minor>\.\d+(?<patch>\.\d+)?)?/u
);
}
}
}
}
});