blob: e464c8300e47e75fc89722b5191cae813b0e7bda [file] [log] [blame]
<!DOCTYPE html>
<title>MathMLElement GlobalEventHandlers</title>
<link rel="author" title="Brian Kardell" href="mailto:bkardell@igalia.com" />
<link rel="help" href="https://mathml-refresh.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"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
<div style="display: none" id="container"></div>
<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"],
]);
setup({ explicit_done: true });
// basic pattern lifted from /html/webappapis/scripting/events/event-handler-all-global-events.html
fetch("/interfaces/html.idl")
.then(res => res.text())
.then(htmlIDL => {
const parsedHTMLIDL = WebIDL2.parse(htmlIDL);
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);
test(() => {
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`);
test(() => {
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`);
test(() => {
const div = document.getElementById("container");
div.innerHTML = `<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`);
test(() => {
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`);
test(() => {
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}`);
}
done();
});
</script>