forked from mirrors/gecko-dev
171 lines
5.2 KiB
JavaScript
171 lines
5.2 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
/**
|
|
* Test that the devtool's client-side CSS properties database is in sync with the values
|
|
* on the platform (in Nightly only). If they are not, then `mach devtools-css-db` needs
|
|
* to be run to make everything up to date. Nightly, aurora, beta, and release may have
|
|
* different CSS properties and values. These are based on preferences and compiler flags.
|
|
*
|
|
* This test broke uplifts as the database needed to be regenerated every uplift. The
|
|
* combination of compiler flags and preferences means that it's too difficult to
|
|
* statically determine which properties are enabled between Firefox releases.
|
|
*
|
|
* Because of these difficulties, the database only needs to be up to date with Nightly.
|
|
* It is a fallback that is only used if the remote debugging protocol doesn't support
|
|
* providing a CSS database, so it's ok if the provided properties don't exactly match
|
|
* the inspected target in this particular case.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const {
|
|
CSS_PROPERTIES,
|
|
} = require("resource://devtools/shared/css/generated/properties-db.js");
|
|
const PREFERENCES = InspectorUtils.getCSSPropertyPrefs();
|
|
const {
|
|
generateCssProperties,
|
|
} = require("resource://devtools/server/actors/css-properties.js");
|
|
const { Preferences } = ChromeUtils.importESModule(
|
|
"resource://gre/modules/Preferences.sys.mjs"
|
|
);
|
|
|
|
function run_test() {
|
|
const propertiesErrorMessage =
|
|
"If this assertion fails, then the client side CSS " +
|
|
"properties list in devtools is out of sync with the " +
|
|
"CSS properties on the platform. To fix this " +
|
|
"assertion run `mach devtools-css-db` to re-generate " +
|
|
"the client side properties.";
|
|
|
|
/**
|
|
* Check that the platform and client match for the details on their CSS properties.
|
|
* Enumerate each property to aid in debugging. Sometimes these properties don't
|
|
* completely agree due to differences in preferences. Check the currently set
|
|
* preference for that property to see if it's enabled.
|
|
*/
|
|
const platformProperties = generateCssProperties();
|
|
|
|
for (const propertyName in CSS_PROPERTIES) {
|
|
const platformProperty = platformProperties[propertyName];
|
|
const clientProperty = CSS_PROPERTIES[propertyName];
|
|
const deepEqual = isJsonDeepEqual(platformProperty, clientProperty);
|
|
|
|
if (deepEqual) {
|
|
ok(true, `The static database and platform match for "${propertyName}".`);
|
|
} else {
|
|
ok(
|
|
false,
|
|
`The static database and platform do not match for ` +
|
|
`
|
|
"${propertyName}". ${propertiesErrorMessage}`
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check that the list of properties on the platform and client are the same. If
|
|
* they are not, check that there may be preferences that are disabling them on the
|
|
* target platform.
|
|
*/
|
|
const mismatches = getKeyMismatches(platformProperties, CSS_PROPERTIES)
|
|
// Filter out OS-specific properties.
|
|
.filter(name => name && !name.includes("-moz-osx-"));
|
|
|
|
if (mismatches.length === 0) {
|
|
ok(
|
|
true,
|
|
"No client and platform CSS property database mismatches were found."
|
|
);
|
|
}
|
|
|
|
mismatches.forEach(propertyName => {
|
|
if (getPreference(propertyName) === false) {
|
|
ok(
|
|
true,
|
|
`The static database and platform do not agree on the property ` +
|
|
`"${propertyName}" This is ok because it is currently disabled through ` +
|
|
`a preference.`
|
|
);
|
|
} else {
|
|
ok(
|
|
false,
|
|
`The static database and platform do not agree on the property ` +
|
|
`"${propertyName}" ${propertiesErrorMessage}`
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Check JSON-serializable objects for deep equality.
|
|
*/
|
|
function isJsonDeepEqual(a, b) {
|
|
// Handle primitives.
|
|
if (a === b) {
|
|
return true;
|
|
}
|
|
|
|
// Handle arrays.
|
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
if (a.length !== b.length) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < a.length; i++) {
|
|
if (!isJsonDeepEqual(a[i], b[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Handle objects
|
|
if (typeof a === "object" && typeof b === "object") {
|
|
for (const key in a) {
|
|
if (!isJsonDeepEqual(a[key], b[key])) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return Object.keys(a).length === Object.keys(b).length;
|
|
}
|
|
|
|
// Not something handled by these cases, therefore not equal.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Take the keys of two objects, and return the ones that don't match.
|
|
*
|
|
* @param {Object} a
|
|
* @param {Object} b
|
|
* @return {Array} keys
|
|
*/
|
|
function getKeyMismatches(a, b) {
|
|
const aNames = Object.keys(a);
|
|
const bNames = Object.keys(b);
|
|
const aMismatches = aNames.filter(key => !bNames.includes(key));
|
|
const bMismatches = bNames.filter(key => {
|
|
return !aNames.includes(key) && !aMismatches.includes(key);
|
|
});
|
|
|
|
return aMismatches.concat(bMismatches);
|
|
}
|
|
|
|
/**
|
|
* Get the preference value of whether this property is enabled. Returns an empty string
|
|
* if no preference exists.
|
|
*
|
|
* @param {String} propertyName
|
|
* @return {Boolean|undefined}
|
|
*/
|
|
function getPreference(propertyName) {
|
|
const preference = PREFERENCES.find(({ name, pref }) => {
|
|
return name === propertyName && !!pref;
|
|
});
|
|
|
|
if (preference) {
|
|
return Preferences.get(preference.pref);
|
|
}
|
|
return undefined;
|
|
}
|