Update web-platform-tests to revision bc60e6f82132cfc9a5b688c566c7772024b3c15c

This commit is contained in:
WPT Sync Bot 2019-07-26 10:25:50 +00:00
parent 449881f566
commit 29156ca9e2
223 changed files with 7517 additions and 2093 deletions

View file

@ -222,6 +222,7 @@ tasks:
script: >-
export TOXENV=py27;
export HYPOTHESIS_PROFILE=ci;
export PY_COLORS=0;
./tools/ci/run_tc.py \
tools_unittest \
tools/ci/ci_tools_unittest.sh
@ -234,6 +235,7 @@ tasks:
script: >-
export TOXENV=py36;
export HYPOTHESIS_PROFILE=ci;
export PY_COLORS=0;
sudo apt update -qqy;
sudo apt install -qqy python3-pip;
./tools/ci/run_tc.py \

View file

@ -0,0 +1,320 @@
// META: script=support-promises.js
// META: title=Indexed DB and Structured Serializing/Deserializing
// META: timeout=long
// Tests Indexed DB coverage of HTML's Safe "passing of structured data"
// https://html.spec.whatwg.org/multipage/structured-data.html
function describe(value) {
let type, str;
if (typeof value === 'object' && value) {
type = value.__proto__.constructor.name;
// Handle Number(-0), etc.
str = Object.is(value.valueOf(), -0) ? '-0' : String(value);
} else {
type = typeof value;
// Handle primitive -0.
str = Object.is(value, -0) ? '-0' : String(value);
}
return `${type}: ${str}`;
}
function cloneTest(value, verifyFunc) {
promise_test(async t => {
const db = await createDatabase(t, db => {
const store = db.createObjectStore('store');
// This index is not used, but evaluating key path on each put()
// call will exercise (de)serialization.
store.createIndex('index', 'dummyKeyPath');
});
t.add_cleanup(() => {
if (db) {
db.close();
indexedDB.deleteDatabase(db.name);
}
});
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
await promiseForRequest(t, store.put(value, 'key'));
const result = await promiseForRequest(t, store.get('key'));
await verifyFunc(value, result);
await promiseForTransaction(t, tx);
}, describe(value));
}
// Specialization of cloneTest() for objects, with common asserts.
function cloneObjectTest(value, verifyFunc) {
cloneTest(value, async (orig, clone) => {
assert_not_equals(orig, clone);
assert_equals(typeof clone, 'object');
assert_equals(orig.__proto__, clone.__proto__);
await verifyFunc(orig, clone);
});
}
function cloneFailureTest(value) {
promise_test(async t => {
const db = await createDatabase(t, db => {
db.createObjectStore('store');
});
t.add_cleanup(() => {
if (db) {
db.close();
indexedDB.deleteDatabase(db.name);
}
});
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
assert_throws('DataCloneError', () => store.put(value, 'key'));
}, 'Not serializable: ' + describe(value));
}
//
// ECMAScript types
//
// Primitive values: Undefined, Null, Boolean, Number, BigInt, String
const booleans = [false, true];
const numbers = [
NaN,
-Infinity,
-Number.MAX_VALUE,
-0xffffffff,
-0x80000000,
-0x7fffffff,
-1,
-Number.MIN_VALUE,
-0,
0,
1,
Number.MIN_VALUE,
0x7fffffff,
0x80000000,
0xffffffff,
Number.MAX_VALUE,
Infinity,
];
const bigints = [
-12345678901234567890n,
-1n,
0n,
1n,
12345678901234567890n,
];
const strings = [
'',
'this is a sample string',
'null(\0)',
];
[undefined, null].concat(booleans, numbers, bigints, strings)
.forEach(value => cloneTest(value, (orig, clone) => {
assert_equals(orig, clone);
}));
// "Primitive" Objects (Boolean, Number, BigInt, String)
[].concat(booleans, numbers, strings)
.forEach(value => cloneObjectTest(Object(value), (orig, clone) => {
assert_equals(orig.valueOf(), clone.valueOf());
}));
// Dates
[
new Date(-1e13),
new Date(-1e12),
new Date(-1e9),
new Date(-1e6),
new Date(-1e3),
new Date(0),
new Date(1e3),
new Date(1e6),
new Date(1e9),
new Date(1e12),
new Date(1e13)
].forEach(value => cloneTest(value, (orig, clone) => {
assert_not_equals(orig, clone);
assert_equals(typeof clone, 'object');
assert_equals(orig.__proto__, clone.__proto__);
assert_equals(orig.valueOf(), clone.valueOf());
}));
// Regular Expressions
[
new RegExp(),
/abc/,
/abc/g,
/abc/i,
/abc/gi,
/abc/m,
/abc/mg,
/abc/mi,
/abc/mgi,
/abc/gimsuy,
].forEach(value => cloneObjectTest(value, (orig, clone) => {
assert_equals(orig.toString(), clone.toString());
}));
// ArrayBuffer
cloneObjectTest(new Uint8Array([0, 1, 254, 255]).buffer, (orig, clone) => {
assert_array_equals(new Uint8Array(orig), new Uint8Array(clone));
});
// TODO SharedArrayBuffer
// Array Buffer Views
[
new Uint8Array([]),
new Uint8Array([0, 1, 254, 255]),
new Uint16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF]),
new Uint32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF]),
new Int8Array([0, 1, 254, 255]),
new Int16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF]),
new Int32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF]),
new Uint8ClampedArray([0, 1, 254, 255]),
new Float32Array([-Infinity, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, Infinity, NaN]),
new Float64Array([-Infinity, -Number.MAX_VALUE, -Number.MIN_VALUE, 0,
Number.MIN_VALUE, Number.MAX_VALUE, Infinity, NaN])
].forEach(value => cloneObjectTest(value, (orig, clone) => {
assert_array_equals(orig, clone);
}));
// Map
cloneObjectTest(new Map([[1,2],[3,4]]), (orig, clone) => {
assert_array_equals([...orig.keys()], [...clone.keys()]);
assert_array_equals([...orig.values()], [...clone.values()]);
});
// Set
cloneObjectTest(new Set([1,2,3,4]), (orig, clone) => {
assert_array_equals([...orig.values()], [...clone.values()]);
});
// Error
[
new Error(),
new Error('abc', 'def'),
new EvalError(),
new EvalError('ghi', 'jkl'),
new RangeError(),
new RangeError('ghi', 'jkl'),
new ReferenceError(),
new ReferenceError('ghi', 'jkl'),
new SyntaxError(),
new SyntaxError('ghi', 'jkl'),
new TypeError(),
new TypeError('ghi', 'jkl'),
new URIError(),
new URIError('ghi', 'jkl'),
].forEach(value => cloneObjectTest(value, (orig, clone) => {
assert_equals(orig.name, clone.name);
assert_equals(orig.message, clone.message);
}));
// Arrays
[
[],
[1,2,3],
Object.assign(
['foo', 'bar'],
{10: true, 11: false, 20: 123, 21: 456, 30: null}),
Object.assign(
['foo', 'bar'],
{a: true, b: false, foo: 123, bar: 456, '': null}),
].forEach(value => cloneObjectTest(value, (orig, clone) => {
assert_array_equals(orig, clone);
assert_array_equals(Object.keys(orig), Object.keys(clone));
Object.keys(orig).forEach(key => {
assert_equals(orig[key], clone[key], `Property ${key}`);
});
}));
// Objects
cloneObjectTest({foo: true, bar: false}, (orig, clone) => {
assert_array_equals(Object.keys(orig), Object.keys(clone));
Object.keys(orig).forEach(key => {
assert_equals(orig[key], clone[key], `Property ${key}`);
});
});
//
// [Serializable] Platform objects
//
// TODO: Test these additional interfaces:
// * DOMQuad
// * DOMException
// * DetectedText, DetectedFace, DetectedBarcode
// * RTCCertificate
// Geometry types
[
new DOMMatrix(),
new DOMMatrixReadOnly(),
new DOMPoint(),
new DOMPointReadOnly(),
new DOMRect,
new DOMRectReadOnly(),
].forEach(value => cloneObjectTest(value, (orig, clone) => {
Object.keys(orig.__proto__).forEach(key => {
assert_equals(orig[key], clone[key], `Property ${key}`);
});
}));
// ImageData
const image_data = new ImageData(8, 8);
for (let i = 0; i < 256; ++i) {
image_data.data[i] = i;
}
cloneObjectTest(image_data, (orig, clone) => {
assert_equals(orig.width, clone.width);
assert_equals(orig.height, clone.height);
assert_array_equals(orig.data, clone.data);
});
// Blob
cloneObjectTest(
new Blob(['This is a test.'], {type: 'a/b'}),
async (orig, clone) => {
assert_equals(orig.size, clone.size);
assert_equals(orig.type, clone.type);
assert_equals(await orig.text(), await clone.text());
});
// File
cloneObjectTest(
new File(['This is a test.'], 'foo.txt', {type: 'c/d'}),
async (orig, clone) => {
assert_equals(orig.size, clone.size);
assert_equals(orig.type, clone.type);
assert_equals(orig.name, clone.name);
assert_equals(orig.lastModified, clone.lastModified);
assert_equals(String(orig.lastModifiedDate),
String(clone.lastModifiedDate));
assert_equals(await orig.text(), await clone.text());
});
// FileList - exposed in Workers, but not constructable.
if ('document' in self) {
// TODO: Test with populated list.
cloneObjectTest(
Object.assign(document.createElement('input'),
{type: 'file', multiple: true}).files,
async (orig, clone) => {
assert_equals(orig.length, clone.length);
});
}
//
// Non-serializable types
//
[
// ECMAScript types
function() {},
Symbol('desc'),
// Non-[Serializable] platform objects
self,
new Event(''),
new MessageChannel()
].forEach(cloneFailureTest);

View file

@ -0,0 +1,20 @@
import collections
import json
import os
def main():
'''Formats spec.src.json.'''
script_directory = os.path.dirname(os.path.abspath(__file__))
for dir in ['mixed-content', 'referrer-policy']:
filename = os.path.join(script_directory, '..', '..', '..', dir,
'spec.src.json')
spec = json.load(
open(filename, 'r'), object_pairs_hook=collections.OrderedDict)
with open(filename, 'w') as f:
f.write(json.dumps(spec, indent=2, separators=(',', ': ')))
f.write('\n')
if __name__ == '__main__':
main()

View file

