Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
/* Any copyright is dedicated to the Public Domain.
"use strict";
// Smoke test for the real MDN compatibility dataset. The behavior of MDNCompatibility is
// covered by test_mdn-compatibility.js, which uses a mock dataset. Here we only check that
// the vendored dataset can still be loaded and used, without asserting on any value which
// could legitimately change when the data is updated.
const {
TARGET_BROWSER_ID,
} = require("resource://devtools/shared/compatibility/constants.js");
const {
getCSSPropertiesCompatData,
} = require("resource://devtools/shared/compatibility/compatibility-dataset.js");
const MDNCompatibility = require("resource://devtools/server/actors/compatibility/lib/MDNCompatibility.js");
let cssPropertiesCompatData;
add_setup(() => {
// Make sure we use the live dataset, even if it should be the default.
Services.prefs.setBoolPref("devtools.compatibility.use-mock-dataset", false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.compatibility.use-mock-dataset");
});
cssPropertiesCompatData = getCSSPropertiesCompatData();
});
// A dataset smaller than this would mean the update script dropped most of the data.
const MINIMUM_PROPERTIES_COUNT = 100;
add_task(function test_dataset_shape() {
const properties = Object.keys(cssPropertiesCompatData);
Assert.greater(
properties.length,
MINIMUM_PROPERTIES_COUNT,
"The dataset contains a plausible number of properties"
);
info("Check the shape of every compat table in the dataset");
let checkedSupportEntries = 0;
for (const property of properties) {
const compatTable = getCompatTable(cssPropertiesCompatData, property);
if (!compatTable) {
// Aliases only hold a `_aliasOf` property.
Assert.equal(
typeof cssPropertiesCompatData[property]._aliasOf,
"string",
`"${property}" has no compat table and is an alias`
);
continue;
}
for (const [browserId, supportEntries] of Object.entries(
compatTable.support
)) {
Assert.ok(
TARGET_BROWSER_ID.includes(browserId),
`"${property}" only has support data for target browsers, got "${browserId}"`
);
Assert.ok(
Array.isArray(supportEntries),
`The support data of "${property}" for "${browserId}" is an array`
);
for (const { added } of supportEntries) {
// `added` is set by the update script from `version_added`, which can either be a
// version number, a boolean, or null when the data is unknown.
Assert.ok(
typeof added === "number" ||
typeof added === "boolean" ||
added === null ||
added === undefined,
`The parsed version of "${property}" for "${browserId}" is usable, got "${added}"`
);
checkedSupportEntries++;
}
}
}
Assert.greater(checkedSupportEntries, 0, "Support entries were checked");
});
add_task(function test_issues_shape() {
const mdnCompatibility = new MDNCompatibility(cssPropertiesCompatData);
const browsers = TARGET_BROWSER_ID.map(id => ({ id, version: "1" }));
// Targeting version 1 of every browser, so that any modern property is unsupported and
// reported as an issue whatever the data says.
const declarations = [
{ name: "background-color" },
{ name: "border-block-color" },
{ name: "user-select" },
{ name: "--custom-property" },
{ name: "this-property-does-not-exist" },
];
const issues = mdnCompatibility.getCSSDeclarationBlockIssues(
declarations,
browsers
);
Assert.greater(issues.length, 0, "Issues were reported");
for (const issue of issues) {
Assert.ok(!!issue.type, `The issue for "${issue.property}" has a type`);
Assert.ok(
declarations.some(
({ name }) => name === issue.property || issue.aliases?.includes(name)
),
`The issue for "${issue.property}" matches one of the declarations`
);
Assert.equal(
typeof issue.deprecated,
"boolean",
`The issue for "${issue.property}" has a deprecated flag`
);
Assert.equal(
typeof issue.experimental,
"boolean",
`The issue for "${issue.property}" has an experimental flag`
);
Assert.ok(
Array.isArray(issue.unsupportedBrowsers),
`The issue for "${issue.property}" has a list of unsupported browsers`
);
}
});
function getCompatTable(dataset, property) {
const node = dataset[property];
if (node.__compat) {
return node.__compat;
}
// Some properties store their compat data in a context node, e.g. `flex_context`.
for (const field in node) {
if (field.endsWith("_context")) {
return node[field].__compat;
}
}
return null;
}