aboutsummaryrefslogtreecommitdiffstats
path: root/tests/wpt/css-tests/css-values-3_dev/xhtml1/reference/support/generalParallelTest.js
diff options
context:
space:
mode:
authorMs2ger <Ms2ger@gmail.com>2015-10-31 14:35:08 +0100
committerMs2ger <Ms2ger@gmail.com>2015-10-31 16:21:47 +0100
commit5450053b026bb842a00824ab0be1211ba0288540 (patch)
treeb5647bf0632bf902289f56125be5656981742e44 /tests/wpt/css-tests/css-values-3_dev/xhtml1/reference/support/generalParallelTest.js
parentb492a3e8b1762491f84ab134d9d2904fce69b1ea (diff)
downloadservo-5450053b026bb842a00824ab0be1211ba0288540.tar.gz
servo-5450053b026bb842a00824ab0be1211ba0288540.zip
Update CSS tests to revision d13905941293af83ea8c3c1750dba652e0423fb0
Diffstat (limited to 'tests/wpt/css-tests/css-values-3_dev/xhtml1/reference/support/generalParallelTest.js')
-rw-r--r--tests/wpt/css-tests/css-values-3_dev/xhtml1/reference/support/generalParallelTest.js231
1 files changed, 231 insertions, 0 deletions
diff --git a/tests/wpt/css-tests/css-values-3_dev/xhtml1/reference/support/generalParallelTest.js b/tests/wpt/css-tests/css-values-3_dev/xhtml1/reference/support/generalParallelTest.js
new file mode 100644
index 00000000000..1a4bf343df0
--- /dev/null
+++ b/tests/wpt/css-tests/css-values-3_dev/xhtml1/reference/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);