@ -28,7 +28,10 @@ def expand_pattern(expansion_pattern, test_expansion_schema):
return expansion
def permute_expansion(expansion, artifact_order, selection = {}, artifact_index = 0):
def permute_expansion(expansion,
artifact_order,
selection={},
artifact_index=0):
assert isinstance(artifact_order, list), "artifact_order should be a list"
if artifact_index >= len(artifact_order):
@ -39,20 +42,23 @@ def permute_expansion(expansion, artifact_order, selection = {}, artifact_index
for artifact_value in expansion[artifact_key]:
selection[artifact_key] = artifact_value
for next_selection in permute_expansion(expansion,
artifact_order,
selection,
artifact_index + 1):
for next_selection in permute_expansion(expansion, artifact_order,
selection, artifact_index + 1):
yield next_selection
def generate_selection(config, selection, spec, test_html_template_basename):
# TODO: Refactor out this referrer-policy-specific part.
if 'referrer_policy' in spec:
# Oddball: it can be None, so in JS it's null.
selection['referrer_policy'] = spec['referrer_policy']
# Dumps the test config `selection` into a serialized JSON string.
# We omit `name` parameter because it is not used by tests.
def dump_test_parameters(selection):
selection = dict(selection)
del selection['name']
test_parameters = json.dumps(selection, indent=2, separators=(',', ':'))
return json.dumps(
selection, indent=2, separators=(',', ': '), sort_keys=True)
def generate_selection(config, selection, spec, test_html_template_basename):
test_parameters = dump_test_parameters(selection)
# Adjust the template for the test invoking JS. Indent it to look nice.
indent = "\n" + " " * 8
test_parameters = test_parameters.replace("\n", indent)
@ -66,14 +72,16 @@ def generate_selection(config, selection, spec, test_html_template_basename):
''' % (config.test_case_name, test_parameters)
selection['spec_name'] = spec['name']
selection['test_page_title'] = config.test_page_title_template % spec['title']
selection[
'test_page_title'] = config.test_page_title_template % spec['title']
selection['spec_description'] = spec['description']
selection['spec_specification_url'] = spec['specification_url']
selection['helper_js'] = config.helper_js
selection['sanity_checker_js'] = config.sanity_checker_js
selection['spec_json_js'] = config.spec_json_js
test_filename = os.path.join(config.spec_directory, config.test_file_path_pattern % selection)
test_filename = os.path.join(config.spec_directory,
config.test_file_path_pattern % selection)
test_headers_filename = test_filename + ".headers"
test_directory = os.path.dirname(test_filename)
@ -83,14 +91,15 @@ def generate_selection(config, selection, spec, test_html_template_basename):
html_template_filename = os.path.join(util.template_directory,
test_html_template_basename)
generated_disclaimer = disclaimer_template \
% {'generating_script_filename': os.path.relpath(__file__,
% {'generating_script_filename': os.path.relpath(sys.argv[0],
util.test_root_directory),
'html_template_filename': os.path.relpath(html_template_filename,
util.test_root_directory)}
# Adjust the template for the test invoking JS. Indent it to look nice.
selection['generated_disclaimer'] = generated_disclaimer.rstrip()
selection['test_description'] = config.test_description_template % selection
selection[
'test_description'] = config.test_description_template % selection
selection['test_description'] = \
selection['test_description'].rstrip().replace("\n", "\n" + " " * 33)
@ -123,9 +132,11 @@ def generate_test_source_files(config, spec_json, target):
specification = spec_json['specification']
spec_json_js_template = util.get_template('spec_json.js.template')
generated_spec_json_filename = os.path.join(config.spec_directory, "spec_json.js")
util.write_file(generated_spec_json_filename,
spec_json_js_template % {'spec_json': json.dumps(spec_json)})
generated_spec_json_filename = os.path.join(config.spec_directory,
"spec_json.js")
util.write_file(
generated_spec_json_filename,
spec_json_js_template % {'spec_json': json.dumps(spec_json)})
# Choose a debug/release template depending on the target.
html_template = "test.%s.html.template" % target
@ -149,13 +160,18 @@ def generate_test_source_files(config, spec_json, target):
output_dict = {}
for expansion_pattern in spec['test_expansion']:
expansion = expand_pattern(expansion_pattern, test_expansion_schema)
expansion = expand_pattern(expansion_pattern,
test_expansion_schema)
for selection in permute_expansion(expansion, artifact_order):
selection['delivery_key'] = spec_json['delivery_key']
selection_path = config.selection_pattern % selection
if not selection_path in exclusion_dict:
if selection_path in output_dict:
if expansion_pattern['expansion'] != 'override':
print("Error: %s's expansion is default but overrides %s" % (selection['name'], output_dict[selection_path]['name']))
print(
"Error: %s's expansion is default but overrides %s"
% (selection['name'],
output_dict[selection_path]['name']))
sys.exit(1)
output_dict[selection_path] = copy.deepcopy(selection)
else:
@ -163,24 +179,30 @@ def generate_test_source_files(config, spec_json, target):
for selection_path in output_dict:
selection = output_dict[selection_path]
generate_selection(config,
selection,
spec,
html_template)
generate_selection(config, selection, spec, html_template)
def main(config):
parser = argparse.ArgumentParser(description='Test suite generator utility')
parser.add_argument('-t', '--target', type = str,
choices = ("release", "debug"), default = "release",
help = 'Sets the appropriate template for generating tests')
parser.add_argument('-s', '--spec', type = str, default = None,
help = 'Specify a file used for describing and generating the tests')
parser = argparse.ArgumentParser(
description='Test suite generator utility')
parser.add_argument(
'-t',
'--target',
type=str,
choices=("release", "debug"),
default="release",
help='Sets the appropriate template for generating tests')
parser.add_argument(
'-s',
'--spec',
type=str,
default=None,
help='Specify a file used for describing and generating the tests')
# TODO(kristijanburnik): Add option for the spec_json file.
args = parser.parse_args()
if args.spec:
config.spec_directory = args.spec
config.spec_directory = args.spec
spec_filename = os.path.join(config.spec_directory, "spec.src.json")
spec_json = util.load_spec_json(spec_filename)

View file

@ -3,7 +3,7 @@
from __future__ import print_function
import json, sys
from common_paths import *
def assert_non_empty_string(obj, field):
assert field in obj, 'Missing field "%s"' % field
@ -31,12 +31,13 @@ def assert_contains(obj, field):
def assert_value_from(obj, field, items):
assert obj[field] in items, \
'Field "%s" must be from: %s' % (field, str(items))
assert obj[field] in items, \
'Field "%s" must be from: %s' % (field, str(items))
def assert_atom_or_list_items_from(obj, field, items):
if isinstance(obj[field], basestring) or isinstance(obj[field], int):
if isinstance(obj[field], basestring) or isinstance(
obj[field], int) or obj[field] is None:
assert_value_from(obj, field, items)
return
@ -71,13 +72,15 @@ def assert_valid_artifact(exp_pattern, artifact_key, schema):
assert_valid_artifact(exp_pattern[artifact_key], sub_artifact_key,
sub_schema)
def validate(spec_json, details):
""" Validates the json specification for generating tests. """
details['object'] = spec_json
assert_contains_only_fields(spec_json, ["specification",
"test_expansion_schema",
"excluded_tests"])
assert_contains_only_fields(spec_json, [
"specification", "delivery_key", "test_expansion_schema",
"excluded_tests"
])
assert_non_empty_list(spec_json, "specification")
assert_non_empty_dict(spec_json, "test_expansion_schema")
assert_non_empty_list(spec_json, "excluded_tests")
@ -93,11 +96,10 @@ def validate(spec_json, details):
details['object'] = spec
# Validate required fields for a single spec.
assert_contains_only_fields(spec, ['name',
'title',
'description',
'specification_url',
'test_expansion'])
assert_contains_only_fields(spec, [
'name', 'title', 'description', 'specification_url',
'test_expansion'
])
assert_non_empty_string(spec, 'name')
assert_non_empty_string(spec, 'title')
assert_non_empty_string(spec, 'description')
@ -123,14 +125,10 @@ def validate(spec_json, details):
# Validate the test_expansion schema members.
details['object'] = test_expansion_schema
assert_contains_only_fields(test_expansion_schema, ['expansion',
'source_scheme',
'opt_in_method',
'context_nesting',
'redirection',
'subresource',
'origin',
'expectation'])
assert_contains_only_fields(test_expansion_schema, [
'expansion', 'source_scheme', 'delivery_type', 'delivery_value',
'redirection', 'subresource', 'origin', 'expectation'
])
# Validate excluded tests.
details['object'] = excluded_tests
for excluded_test_expansion in excluded_tests:
@ -139,10 +137,8 @@ def validate(spec_json, details):
details['object'] = excluded_test_expansion
for artifact in test_expansion_schema:
details['test_expansion_field'] = artifact
assert_valid_artifact(
excluded_test_expansion,
artifact,
test_expansion_schema[artifact])
assert_valid_artifact(excluded_test_expansion, artifact,
test_expansion_schema[artifact])
del details['test_expansion_field']
del details['object']
@ -159,7 +155,7 @@ def assert_valid_spec_json(spec_json):
def main():
spec_json = load_spec_json();
spec_json = load_spec_json()
assert_valid_spec_json(spec_json)
print("Spec JSON is valid.")

View file

@ -3,10 +3,10 @@ from __future__ import print_function
import os, sys, json, re
script_directory = os.path.dirname(os.path.abspath(__file__))
template_directory = os.path.abspath(os.path.join(script_directory,
'template'))
test_root_directory = os.path.abspath(os.path.join(script_directory,
'..', '..', '..'))
template_directory = os.path.abspath(
os.path.join(script_directory, 'template'))
test_root_directory = os.path.abspath(
os.path.join(script_directory, '..', '..', '..'))
def get_template(basename):
@ -20,22 +20,22 @@ def write_file(filename, contents):
def read_nth_line(fp, line_number):
fp.seek(0)
for i, line in enumerate(fp):
if (i + 1) == line_number:
return line
fp.seek(0)
for i, line in enumerate(fp):
if (i + 1) == line_number:
return line
def load_spec_json(path_to_spec):
re_error_location = re.compile('line ([0-9]+) column ([0-9]+)')
with open(path_to_spec, "r") as f:
try:
return json.load(f)
return json.load(f)
except ValueError as ex:
print(ex.message)
match = re_error_location.search(ex.message)
if match:
line_number, column = int(match.group(1)), int(match.group(2))
print(read_nth_line(f, line_number).rstrip())
print(" " * (column - 1) + "^")
sys.exit(1)
print(ex.message)
match = re_error_location.search(ex.message)
if match:
line_number, column = int(match.group(1)), int(match.group(2))
print(read_nth_line(f, line_number).rstrip())
print(" " * (column - 1) + "^")
sys.exit(1)

View file

@ -0,0 +1,19 @@
'use strict';
promise_test(async t => {
await cookieStore.set('cookie-name', 'cookie-value', { secure: false });
t.add_cleanup(async () => { await cookieStore.delete('cookie-name'); });
await cookieStore.delete('cookie-name');
const cookie = await cookieStore.get('cookie-name');
assert_equals(cookie, null);
}, 'cookieStore.delete(name) can delete an insecure cookie');
promise_test(async t => {
await cookieStore.set('cookie-name', 'cookie-value', { secure: false });
t.add_cleanup(async () => { await cookieStore.delete('cookie-name'); });
await cookieStore.delete({ name: 'cookie-name' });
const cookie = await cookieStore.get('cookie-name');
assert_equals(cookie, null);
}, 'cookieStore.delete(options) can delete an insecure cookie');

View file

@ -5,31 +5,32 @@
'use strict';
promise_test(async () => {
const idl = await fetch('/interfaces/credential-management.idl').then(r => r.text());
const html = await fetch('/interfaces/html.idl').then(r => r.text());
idl_test(
['credential-management'],
['html', 'dom'],
idl_array => {
idl_array.add_objects({
CredentialsContainer: ['navigator.credentials'],
PasswordCredential: ['passwordCredential'],
FederatedCredential: ['federatedCredential'],
});
var idl_array = new IdlArray();
idl_array.add_idls(idl);
idl_array.add_dependency_idls(html);
idl_array.add_objects({
CredentialsContainer: ['navigator.credentials'],
PasswordCredential: [
`new PasswordCredential({
try {
self.passwordCredential = new PasswordCredential({
id: "id",
password: "pencil",
iconURL: "https://example.com/",
name: "name"
})`
],
FederatedCredential: [
`new FederatedCredential({
});
} catch (e) {}
try {
self.federatedCredential = new FederatedCredential({
id: "id",
provider: "https://example.com",
iconURL: "https://example.com/",
name: "name"
})`
]
});
idl_array.test();
})
});
} catch (e) {}
}
)

View file

@ -8,3 +8,4 @@
display: none
}
</style>
<body></body>

View file

@ -6,3 +6,4 @@
html { display: none; }
body { background: red; }
</style>
<body></body>

View file

@ -14,3 +14,4 @@
}));
};
</script>
<body></body>

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<title>CSS Backgrounds and Borders Test: don't propagate body background when display:contents</title>
<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#special-backgrounds">
<link rel="match" href="../reference/blank.html">
<style>
body {
background: red;
display: contents
}
</style>
<body></body>

View file

@ -13,7 +13,7 @@
<div id="target"></div>
<script>
test_computed_value("border-image-source", "none");
test_computed_value("border-image-source", 'url("http://www.example.com/")');
test_computed_value("border-image-source", 'url("http://{{host}}/")');
test(() => {
const target = document.getElementById('target');

View file

@ -0,0 +1,51 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html><head>
<meta charset="utf-8">
<title>Reference: Insert text node as first child in LI</title>
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.org">
<style>
ul.inside { list-style-position: inside; }
.before::before { content: "before"; }
.after::after { content: "after"; }
</style>
</head>
<body>
<ul class="inside">
<li>AB</li>
</ul>
<ul class="inside">
<li class="before">AB</li>
</ul>
<ul class="inside">
<li class="after">AB</li>
</ul>
<ul class="inside">
<li class="before after">AB</li>
</ul>
<ul>
<li>AB</li>
</ul>
<ul>
<li class="before">AB</li>
</ul>
<ul>
<li class="after">AB</li>
</ul>
<ul>
<li class="before after">AB</li>
</ul>
</body>
</html>

View file

@ -0,0 +1,60 @@
<!DOCTYPE HTML>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html class="reftest-wait"><head>
<meta charset="utf-8">
<title>Test: Insert text node as first child in LI</title>
<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.org">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1567773">
<link rel="match" href="li-insert-child-ref.html">
<style>
ul.inside { list-style-position: inside; }
.before::before { content: "before"; }
.after::after { content: "after"; }
</style>
</head>
<body>
<ul class="inside">
<li>B</li>
</ul>
<ul class="inside">
<li class="before">B</li>
</ul>
<ul class="inside">
<li class="after">B</li>
</ul>
<ul class="inside">
<li class="before after">B</li>
</ul>
<ul>
<li>B</li>
</ul>
<ul>
<li class="before">B</li>
</ul>
<ul>
<li class="after">B</li>
</ul>
<ul>
<li class="before after">B</li>
</ul>
<script>
document.body.offsetHeight;
let items = Array.prototype.slice.call(document.querySelectorAll('li'));
items.map(li => li.insertBefore(document.createTextNode('A'), li.firstChild));
document.documentElement.className = '';
</script>
</body>
</html>

View file

@ -15,10 +15,10 @@
test_computed_value('list-style', 'none', 'outside none none');
test_computed_value('list-style', 'inside', 'inside none disc');
test_computed_value('list-style', 'url("https://example.com/")', 'outside url("https://example.com/") disc');
test_computed_value('list-style', 'url("https://{{host}}/")', 'outside url("https://{{host}}/") disc');
test_computed_value('list-style', 'square', 'outside none square');
test_computed_value('list-style', 'inside url("https://example.com/") square');
test_computed_value('list-style', 'inside url("https://{{host}}/") square');
</script>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!doctype html>
<title>CSS Overflow Test: Propagation of body overflow to viewport</title>
<link rel="help" href="https://drafts.csswg.org/css-overflow/#overflow-propagation">
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148">
<link rel="match" href="reference/overflow-body-propagation-ref.html">
<style>
body {
overflow: scroll;
margin-top: 100px;
}
</style>
<body>The viewport should have scrollbars, not the body.</body>

View file

@ -0,0 +1,6 @@
<!doctype html>
<title>CSS Overflow Test: Do not propagate overflow of display:none body to viewport</title>
<link rel="help" href="https://drafts.csswg.org/css-overflow-3/#overflow-propagation">
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148">
<link rel="match" href="/css/reference/blank.html">
<body style="display:none; overflow:scroll"></body>

View file

@ -0,0 +1,6 @@
<!doctype html>
<title>CSS Overflow Test: Do not propagate overflow of display:contents body to viewport</title>
<link rel="help" href="https://drafts.csswg.org/css-overflow-3/#overflow-propagation">
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148">
<link rel="match" href="/css/reference/blank.html">
<body style="display:contents; overflow:scroll"></body>

View file

@ -0,0 +1,14 @@
<!doctype html>
<link rel="help" href="https://drafts.csswg.org/css-overflow/#overflow-propagation">
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/4148">
<link rel="match" href="reference/overflow-body-no-propagation-ref.html">
<style>
html {
overflow: hidden;
}
body {
overflow: scroll;
margin-top: 100px;
}
</style>
<body>The body should have scrollbars, not the viewport.</body>

View file

@ -0,0 +1,5 @@
<!doctype html>
<html style="overflow:auto">
<title>CSS Overflow Test Reference</title>
<body style="margin-top:100px;overflow:scroll">The body should have scrollbars, not the viewport.</body>
</html>

View file

@ -0,0 +1,5 @@
<!doctype html>
<html style="overflow:scroll">
<title>CSS Overflow Test Reference</title>
<body style="margin-top:100px">The viewport should have scrollbars, not the body.</body>
</html>

View file

@ -3,7 +3,7 @@
<title>CSS Overflow: -webkit-line-clamp with an empty line</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="help" href="https://drafts.csswg.org/css-overflow-3/#webkit-line-clamp">
<link rel="match" href="about:blank">
<link rel="match" href="/css/reference/blank.html">
<style>
.clamp {
display: -webkit-box;

View file

@ -52,9 +52,9 @@ test(function() {
test(function() {
inlineStyle.setProperty('--length', 'hi');
inlineStyle.setProperty('--color', '20');
assert_equals(inlineStyle.getPropertyValue('--length'), '5');
assert_equals(inlineStyle.getPropertyValue('--color'), 'hello');
}, "Values not matching the registered type can't be set");
assert_equals(inlineStyle.getPropertyValue('--length'), 'hi');
assert_equals(inlineStyle.getPropertyValue('--color'), '20');
}, "Values not matching the registered type can still be set");
test(function() {
inlineStyle.removeProperty('--length');
@ -66,8 +66,9 @@ test(function() {
}, "Values can be removed from inline styles");
test(function() {
sheetStyle.setProperty('--length', 'banana'); // Invalid, no change
assert_equals(computedStyle.getPropertyValue('--length'), '10px');
// 'banana' is not a valid <length>, but still accepted.
sheetStyle.setProperty('--length', 'banana');
assert_equals(computedStyle.getPropertyValue('--length'), '0px');
sheetStyle.setProperty('--length', '20px');
assert_equals(computedStyle.getPropertyValue('--length'), '20px');
sheetStyle.setProperty('--length', 'initial');

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<link rel="help" href="https://crbug.com/926167">
<style>
#container {
width: 200px;
height: 150px;
border: 1px solid black;
overflow: scroll;
}
#target {
width: 100px;
height: 50px;
background: green;
transform: scale(4);
}
</style>
<!-- -->
<div id="container">
<div id="target"></div>
</div>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>CSS Overflow: css-overflow-3</title>
<link rel="author" href="mailto:atotic@google.com">
<link rel="help" href="https://crbug.com/926167">
<link rel="match" href="scrollbars-chrome-bug-001-ref.html">
<meta name="assert" content="scrollbars keep up to date with a changing transform">
<style>
#container {
width: 200px;
height: 150px;
border: 1px solid black;
overflow: scroll;
}
#target {
width: 100px;
height: 50px;
background: green;
transform: scale(1);
}
</style>
<!-- -->
<div id="container">
<div id="target"></div>
</div>
<script>
// 1st transform triggers layer creation, and full layout.
// 2nd transform just updates overflow, which does not update scrollbars.
// This triggers the bug.
document.body.offsetTop;
document.querySelector("#target").style.transform = "scale(1.5)";
document.body.offsetTop;
document.querySelector("#target").style.transform = "scale(4.0)";
</script>

View file

@ -15,6 +15,11 @@
test_computed_value("shape-image-threshold", "-7", "0");
test_computed_value("shape-image-threshold", "0.5");
test_computed_value("shape-image-threshold", "12.5", "1");
// https://github.com/w3c/csswg-drafts/issues/4102
test_computed_value("shape-image-threshold", "-100%", "0");
test_computed_value("shape-image-threshold", "50%", "0.5");
test_computed_value("shape-image-threshold", "300%", "1");
</script>
</body>
</html>

View file

@ -14,7 +14,6 @@
<script>
test_invalid_value("shape-image-threshold", "auto");
test_invalid_value("shape-image-threshold", "10px");
test_invalid_value("shape-image-threshold", "100%");
</script>
</body>
</html>

View file

@ -14,6 +14,11 @@
<script>
test_valid_value("shape-image-threshold", "12.5");
test_valid_value("shape-image-threshold", "-7");
// https://github.com/w3c/csswg-drafts/issues/4102
test_valid_value("shape-image-threshold", "-100%", "-1");
test_valid_value("shape-image-threshold", "50%", "0.5");
test_valid_value("shape-image-threshold", "300%", "3");
</script>
</body>
</html>

View file

@ -0,0 +1,40 @@
<!doctype HTML>
<meta charset="utf8">
<title>Perspective with transforms equivalencies.</title>
<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org">
<style>
#container {
transform: translate(-200px, -200px);
width: 500px;
height: 500px;
perspective: 500px;
}
#container > div {
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: translateZ(-250px) rotateZ(45deg);
}
#container > div > div {
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(3, 121, 255, 0.3);
box-sizing: border-box;
border: 3px solid black;
}
#one { transform: rotateY(90deg) translateZ(250px); }
</style>
<div id="container">
<div>
<div id="one"></div>
<div id="one"></div>
<div id="one"></div>
<div id="one"></div>
</div>
</div>

View file

@ -0,0 +1,52 @@
<!doctype HTML>
<meta charset="utf8">
<title>Perspective with transforms equivalencies.</title>
<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org">
<link rel="help" href="http://www.w3.org/TR/css-transforms-2/#perspective-property">
<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-property">
<link rel="match" href="perspective-transforms-equivalence-ref.html">
<!--
Perspective with different transforms can have small anti-aliasing
pixel differences, so the test should fuzzy patch to the ref.
-->
<meta name="fuzzy" content="maxDifference=10;totalPixels=10">
<style>
#container {
transform: translate(-200px, -200px);
width: 500px;
height: 500px;
perspective: 500px;
}
#container > div {
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: translateZ(-250px) rotateZ(45deg);
}
#container > div > div {
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(3, 121, 255, 0.3);
box-sizing: border-box;
border: 3px solid black;
}
/* The following four should be equivalent. */
#one { transform: rotateY(90deg) translateZ(250px); }
#two { transform: rotateZ(90deg) rotateX(90deg) translateZ(250px); }
#three { transform: rotateY(-90deg) translateZ(-250px); }
#four { transform: rotateZ(-90deg) rotateX(90deg) translateZ(-250px); }
</style>
<div id="container">
<div>
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
<div id="four"></div>
</div>
</div>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<title>Don't crash when setting a CSSVariableReferenceValue</title>
<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#cssvariablereferencevalue">
<link rel="help" href="https://crbug.com/986710<">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
:root { --x: green; }
</style>
<div id="target"></div>
<script>
test(function(){
let ref = new CSSVariableReferenceValue('--x')
let unparsed = new CSSUnparsedValue([' ', ref]);
target.attributeStyleMap.set('color', unparsed);
assert_equals('rgb(0, 128, 0)', target.computedStyleMap().get('color').toString());
}, 'Do not crash when referencing a variable with CSSVariableReferenceValue');
</script>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test reference</title>
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
<style>
.v-rl {
writing-mode: vertical-rl;
width: 200px;
}
span {
-webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/
text-combine-upright: all;
white-space: normal;
}
#test { color: blue; }
#ref { color: orange; }
</style>
<p>Test passes if the blue and orange lines of text are identical.
<div class=v-rl>
<div id=test><span>12</span><span>34</span><span>5&nbsp;6</span>えお</div>
<div id=ref><span>12</span><span>34</span><span>5&nbsp;6</span>えお</div>
</div>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test Reference</title>
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
<style>
.v-rl {
writing-mode: vertical-rl;
width: 200px;
}
span {
-webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/
text-combine-upright: all;
white-space: pre;
}
#test { color: blue; }
#ref { color: orange; }
</style>
<p>Test passes if the blue and orange lines of text are identical.
<div class=v-rl>
<div id=test><span>&nbsp;&nbsp;12</span><span>34&nbsp;&nbsp;</span><span>5&nbsp;&nbsp;&nbsp;&nbsp;6</span>えお</div>
<div id=ref><span>&nbsp;&nbsp;12</span><span>34&nbsp;&nbsp;</span><span>5&nbsp;&nbsp;&nbsp;&nbsp;6</span>えお</div>
</div>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test Reference</title>
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
<style>
.v-rl {
writing-mode: vertical-rl;
width: 200px;
}
span {
display: inline-block;
height: 1em;
}
#test { color: blue; }
#test2 { color: brown; }
#ref { color: orange; }
.v-rl > div {
display: inline-block;
border: solid;
margin: 0 5px;
}
</style>
<p>Test passes if the blue, orange, brown boxes are identical.
<div class=v-rl>
<div id=test>あいう<span></span>えお<span></span></div>
<br>
<div id=test2>あいう<span></span>えお<span></span></div>
<br>
<div id=ref>あいう<span></span>えお<span></span></div>
</div>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Writing Modes Test: white-space:normal space processing in text-combine-horizontal</title>
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
<link rel="help" href="https://www.w3.org/TR/css-writing-modes-4/#text-combine-layout">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-rules">
<link rel="match" href="reference/tcy-white-space-processing-001-ref.html">
<meta name="assert" content="Spaces with white-space:normal in a text-combine horizontal is trimmed at the start and end, and collapsed in the middle.">
<style>
.v-rl {
writing-mode: vertical-rl;
width: 200px;
}
span {
-webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/
text-combine-upright: all;
white-space: normal;
}
#test { color: blue; }
#ref { color: orange; }
</style>
<p>Test passes if the blue and orange lines of text are identical.
<div class=v-rl>
<div id=test><span> 12</span><span>34 </span><span>5 6</span>えお</div>
<div id=ref><span>12</span><span>34</span><span>5&nbsp;6</span>えお</div>
</div>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Writing Modes Test: white-space:pre space processing in text-combine-horizontal</title>
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
<link rel="help" href="https://www.w3.org/TR/css-writing-modes-4/#text-combine-layout">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-rules">
<link rel="match" href="reference/tcy-white-space-processing-002-ref.html">
<meta name="assert" content="Spaces with white-space:pre in a text-combine-upright are preserved">
<style>
.v-rl {
writing-mode: vertical-rl;
width: 200px;
}
span {
-webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/
text-combine-upright: all;
white-space: pre;
}
#test { color: blue; }
#ref { color: orange; }
</style>
<p>Test passes if the blue and orange lines of text are identical.
<div class=v-rl>
<div id=test><span> 12</span><span>34 </span><span>5 6</span>えお</div>
<div id=ref><span>&nbsp;&nbsp;12</span><span>34&nbsp;&nbsp;</span><span>5&nbsp;&nbsp;&nbsp;&nbsp;6</span>えお</div>
</div>

View file

@ -0,0 +1,44 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Writing Modes Test: white space only text-combine-horizontal</title>
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
<link rel="help" href="https://www.w3.org/TR/css-writing-modes-4/#text-combine-layout">
<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-rules">
<link rel="match" href="reference/tcy-white-space-processing-003-ref.html">
<meta name="assert" content="a text-combine-upright with only white-space is preserved as a 1em square, including at the end of the containing line, regardless of the value of the white-space property">
<style>
.v-rl {
writing-mode: vertical-rl;
width: 200px;
}
#test span {
-webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/
text-combine-upright: all;
}
#test2 span {
-webkit-text-combine: horizontal; /*testing the layout text-combine, not it's support in general*/
text-combine-upright: all;
white-space: pre;
}
#ref span {
display: inline-block;
height: 1em;
}
#test { color: blue; }
#test2 { color: brown; }
#ref { color: orange; }
.v-rl > div {
display: inline-block;
border: solid;
margin: 0 5px;
}
</style>
<p>Test passes if the blue, orange, brown boxes are identical.
<div class=v-rl>
<div id=test>あいう<span> </span>えお<span> </span></div>
<br>
<div id=test2>あいう<span> </span>えお<span> </span></div>
<br>
<div id=ref>あいう<span></span>えお<span></span></div>
</div>

View file

@ -37,11 +37,10 @@ on [file names][file-name-flags].
#### Support Files
Various support files are available in in the `/common/` and `/media/`
directories (web-platform-tests) and `/support/` (in css/). Reusing
existing resources is encouraged where possible, as is adding
generally useful files to these common areas rather than to specific
test suites.
Various support files are available in in the directories named `/common/`,
`/media/`, and `/css/support/`. Reusing existing resources is encouraged where
possible, as is adding generally-useful files to these common areas rather than
to specific test suites.
#### Tools
@ -61,9 +60,17 @@ subdirectory and put your script there.
### File Formats
Tests must be HTML or XML (inc. XHTML and SVG) files; some
testharness.js tests
are [auto-generated from JS files][server features].
Tests are generally formatted as HTML (including XHTML) or XML (including SVG).
Some test types support other formats:
- [testharness.js tests](testharness) may be expressed as JavaScript files
([the WPT server automatically generates the HTML documents for these][server
features])
- [WebDriver specification tests](wdspec) are expressed as Python files
The best way to determine how to format a new test is to look at how similar
tests have been formatted. You can also ask for advice in [the project's IRC
room][IRC].
### Character Encoding
@ -179,6 +186,7 @@ for CSS have some additional requirements for:
[server features]: server-features
[assumptions]: assumptions
[ahem]: ahem
[IRC]: irc://irc.w3.org:6667/testing
[lint-tool]: lint-tool
[css-metadata]: css-metadata
[css-user-styles]: css-user-styles

View file

@ -5,10 +5,6 @@ these are especially using for [visual](visual) tests which need to be manually
judged and following common patterns makes it easier to correctly tell if a
given test passed or not.
## Make tests self-describing
Tests should make it obvious when they pass and when they fail. It shouldn't be necessary to consult the specification to figure out whether a test has passed of failed.
## Indicating success
Success is largely indicated by the color green; typically in one of
@ -80,7 +76,7 @@ ways:
* Silver or light gray is often used for irrelevant content, such as
filler text.
Obviously, none of this can be taken as absolute rules, as testing of
None of these rules are absolute because testing
color-related functionality will necessitate using some of these
colors!

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>ElementTiming: element is only exposed for fully active documents.</title>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe src="resources/iframe-stores-entry.html" id="ifr"></iframe>
<script>
let t = async_test('Only expose element attribute for fully active documents');
window.triggerTest = t.step_func_done(elementEntry => {
assert_not_equals(elementEntry.element, null);
const iframe = document.getElementById('ifr');
iframe.remove();
assert_equals(elementEntry.element, null);
});
</script>
</body>

View file

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Element Timing: entry does not change its id or identifier value</title>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/element-timing-helpers.js"></script>
<p elementtiming='my_identifier' id='my_id'>Text</p>
<script>
async_test(function (t) {
if (!window.PerformanceElementTiming) {
assert_unreached("PerformanceElementTiming is not implemented");
}
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
assert_equals(entry.id, 'my_id');
assert_equals(entry.identifier, 'my_identifier');
const element = document.getElementById('my_id');
element.id = 'other_id';
element.setAttribute('elementtiming', 'other_identifier');
assert_equals(entry.id, 'my_id');
assert_equals(entry.identifier, 'my_identifier');
})
);
observer.observe({type: 'element', buffered: true});
}, 'PerformanceElementTiming id and identifier do not change when Element changes.');
</script>
</body>

View file

@ -0,0 +1,16 @@
// META: script=/resources/WebIDLParser.js
// META: script=/resources/idlharness.js
// https://wicg.github.io/element-timing/
'use strict';
idl_test(
['element-timing'],
['performance-timeline', 'dom'],
idl_array => {
idl_array.add_objects({
// PerformanceElementTiming: [ TODO ]
});
}
);

View file

@ -4,13 +4,22 @@ function checkElementInternal(entry, expectedUrl, expectedIdentifier, expectedID
assert_equals(entry.entryType, 'element');
assert_equals(entry.url, expectedUrl);
assert_equals(entry.identifier, expectedIdentifier);
assert_equals(entry.startTime, 0);
if (beforeRender != 0) {
// In this case, renderTime is not 0.
assert_equals(entry.startTime, entry.renderTime);
} else {
// In this case, renderTime is 0, so compare to loadTime.
assert_equals(entry.startTime, entry.loadTime);
}
assert_equals(entry.duration, 0);
assert_equals(entry.id, expectedID);
assert_greater_than_equal(entry.renderTime, beforeRender);
assert_greater_than_equal(performance.now(), entry.renderTime);
if (expectedElement !== null)
if (expectedElement !== null) {
assert_equals(entry.element, expectedElement);
assert_equals(entry.identifier, expectedElement.elementTiming);
assert_equals(entry.id, expectedElement.id);
}
}
// Checks that this is an ElementTiming entry with url |expectedUrl|. It also

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<p elementtiming='text'>Text</p>
<script>
const observer = new PerformanceObserver(entryList => {
window.parent.triggerTest(entryList.getEntries()[0]);
});
observer.observe({type: 'element', buffered: true});
</script>
</body>
</html>

View file

@ -38,8 +38,16 @@ const waitForLoad = new Promise(resolve => { addEventListener('load', resolve);
idl_test(
['html'],
['SVG', 'cssom', 'touch-events', 'uievents', 'dom', 'xhr'],
['SVG', 'cssom', 'touch-events', 'uievents', 'dom', 'xhr', 'FileAPI'],
async idlArray => {
self.documentWithHandlers = new Document();
const handler = function(e) {};
for (const callback of idlArray.members['GlobalEventHandlers'].members) {
if (callback.idlType && callback.idlType.idlType === 'EventHandler') {
documentWithHandlers[callback.name] = handler;
}
}
idlArray.add_objects({
NodeList: ['document.getElementsByName("name")'],
HTMLAllCollection: ['document.all'],
@ -48,7 +56,7 @@ idl_test(
HTMLOptionsCollection: ['document.createElement("select").options'],
DOMStringMap: ['document.head.dataset'],
Transferable: [],
Document: ['iframe.contentDocument', 'new Document()'],
Document: ['iframe.contentDocument', 'new Document()', 'documentWithHandlers'],
XMLDocument: ['document.implementation.createDocument(null, "", null)'],
HTMLElement: ['document.createElement("noscript")'], // more tests in html/semantics/interfaces.js
HTMLUnknownElement: ['document.createElement("bgsound")'], // more tests in html/semantics/interfaces.js

View file

@ -23,6 +23,7 @@
<div id="null"></div>
<div name="divwithname"></div>
<div id="-0"></div>
<div id="log"></div>
<script>
var anchors = document.querySelectorAll("a");
var divs = document.querySelectorAll("div");
@ -34,7 +35,7 @@ test(function() {
}, "document.all is an HTMLAllCollection");
test(function() {
assert_equals(document.all.length, 24);
assert_equals(document.all.length, 25);
}, "length attribute");
// indexed property getter
@ -42,12 +43,12 @@ test(function() {
test(function() {
assert_equals(document.all[0], document.documentElement);
assert_equals(document.all[-0], document.documentElement);
assert_equals(document.all[23], scripts[2]);
assert_equals(document.all[24], scripts[2]);
}, "indexed property getter");
test(function() {
assert_equals(document.all[-1], undefined);
assert_equals(document.all[24], undefined);
assert_equals(document.all[25], undefined);
assert_equals(document.all[42], undefined);
assert_equals(document.all[43], undefined);
assert_equals(document.all[4294967294], undefined);
@ -86,8 +87,8 @@ test(function() {
test(function() {
assert_equals(document.all["0"], document.documentElement);
assert_equals(document.all["23"], document.scripts[2]);
assert_equals(document.all["24"], undefined);
assert_equals(document.all["24"], document.scripts[2]);
assert_equals(document.all["25"], undefined);
assert_equals(document.all["42"], undefined);
assert_equals(document.all["43"], undefined);
}, "named property getter with \"array index property name\"");
@ -187,16 +188,16 @@ test(function() {
test(function() {
assert_equals(document.all("0"), document.documentElement);
assert_equals(document.all("23"), document.scripts[2]);
assert_equals(document.all("24"), null);
assert_equals(document.all("24"), document.scripts[2]);
assert_equals(document.all("25"), null);
assert_equals(document.all("42"), null);
assert_equals(document.all("43"), null);
}, "legacy caller with \"array index property name\"");
test(function() {
assert_equals(document.all(0), document.documentElement);
assert_equals(document.all(23), document.scripts[2]);
assert_equals(document.all(24), null);
assert_equals(document.all(24), document.scripts[2]);
assert_equals(document.all(25), null);
assert_equals(document.all(42), null);
assert_equals(document.all(43), null);
}, "legacy caller with \"array index property name\" as number");
@ -267,16 +268,16 @@ test(function() {
test(function() {
assert_equals(document.all.item("0"), document.documentElement);
assert_equals(document.all.item("23"), document.scripts[2]);
assert_equals(document.all.item("24"), null);
assert_equals(document.all.item("24"), document.scripts[2]);
assert_equals(document.all.item("25"), null);
assert_equals(document.all.item("42"), null);
assert_equals(document.all.item("43"), null);
}, "item method with \"array index property name\"");
test(function() {
assert_equals(document.all.item(0), document.documentElement);
assert_equals(document.all.item(23), document.scripts[2]);
assert_equals(document.all.item(24), null);
assert_equals(document.all.item(24), document.scripts[2]);
assert_equals(document.all.item(25), null);
assert_equals(document.all.item(42), null);
assert_equals(document.all.item(43), null);
}, "item method with \"array index property name\" as number");
@ -329,6 +330,5 @@ test(function() {
}
}, "collections are new live HTMLCollection instances");
</script>
<div id="log"></div>
</body>
</html>

View file

@ -4,4 +4,4 @@
[TestDriver actions: actions with key pressed]
expected:
if os == "mac" and product == "chrome": FAIL
if os == "mac" and (product == "chrome" or product=="firefox"): FAIL

View file

@ -4,7 +4,7 @@
// Source: File API (https://w3c.github.io/FileAPI/)
[Constructor(optional sequence<BlobPart> blobParts,
optional BlobPropertyBag options),
optional BlobPropertyBag options = {}),
Exposed=(Window,Worker), Serializable]
interface Blob {
@ -33,7 +33,7 @@ typedef (BufferSource or Blob or USVString) BlobPart;
[Constructor(sequence<BlobPart> fileBits,
USVString fileName,
optional FilePropertyBag options),
optional FilePropertyBag options = {}),
Exposed=(Window,Worker), Serializable]
interface File : Blob {
readonly attribute DOMString name;

View file

@ -0,0 +1,20 @@
// GENERATED CONTENT - DO NOT EDIT
// Content was automatically extracted by Reffy into reffy-reports
// (https://github.com/tidoust/reffy-reports)
// Source: Element Timing API (https://wicg.github.io/element-timing/)
interface PerformanceElementTiming : PerformanceEntry {
readonly attribute DOMHighResTimeStamp renderTime;
readonly attribute DOMHighResTimeStamp loadTime;
readonly attribute DOMRectReadOnly intersectionRect;
readonly attribute DOMString identifier;
readonly attribute unsigned long naturalWidth;
readonly attribute unsigned long naturalHeight;
readonly attribute DOMString id;
readonly attribute Element? element;
readonly attribute DOMString url;
};
partial interface Element {
[CEReactions] attribute DOMString elementTiming;
};

View file

@ -4,11 +4,11 @@
// Source: Input Events Level 1 (https://cdn.staticaly.com/gh/w3c/input-events/v1/index.html)
partial interface InputEvent {
readonly attribute DataTransfer? dataTransfer;
sequence<StaticRange> getTargetRanges();
readonly attribute DataTransfer? dataTransfer;
sequence<StaticRange> getTargetRanges();
};
partial dictionary InputEventInit {
DataTransfer? dataTransfer = null;
sequence<StaticRange> targetRanges = [];
DataTransfer? dataTransfer = null;
sequence<StaticRange> targetRanges = [];
};

View file

@ -0,0 +1,13 @@
// GENERATED CONTENT - DO NOT EDIT
// Content was automatically extracted by Reffy into reffy-reports
// (https://github.com/tidoust/reffy-reports)
// Source: Largest Contentful Paint (https://wicg.github.io/largest-contentful-paint/)
interface LargestContentfulPaint : PerformanceEntry {
readonly attribute DOMHighResTimeStamp renderTime;
readonly attribute DOMHighResTimeStamp loadTime;
readonly attribute unsigned long size;
readonly attribute DOMString id;
readonly attribute DOMString url;
readonly attribute Element? element;
};

View file

@ -23,8 +23,8 @@ callback PerformanceObserverCallback = void (PerformanceObserverEntryList entrie
PerformanceObserver observer);
[Constructor(PerformanceObserverCallback callback), Exposed=(Window,Worker)]
interface PerformanceObserver {
void observe(optional PerformanceObserverInit options);
void disconnect();
void observe (optional PerformanceObserverInit options = {});
void disconnect ();
PerformanceEntryList takeRecords();
[SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
};

View file

@ -4,23 +4,23 @@
// Source: User Timing Level 3 (https://w3c.github.io/user-timing/)
dictionary PerformanceMarkOptions {
any detail;
DOMHighResTimeStamp startTime;
};
any detail;
DOMHighResTimeStamp startTime;
};
dictionary PerformanceMeasureOptions {
any detail;
(DOMString or DOMHighResTimeStamp) start;
DOMHighResTimeStamp duration;
(DOMString or DOMHighResTimeStamp) end;
};
dictionary PerformanceMeasureOptions {
any detail;
(DOMString or DOMHighResTimeStamp) start;
DOMHighResTimeStamp duration;
(DOMString or DOMHighResTimeStamp) end;
};
partial interface Performance {
PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {});
void clearMarks(optional DOMString markName);
PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark);
void clearMeasures(optional DOMString measureName);
};
partial interface Performance {
PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {});
void clearMarks(optional DOMString markName);
PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark);
void clearMeasures(optional DOMString measureName);
};
[Exposed=(Window,Worker),
Constructor(DOMString markName, optional PerformanceMarkOptions markOptions)]

View file

@ -3,6 +3,10 @@
// (https://github.com/tidoust/reffy-reports)
// Source: Web Share API - Level 1 (https://wicg.github.io/web-share/)
partial interface Navigator {
[SecureContext] Promise<void> share(optional ShareData data = {});
};
dictionary ShareData {
USVString title;
USVString text;

View file

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html dir="rtl">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/intersection-observer-test-utils.js"></script>
<style>
pre, #log {
position: absolute;
top: 120px;
left: 0;
}
#root {
width: 350px;
height: 100px;
border: 1px solid black;
display: flex;
flex-direction: row;
overflow-x: auto;
}
#target-start, #target-end {
width: 100px;
height: 100px;
flex-shrink: 0;
background-color: green;
text-align: center;
}
#target-end {
margin-inline-start: 500px;
}
</style>
</head>
<div id="root">
<div id="target-start">start</div>
<div id="target-end">end</div>
</div>
<script>
runTestCycle(function() {
let io = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add("intersecting");
} else {
entry.target.classList.remove("intersecting");
}
});
}, { root: document.getElementById("root") });
document.querySelectorAll("#root > div").forEach(element => {
io.observe(element);
});
runTestCycle(step0, "First rAF");
}, "Explicit rtl root with overflow clipping");
function step0() {
assert_true(
document.getElementById("target-start").classList.contains("intersecting"),
"Target at scroll start is intersecting");
assert_false(
document.getElementById("target-end").classList.contains("intersecting"),
"Target at scroll end is not intersecting");
}
</script>

View file

@ -7,7 +7,7 @@
<script src="/resources/testharnessreport.js"></script>
<script type="module">
import { storage } from "std:kv-storage";
import storage from "std:kv-storage";
test(() => {
assert_equals(storage.backingStore, storage.backingStore);

View file

@ -1,4 +1,4 @@
import { StorageArea, storage as defaultArea } from "std:kv-storage";
import defaultArea, { StorageArea } from "std:kv-storage";
import { assertAsyncIteratorEquals, assertAsyncIteratorCustomEquals } from "./equality-asserters.js";
// Used when we're manually creating the database, and so the IDB helpers also want to clean it up.

View file

@ -8,7 +8,7 @@
<script src="/resources/idlharness.js"></script>
<script type="module">
import { storage, StorageArea } from "std:kv-storage";
import storage, { StorageArea } from "std:kv-storage";
// Web IDL/idlharness.js do not yet have support for the spec's IDL, which uses module {},
// async_iterator, and some new extended attributes. This IDL is a mutated version to work with the
@ -172,4 +172,4 @@ function frameLoadPromise(frame) {
frame.onerror = () => reject(new Error(`${frame.src} failed to load`));
});
}
</script>
</script>

View file

@ -8,7 +8,6 @@
<script type="module">
import { testVariousMethodsWithDefaultArea } from "./helpers/kvs-tests.js";
import { storage } from "std:kv-storage";
testVariousMethodsWithDefaultArea(
"Storage methods smoke test with string key and value", "key", "value", assert_equals

View file

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Largest Contentful Paint: element is only exposed for fully active documents.</title>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe src="resources/iframe-stores-entry.html" id="ifr"></iframe>
<script>
let t = async_test('Only expose element attribute for fully active documents');
window.triggerTest = t.step_func_done(entry => {
assert_not_equals(entry.element, null);
const iframe = document.getElementById('ifr');
iframe.remove();
assert_equals(entry.element, null);
});
</script>
</body>

View file

@ -0,0 +1,30 @@
<!doctype html>
<title>Largest Contentful Paint IDL tests</title>
<link rel="help" href="https://wicg.github.io/largest-contentful-paint/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
<script src="/resources/idlharness.js"></script>
<script>
'use strict';
idl_test(
['largest-contentful-paint'],
['performance-timeline', 'dom'],
async (idl_array, t) => {
idl_array.add_objects({
LargestContentfulPaint: ['lcp']
});
window.lcp = await new Promise((resolve, reject) => {
const observer = new PerformanceObserver(entryList => {
resolve(entryList.getEntries()[0]);
});
observer.observe({type: 'largest-contentful-paint', buffered: true});
t.step_timeout(() => reject('Timed out waiting for LargestContentfulPaint entry'), 3000);
});
}
);
</script>
<!-- a contentful element to observe -->
<img src=/images/green-100x50.png>

View file

@ -0,0 +1,47 @@
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Largest Contentful Paint: observe image.</title>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
async_test(function (t) {
if (!window.LargestContentfulPaint) {
assert_unreached("LargestContentfulPaint is not implemented");
}
const beforeRender = performance.now();
const observer = new PerformanceObserver(
t.step_func_done(function(entryList) {
assert_equals(entryList.getEntries().length, 1);
const entry = entryList.getEntries()[0];
assert_equals(entry.entryType, 'largest-contentful-paint');
assert_greater_than_equal(entry.renderTime, beforeRender,
'The rendering timestamp should occur after script starts running.');
assert_greater_than_equal(performance.now(), entry.renderTime,
'The rendering timestamp should occur before the entry is dispatched to the observer.');
assert_equals(entry.startTime, 0);
assert_equals(entry.duration, 0);
// blue.png is 133 x 106.
assert_equals(entry.size, 14098);
assert_equals(entry.id, 'image_id');
// 25 is the length of "largest-contentful-paint/".
const index = window.location.href.lastIndexOf('/') - 25;
const pathname = window.location.href.substring(0, index) + '/images/blue.png';
assert_equals(entry.url, pathname);
assert_greater_than(entry.loadTime, beforeRender,
'The load timestamp should occur after script starts running.');
assert_less_than(entry.loadTime, entry.renderTime,
'The load timestamp should occur before the render timestamp.')
assert_equals(entry.element, document.getElementById('image_id'));
})
);
observer.observe({type: 'largest-contentful-paint', buffered: true});
}, 'Same-origin image after a JS initiated scroll event is observable.');
document.body.dispatchEvent(new Event('scroll'));
const image = new Image();
image.id = 'image_id';
image.src = '/images/blue.png';
document.body.appendChild(image);
</script>
</body>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<p>Text</p>
<script>
const observer = new PerformanceObserver(entryList => {
window.parent.triggerTest(entryList.getEntries()[0]);
});
observer.observe({type: 'largest-contentful-paint', buffered: true});
</script>
</body>
</html>

View file

@ -62,5 +62,7 @@
</math>
</p>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mspace");</script>
</body>
</html>

View file

@ -6,15 +6,11 @@
</head>
<body>
<!-- Test dir="rtl" on MathML token elements. The text contains RTL and
LTR characters, so the attribute is needed to specify the actual
direction. -->
<p><math><mtext dir="rtl">חוק \left חסר או חוק \right מיותר</mtext></math></p>
<p><math><ms dir="rtl">חוק \left חסר או חוק \right מיותר</ms></math></p>
<p><math><mo dir="rtl">חוק \left חסר או חוק \right מיותר</mo></math></p>
<p><math><mi dir="rtl">חוק \left חסר או חוק \right מיותר</mi></math></p>
<p><math><mn dir="rtl">חוק \left חסר או חוק \right מיותר</mn></math></p>
<p><math><mtext style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mtext></math></p>
<p><math><ms style="direction: rtl;">חוק \left חסר או חוק \right מיותר</ms></math></p>
<p><math><mo style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mo></math></p>
<p><math><mi style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mi></math></p>
<p><math><mn style="direction: rtl;">חוק \left חסר או חוק \right מיותר</mn></math></p>
</body>
</html>

View file

@ -21,5 +21,8 @@
<p><math><mi dir="rtl">חוק \left חסר או חוק \right מיותר</mi></math></p>
<p><math><mn dir="rtl">חוק \left חסר או חוק \right מיותר</mn></math></p>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_dir");</script>
</body>
</html>

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Verify fraction metrics for different sizes of numerator and denominator.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -33,6 +34,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 3;
var mathAxis = getBox("axis").middle;
// For stacks, nothing in the OpenType MATH specification seems to ensure
@ -51,6 +54,8 @@
}, "Fraction axis is aligned on the math axis");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
for (var i = 0; i < 10; i++) {
assert_less_than(getBox("frac" + i + "num").bottom, getBox("frac" + i + "den").top, "numerator is above denominator");
assert_less_than(getBox("frac" + i + "den").top - getBox("frac" + i + "num").bottom, 5, "The gap between numerator and denominator is not too large");
@ -58,12 +63,16 @@
}, "Vertical positions of numerator and denominator");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 3;
for (var i = 0; i < 10; i++)
assert_approx_equals(getBox("frac" + i + "num").center, getBox("frac" + i + "den").center, e, "numerator and denominator are horizontally centered");
}, "Horizontal alignments of numerator and denominator");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 5;
for (var i = 0; i < 10; i++) {
var frac = getBox("frac" + i);

View file

@ -51,5 +51,7 @@
</mfrac>
</math>
</div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -28,5 +28,7 @@
</mfrac>
</math>
</div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -37,6 +37,8 @@
</head>
<body>
<p>This test passes if it renders the same as an invalid fraction with 3 children.</p>
<math>
<math></math>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -30,5 +30,7 @@
<mn id="mn2">2</mn>
</mfrac>
</math>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -32,6 +32,8 @@
</head>
<body>
<p>This test passes if you see a fraction.</p>
<math>
<math></math>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -41,5 +41,7 @@
<mspace width="20px" height="10px" style="background: cyan"></mspace>
</mfrac>
</math>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Verifies fraction with positive, negative, percent and named space linethickness values.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style type="text/css">
@font-face {
font-family: TestFont;
@ -37,19 +38,23 @@
var epsilon = 2;
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
assert_approx_equals(LineThickness("positive"), 5.67 * 10, epsilon);
}, "Positive");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
/* Negative values are treated as 0 */
assert_approx_equals(LineThickness("negative"), 0, epsilon);
}, "Negative");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
assert_approx_equals(LineThickness("percent"), defaultRuleThickness * 234 / 100, epsilon);
}, "Percentage");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
/* Namedspace values are invalid in MathML Core. */
assert_approx_equals(LineThickness("namedspace"), defaultRuleThickness, epsilon);
}, "Named space");

View file

@ -26,5 +26,7 @@
<mspace width="20px" height="10px" style="background: cyan"></mspace>
</mfrac>
</math>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -22,5 +22,7 @@
</mrow>
</mfrac>
</math>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -52,5 +52,7 @@
</mfrac>
</math>
</p>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Element mfrac correctly uses the fraction parameters from the MATH table.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -68,6 +69,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 7000 * emToPx;
var v2 = 1000 * emToPx;
assert_approx_equals(getBox("ref0001").top - getBox("num0001").bottom,
@ -75,54 +78,72 @@
}, "AxisHeight");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 5000 * emToPx;
assert_approx_equals(getBox("den0002").top - getBox("ref0002").bottom,
v1, epsilon, "mfrac: denominator gap");
}, "DenominatorDisplayStyleGapMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 6000 * emToPx;
assert_approx_equals(getBox("den0003").top - getBox("ref0003").bottom,
v1, epsilon, "mfrac: denominator shift");
}, "DenominatorDisplayStyleShiftDown");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 4000 * emToPx;
assert_approx_equals(getBox("den0004").top - getBox("ref0004").bottom,
v1, epsilon, "mfrac: denominator gap");
}, "DenominatorGapMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 3000 * emToPx;
assert_approx_equals(getBox("den0005").top - getBox("ref0005").bottom,
v1, epsilon, "mfrac: denominator shift");
}, "DenominatorShiftDown");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 8000 * emToPx;
assert_approx_equals(getBox("ref0006").top - getBox("num0006").bottom,
v1, epsilon, "mfrac: numerator gap");
}, "NumeratorDisplayStyleGapMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 2000 * emToPx;
assert_approx_equals(getBox("ref0007").top - getBox("num0007").bottom,
v1, epsilon, "mfrac: numerator shift");
}, "NumeratorDisplayStyleShiftDown");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 9000 * emToPx;
assert_approx_equals(getBox("ref0008").top - getBox("num0008").bottom,
v1, epsilon, "mfrac: numerator gap");
}, "NumeratorGapMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 11000 * emToPx;
assert_approx_equals(getBox("ref0009").top - getBox("num0009").bottom,
v1, epsilon, "mfrac: numerator shift");
}, "NumeratorShiftDown");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 10000 * emToPx;
assert_approx_equals(getBox("den0010").top - getBox("num0010").bottom,
v1, epsilon, "mfrac: rule thickness");

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Element mfrac correctly uses the stack parameters from the MATH table.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -56,42 +57,56 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 7000 * emToPx;
assert_approx_equals(getBox("ref0001").top - getBox("num0001").bottom,
v, epsilon, "mfrac: axis height");
}, "AxisHeight");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 5000 * emToPx;
assert_approx_equals(getBox("den0002").top - getBox("ref0002").bottom,
v, epsilon, "mfrac: denominator shift");
}, "BottomDisplayStyleShiftDown");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 6000 * emToPx;
assert_approx_equals(getBox("den0003").top - getBox("ref0003").bottom,
v, epsilon, "mfrac: denominator shift");
}, "BottomShiftDown");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 4000 * emToPx;
assert_approx_equals(getBox("den0004").top - getBox("num0004").bottom,
v, epsilon, "mfrac: gap");
}, "DisplayStyleGapMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 8000 * emToPx;
assert_approx_equals(getBox("den0005").top - getBox("num0005").bottom,
v, epsilon, "mfrac: gap");
}, "GapMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 3000 * emToPx;
assert_approx_equals(getBox("ref0006").top - getBox("num0006").bottom,
v, epsilon, "mfrac: numerator shift");
}, "TopDisplayStyleShiftUp");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 9000 * emToPx;
assert_approx_equals(getBox("ref0007").top - getBox("num0007").bottom,
v, epsilon, "mfrac: numerator shift");

View file

@ -86,5 +86,7 @@
</math>
</p>
<div id="frame"></div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -86,5 +86,7 @@
</math>
</p>
<div id="frame"></div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -86,5 +86,7 @@
</math>
</p>
<div id="frame"></div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -86,5 +86,7 @@
</math>
</p>
<div id="frame"></div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -86,5 +86,7 @@
</math>
</p>
<div id="frame"></div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -86,5 +86,7 @@
</math>
</p>
<div id="frame"></div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -18,5 +18,7 @@
</mfrac>
</math>
</div>
<script src="/mathml/support/feature-detection.js"></script>
<script>MathMLFeatureDetection.ensure_for_match_reftest("has_mfrac");</script>
</body>
</html>

View file

@ -12,6 +12,7 @@
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#enclose-expression-inside-notation-menclose">
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#adjust-space-around-content-mpadded">
<meta name="assert" content="Baseline for mrow-like elements is correct.">
<script src="/mathml/support/feature-detection.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">
@ -23,6 +24,7 @@
var x = document.getElementById("above" + tag).getBoundingClientRect();
var y = document.getElementById("below" + tag).getBoundingClientRect();
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
assert_equals(x.bottom, y.top);
}, "baseline alignment inside " + tag);
});

View file

@ -13,6 +13,7 @@
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#adjust-space-around-content-mpadded">
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#operator-fence-separator-or-accent-mo">
<meta name="assert" content="Operators can stretch inside mrow-like elements.">
<script src="/mathml/support/feature-detection.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
@ -36,6 +37,7 @@
["Mrow", "Sqrt", "Style", "Error", "Phantom", "Math", "Menclose", "Mpadded"].forEach((tag) => {
var mo = document.getElementById("mo" + tag);
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
assert_greater_than_equal(mo.getBoundingClientRect().height, 100);
}, "operator stretching inside " + tag);
});

View file

@ -0,0 +1,155 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Embellished operators</title>
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#embellished-operators">
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements">
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-of-mrow">
<meta name="assert" content="Verify definition of embellished operators">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
/* Default spacing of operator 'X' is 0.2777777777777778em so quite different
from the measured/specified 0em and 1em. */
math, math * {
font: 25px/1 Ahem;
}
mn {
color: black;
}
.testedElement mo {
color: yellow !important;
}
.testedElement, .testedElement * {
color: blue !important;
background: blue !important;
}
</style>
<script>
function spaceBeforeElement(id) {
var element = document.getElementById(id);
var mnBefore = element.previousElementSibling;
return element.getBoundingClientRect().left - mnBefore.getBoundingClientRect().right;
}
function spaceBeforeCoreOperator(id) {
var element = document.getElementById(id);
var coreMo = element.getElementsByTagName("mo")[0];
return coreMo.getBoundingClientRect().left - element.getBoundingClientRect().left;
}
setup({ explicit_done: true });
window.addEventListener("load", runTests);
function runTests() {
var epsilon = 1;
var emToPx = 25;
["mrow", "mstyle", "mphantom", "mpadded"].forEach(tag => {
test(function() {
assert_true(MathMLFeatureDetection.has_operator_spacing());
assert_approx_equals(spaceBeforeElement(`${tag}-op`), 2 * emToPx, epsilon);
assert_approx_equals(spaceBeforeCoreOperator(`${tag}-op`), 0, epsilon);
}, `${tag} (embellished operator)`);
test(function() {
assert_true(MathMLFeatureDetection.has_operator_spacing());
assert_approx_equals(spaceBeforeElement(`${tag}-nonop`), 0, epsilon);
assert_approx_equals(spaceBeforeCoreOperator(`${tag}-nonop`), 2 * emToPx, epsilon);
}, `${tag} (not embellished operator)`);
});
done();
}
</script>
</head>
<body>
<div id="log"></div>
<p>
<math>
<mn>X</mn>
<mrow id="mrow-op" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mtext class="space-like">X</mtext>
</mrow>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mrow id="mrow-nonop" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn> <!-- "mn" is not space-like -->
</mrow>
<mn>X</mn>
</math>
</p>
<!-- mstyle is an embellished operator if its children consist
of one embellished operator and zero or more space-like elements. -->
<p>
<math>
<mn>X</mn>
<mstyle id="mstyle-op" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
</mstyle>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mstyle id="mstyle-nonop" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn> <!-- "mn" is not space-like -->
</mstyle>
<mn>X</mn>
</math>
</p>
<!-- mphantom is an embellished operator if its children consist
of one embellished operator and zero or more space-like elements. -->
<p>
<math>
<mn>X</mn>
<mphantom id="mphantom-op" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
</mphantom>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mphantom id="mphantom-nonop" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn> <!-- "mn" is not space-like -->
</mphantom>
<mn>X</mn>
</math>
</p>
<!-- mpadded is an embellished operator if its children consist
of one embellished operator and zero or more space-like elements. -->
<p>
<math>
<mn>X</mn>
<mpadded id="mpadded-op" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
</mpadded>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mpadded id="mpadded-nonop" class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn> <!-- "mn" is not space-like -->
</mpadded>
<mn>X</mn>
</math>
</p>
</body>
</html>

View file

@ -0,0 +1,286 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Embellished operators</title>
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#embellished-operators">
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#definition-of-space-like-elements">
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-of-mrow">
<meta name="assert" content="Verify definition of embellished operators">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
/* Default spacing of operator 'X' is 0.2777777777777778em so quite different
from the measured/specified 0em and 1em. */
math, math * {
font: 25px/1 Ahem;
}
mn {
color: black;
}
mtext.space-like {
color: lightblue !important;
}
.testedElement mo {
color: yellow !important;
}
.testedElement, .testedElement * {
color: blue !important;
background: blue !important;
}
</style>
<script>
function spaceBeforeElement(element) {
var mnBefore = element.previousElementSibling;
return element.getBoundingClientRect().left - mnBefore.getBoundingClientRect().right;
}
setup({ explicit_done: true });
window.addEventListener("load", runTests);
function runTests() {
var epsilon = 1;
var emToPx = 25;
["msub", "msup", "msubsup", "munder", "mover", "munderover",
"mmultiscripts", "mfrac", "maction", "semantics"].forEach(tag => {
test(function() {
assert_true(MathMLFeatureDetection.has_operator_spacing());
var element = document.getElementsByTagName(tag)[0];
assert_approx_equals(spaceBeforeElement(element), 2 * emToPx, epsilon);
}, `${tag} (embellished operator)`);
test(function() {
assert_true(MathMLFeatureDetection.has_operator_spacing());
var element = document.getElementsByTagName(tag)[1];
assert_approx_equals(spaceBeforeElement(element), 0, epsilon);
}, `${tag} (not embellished operator)`);
});
done();
}
</script>
</head>
<body>
<div id="log"></div>
<!-- <msub>, <msup>, <msubsup>, <munder>, <mover>, <munderover>,
<mmultiscripts>, <mfrac>, <semantics> or <maction> are embellished
operators if their first child exists and is an embellished operator -->
<p>
<math>
<mn>X</mn>
<msub class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
</msub>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<msup class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
</msup>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<msubsup class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
<mn>X</mn>
</msubsup>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<munder class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
</munder>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mover class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
</mover>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<munderover class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
</munderover>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mmultiscripts class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
<mn>X</mn>
<mn>X</mn>
<mn>X</mn>
</mmultiscripts>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mfrac class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
</mfrac>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<maction class="testedElement" actiontype="statusline">
<mo lspace="2em" rspace="0em">X</mo>
<mn>STATUS MESSAGE</mn>
</maction>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<semantics class="testedElement">
<mo lspace="2em" rspace="0em">X</mo>
<annotation>TEXT ANNOTATION</annotation>
<mn>X</mn>
</semantics>
<mn>X</mn>
</math>
</p>
<!-- <msub>, <msup>, <msubsup>, <munder>, <mover>, <munderover>,
<mmultiscripts>, <mfrac>, <semantics> or <maction> are not embellished
operators if their first child is not an embellished operator -->
<p>
<math>
<mn>X</mn>
<msub class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
</msub>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<msup class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
</msup>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<msubsup class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
</msubsup>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<munder class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
</munder>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mover class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
</mover>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<munderover class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
</munderover>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mmultiscripts class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
<mn>X</mn>
<mn>X</mn>
<mn>X</mn>
</mmultiscripts>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<mfrac class="testedElement">
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
</mfrac>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<maction class="testedElement" actiontype="statusline">
<mn>X</mn>
<mo lspace="2em" rspace="0em">STATUS MESSAGE</mo>
</maction>
<mn>X</mn>
</math>
</p>
<p>
<math>
<mn>X</mn>
<semantics class="testedElement">
<mrow>
<mn>X</mn>
<mo lspace="2em" rspace="0em">X</mo>
</mrow>
<annotation>TEXT ANNOTATION</annotation>
</semantics>
<mn>X</mn>
</math>
</p>
</body>
</html>

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Elements msqrt and mroot correctly use the radical parameters from the MATH table.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -56,6 +57,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 25;
var v2 = 1000 * emToPx;
var radicalHeight = getBox("base001").height + v2;
@ -65,6 +68,8 @@
}, "RadicalDegreeBottomRaisePercent");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 7000 * emToPx;
var v2 = 1000 * emToPx;
assert_approx_equals(getBox("base0021").top - getBox("radical0021").top,
@ -76,6 +81,8 @@
}, "RadicalDisplayStyleVerticalGap");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 3000 * emToPx;
var v2 = 1000 * emToPx;
assert_approx_equals(getBox("base0031").top - getBox("radical0031").top,
@ -86,7 +93,9 @@
"mroot: vertical gap");
}, "RadicalExtraAscender");
test(function() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
// Note: the size variants of U+221A in this font have width 1000.
var v1 = 5000 * emToPx;
var radicalSymbolWidth = 1000 * emToPx;
@ -97,6 +106,8 @@
}, "RadicalKernAfterDegree");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 4000 * emToPx;
assert_approx_equals(getBox("index005").left - getBox("radical005").left,
v1, epsilon,
@ -104,6 +115,8 @@
}, "RadicalKernBeforeDegree");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 8000 * emToPx;
assert_approx_equals(getBox("base0061").top - getBox("radical0061").top,
v, epsilon,
@ -114,6 +127,8 @@
}, "RadicalRuleThickness");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 6000 * emToPx;
var v2 = 1000 * emToPx;
assert_approx_equals(getBox("base0071").top - getBox("radical0071").top,

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Basic metrics for elements msub, msup and msubsup.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -28,6 +29,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
assert_less_than_equal(getBox("msubBase").right, getBox("msubSub").left, e, "msub: subscript is after base");
assert_less_than_equal(getBox("msupBase").right, getBox("msupSup").left, e, "msup: superscript is after base");
@ -43,6 +46,8 @@
}, "Respective horizontal positions");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
assert_approx_equals(getBox("msubBase").middle, getBox("baseline").bottom, e, "msub: base is placed on the baseline");
assert_approx_equals(getBox("msupBase").middle, getBox("baseline").bottom, e, "msup: base is placed on the baseline");
@ -50,6 +55,8 @@
}, "Alignment of the base on the baseline");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 3;
assert_approx_equals(getBox("msubSub").middle, getBox("msubBase").bottom, e, "msub: script is placed at the bottom of the base");
assert_approx_equals(getBox("msupSup").middle, getBox("msupBase").top, e, "msup: script is placed at the top of the base");
@ -58,6 +65,8 @@
}, "Vertical position of scripts");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 3;
assert_approx_equals(getBox("msub").width, getBox("msubSub").right - getBox("msubBase").left, e, "msub: width is determined by the left/right sides of base/script (+ some space after script)");
assert_approx_equals(getBox("msup").width, getBox("msupSup").right - getBox("msupBase").left, e, "msup: width is determined by the left/right sides of base/script (+ some space after script)");
@ -65,6 +74,8 @@
}, "Width of scripted elements");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
assert_greater_than_equal(getBox("msub").height, getBox("msubBase").height, e, "msub: height is at least the one of the base");
assert_greater_than_equal(getBox("msup").height, getBox("msupBase").height, e, "msup: height is at least the one of the base");

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Basic metrics for the mmultiscript element.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -28,6 +29,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
assert_less_than_equal(getBox("msubBase").right, getBox("msubSub").left, e, "subscript is after base");
assert_less_than_equal(getBox("msupBase").right, getBox("msupSup").left, e, "superscript is after base");
@ -54,6 +57,8 @@
}, "Respective horizontal positions");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
assert_approx_equals(getBox("msubBase").middle, getBox("baseline").bottom, e, "base is placed on the baseline");
assert_approx_equals(getBox("msupBase").middle, getBox("baseline").bottom, e, "base is placed on the baseline");
@ -64,6 +69,8 @@
}, "Alignment of the base on the baseline");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 3;
assert_approx_equals(getBox("msubSub").middle, getBox("msubBase").bottom, e, "script is placed at the bottom of the base");
assert_approx_equals(getBox("msupSup").middle, getBox("msupBase").top, e, "script is placed at the top of the base");
@ -77,6 +84,8 @@
}, "Vertical position of scripts");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 3;
assert_approx_equals(getBox("msub").width, getBox("msubSub").right - getBox("msubBase").left, e, "width is determined by the left/right sides of base/script (+ some space after script)");
assert_approx_equals(getBox("msup").width, getBox("msupSup").right - getBox("msupBase").left, e, "width is determined by the left/right sides of base/script (+ some space after script)");
@ -88,6 +97,8 @@
}, "Width of scripted elements");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
assert_greater_than_equal(getBox("msub").height, getBox("msubBase").height, e, "height is at least the one of the base");
assert_greater_than_equal(getBox("msup").height, getBox("msupBase").height, e, "height is at least the one of the base");

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Basic metrics for the mmultiscript element with many scripts.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -28,12 +29,16 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
for (var i = 0; i < 5; i++)
assert_approx_equals(getBox("multi" + i + "base").middle, getBox("baseline").bottom, e, "base " + i + "is placed on the baseline");
}, "Alignment of the base on the baseline");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 5;
assert_approx_equals(getBox("multi0").width, 30, e, "width of multi0");
assert_approx_equals(getBox("multi0").height, 30, e, "height of multi0");
@ -49,6 +54,8 @@
}, "Dimensions of the scripted elements");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 3;
for (var i = 2; i <= 4; i++) {
var base = getBox("multi" + i + "base");
@ -66,6 +73,8 @@
}, "Vertical positions of scripts");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
for (var i = 2; i <= 4; i++) {
var base = getBox("multi" + i + "base");
@ -81,6 +90,8 @@
}, "Horizontal alignment of scripts");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
for (var i = 2; i <= 4; i++) {
var base = getBox("multi" + i + "base");
var firstPostScript = getBox("multi" + i + "postsub1");

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Verify metrics of scripted elements for bases of different heights.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -30,6 +31,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
sizeArray.forEach(function(size) {
assert_approx_equals(getBox("msub" + size + "base").middle, getBox("baseline").bottom, e, "msub base " + size + "is placed on the baseline");
@ -40,6 +43,8 @@
}, "Alignment on the baseline for bases of different heights");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 5;
sizeArray.forEach(function(size) {
assert_approx_equals(getBox("msub" + size + "sub").middle, getBox("msub" + size + "base").bottom, e, "msub script " + size + "is placed at the top of of the base");

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Verify metrics of scripted elements with tall scripts.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -30,6 +31,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var e = 1;
assert_approx_equals(getBox("msubbase").middle, getBox("baseline").bottom, e, "msub base is placed on the baseline");
assert_approx_equals(getBox("msupbase").middle, getBox("baseline").bottom, e, "msup base is placed on the baseline");
@ -38,6 +41,8 @@
}, "Alignment on the baseline with different and large script heights");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
assert_greater_than(getBox("msubsub").top, getBox("msubbase").top, "msub: subscript is below the top of the base");
assert_less_than(getBox("msupsup").bottom, getBox("msupbase").bottom, "msup: supscript is above the bottom of the base");
assert_greater_than(getBox("msubsupsub").top, getBox("msubsupbase").top, "msubsup: subscript is below the top of the base");
@ -49,6 +54,8 @@
}, "Tall subscripts/superscripts are not placed too high/low");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
assert_greater_than(getBox("msubsupsub").top, getBox("msubsupsup").bottom, "msubsup: subscript is below the superscript");
assert_greater_than(getBox("multipresub").top, getBox("multipresup").bottom, "mmultiscripts: presubscript is below the presuperscript");
assert_greater_than(getBox("multipostsub").top, getBox("multipostsup").bottom, "mmultiscripts: postsubscript is below the postsuperscript");

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Elements msub, msup, subsup and msubsup correctly use the subscript and superscript parameters from the MATH table.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -68,6 +69,8 @@
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 3000 * emToPx;
assert_approx_equals(getBox("ref001").left - getBox("sub001").right, v, epsilon, "msub: Space after subscript");
assert_approx_equals(getBox("ref002").left - getBox("sup002").right, v, epsilon, "msup: Space after superscript");
@ -78,6 +81,8 @@
}, "SpaceAfterScript");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 7000 * emToPx;
assert_approx_equals(getBox("ref101").bottom - getBox("sup102").bottom, v, epsilon, "msup: Superscript shift");
assert_approx_equals(getBox("ref101").bottom - getBox("sup103").bottom, v, epsilon, "msubsup: Superscript shift");
@ -87,6 +92,8 @@
}, "SuperscriptShiftUp");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 5000 * emToPx;
assert_approx_equals(getBox("ref201").bottom - getBox("sup202").bottom, v, epsilon, "msup: Superscript shift");
assert_approx_equals(getBox("ref201").bottom - getBox("sup203").bottom, v, epsilon, "msubsup: Superscript shift");
@ -96,6 +103,8 @@
}, "SuperscriptShiftUpCramped");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 6000 * emToPx;
assert_approx_equals(getBox("sub301").bottom - getBox("ref300").bottom, v, epsilon, "msup: Subscript shift");
assert_approx_equals(getBox("sub302").bottom - getBox("ref300").bottom, v, epsilon, "msubsup: Subscript shift");
@ -104,12 +113,16 @@
}, "SubscriptShiftDown");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 11000 * emToPx;
assert_approx_equals(getBox("sub4011").top - getBox("sup4012").bottom, v, epsilon, "msubsup: SubSuperscript gap");
assert_approx_equals(getBox("sub4021").top - getBox("sup4022").bottom, v, epsilon, "mmultiscripts: SubSuperscript gap");
}, "SubSuperscriptGapMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v1 = 11000 * emToPx;
var v2 = 3000 * emToPx;
assert_approx_equals(getBox("sub501").top - getBox("sup501").bottom, v1, epsilon, "msubsup: SubSuperscript gap");
@ -119,21 +132,29 @@
}, "SuperscriptBottomMaxWithSubscript");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 4000 * emToPx;
assert_approx_equals(getBox("ref600").bottom - getBox("sub601").top, v, epsilon, "msub: Subscript top");
}, "SubscriptTopMax");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 8000 * emToPx;
assert_approx_equals(getBox("ref700").bottom - getBox("sub701").bottom, v, epsilon, "msub: Superscript bottom");
}, "SuperscriptBottomMin");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 9000 * emToPx;
assert_approx_equals(getBox("sub801").bottom - getBox("base801").bottom, v, epsilon, "msub: Superscript drop");
}, "SubscriptBaselineDrop");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 10000 * emToPx;
assert_approx_equals(getBox("sup901").bottom - getBox("base901").top, v, epsilon, "msup: Superscript drop");
}, "SuperscriptBaselineDrop");

View file

@ -7,6 +7,7 @@
<meta name="assert" content="Elements msub, msup, subsup and msubsup correctly use the italic correction from the MATH table.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/mathml/support/feature-detection.js"></script>
<style>
math, mspace {
font-size: 10px;
@ -42,6 +43,8 @@
var epsilon = 1;
function runTests() {
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var v = 0;
assert_approx_equals(getBox("base001").right - getBox("sub001").left, v, epsilon, "msub");
assert_approx_equals(getBox("sup002").left, getBox("base002").right, epsilon, "msup");
@ -50,6 +53,8 @@
assert_approx_equals(getBox("sup005").left - getBox("sub005").left, 0, epsilon, "mmultiscripts prescripts");
}, "Null Italic Correction");
test(function() {
assert_true(MathMLFeatureDetection.has_mspace());
var emToPx = 10 / 1000; // font-size: 10px, font.em = 1000
var v = 3000 * emToPx;
assert_approx_equals(getBox("base011").right - getBox("sub011").left, v, epsilon, "msub");

Some files were not shown because too many files have changed in this diff Show more