155 lines
5.7 KiB
HTML
155 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<title>MathMLElement GlobalEventHandlers</title>
|
|
<link rel="author" title="Brian Kardell" href="mailto:bkardell@igalia.com" />
|
|
<link rel="help" href="https://w3c.github.io/mathml-core/#dom-and-javascript"/>
|
|
<link rel="help" href="https://html.spec.whatwg.org/multipage/#event-handler-idl-attributes"/>
|
|
<link rel="help" href="https://html.spec.whatwg.org/multipage/#event-handler-content-attributes"/>
|
|
<meta name="timeout" content="long">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="/resources/WebIDLParser.js"></script>
|
|
|
|
<script>
|
|
"use strict";
|
|
|
|
// The prefixed animation events are special; their event types are
|
|
// camel-case.
|
|
const prefixedAnimationAttributeToEventType = new Map([
|
|
["webkitanimationend", "webkitAnimationEnd"],
|
|
["webkitanimationiteration", "webkitAnimationIteration"],
|
|
["webkitanimationstart", "webkitAnimationStart"],
|
|
["webkittransitionend", "webkitTransitionEnd"],
|
|
]);
|
|
|
|
// basic pattern lifted from /html/webappapis/scripting/events/event-handler-all-global-events.html
|
|
promise_setup(async function() {
|
|
const res = await fetch("/interfaces/html.idl");
|
|
const htmlIDL = await res.text();
|
|
// Parsing the whole IDL file is slow, so use a small regexp to extract only
|
|
// the part that is relevant for this test.
|
|
const parsedHTMLIDL = WebIDL2.parse(htmlIDL.
|
|
match(/^interface mixin GlobalEventHandlers {[^{}]*};$/m)[0]);
|
|
const globalEventHandlers = parsedHTMLIDL.find(
|
|
idl => idl.name === "GlobalEventHandlers"
|
|
);
|
|
|
|
// onerror is too special
|
|
const names = globalEventHandlers.members
|
|
.map(member => member.name)
|
|
.filter(name => name !== "onerror");
|
|
|
|
for (const name of names) {
|
|
const withoutOn = name.substring(2);
|
|
|
|
promise_test(async () => {
|
|
const location = MathMLElement.prototype;
|
|
assert_true(
|
|
location.hasOwnProperty(name),
|
|
`${location.constructor.name} has an own property named "${name}"`
|
|
);
|
|
|
|
assert_false(
|
|
name in Element.prototype,
|
|
`Element.prototype must not contain a "${name}" property`
|
|
);
|
|
}, `${name}: must be on the appropriate locations for GlobalEventHandlers`);
|
|
|
|
promise_test(async () => {
|
|
const location = document.createElementNS(
|
|
"http://www.w3.org/1998/Math/MathML",
|
|
"math"
|
|
);
|
|
|
|
assert_equals(
|
|
location[name],
|
|
null,
|
|
`The default value of the property is null for a ${
|
|
location.constructor.name
|
|
} instance`
|
|
);
|
|
}, `${name}: the default value must be null`);
|
|
|
|
promise_test(async () => {
|
|
const div = document.createElement("div");
|
|
div.insertAdjacentHTML("beforeend", `<math ${name}="window.${name}Happened1 = true;"></math>`);
|
|
const compiledHandler = div.firstElementChild[name];
|
|
assert_equals(
|
|
typeof compiledHandler,
|
|
"function",
|
|
`The ${name} property must be a function`
|
|
);
|
|
compiledHandler();
|
|
assert_true(
|
|
window[`${name}Happened1`],
|
|
"Calling the handler must run the code"
|
|
);
|
|
}, `${name}: the content attribute must be compiled into a function as the corresponding property`);
|
|
|
|
promise_test(async () => {
|
|
const el = document.createElementNS(
|
|
"http://www.w3.org/1998/Math/MathML",
|
|
"math"
|
|
);
|
|
assert_equals(el[name], null, `The ${name} property must be null (no attribute)`);
|
|
|
|
el.setAttribute(name, `window.${name}Happened2 = true;`);
|
|
const compiledHandler = el[name];
|
|
assert_equals(
|
|
typeof compiledHandler,
|
|
"function",
|
|
`The ${name} property must be a function (set attribute)`
|
|
);
|
|
compiledHandler();
|
|
assert_true(
|
|
window[`${name}Happened2`],
|
|
"Calling the handler must run the code (set attribute)"
|
|
);
|
|
|
|
window[`${name}Happened2`] = false;
|
|
const clonedEl = el.cloneNode(true);
|
|
const clonedCompiledHandler = clonedEl[name];
|
|
assert_equals(
|
|
typeof clonedCompiledHandler,
|
|
"function",
|
|
`The ${name} property must be a function (clone node)`
|
|
);
|
|
clonedCompiledHandler();
|
|
assert_true(
|
|
window[`${name}Happened2`],
|
|
"Calling the handler must run the code (clone node)"
|
|
);
|
|
|
|
el.setAttribute(name, `window.${name}Happened3 = true;`);
|
|
const newCompiledHandler = el[name];
|
|
assert_equals(
|
|
typeof newCompiledHandler,
|
|
"function",
|
|
`The ${name} property must be a function (modify attribute)`
|
|
);
|
|
newCompiledHandler();
|
|
assert_true(
|
|
window[`${name}Happened3`],
|
|
"Calling the handler must run the code (modify attribute)"
|
|
);
|
|
|
|
el.removeAttribute(name);
|
|
assert_equals(el[name], null, `The ${name} property must be null (remove attribute)`);
|
|
}, `${name}: dynamic changes on the attribute`);
|
|
|
|
promise_test(async () => {
|
|
const element = document.createElementNS(
|
|
"http://www.w3.org/1998/Math/MathML",
|
|
"math"
|
|
);
|
|
let target = undefined;
|
|
element[name] = (e) => { target = e.currentTarget; }
|
|
let eventType = withoutOn;
|
|
if (prefixedAnimationAttributeToEventType.has(eventType)) {
|
|
eventType = prefixedAnimationAttributeToEventType.get(eventType);
|
|
}
|
|
element.dispatchEvent(new Event(eventType));
|
|
assert_equals(target, element, "The event must be fired at the <math> element");
|
|
}, `${name}: dispatching an Event at a <math> element must trigger element.${name}`);
|
|
}
|
|
});
|
|
</script>
|