summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-transitions/support
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/css/css-transitions/support
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-transitions/support')
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/1x1-green.pngbin0 -> 135 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/1x1-lime.pngbin0 -> 135 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/1x1-maroon.pngbin0 -> 109 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/1x1-navy.pngbin0 -> 109 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/1x1-red.pngbin0 -> 135 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/1x1-white.pngbin0 -> 109 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/60x60-gg-rr.pngbin0 -> 224 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/60x60-green.pngbin0 -> 218 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/README28
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/a-green-transition.css1
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/a-green.css1
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/b-green.css1
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/c-red.css1
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/cat.pngbin0 -> 1883 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/generalParallelTest.js231
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/helper.js326
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/import-green.css1
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/import-red.css1
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/one.gifbin0 -> 184 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/pattern-grg-rgr-grg.pngbin0 -> 222 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/pattern-grg-rrg-rgg.pngbin0 -> 231 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/pattern-rgr-grg-rgr.pngbin0 -> 223 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/pattern-tr.pngbin0 -> 137 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/properties.js410
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/ruler-h-50%.pngbin0 -> 691 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/ruler-h-50px.pngbin0 -> 671 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/ruler-v-100px.pngbin0 -> 760 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/ruler-v-50px.pngbin0 -> 757 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/runParallelAsyncHarness.js148
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/square-purple.pngbin0 -> 92 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/square-teal.pngbin0 -> 92 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/square-white.pngbin0 -> 78 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/support/README4
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/support/swatch-green.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/support/swatch-red.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-blue.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-green.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-lime.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-orange.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-red.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-teal.pngbin0 -> 156 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-white.pngbin0 -> 85 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/swatch-yellow.pngbin0 -> 84 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/test-bl.pngbin0 -> 1368 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/test-br.pngbin0 -> 1045 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/test-inner-half-size.pngbin0 -> 180 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/test-outer.pngbin0 -> 2412 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/test-tl.pngbin0 -> 1025 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/test-tr.pngbin0 -> 1235 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/two.gifbin0 -> 184 bytes
-rw-r--r--testing/web-platform/tests/css/css-transitions/support/vendorPrefix.js86
51 files changed, 1239 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-transitions/support/1x1-green.png b/testing/web-platform/tests/css/css-transitions/support/1x1-green.png
new file mode 100644
index 0000000000..b98ca0ba0a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/1x1-green.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/1x1-lime.png b/testing/web-platform/tests/css/css-transitions/support/1x1-lime.png
new file mode 100644
index 0000000000..cb397fb090
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/1x1-lime.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/1x1-maroon.png b/testing/web-platform/tests/css/css-transitions/support/1x1-maroon.png
new file mode 100644
index 0000000000..3f86b07219
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/1x1-maroon.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/1x1-navy.png b/testing/web-platform/tests/css/css-transitions/support/1x1-navy.png
new file mode 100644
index 0000000000..9b9a03955b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/1x1-navy.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/1x1-red.png b/testing/web-platform/tests/css/css-transitions/support/1x1-red.png
new file mode 100644
index 0000000000..6bd73ac101
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/1x1-red.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/1x1-white.png b/testing/web-platform/tests/css/css-transitions/support/1x1-white.png
new file mode 100644
index 0000000000..dd43faec54
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/1x1-white.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/60x60-gg-rr.png b/testing/web-platform/tests/css/css-transitions/support/60x60-gg-rr.png
new file mode 100644
index 0000000000..84f5b2a4f1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/60x60-gg-rr.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/60x60-green.png b/testing/web-platform/tests/css/css-transitions/support/60x60-green.png
new file mode 100644
index 0000000000..b3c8cf3eb4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/60x60-green.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/README b/testing/web-platform/tests/css/css-transitions/support/README
new file mode 100644
index 0000000000..2e5f2ad073
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/README
@@ -0,0 +1,28 @@
+CSS Global Support Directory
+============================
+
+This directory contains common support files (such as images and external
+style sheets). These are sync'ed into the support directories of all our
+test suites. If you have test-suite-specific support files, please add
+them to the appropriate test-suite-specific support/ directory.
+
+If you add to a support/ directory, please run the tools/supportprop.py
+script from the top of the repository to cascade support files into the
+lower-level support directories.
+
+Description of the Common Support File Collection
+-------------------------------------------------
+
+The 1x1-* images are all exactly one pixel.
+
+The swatch-* images all use 15x15 cells.
+
+The square-* images all use 15x15 cells with one pixel borders.
+
+The pattern-* images use cells of various sizes:
+
+ pattern-grg-rgr-grg.png 20x20
+ pattern-rgr-grg-rgr.png 20x20
+ pattern-tr.png 15x15
+ pattern-grg-rrg-rgg.png 15x15
+
diff --git a/testing/web-platform/tests/css/css-transitions/support/a-green-transition.css b/testing/web-platform/tests/css/css-transitions/support/a-green-transition.css
new file mode 100644
index 0000000000..3f68e53cd6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/a-green-transition.css
@@ -0,0 +1 @@
+.a { color: green; transition: 10s; transition-timing-function: step-end; }
diff --git a/testing/web-platform/tests/css/css-transitions/support/a-green.css b/testing/web-platform/tests/css/css-transitions/support/a-green.css
new file mode 100644
index 0000000000..b0dbb071d5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/a-green.css
@@ -0,0 +1 @@
+.a { color: green; }
diff --git a/testing/web-platform/tests/css/css-transitions/support/b-green.css b/testing/web-platform/tests/css/css-transitions/support/b-green.css
new file mode 100644
index 0000000000..a0473f5ca2
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/b-green.css
@@ -0,0 +1 @@
+.b { color: green; } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-transitions/support/c-red.css b/testing/web-platform/tests/css/css-transitions/support/c-red.css
new file mode 100644
index 0000000000..d4ba5c64e9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/c-red.css
@@ -0,0 +1 @@
+.c { color: red; } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-transitions/support/cat.png b/testing/web-platform/tests/css/css-transitions/support/cat.png
new file mode 100644
index 0000000000..85dd732481
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/cat.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/generalParallelTest.js b/testing/web-platform/tests/css/css-transitions/support/generalParallelTest.js
new file mode 100644
index 0000000000..f6e14128fc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/generalParallelTest.js
@@ -0,0 +1,231 @@
+(function(root) {
+'use strict';
+//
+var index = 0;
+var suite = root.generalParallelTest = {
+ // prepare individual test
+ setup: function(data, options) {
+ suite._setupDom(data, options);
+ suite._setupEvents(data, options);
+ },
+ // clone fixture and prepare data containers
+ _setupDom: function(data, options) {
+ // clone fixture into off-viewport test-canvas
+ data.fixture = document.getElementById('fixture').cloneNode(true);
+ data.fixture.id = 'test-' + (index++);
+ (document.getElementById('offscreen') || document.body).appendChild(data.fixture);
+
+ // data container for #fixture > .container > .transition
+ data.transition = {
+ node: data.fixture.querySelector('.transition'),
+ values: [],
+ events: [],
+ computedStyle: function(property) {
+ return computedStyle(data.transition.node, property);
+ }
+ };
+
+ // data container for #fixture > .container
+ data.container = {
+ node: data.transition.node.parentNode,
+ values: [],
+ events: [],
+ computedStyle: function(property) {
+ return computedStyle(data.container.node, property);
+ }
+ };
+
+ // data container for #fixture > .container > .transition[:before | :after]
+ if (data.pseudo) {
+ data.pseudo = {
+ name: data.pseudo,
+ values: [],
+ computedStyle: function(property) {
+ return computedStyle(data.transition.node, property, ':' + data.pseudo.name);
+ }
+ };
+ }
+ },
+ // bind TransitionEnd event listeners
+ _setupEvents: function(data, options) {
+ ['transition', 'container'].forEach(function(elem) {
+ var handler = function(event) {
+ event.stopPropagation();
+ var name = event.propertyName;
+ var time = Math.round(event.elapsedTime * 1000) / 1000;
+ var pseudo = event.pseudoElement ? (':' + event.pseudoElement) : '';
+ data[elem].events.push(name + pseudo + ":" + time + "s");
+ };
+ data[elem].node.addEventListener('transitionend', handler, false);
+ data[elem]._events = {'transitionend': handler};
+ });
+ },
+ // cleanup after individual test
+ teardown: function(data, options) {
+ // data.fixture.remove();
+ if (data.fixture.parentNode) {
+ data.fixture.parentNode.removeChild(data.fixture);
+ }
+ },
+ // invoked prior to running a slice of tests
+ sliceStart: function(options, tests) {
+ // inject styles into document
+ setStyle(options.styles);
+ // kick off value collection loop
+ generalParallelTest.startValueCollection(options);
+ },
+ // invoked after running a slice of tests
+ sliceDone: function(options, tests) {
+ // stop value collection loop
+ generalParallelTest.stopValueCollection(options);
+ // reset styles cache
+ options.styles = {};
+ },
+ // called once all tests are done
+ done: function(options) {
+ // reset document styles
+ setStyle();
+ reflow();
+ },
+ // add styles of individual test to slice cache
+ addStyles: function(data, options, styles) {
+ if (!options.styles) {
+ options.styles = {};
+ }
+
+ Object.keys(styles).forEach(function(key) {
+ var selector = '#' + data.fixture.id
+ // fixture must become #fixture.fixture rather than a child selector
+ + (key.substring(0, 8) === '.fixture' ? '' : ' ')
+ + key;
+
+ options.styles[selector] = styles[key];
+ });
+ },
+ // set style and compute values for container and transition
+ getStyle: function(data) {
+ reflow();
+ // grab current styles: "initial state"
+ suite._getStyleFor(data, 'from');
+ // apply target state
+ suite._addClass(data, 'to', true);
+ // grab current styles: "target state"
+ suite._getStyleFor(data, 'to');
+ // remove target state
+ suite._removeClass(data, 'to', true);
+
+ // clean up the mess created for value collection
+ data.container._values = [];
+ data.transition._values = [];
+ if (data.pseudo) {
+ data.pseudo._values = [];
+ }
+ },
+ // grab current styles and store in respective element's data container
+ _getStyleFor: function(data, key) {
+ data.container[key] = data.container.computedStyle(data.property);
+ data.transition[key] = data.transition.computedStyle(data.property);
+ if (data.pseudo) {
+ data.pseudo[key] = data.pseudo.computedStyle(data.property);
+ }
+ },
+ // add class to test's elements and possibly reflow
+ _addClass: function(data, className, forceReflow) {
+ data.container.node.classList.add(className);
+ data.transition.node.classList.add(className);
+ if (forceReflow) {
+ reflow();
+ }
+ },
+ // remove class from test's elements and possibly reflow
+ _removeClass: function(data, className, forceReflow) {
+ data.container.node.classList.remove(className);
+ data.transition.node.classList.remove(className);
+ if (forceReflow) {
+ reflow();
+ }
+ },
+ // add transition and to classes to container and transition
+ startTransition: function(data) {
+ // add transition-defining class
+ suite._addClass(data, 'how', true);
+ // add target state (without reflowing)
+ suite._addClass(data, 'to', false);
+ },
+ // requestAnimationFrame runLoop to collect computed values
+ startValueCollection: function(options) {
+ var raf = window.requestAnimationFrame || function(callback){
+ setTimeout(callback, 20);
+ };
+
+ // flag denoting if the runLoop should continue (true) or exit (false)
+ options._collectValues = true;
+
+ function runLoop() {
+ if (!options._collectValues) {
+ // test's are done, stop annoying the CPU
+ return;
+ }
+
+ // collect current style for test's elements
+ options.tests.forEach(function(data) {
+ if (!data.property) {
+ return;
+ }
+
+ ['transition', 'container', 'pseudo'].forEach(function(elem) {
+ var pseudo = null;
+ if (!data[elem] || (elem === 'pseudo' && !data.pseudo)) {
+ return;
+ }
+
+ var current = data[elem].computedStyle(data.property);
+ var values = data[elem].values;
+ var length = values.length;
+ if (!length || values[length - 1] !== current) {
+ values.push(current);
+ }
+ });
+ });
+
+ // rinse and repeat
+ raf(runLoop);
+ }
+
+ runLoop();
+ },
+ // stop requestAnimationFrame runLoop collecting computed values
+ stopValueCollection: function(options) {
+ options._collectValues = false;
+ },
+
+ // generate test.step function asserting collected events match expected
+ assertExpectedEventsFunc: function(data, elem, expected) {
+ return function() {
+ var _result = data[elem].events.sort().join(" ");
+ var _expected = typeof expected === 'string' ? expected : expected.sort().join(" ");
+ assert_equals(_result, _expected, "Expected TransitionEnd events triggered on ." + elem);
+ };
+ },
+ // generate test.step function asserting collected values are neither initial nor target
+ assertIntermediateValuesFunc: function(data, elem) {
+ return function() {
+ // the first value (index: 0) is always going to be the initial value
+ // the last value is always going to be the target value
+ var values = data[elem].values;
+ if (data.flags.discrete) {
+ // a discrete value will just switch from one state to another without having passed intermediate states.
+ assert_equals(values[0], data[elem].from, "must be initial value while transitioning on ." + elem);
+ assert_equals(values[1], data[elem].to, "must be target value after transitioning on ." + elem);
+ assert_equals(values.length, 2, "discrete property only has 2 values ." + elem);
+ } else {
+ assert_not_equals(values[1], data[elem].from, "may not be initial value while transitioning on ." + elem);
+ assert_not_equals(values[1], data[elem].to, "may not be target value while transitioning on ." + elem);
+ }
+
+ // TODO: first value must be initial, last value must be target
+ };
+ }
+};
+
+})(window);
diff --git a/testing/web-platform/tests/css/css-transitions/support/helper.js b/testing/web-platform/tests/css/css-transitions/support/helper.js
new file mode 100644
index 0000000000..a37aae9183
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/helper.js
@@ -0,0 +1,326 @@
+//
+// Simple Helper Functions For Testing CSS
+//
+
+(function(root) {
+'use strict';
+
+// serialize styles object and dump to dom
+// appends <style id="dynamic-style"> to <head>
+// setStyle("#some-selector", {"some-style" : "value"})
+// setStyle({"#some-selector": {"some-style" : "value"}})
+root.setStyle = function(selector, styles) {
+ var target = document.getElementById('dynamic-style');
+ if (!target) {
+ target = document.createElement('style');
+ target.id = 'dynamic-style';
+ target.type = "text/css";
+ document.getElementsByTagName('head')[0].appendChild(target);
+ }
+
+ var data = [];
+ // single selector/styles
+ if (typeof selector === 'string' && styles !== undefined) {
+ data = [selector, '{', serializeStyles(styles), '}'];
+ target.textContent = data.join("\n");
+ return;
+ }
+ // map of selector/styles
+ for (var key in selector) {
+ if (Object.prototype.hasOwnProperty.call(selector, key)) {
+ var _data = [key, '{', serializeStyles(selector[key]), '}'];
+ data.push(_data.join('\n'));
+ }
+ }
+
+ target.textContent = data.join("\n");
+};
+
+function serializeStyles(styles) {
+ var data = [];
+ for (var property in styles) {
+ if (Object.prototype.hasOwnProperty.call(styles, property)) {
+ var prefixedProperty = addVendorPrefix(property);
+ data.push(prefixedProperty + ":" + styles[property] + ";");
+ }
+ }
+
+ return data.join('\n');
+}
+
+
+// shorthand for computed style
+root.computedStyle = function(element, property, pseudo) {
+ var prefixedProperty = addVendorPrefix(property);
+ return window
+ .getComputedStyle(element, pseudo || null)
+ .getPropertyValue(prefixedProperty);
+};
+
+// flush rendering buffer
+root.reflow = function() {
+ document.body.offsetWidth;
+};
+
+// merge objects
+root.extend = function(target /*, ..rest */) {
+ Array.prototype.slice.call(arguments, 1).forEach(function(obj) {
+ Object.keys(obj).forEach(function(key) {
+ target[key] = obj[key];
+ });
+ });
+
+ return target;
+};
+
+// dom fixture helper ("resetting dom test elements")
+var _domFixture;
+var _domFixtureSelector;
+root.domFixture = function(selector) {
+ var fixture = document.querySelector(selector || _domFixtureSelector);
+ if (!fixture) {
+ throw new Error('fixture ' + (selector || _domFixtureSelector) + ' not found!');
+ }
+ if (!_domFixture && selector) {
+ // save a copy
+ _domFixture = fixture.cloneNode(true);
+ _domFixtureSelector = selector;
+ } else if (_domFixture) {
+ // restore the copy
+ var tmp = _domFixture.cloneNode(true);
+ fixture.parentNode.replaceChild(tmp, fixture);
+ } else {
+ throw new Error('domFixture must be initialized first!');
+ }
+};
+
+root.MS_PER_SEC = 1000;
+
+/*
+ * The recommended minimum precision to use for time values.
+ *
+ * Based on Web Animations:
+ * https://w3c.github.io/web-animations/#precision-of-time-values
+ */
+const TIME_PRECISION = 0.0005; // ms
+
+/*
+ * Allow implementations to substitute an alternative method for comparing
+ * times based on their precision requirements.
+ */
+root.assert_times_equal = function(actual, expected, description) {
+ assert_approx_equals(actual, expected, TIME_PRECISION, description);
+};
+
+/*
+ * Compare a time value based on its precision requirements with a fixed value.
+ */
+root.assert_time_equals_literal = (actual, expected, description) => {
+ assert_approx_equals(actual, expected, TIME_PRECISION, description);
+};
+
+/**
+ * Assert that CSSTransition event, |evt|, has the expected property values
+ * defined by |propertyName|, |elapsedTime|, and |pseudoElement|.
+ */
+root.assert_end_events_equal = function(evt, propertyName, elapsedTime,
+ pseudoElement = '') {
+ assert_equals(evt.propertyName, propertyName);
+ assert_times_equal(evt.elapsedTime, elapsedTime);
+ assert_equals(evt.pseudoElement, pseudoElement);
+};
+
+/**
+ * Assert that array of simultaneous CSSTransition events, |evts|, have the
+ * corresponding property names listed in |propertyNames|, and the expected
+ * |elapsedTimes| and |pseudoElement| members.
+ *
+ * |elapsedTimes| may be a single value if all events are expected to have the
+ * same elapsedTime, or an array parallel to |propertyNames|.
+ */
+root.assert_end_event_batch_equal = function(evts, propertyNames, elapsedTimes,
+ pseudoElement = '') {
+ assert_equals(
+ evts.length,
+ propertyNames.length,
+ 'Test harness error: should have waited for the correct number of events'
+ );
+ assert_true(
+ typeof elapsedTimes === 'number' ||
+ (Array.isArray(elapsedTimes) &&
+ elapsedTimes.length === propertyNames.length),
+ 'Test harness error: elapsedTimes must either be a number or an array of' +
+ ' numbers with the same length as propertyNames'
+ );
+
+ if (typeof elapsedTimes === 'number') {
+ elapsedTimes = Array(propertyNames.length).fill(elapsedTimes);
+ }
+ const testPairs = propertyNames.map((propertyName, index) => ({
+ propertyName,
+ elapsedTime: elapsedTimes[index]
+ }));
+
+ const sortByPropertyName = (a, b) =>
+ a.propertyName.localeCompare(b.propertyName);
+ evts.sort(sortByPropertyName);
+ testPairs.sort(sortByPropertyName);
+
+ for (let evt of evts) {
+ const expected = testPairs.shift();
+ assert_end_events_equal(
+ evt,
+ expected.propertyName,
+ expected.elapsedTime,
+ pseudoElement
+ );
+ }
+}
+
+/**
+ * Appends a div to the document body.
+ *
+ * @param t The testharness.js Test object. If provided, this will be used
+ * to register a cleanup callback to remove the div when the test
+ * finishes.
+ *
+ * @param attrs A dictionary object with attribute names and values to set on
+ * the div.
+ */
+root.addDiv = function(t, attrs) {
+ var div = document.createElement('div');
+ if (attrs) {
+ for (var attrName in attrs) {
+ div.setAttribute(attrName, attrs[attrName]);
+ }
+ }
+ document.body.appendChild(div);
+ if (t && typeof t.add_cleanup === 'function') {
+ t.add_cleanup(function() {
+ if (div.parentNode) {
+ div.remove();
+ }
+ });
+ }
+ return div;
+};
+
+/**
+ * Appends a style div to the document head.
+ *
+ * @param t The testharness.js Test object. If provided, this will be used
+ * to register a cleanup callback to remove the style element
+ * when the test finishes.
+ *
+ * @param rules A dictionary object with selector names and rules to set on
+ * the style sheet.
+ */
+root.addStyle = (t, rules) => {
+ const extraStyle = document.createElement('style');
+ document.head.appendChild(extraStyle);
+ if (rules) {
+ const sheet = extraStyle.sheet;
+ for (const selector in rules) {
+ sheet.insertRule(selector + '{' + rules[selector] + '}',
+ sheet.cssRules.length);
+ }
+ }
+
+ if (t && typeof t.add_cleanup === 'function') {
+ t.add_cleanup(() => {
+ extraStyle.remove();
+ });
+ }
+ return extraStyle;
+};
+
+/**
+ * Promise wrapper for requestAnimationFrame.
+ */
+root.waitForFrame = () => {
+ return new Promise(resolve => {
+ window.requestAnimationFrame(resolve);
+ });
+};
+
+/**
+ * Returns a Promise that is resolved after the given number of consecutive
+ * animation frames have occured (using requestAnimationFrame callbacks).
+ *
+ * @param frameCount The number of animation frames.
+ * @param onFrame An optional function to be processed in each animation frame.
+ */
+root.waitForAnimationFrames = (frameCount, onFrame) => {
+ const timeAtStart = document.timeline.currentTime;
+ return new Promise(resolve => {
+ function handleFrame() {
+ if (onFrame && typeof onFrame === 'function') {
+ onFrame();
+ }
+ if (timeAtStart != document.timeline.currentTime &&
+ --frameCount <= 0) {
+ resolve();
+ } else {
+ window.requestAnimationFrame(handleFrame); // wait another frame
+ }
+ }
+ window.requestAnimationFrame(handleFrame);
+ });
+};
+
+/**
+ * Wrapper that takes a sequence of N animations and returns:
+ *
+ * Promise.all([animations[0].ready, animations[1].ready, ... animations[N-1].ready]);
+ */
+root.waitForAllAnimations = animations =>
+ Promise.all(animations.map(animation => animation.ready));
+
+/**
+ * Utility that takes a Promise and a maximum number of frames to wait and
+ * returns a new Promise that behaves as follows:
+ *
+ * - If the provided Promise resolves _before_ the specified number of frames
+ * have passed, resolves with the result of the provided Promise.
+ * - If the provided Promise rejects _before_ the specified number of frames
+ * have passed, rejects with the error result of the provided Promise.
+ * - Otherwise, rejects with a 'Timed out' error message. If |message| is
+ * provided, it will be appended to the error message.
+ */
+root.frameTimeout = (promiseToWaitOn, framesToWait, message) => {
+ let framesRemaining = framesToWait;
+ let aborted = false;
+
+ const timeoutPromise = new Promise(function waitAFrame(resolve, reject) {
+ if (aborted) {
+ resolve();
+ return;
+ }
+ if (framesRemaining-- > 0) {
+ requestAnimationFrame(() => {
+ waitAFrame(resolve, reject);
+ });
+ return;
+ }
+ let errorMessage = 'Timed out waiting for Promise to resolve';
+ if (message) {
+ errorMessage += `: ${message}`;
+ }
+ reject(new Error(errorMessage));
+ });
+
+ const wrappedPromiseToWaitOn = promiseToWaitOn.then(result => {
+ aborted = true;
+ return result;
+ });
+
+ return Promise.race([timeoutPromise, wrappedPromiseToWaitOn]);
+};
+
+root.supportsStartingStyle = () => {
+ let sheet = new CSSStyleSheet();
+ sheet.replaceSync("@starting-style{}");
+ return sheet.cssRules.length == 1;
+};
+
+})(window);
diff --git a/testing/web-platform/tests/css/css-transitions/support/import-green.css b/testing/web-platform/tests/css/css-transitions/support/import-green.css
new file mode 100644
index 0000000000..537104e663
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/import-green.css
@@ -0,0 +1 @@
+.import { color: green; }
diff --git a/testing/web-platform/tests/css/css-transitions/support/import-red.css b/testing/web-platform/tests/css/css-transitions/support/import-red.css
new file mode 100644
index 0000000000..9945ef4711
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/import-red.css
@@ -0,0 +1 @@
+.import { color: red; }
diff --git a/testing/web-platform/tests/css/css-transitions/support/one.gif b/testing/web-platform/tests/css/css-transitions/support/one.gif
new file mode 100644
index 0000000000..74cf7839c9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/one.gif
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/pattern-grg-rgr-grg.png b/testing/web-platform/tests/css/css-transitions/support/pattern-grg-rgr-grg.png
new file mode 100644
index 0000000000..9b88fbd811
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/pattern-grg-rgr-grg.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/pattern-grg-rrg-rgg.png b/testing/web-platform/tests/css/css-transitions/support/pattern-grg-rrg-rgg.png
new file mode 100644
index 0000000000..fcf4f3fd7d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/pattern-grg-rrg-rgg.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/pattern-rgr-grg-rgr.png b/testing/web-platform/tests/css/css-transitions/support/pattern-rgr-grg-rgr.png
new file mode 100644
index 0000000000..d454e3a630
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/pattern-rgr-grg-rgr.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/pattern-tr.png b/testing/web-platform/tests/css/css-transitions/support/pattern-tr.png
new file mode 100644
index 0000000000..8b4b25364e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/pattern-tr.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/properties.js b/testing/web-platform/tests/css/css-transitions/support/properties.js
new file mode 100644
index 0000000000..0c0057b39e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/properties.js
@@ -0,0 +1,410 @@
+(function(root){
+
+/*
+ * General Value Types definition
+ * they return an object of arrays of type { <name>: [<start-value>, <end-value>], ... }
+ */
+var values = {
+ 'length' : function() {
+ // http://www.w3.org/TR/css3-values/#lengths
+ return {
+ // CSS Values and Module Level 3
+ // ch: ['1ch', '10ch'],
+ // rem: ['1rem', '10rem'],
+ // vw: ['1vw', '10vw'],
+ // vh: ['1vh', '10vh'],
+ // vmin: ['1vmin', '10vmin'],
+ // vmax: ['1vmax', '10vmax'],
+ // CSS Values and Module Level 2
+ pt: ['1pt', '10pt'],
+ pc: ['1pc', '10pc'],
+ px: ['1px', '10px'],
+ // CSS Values and Module Level 1
+ em: ['1em', '10em'],
+ ex: ['1ex', '10ex'],
+ mm: ['1mm', '10mm'],
+ cm: ['1cm', '10cm'],
+ 'in': ['1in', '10in']
+ };
+ },
+ 'length-em': function() {
+ return {
+ em: ['1.1em', '1.5em']
+ };
+ },
+ 'percentage': function() {
+ // http://www.w3.org/TR/css3-values/#percentages
+ return {
+ '%': ['33%', '80%']
+ };
+ },
+ 'color': function() {
+ // http://www.w3.org/TR/css3-values/#colors
+ // http://www.w3.org/TR/css3-color/
+ return {
+ rgba: ['rgba(100,100,100,1)', 'rgba(10,10,10,0.4)']
+ };
+ },
+ 'rectangle': function() {
+ // http://www.w3.org/TR/CSS2/visufx.html#value-def-shape
+ return {
+ rectangle: ['rect(10px,10px,10px,10px)', 'rect(15px,15px,5px,5px)']
+ };
+ },
+ 'font-weight': function() {
+ // http://www.w3.org/TR/css3-fonts/#font-weight-prop
+ return {
+ keyword: ["normal", "bold"],
+ numeric: ["100", "900"]
+ };
+ },
+ 'number': function() {
+ // http://www.w3.org/TR/css3-values/#number
+ return {
+ integer: ["1", "10"],
+ decimal: ["1.1", "9.55"]
+ };
+ },
+ 'number[0,1]': function() {
+ // http://www.w3.org/TR/css3-values/#number
+ // applies to [0,1]-ranged properties like opacity
+ return {
+ "zero-to-one": ["0.2", "0.9"]
+ };
+ },
+ 'integer': function() {
+ // http://www.w3.org/TR/css3-values/#integer
+ return {
+ integer: ["1", "10"]
+ };
+ },
+ 'shadow': function() {
+ // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property
+ return {
+ shadow: ['rgba(0,0,0,0.1) 5px 6px 7px', 'rgba(10,10,10,0.9) 5px 6px 7px']
+ };
+ },
+ 'visibility': function() {
+ // http://www.w3.org/TR/CSS2/visufx.html#visibility
+ return {
+ keyword: ['visible', 'hidden', {discrete: true}]
+ };
+ },
+ // types reqired for non-specified properties
+ 'border-radius': function() {
+ return {
+ px: ['1px', '10px'],
+ "px-px": ['1px 3px', '10px 13px']
+ };
+ },
+ 'image' : function() {
+ var prefix = getValueVendorPrefix('background-image', 'linear-gradient(top, hsl(0, 80%, 70%), #bada55)');
+ return {
+ // Chrome implements this
+ url: ['url(support/one.gif)', 'url(support/two.gif)'],
+ data: ['url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=)', 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==)'],
+ // A hunch, as from the spec:
+ // http://www.w3.org/TR/css3-transitions/#animatable-types
+ // gradient: interpolated via the positions and colors of each stop. They must have the same type (radial or linear) and same number of stops in order to be animated. Note: [CSS3-IMAGES] may extend this definition.
+ gradient: [prefix + 'linear-gradient(top, hsl(0, 80%, 70%), #bada55)', prefix + 'linear-gradient(top, #bada55, hsl(0, 80%, 70%))']
+ };
+ },
+ 'background-size': function() {
+ return {
+ keyword: ['cover', 'contain']
+ };
+ },
+ 'box-shadow': function() {
+ // http://www.w3.org/TR/css3-background/#ltshadowgt
+ return {
+ shadow: ['60px -16px teal', '60px -16px red']
+ };
+ },
+ 'vertical': function() {
+ return {
+ keyword: ['top', 'bottom']
+ };
+ },
+ 'horizontal': function() {
+ return {
+ keyword: ['left', 'right']
+ };
+ },
+ 'font-stretch': function() {
+ return {
+ keyword: ['condensed', 'expanded']
+ };
+ },
+ 'transform': function() {
+ return {
+ rotate: ['rotate(10deg)', 'rotate(20deg)']
+ };
+ },
+ 'position': function() {
+ return {
+ 'static to absolute': ['static', 'absolute', {discrete: true}],
+ 'relative to absolute': ['relative', 'absolute', {discrete: true}],
+ 'absolute to fixed': ['absolute', 'fixed', {discrete: true}]
+ };
+ },
+ 'display': function() {
+ return {
+ 'static to absolute': ['none', 'block', {discrete: true}],
+ 'block to inline-block': ['block', 'inline-block', {discrete: true}]
+ };
+ },
+ 'object-view-box': function() {
+ return {
+ inset: ['inset(10% 10% 20% 20%)', 'inset(20% 20% 30% 30%)'],
+ rect: ['rect(10px 20px 30px 40px)', 'rect(20px 30px 40px 50px)'],
+ xywh: ['xywh(10px 20px 30px 40px)', 'xywh(20px 30px 40px 50px)'],
+ };
+ }
+};
+
+/*
+ * Property to Type table
+ * (as stated in specification)
+ */
+var properties = {
+ 'background-color': ['color'],
+ 'background-position': ['length', 'percentage'],
+
+ 'border-top-width': ['length'],
+ 'border-right-width': ['length'],
+ 'border-bottom-width': ['length'],
+ 'border-left-width': ['length'],
+
+ 'border-top-color': ['color'],
+ 'border-right-color': ['color'],
+ 'border-bottom-color': ['color'],
+ 'border-left-color': ['color'],
+
+ 'padding-bottom': ['length'],
+ 'padding-left': ['length'],
+ 'padding-right': ['length'],
+ 'padding-top': ['length'],
+
+ 'margin-bottom': ['length'],
+ 'margin-left': ['length'],
+ 'margin-right': ['length'],
+ 'margin-top': ['length'],
+
+ 'height': ['length', 'percentage'],
+ 'width': ['length', 'percentage'],
+ 'min-height': ['length', 'percentage'],
+ 'min-width': ['length', 'percentage'],
+ 'max-height': ['length', 'percentage'],
+ 'max-width': ['length', 'percentage'],
+
+ 'top': ['length', 'percentage'],
+ 'right': ['length', 'percentage'],
+ 'bottom': ['length', 'percentage'],
+ 'left': ['length', 'percentage'],
+
+ 'color': ['color'],
+ 'font-size': ['length', 'percentage'],
+ 'font-weight': ['font-weight'],
+ 'line-height': ['number', 'length', 'percentage'],
+ 'letter-spacing': ['length'],
+ // Note: percentage is Level3 and not implemented anywhere yet
+ // https://drafts.csswg.org/css3-text/#word-spacing
+ 'word-spacing': ['length', 'percentage'],
+ 'text-indent': ['length', 'percentage'],
+ 'text-shadow': ['shadow'],
+
+ 'outline-color': ['color'],
+ // outline-offset <integer> used to be an error in the spec
+ 'outline-offset': ['length'],
+ 'outline-width': ['length'],
+
+ 'clip': ['rectangle'],
+
+ 'vertical-align': ['length', 'percentage'],
+ 'opacity': ['number[0,1]'],
+ 'visibility': ['visibility'],
+ 'z-index': ['integer']
+};
+
+/*
+ * Property to Type table
+ * (missing value-types of specified properties)
+ */
+var missing_properties = {
+ 'margin-bottom': ['percentage'],
+ 'margin-left': ['percentage'],
+ 'margin-right': ['percentage'],
+ 'margin-top': ['percentage'],
+ 'padding-bottom': ['percentage'],
+ 'padding-left': ['percentage'],
+ 'padding-right': ['percentage'],
+ 'padding-top': ['percentage'],
+ 'vertical-align': ['vertical']
+};
+
+/*
+ * Property to Type table
+ * (properties that haven't been specified but implemented)
+ */
+var unspecified_properties = {
+ // http://oli.jp/2010/css-animatable-properties/
+ 'border-top-left-radius': ['border-radius'],
+ 'border-top-right-radius': ['border-radius'],
+ 'border-bottom-left-radius': ['border-radius'],
+ 'border-bottom-right-radius': ['border-radius'],
+ 'background-image': ['image'],
+ 'background-size': ['background-size'],
+ // https://drafts.csswg.org/css3-background/#the-box-shadow
+ // Animatable: yes, except between inner and outer shadows (Transition to/from an absent shadow is a transition to/from ‘0 0 transparent’ or ‘0 0 transparent inset’, as appropriate.)
+ 'box-shadow': ['box-shadow'],
+ 'font-size-adjust': ['number'],
+ 'font-stretch': ['font-stretch'],
+ 'text-decoration-color': ['color'],
+ 'column-count': ['integer'],
+ 'column-gap': ['length'],
+ 'column-rule-color': ['color'],
+ 'column-rule-width': ['length'],
+ 'column-width': ['length'],
+ 'transform': ['transform'],
+ 'transform-origin': ['horizontal'],
+ 'display': ['display'],
+ 'position': ['position'],
+ 'object-view-box': ['object-view-box']
+};
+
+/*
+ * additional styles required to actually render
+ * (different browsers expect different environment)
+ */
+var additional_styles = {
+ // all browsers
+ 'border-top-width': {'border-top-style' : 'solid'},
+ 'border-right-width': {'border-right-style' : 'solid'},
+ 'border-bottom-width': {'border-bottom-style' : 'solid'},
+ 'border-left-width': {'border-left-style' : 'solid'},
+ 'top': {'position': 'absolute'},
+ 'right': {'position': 'absolute'},
+ 'bottom': {'position': 'absolute'},
+ 'left': {'position': 'absolute'},
+ 'z-index': {'position': 'absolute'},
+ 'outline-offset': {'outline-style': 'solid'},
+ 'outline-width': {'outline-style': 'solid'},
+ 'word-spacing': {'width': '100px', 'height': '100px'},
+ // unspecified properties
+ 'column-rule-width': {'column-rule-style': 'solid'},
+ 'position': {'width': '50px', 'height': '50px', top: '10px', left: '50px'}
+};
+
+/*
+ * additional styles required *on the parent* to actually render
+ * (different browsers expect different environment)
+ */
+var parent_styles = {
+ 'border-top-width': {'border-top-style' : 'solid'},
+ 'border-right-width': {'border-right-style' : 'solid'},
+ 'border-bottom-width': {'border-bottom-style' : 'solid'},
+ 'border-left-width': {'border-left-style' : 'solid'},
+ 'height': {'width': '100px', 'height': '100px'},
+ 'min-height': {'width': '100px', 'height': '100px'},
+ 'max-height': {'width': '100px', 'height': '100px'},
+ 'width': {'width': '100px', 'height': '100px'},
+ 'min-width': {'width': '100px', 'height': '100px'},
+ 'max-width': {'width': '100px', 'height': '100px'},
+ // unspecified properties
+ 'position': {'position': 'relative', 'width': '100px', 'height': '100px'},
+ // inheritance tests
+ 'top': {'width': '100px', 'height': '100px', 'position': 'relative'},
+ 'right': {'width': '100px', 'height': '100px', 'position': 'relative'},
+ 'bottom': {'width': '100px', 'height': '100px', 'position': 'relative'},
+ 'left': {'width': '100px', 'height': '100px', 'position': 'relative'}
+};
+
+
+function assemble(props) {
+ var tests = [];
+
+ // assemble tests
+ for (var property in props) {
+ props[property].forEach(function(type) {
+ var _values = values[type](property);
+ Object.keys(_values).forEach(function(unit) {
+ var data = {
+ name: property + ' ' + type + '(' + unit + ')',
+ property: property,
+ valueType : type,
+ unit : unit,
+ parentStyle: extend({}, parent_styles[property] || {}),
+ from: extend({}, additional_styles[property] || {}),
+ to: {}
+ };
+
+ data.from[property] = _values[unit][0];
+ data.to[property] = _values[unit][1];
+ data.flags = _values[unit][2] || {};
+
+ tests.push(data);
+ });
+ });
+ }
+
+ return tests;
+}
+
+root.getPropertyTests = function() {
+ return assemble(properties);
+};
+
+root.getMissingPropertyTests = function() {
+ return assemble(missing_properties);
+};
+
+root.getUnspecifiedPropertyTests = function() {
+ return assemble(unspecified_properties);
+};
+
+root.getFontSizeRelativePropertyTests = function() {
+ var accepted = {};
+
+ for (var key in properties) {
+ if (!Object.prototype.hasOwnProperty.call(properties, key) || key === "font-size") {
+ continue;
+ }
+
+ if (properties[key].indexOf('length') > -1) {
+ accepted[key] = ['length-em'];
+ }
+ }
+
+ return assemble(accepted);
+};
+
+root.filterPropertyTests = function(tests, names) {
+ var allowed = {};
+ var accepted = [];
+
+ if (typeof names === "string") {
+ names = [names];
+ }
+
+ if (!(names instanceof RegExp)) {
+ names.forEach(function(name) {
+ allowed[name] = true;
+ });
+ }
+
+ tests.forEach(function(test) {
+ if (names instanceof RegExp) {
+ if (!test.name.match(names)) {
+ return;
+ }
+ } else if (!allowed[test.name]) {
+ return;
+ }
+
+ accepted.push(test);
+ });
+
+ return accepted;
+};
+
+})(window);
diff --git a/testing/web-platform/tests/css/css-transitions/support/ruler-h-50%.png b/testing/web-platform/tests/css/css-transitions/support/ruler-h-50%.png
new file mode 100644
index 0000000000..cf2eea6b43
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/ruler-h-50%.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/ruler-h-50px.png b/testing/web-platform/tests/css/css-transitions/support/ruler-h-50px.png
new file mode 100644
index 0000000000..9f46583665
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/ruler-h-50px.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/ruler-v-100px.png b/testing/web-platform/tests/css/css-transitions/support/ruler-v-100px.png
new file mode 100644
index 0000000000..a837eca222
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/ruler-v-100px.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/ruler-v-50px.png b/testing/web-platform/tests/css/css-transitions/support/ruler-v-50px.png
new file mode 100644
index 0000000000..8414102802
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/ruler-v-50px.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/runParallelAsyncHarness.js b/testing/web-platform/tests/css/css-transitions/support/runParallelAsyncHarness.js
new file mode 100644
index 0000000000..de9b783790
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/runParallelAsyncHarness.js
@@ -0,0 +1,148 @@
+(function(root){
+'use strict';
+// testharness doesn't know about async test queues,
+// so this wrapper takes care of that
+
+/* USAGE:
+ runParallelAsyncHarness({
+ // list of data to test, must be array of objects.
+ // each object must contain a "name" property to describe the test
+ // besides name, the object can contain whatever data you need
+ tests: [
+ {name: "name of test 1", custom: "data"},
+ {name: "name of test 2", custom: "data"},
+ // ...
+ ],
+
+ // number of tests (tests, not test-cases!) to run concurrently
+ testsPerSlice: 100,
+
+ // time in milliseconds a test-run takes
+ duration: 1000,
+
+ // test-cases to run for for the test - there must be at least one
+ // each case creates its separate async_test() instance
+ cases: {
+ // test case named "test1"
+ test1: {
+ // run as a async_test.step() this callback contains your primary assertions
+ start: function(testCaseKey, data, options){},
+ // run as a async_test.step() this callback contains assertions to be run
+ // when the test ended, immediately before teardown
+ done: function(testCaseKey, data, options){}
+ },
+ // ...
+ }
+
+ // all callbacks are optional:
+
+ // invoked for individual test before it starts so you can setup the environment
+ // like DOM, CSS, adding event listeners and such
+ setup: function(data, options){},
+
+ // invoked after a test ended, so you can clean up the environment
+ // like DOM, CSS, removing event listeners and such
+ teardown: function(data, options){},
+
+ // invoked before a batch of tests ("slice") are run concurrently
+ // tests is an array of test data objects
+ sliceStart: function(options, tests)
+
+ // invoked after a batch of tests ("slice") were run concurrently
+ // tests is an array of test data objects
+ sliceDone: function(options, tests)
+
+ // invoked once all tests are done
+ done: function(options){}
+ })
+*/
+root.runParallelAsyncHarness = function(options) {
+ if (!options.cases) {
+ throw new Error("Options don't contain test cases!");
+ }
+
+ var noop = function(){};
+
+ // add a 100ms buffer to the test timeout, just in case
+ var duration = Math.ceil(options.duration + 100);
+
+ // names of individual tests
+ var cases = Object.keys(options.cases);
+
+ // run tests in a batch of slices
+ // primarily not to overload weak devices (tablets, phones, …)
+ // with too many tests running simultaneously
+ var iteration = -1;
+ var testPerSlice = options.testsPerSlice || 100;
+ var slices = Math.ceil(options.tests.length / testPerSlice);
+
+ // initialize all async test cases
+ // Note: satisfying testharness.js needs to know all async tests before load-event
+ options.tests.forEach(function(data, index) {
+ data.cases = {};
+ cases.forEach(function(name) {
+ data.cases[name] = async_test(data.name + " / " + name);
+ });
+ });
+
+ function runLoop() {
+ iteration++;
+ if (iteration >= slices) {
+ // no more slice, we're done
+ (options.done || noop)(options);
+ return;
+ }
+
+ // grab a slice of testss and initialize them
+ var offset = iteration * testPerSlice;
+ var tests = options.tests.slice(offset, offset + testPerSlice);
+ tests.forEach(function(data) {
+ (options.setup || noop)(data, options);
+
+ });
+
+ // kick off the current slice of tests
+ (options.sliceStart || noop)(options, tests);
+
+ // perform individual "start" test-case
+ tests.forEach(function(data) {
+ cases.forEach(function(name) {
+ data.cases[name].step(function() {
+ (options.cases[name].start || noop)(data.cases[name], data, options);
+ });
+ });
+ });
+
+ // conclude slice (possibly abort)
+ var concludeSlice = function() {
+ tests.forEach(function(data) {
+ // perform individual "done" test-case
+ cases.forEach(function(name) {
+ data.cases[name].step(function() {
+ (options.cases[name].done || noop)(data.cases[name], data, options);
+ });
+ });
+ // clean up after individual test
+ (options.teardown || noop)(data, options);
+ // tell harness we're done with individual test-cases
+ cases.forEach(function(name) {
+ data.cases[name].done();
+ });
+ });
+
+ // finish the test for current slice of tests
+ (options.sliceDone || noop)(options, tests);
+
+ // next test please, give the browser 50ms to do catch its breath
+ setTimeout(runLoop, 50);
+ }
+
+ // wait on RAF before cleanup to make sure all queued event handlers have run
+ setTimeout(function() {requestAnimationFrame(concludeSlice)},duration);
+ }
+
+ // allow DOMContentLoaded before actually doing something
+ setTimeout(runLoop, 100);
+};
+
+})(window);
diff --git a/testing/web-platform/tests/css/css-transitions/support/square-purple.png b/testing/web-platform/tests/css/css-transitions/support/square-purple.png
new file mode 100644
index 0000000000..0f522d7872
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/square-purple.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/square-teal.png b/testing/web-platform/tests/css/css-transitions/support/square-teal.png
new file mode 100644
index 0000000000..e567f51b91
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/square-teal.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/square-white.png b/testing/web-platform/tests/css/css-transitions/support/square-white.png
new file mode 100644
index 0000000000..5853cbb238
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/square-white.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/support/README b/testing/web-platform/tests/css/css-transitions/support/support/README
new file mode 100644
index 0000000000..ea8cb9ef35
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/support/README
@@ -0,0 +1,4 @@
+The swatch-green.png file in this directory is really a RED swatch,
+and the swatch-red.png file is really a green swatch.
+
+This directory is used to test relative URIs. \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-transitions/support/support/swatch-green.png b/testing/web-platform/tests/css/css-transitions/support/support/swatch-green.png
new file mode 100644
index 0000000000..1caf25c992
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/support/swatch-green.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/support/swatch-red.png b/testing/web-platform/tests/css/css-transitions/support/support/swatch-red.png
new file mode 100644
index 0000000000..0aa79b0c86
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/support/swatch-red.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-blue.png b/testing/web-platform/tests/css/css-transitions/support/swatch-blue.png
new file mode 100644
index 0000000000..bf2759634d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-blue.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-green.png b/testing/web-platform/tests/css/css-transitions/support/swatch-green.png
new file mode 100644
index 0000000000..0aa79b0c86
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-green.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-lime.png b/testing/web-platform/tests/css/css-transitions/support/swatch-lime.png
new file mode 100644
index 0000000000..55fd7fdaed
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-lime.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-orange.png b/testing/web-platform/tests/css/css-transitions/support/swatch-orange.png
new file mode 100644
index 0000000000..d3cd498b52
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-orange.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-red.png b/testing/web-platform/tests/css/css-transitions/support/swatch-red.png
new file mode 100644
index 0000000000..1caf25c992
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-red.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-teal.png b/testing/web-platform/tests/css/css-transitions/support/swatch-teal.png
new file mode 100644
index 0000000000..0293ce89de
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-teal.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-white.png b/testing/web-platform/tests/css/css-transitions/support/swatch-white.png
new file mode 100644
index 0000000000..1a7d4323d7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-white.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/swatch-yellow.png b/testing/web-platform/tests/css/css-transitions/support/swatch-yellow.png
new file mode 100644
index 0000000000..1591aa0e2e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/swatch-yellow.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/test-bl.png b/testing/web-platform/tests/css/css-transitions/support/test-bl.png
new file mode 100644
index 0000000000..904e24e996
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/test-bl.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/test-br.png b/testing/web-platform/tests/css/css-transitions/support/test-br.png
new file mode 100644
index 0000000000..f413ff5c1a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/test-br.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/test-inner-half-size.png b/testing/web-platform/tests/css/css-transitions/support/test-inner-half-size.png
new file mode 100644
index 0000000000..e473bf80ef
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/test-inner-half-size.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/test-outer.png b/testing/web-platform/tests/css/css-transitions/support/test-outer.png
new file mode 100644
index 0000000000..82eeace7fc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/test-outer.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/test-tl.png b/testing/web-platform/tests/css/css-transitions/support/test-tl.png
new file mode 100644
index 0000000000..f6ac0ef7e8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/test-tl.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/test-tr.png b/testing/web-platform/tests/css/css-transitions/support/test-tr.png
new file mode 100644
index 0000000000..59843ae54b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/test-tr.png
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/two.gif b/testing/web-platform/tests/css/css-transitions/support/two.gif
new file mode 100644
index 0000000000..01435c8020
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/two.gif
Binary files differ
diff --git a/testing/web-platform/tests/css/css-transitions/support/vendorPrefix.js b/testing/web-platform/tests/css/css-transitions/support/vendorPrefix.js
new file mode 100644
index 0000000000..1e7eed0481
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transitions/support/vendorPrefix.js
@@ -0,0 +1,86 @@
+//
+// Vendor-Prefix Helper Functions For Testing CSS
+//
+
+(function(root) {
+'use strict';
+
+var prefixCache = {};
+
+// convert "foo-bar" to "fooBar"
+function camelCase(str) {
+ return str.replace(/\-(\w)/g, function(match, letter){
+ return letter.toUpperCase();
+ });
+}
+
+// vendor-prefix a css property
+root.addVendorPrefix = function (name) {
+ var prefix = getVendorPrefix(name);
+ if (prefix === false) {
+ // property unknown to browser
+ return name;
+ }
+
+ return prefix + name;
+};
+
+// vendor-prefix a css property value
+root.addValueVendorPrefix = function (property, value) {
+ var prefix = getValueVendorPrefix(property, value);
+ if (prefix === false) {
+ // property unknown to browser
+ return name;
+ }
+
+ return prefix + value;
+};
+
+// identify vendor-prefix for css property
+root.getVendorPrefix = function(name) {
+ if (prefixCache[name] !== undefined) {
+ return prefixCache[name];
+ }
+
+ var elem = document.createElement("div");
+ name = camelCase(name);
+
+ if (name in elem.style) {
+ return prefixCache[name] = "";
+ }
+
+ var prefixes = ["Webkit", "Moz", "O", "ms"];
+ var styles = ["-webkit-", "-moz-", "-o-", "-ms-"];
+ var _name = name.substring(0, 1).toUpperCase() + name.substring(1);
+
+ for (var i = 0, length = prefixes.length; i < length; i++) {
+ if (prefixes[i] + _name in elem.style) {
+ return prefixCache[name] = styles[i];
+ }
+ }
+
+ return prefixCache[name] = name in elem.style ? "" : false;
+};
+
+// identify vendor-prefix for css property value
+root.getValueVendorPrefix = function(property, value) {
+ var elem = document.createElement("div");
+ // note: webkit needs the element to be attached to the dom
+ document.body.appendChild(elem);
+ var styles = ["-webkit-", "-moz-", "-o-", "-ms-", ""];
+ var _property = getVendorPrefix(property) + property;
+ for (var i=0, length = styles.length; i < length; i++) {
+ var _value = styles[i] + value;
+ elem.setAttribute('style', _property + ": " + _value);
+ var _computed = computedStyle(elem, _property);
+ if (_computed && _computed !== 'none') {
+ document.body.removeChild(elem);
+ return styles[i];
+ }
+ }
+ document.body.removeChild(elem);
+ return false;
+};
+
+
+})(window);