Split operator-dictionary-001.html into smaller pieces to avoid timeout in debug modes. (#19516)
diff --git a/mathml/presentation-markup/operators/operator-dictionary-001.html b/mathml/presentation-markup/operators/operator-dictionary-001.html
index ea3d5ae..e4e5c68 100644
--- a/mathml/presentation-markup/operators/operator-dictionary-001.html
+++ b/mathml/presentation-markup/operators/operator-dictionary-001.html
@@ -13,266 +13,14 @@
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<script src="/mathml/support/operator-dictionary.js"></script>
-<style>
- @font-face {
- font-family: operators;
- src: url("/fonts/math/operators.woff");
- }
- math, math * {
- font-family: operators;
- /* Use large enough font-size so that 1/18em = 2.77px > epsilon and
- one can really distinguish lspace/rspace values. */
- font-size: 50px;
- }
-</style>
+<script src="./support/operator-dictionary-tests.js"></script>
+<link rel="stylesheet" href="./support/operator-dictionary-tests.css"/>
<script>
setup({ explicit_done: true });
window.addEventListener("load", () => { document.fonts.ready.then(runTests); });
-
async function runTests() {
- let epsilon = 1;
let json = await fetchOperatorDictionary();
-
- // The operator dictionary has more than one thousand of entries so the
- // tests are grouped in chunks so that these don't get much more
- // importance than other MathML tests. For easy debugging, one can set the
- // chunk size to 1. Also, note that the test div will remain visible for
- // failed tests.
- const entryPerChunk = 50
-
- var counter = 0;
- var tests = {
- "lspace/rspace": null,
- "movablelimits": null,
- "largeop": null,
- "stretchy": null,
- "symmetric": null,
- "accent": null
- };
-
- for (key in json.dictionary) {
-
- if (counter % entryPerChunk === 0) {
- // Start of a new chunk.
- // Complete current async tests and create new ones for the next chunk.
- for (name in tests) {
- if (tests[name]) tests[name].done();
- tests[name] = async_test(`Operator dictionary chunk ${1 + counter / entryPerChunk} - ${name}`);
- }
- }
-
- let parsedKey = splitKey(key);
- let entry = json.dictionary[key];
-
- tests["lspace/rspace"].step(function() {
- assert_true(MathMLFeatureDetection.has_operator_spacing());
- document.body.insertAdjacentHTML("beforeend", `<div>\
-lspace/rspace for "${parsedKey.characters}" (${parsedKey.form}): \
-<math>\
- <mrow>\
- <mn> </mn>\
- <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
- <mn> </mn>\
- </mrow>\
-</math>\
- VS \
-<math>\
- <mrow>\
- <mn> </mn>\
- <mo form="${parsedKey.form}" lspace="${defaultPropertyValue(entry, 'lspace')}" rspace="${defaultPropertyValue(entry, 'rspace')}">${parsedKey.characters}</mo>\
- <mn> </mn>\
- </mrow>\
-</math>\
-</div>`);
- var div = document.body.lastElementChild;
- var mrows = div.getElementsByTagName("mrow");
- function spaceBetween(element, i, j) {
- return element.children[j].getBoundingClientRect().left -
- element.children[i].getBoundingClientRect().right;
- }
- var lspace = spaceBetween(mrows[0], 0, 1);
- var rspace = spaceBetween(mrows[0], 1, 2);
- var lspaceRef = spaceBetween(mrows[1], 0, 1);
- var rspaceRef = spaceBetween(mrows[1], 1, 2);
- assert_approx_equals(lspace, lspaceRef, epsilon, `lspace (${key})`);
- assert_approx_equals(rspace, rspaceRef, epsilon, `rspace (${key})`);
- div.style.display = "none";
- });
-
- tests["movablelimits"].step(function() {
- assert_true(MathMLFeatureDetection.has_movablelimits());
- var defaultValue = defaultPropertyValue(entry, "movablelimits");
- document.body.insertAdjacentHTML("beforeend", `<div>\
-movablelimits for "${parsedKey.characters}" (${parsedKey.form}): \
-<math>\
- <munder>\
- <mo stretchy="false" form="${parsedKey.form}">${parsedKey.characters}</mo>\
- <mn> </mn>\
- </munder>\
-</math>\
- VS \
-<math>\
- <munder>\
- <mo stretchy="false" form="${parsedKey.form}" movablelimits="${defaultValue}">${parsedKey.characters}</mo>\
- <mn> </mn>\
- </munder>\
-</math>\
-</div>`);
- var div = document.body.lastElementChild;
- var munders = div.getElementsByTagName("munder");
- munder = munders[0].getBoundingClientRect()
- munderRef = munders[1].getBoundingClientRect()
- assert_approx_equals(munder.height, munderRef.height, epsilon, `Movablelimits property for ${key} should be '${defaultValue}'`);
- div.style.display = "none";
- });
-
- tests["largeop"].step(function() {
- // FIXME: Should really detect largeop support...
- assert_true(MathMLFeatureDetection.has_mspace());
- var defaultValue = defaultPropertyValue(entry, "largeop");
- document.body.insertAdjacentHTML("beforeend", `<div>\
-largeop for "${parsedKey.characters}" (${parsedKey.form}): \
-<math displaystyle="true">\
- <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
-</math>\
- VS \
-<math displaystyle="true">\
- <mo form="${parsedKey.form}" largeop="${defaultValue}">${parsedKey.characters}</mo>\
-</math>\
-</div>`);
- var div = document.body.lastElementChild;
- var mos = div.getElementsByTagName("mo");
- mo = mos[0].getBoundingClientRect()
- moRef = mos[1].getBoundingClientRect()
- assert_approx_equals(mo.height, moRef.height, epsilon, `Largeop property for ${key} should be '${defaultValue}'`);
- div.style.display = "none";
- });
-
- if (entry.horizontal) {
- tests["stretchy"].step(function() {
- // FIXME: Should really detect stretchy support...
- assert_true(MathMLFeatureDetection.has_munder());
- var defaultValue = defaultPropertyValue(entry, "stretchy");
- document.body.insertAdjacentHTML("beforeend", `<div>\
-stretchy for "${parsedKey.characters}" (${parsedKey.form}): \
-<math>\
- <munder>\
- <mn> </mn>\
- <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
- </munder>\
-</math>\
- VS \
-<math>\
- <munder>\
- <mn> </mn>\
- <mo form="${parsedKey.form}" stretchy="${defaultValue}">${parsedKey.characters}</mo>\
- </munder>\
-</math>\
-</div>`);
- var div = document.body.lastElementChild;
- var mos = div.getElementsByTagName("mo");
- mo = mos[0].getBoundingClientRect()
- moRef = mos[1].getBoundingClientRect()
- assert_approx_equals(mo.width, moRef.width, epsilon, `Stretchy property for ${key} should be '${defaultValue}'`);
- div.style.display = "none";
- });
- } else {
- tests["stretchy"].step(function() {
- // FIXME: Should really detect stretchy support...
- assert_true(MathMLFeatureDetection.has_mspace());
- var defaultValue = defaultPropertyValue(entry, "stretchy");
- document.body.insertAdjacentHTML("beforeend", `<div>\
-stretchy for "${parsedKey.characters}" (${parsedKey.form}): \
-<math>\
- <mrow>\
- <mo form="${parsedKey.form}" symmetric="false">${parsedKey.characters}</mo>\
- <mspace height="2em"></mspace>\
- </mrow>\
-</math>\
- VS \
-<math>\
- <mrow>\
- <mo form="${parsedKey.form}" symmetric="false" stretchy="${defaultValue}">${parsedKey.characters}</mo>\
- <mspace height="2em"></mspace>\
- </mrow>\
-</math>\
-</div>`);
- var div = document.body.lastElementChild;
- var mos = div.getElementsByTagName("mo");
- mo = mos[0].getBoundingClientRect()
- moRef = mos[1].getBoundingClientRect()
- assert_approx_equals(mo.height, moRef.height, epsilon, `Stretchy property for ${key} should be '${defaultValue}'`);
- div.style.display = "none";
- });
- tests["symmetric"].step(function() {
- // FIXME: Should really detect symmetric support...
- assert_true(MathMLFeatureDetection.has_mspace());
- var defaultValue = defaultPropertyValue(entry, "symmetric");
- document.body.insertAdjacentHTML("beforeend", `<div>\
-symmetric for "${parsedKey.characters}" (${parsedKey.form}): \
-<math>\
- <mrow>\
- <mo form="${parsedKey.form}" stretchy="true">${parsedKey.characters}</mo>\
- <mspace height="1.5em"></mspace>\
- </mrow>\
-</math>\
- VS \
-<math>\
- <mrow>\
- <mo form="${parsedKey.form}" stretchy="true" symmetric="${defaultValue}">${parsedKey.characters}</mo>\
- <mspace height="1.5em"></mspace>\
- </mrow>\
-</math>\
-</div>`);
- var div = document.body.lastElementChild;
- var mos = div.getElementsByTagName("mo");
- mo = mos[0].getBoundingClientRect()
- moRef = mos[1].getBoundingClientRect()
- assert_approx_equals(mo.height, moRef.height, epsilon, `Symmetric property for ${key} should be '${defaultValue}'`);
- div.style.display = "none";
- });
- }
-
- tests["accent"].step(function() {
- // FIXME: Should really detect accent support...
- assert_true(MathMLFeatureDetection.has_mover());
- var defaultValue = defaultPropertyValue(entry, "accent");
- document.body.insertAdjacentHTML("beforeend", `<div>\
-accent for "${parsedKey.characters}" (${parsedKey.form}): \
-<math>\
- <mover>\
- <mn> </mn>\
- <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
- </mover>\
-</math>\
- VS \
-<math>\
- <mover>\
- <mn> </mn>\
- <mo form="${parsedKey.form}" accent="${defaultValue}">${parsedKey.characters}</mo>\
- </mover>\
-</math>\
-</div>`);
- var div = document.body.lastElementChild;
- var movers = div.getElementsByTagName("mover");
- function gapBetweenBaseAndScript(mover) {
- return mover.children[0].getBoundingClientRect().top -
- mover.children[1].getBoundingClientRect().bottom;
- }
- var gap = gapBetweenBaseAndScript(movers[0])
- var gapRef = gapBetweenBaseAndScript(movers[1])
- assert_approx_equals(gap, gapRef, epsilon, `Accent property for ${key} should be '${defaultValue}'`);
- div.style.display = "none";
- });
-
- counter++;
- }
-
- // Complete current async tests.
- for (name in tests) {
- if (tests[name]) tests[name].done();
- }
-
+ OperatorDictionaryTests.run(json, "lspace/rspace");
done();
}
</script>
diff --git a/mathml/presentation-markup/operators/operator-dictionary-002.html b/mathml/presentation-markup/operators/operator-dictionary-002.html
new file mode 100644
index 0000000..ede3adc
--- /dev/null
+++ b/mathml/presentation-markup/operators/operator-dictionary-002.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Operator dictionary</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#dictionary-based-attributes">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-dictionary">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#stretchy-operator-axis">
+<meta name="assert" content="Verify default properties for characters that are in the operator dictionary, as well as for U+00A0 NO-BREAK SPACE">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/operator-dictionary.js"></script>
+<script src="./support/operator-dictionary-tests.js"></script>
+<link rel="stylesheet" href="./support/operator-dictionary-tests.css"/>
+<script>
+ setup({ explicit_done: true });
+ window.addEventListener("load", () => { document.fonts.ready.then(runTests); });
+ async function runTests() {
+ let json = await fetchOperatorDictionary();
+ OperatorDictionaryTests.run(json, "movablelimits");
+ done();
+ }
+</script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/mathml/presentation-markup/operators/operator-dictionary-003.html b/mathml/presentation-markup/operators/operator-dictionary-003.html
new file mode 100644
index 0000000..bb3c638
--- /dev/null
+++ b/mathml/presentation-markup/operators/operator-dictionary-003.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Operator dictionary</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#dictionary-based-attributes">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-dictionary">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#stretchy-operator-axis">
+<meta name="assert" content="Verify default properties for characters that are in the operator dictionary, as well as for U+00A0 NO-BREAK SPACE">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/operator-dictionary.js"></script>
+<script src="./support/operator-dictionary-tests.js"></script>
+<link rel="stylesheet" href="./support/operator-dictionary-tests.css"/>
+<script>
+ setup({ explicit_done: true });
+ window.addEventListener("load", () => { document.fonts.ready.then(runTests); });
+ async function runTests() {
+ let json = await fetchOperatorDictionary();
+ OperatorDictionaryTests.run(json, "largeop");
+ done();
+ }
+</script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/mathml/presentation-markup/operators/operator-dictionary-004.html b/mathml/presentation-markup/operators/operator-dictionary-004.html
new file mode 100644
index 0000000..79bf523
--- /dev/null
+++ b/mathml/presentation-markup/operators/operator-dictionary-004.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Operator dictionary</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#dictionary-based-attributes">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-dictionary">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#stretchy-operator-axis">
+<meta name="assert" content="Verify default properties for characters that are in the operator dictionary, as well as for U+00A0 NO-BREAK SPACE">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/operator-dictionary.js"></script>
+<script src="./support/operator-dictionary-tests.js"></script>
+<link rel="stylesheet" href="./support/operator-dictionary-tests.css"/>
+<script>
+ setup({ explicit_done: true });
+ window.addEventListener("load", () => { document.fonts.ready.then(runTests); });
+ async function runTests() {
+ let json = await fetchOperatorDictionary();
+ OperatorDictionaryTests.run(json, "stretchy");
+ done();
+ }
+</script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/mathml/presentation-markup/operators/operator-dictionary-005.html b/mathml/presentation-markup/operators/operator-dictionary-005.html
new file mode 100644
index 0000000..4c1ee6d
--- /dev/null
+++ b/mathml/presentation-markup/operators/operator-dictionary-005.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Operator dictionary</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#dictionary-based-attributes">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-dictionary">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#stretchy-operator-axis">
+<meta name="assert" content="Verify default properties for characters that are in the operator dictionary, as well as for U+00A0 NO-BREAK SPACE">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/operator-dictionary.js"></script>
+<script src="./support/operator-dictionary-tests.js"></script>
+<link rel="stylesheet" href="./support/operator-dictionary-tests.css"/>
+<script>
+ setup({ explicit_done: true });
+ window.addEventListener("load", () => { document.fonts.ready.then(runTests); });
+ async function runTests() {
+ let json = await fetchOperatorDictionary();
+ OperatorDictionaryTests.run(json, "symmetric");
+ done();
+ }
+</script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/mathml/presentation-markup/operators/operator-dictionary-006.html b/mathml/presentation-markup/operators/operator-dictionary-006.html
new file mode 100644
index 0000000..cdd3e16
--- /dev/null
+++ b/mathml/presentation-markup/operators/operator-dictionary-006.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Operator dictionary</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#dictionary-based-attributes">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-dictionary">
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#stretchy-operator-axis">
+<meta name="assert" content="Verify default properties for characters that are in the operator dictionary, as well as for U+00A0 NO-BREAK SPACE">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/operator-dictionary.js"></script>
+<script src="./support/operator-dictionary-tests.js"></script>
+<link rel="stylesheet" href="./support/operator-dictionary-tests.css"/>
+<script>
+ setup({ explicit_done: true });
+ window.addEventListener("load", () => { document.fonts.ready.then(runTests); });
+ async function runTests() {
+ let json = await fetchOperatorDictionary();
+ OperatorDictionaryTests.run(json, "accent");
+ done();
+ }
+</script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/mathml/presentation-markup/operators/support/operator-dictionary-tests.css b/mathml/presentation-markup/operators/support/operator-dictionary-tests.css
new file mode 100644
index 0000000..4f80ad7
--- /dev/null
+++ b/mathml/presentation-markup/operators/support/operator-dictionary-tests.css
@@ -0,0 +1,10 @@
+@font-face {
+ font-family: operators;
+ src: url("/fonts/math/operators.woff");
+}
+math, math * {
+ font-family: operators;
+ /* Use large enough font-size so that 1/18em = 2.77px > epsilon and
+ one can really distinguish lspace/rspace values. */
+ font-size: 50px;
+}
diff --git a/mathml/presentation-markup/operators/support/operator-dictionary-tests.js b/mathml/presentation-markup/operators/support/operator-dictionary-tests.js
new file mode 100644
index 0000000..838a22c
--- /dev/null
+++ b/mathml/presentation-markup/operators/support/operator-dictionary-tests.js
@@ -0,0 +1,256 @@
+var OperatorDictionaryTests = {
+ "lspace/rspace": function(json, key) {
+ let parsedKey = splitKey(key);
+ let entry = json.dictionary[key];
+ let epsilon = 1;
+
+ assert_true(MathMLFeatureDetection.has_operator_spacing());
+ document.body.insertAdjacentHTML("beforeend", `<div>\
+lspace/rspace for "${parsedKey.characters}" (${parsedKey.form}): \
+<math>\
+ <mrow>\
+ <mn> </mn>\
+ <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
+ <mn> </mn>\
+ </mrow>\
+</math>\
+ VS \
+<math>\
+ <mrow>\
+ <mn> </mn>\
+ <mo form="${parsedKey.form}" lspace="${defaultPropertyValue(entry, 'lspace')}" rspace="${defaultPropertyValue(entry, 'rspace')}">${parsedKey.characters}</mo>\
+ <mn> </mn>\
+ </mrow>\
+</math>\
+</div>`);
+ var div = document.body.lastElementChild;
+ var mrows = div.getElementsByTagName("mrow");
+ function spaceBetween(element, i, j) {
+ return element.children[j].getBoundingClientRect().left -
+ element.children[i].getBoundingClientRect().right;
+ }
+ var lspace = spaceBetween(mrows[0], 0, 1);
+ var rspace = spaceBetween(mrows[0], 1, 2);
+ var lspaceRef = spaceBetween(mrows[1], 0, 1);
+ var rspaceRef = spaceBetween(mrows[1], 1, 2);
+ assert_approx_equals(lspace, lspaceRef, epsilon, `lspace (${key})`);
+ assert_approx_equals(rspace, rspaceRef, epsilon, `rspace (${key})`);
+ div.style.display = "none";
+ },
+
+ "movablelimits": function(json, key) {
+ let parsedKey = splitKey(key);
+ let entry = json.dictionary[key];
+ let epsilon = 1;
+
+ assert_true(MathMLFeatureDetection.has_movablelimits());
+ var defaultValue = defaultPropertyValue(entry, "movablelimits");
+ document.body.insertAdjacentHTML("beforeend", `<div>\
+movablelimits for "${parsedKey.characters}" (${parsedKey.form}): \
+<math>\
+ <munder>\
+ <mo stretchy="false" form="${parsedKey.form}">${parsedKey.characters}</mo>\
+ <mn> </mn>\
+ </munder>\
+</math>\
+ VS \
+<math>\
+ <munder>\
+ <mo stretchy="false" form="${parsedKey.form}" movablelimits="${defaultValue}">${parsedKey.characters}</mo>\
+ <mn> </mn>\
+ </munder>\
+</math>\
+</div>`);
+ var div = document.body.lastElementChild;
+ var munders = div.getElementsByTagName("munder");
+ munder = munders[0].getBoundingClientRect()
+ munderRef = munders[1].getBoundingClientRect()
+ assert_approx_equals(munder.height, munderRef.height, epsilon, `Movablelimits property for ${key} should be '${defaultValue}'`);
+ div.style.display = "none";
+ },
+
+ "largeop": function(json, key) {
+ let parsedKey = splitKey(key);
+ let entry = json.dictionary[key];
+ let epsilon = 1;
+
+ // FIXME: Should really detect largeop support...
+ assert_true(MathMLFeatureDetection.has_mspace());
+ var defaultValue = defaultPropertyValue(entry, "largeop");
+ document.body.insertAdjacentHTML("beforeend", `<div>\
+largeop for "${parsedKey.characters}" (${parsedKey.form}): \
+<math displaystyle="true">\
+ <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
+</math>\
+ VS \
+<math displaystyle="true">\
+ <mo form="${parsedKey.form}" largeop="${defaultValue}">${parsedKey.characters}</mo>\
+</math>\
+</div>`);
+ var div = document.body.lastElementChild;
+ var mos = div.getElementsByTagName("mo");
+ mo = mos[0].getBoundingClientRect()
+ moRef = mos[1].getBoundingClientRect()
+ assert_approx_equals(mo.height, moRef.height, epsilon, `Largeop property for ${key} should be '${defaultValue}'`);
+ div.style.display = "none";
+ },
+
+ "stretchy": function(json, key) {
+ let parsedKey = splitKey(key);
+ let entry = json.dictionary[key];
+ let epsilon = 1;
+
+ if (entry.horizontal) {
+ // FIXME: Should really detect stretchy support...
+ assert_true(MathMLFeatureDetection.has_munder());
+ var defaultValue = defaultPropertyValue(entry, "stretchy");
+ document.body.insertAdjacentHTML("beforeend", `<div>\
+stretchy for "${parsedKey.characters}" (${parsedKey.form}): \
+<math>\
+ <munder>\
+ <mn> </mn>\
+ <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
+ </munder>\
+</math>\
+ VS \
+<math>\
+ <munder>\
+ <mn> </mn>\
+ <mo form="${parsedKey.form}" stretchy="${defaultValue}">${parsedKey.characters}</mo>\
+ </munder>\
+</math>\
+</div>`);
+ var div = document.body.lastElementChild;
+ var mos = div.getElementsByTagName("mo");
+ mo = mos[0].getBoundingClientRect()
+ moRef = mos[1].getBoundingClientRect()
+ assert_approx_equals(mo.width, moRef.width, epsilon, `Stretchy property for ${key} should be '${defaultValue}'`);
+ div.style.display = "none";
+ } else {
+ // FIXME: Should really detect stretchy support...
+ assert_true(MathMLFeatureDetection.has_mspace());
+ var defaultValue = defaultPropertyValue(entry, "stretchy");
+ document.body.insertAdjacentHTML("beforeend", `<div>\
+stretchy for "${parsedKey.characters}" (${parsedKey.form}): \
+<math>\
+ <mrow>\
+ <mo form="${parsedKey.form}" symmetric="false">${parsedKey.characters}</mo>\
+ <mspace height="2em"></mspace>\
+ </mrow>\
+</math>\
+ VS \
+<math>\
+ <mrow>\
+ <mo form="${parsedKey.form}" symmetric="false" stretchy="${defaultValue}">${parsedKey.characters}</mo>\
+ <mspace height="2em"></mspace>\
+ </mrow>\
+</math>\
+</div>`);
+ var div = document.body.lastElementChild;
+ var mos = div.getElementsByTagName("mo");
+ mo = mos[0].getBoundingClientRect()
+ moRef = mos[1].getBoundingClientRect()
+ assert_approx_equals(mo.height, moRef.height, epsilon, `Stretchy property for ${key} should be '${defaultValue}'`);
+ div.style.display = "none";
+ }
+ },
+
+ "symmetric": function(json, key) {
+ let parsedKey = splitKey(key);
+ let entry = json.dictionary[key];
+ let epsilon = 1;
+
+ // FIXME: Should really detect symmetric support...
+ assert_true(MathMLFeatureDetection.has_mspace());
+ var defaultValue = defaultPropertyValue(entry, "symmetric");
+ document.body.insertAdjacentHTML("beforeend", `<div>\
+symmetric for "${parsedKey.characters}" (${parsedKey.form}): \
+<math>\
+ <mrow>\
+ <mo form="${parsedKey.form}" stretchy="true">${parsedKey.characters}</mo>\
+ <mspace height="1.5em"></mspace>\
+ </mrow>\
+</math>\
+ VS \
+<math>\
+ <mrow>\
+ <mo form="${parsedKey.form}" stretchy="true" symmetric="${defaultValue}">${parsedKey.characters}</mo>\
+ <mspace height="1.5em"></mspace>\
+ </mrow>\
+</math>\
+</div>`);
+ var div = document.body.lastElementChild;
+ var mos = div.getElementsByTagName("mo");
+ mo = mos[0].getBoundingClientRect()
+ moRef = mos[1].getBoundingClientRect()
+ assert_approx_equals(mo.height, moRef.height, epsilon, `Symmetric property for ${key} should be '${defaultValue}'`);
+ div.style.display = "none";
+ },
+
+ "accent": function(json, key) {
+ let parsedKey = splitKey(key);
+ let entry = json.dictionary[key];
+ let epsilon = 1;
+
+ // FIXME: Should really detect accent support...
+ assert_true(MathMLFeatureDetection.has_mover());
+ var defaultValue = defaultPropertyValue(entry, "accent");
+ document.body.insertAdjacentHTML("beforeend", `<div>\
+accent for "${parsedKey.characters}" (${parsedKey.form}): \
+<math>\
+ <mover>\
+ <mn> </mn>\
+ <mo form="${parsedKey.form}">${parsedKey.characters}</mo>\
+ </mover>\
+</math>\
+ VS \
+<math>\
+ <mover>\
+ <mn> </mn>\
+ <mo form="${parsedKey.form}" accent="${defaultValue}">${parsedKey.characters}</mo>\
+ </mover>\
+</math>\
+</div>`);
+ var div = document.body.lastElementChild;
+ var movers = div.getElementsByTagName("mover");
+ function gapBetweenBaseAndScript(mover) {
+ return mover.children[0].getBoundingClientRect().top -
+ mover.children[1].getBoundingClientRect().bottom;
+ }
+ var gap = gapBetweenBaseAndScript(movers[0])
+ var gapRef = gapBetweenBaseAndScript(movers[1])
+ assert_approx_equals(gap, gapRef, epsilon, `Accent property for ${key} should be '${defaultValue}'`);
+ div.style.display = "none";
+ },
+
+ run: function(json, name) {
+ // The operator dictionary has more than one thousand of entries so the
+ // tests are grouped in chunks so that these don't get much more
+ // importance than other MathML tests. For easy debugging, one can set the
+ // chunk size to 1. Also, note that the test div will remain visible for
+ // failed tests.
+ const entryPerChunk = 50
+
+ var counter = 0;
+ var test;
+
+ for (key in json.dictionary) {
+
+ if (counter % entryPerChunk === 0) {
+ // Start of a new chunk.
+ // Complete current async tests and create new ones for the next chunk.
+ if (test) test.done();
+ test = async_test(`Operator dictionary chunk ${1 + counter / entryPerChunk} - ${name}`);
+ }
+
+ test.step(function() {
+ OperatorDictionaryTests[name](json, key);
+ });
+
+ counter++;
+ }
+
+ // Complete current async test.
+ if (test) test.done();
+ }
+};