Bug 1070745 part 1 - Factor out new_div etc. to animation_utils.js; r=dholbert

We use new_div, check_events etc. in a number of animation-related mochitests
and with this bug we'll want to use them in a few more. This patch factors them
out into animation_utils.js and tidies them up a little.
This commit is contained in:
Brian Birtles 2014-10-20 13:55:43 +09:00
parent 11fdb24683
commit b5cac727ee
4 changed files with 159 additions and 189 deletions

View File

@ -1,3 +1,108 @@
//----------------------------------------------------------------------
//
// Common testing functions
//
//----------------------------------------------------------------------
function advance_clock(milliseconds) {
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
}
// Test-element creation/destruction and event checking
(function() {
var gElem;
var gEventsReceived = [];
function new_div(style) {
return new_element("div", style);
}
// Creates a new |tagname| element with inline style |style| and appends
// it as a child of the element with ID 'display'.
// The element will also be given the class 'target' which can be used
// for additional styling.
function new_element(tagname, style) {
if (gElem) {
ok(false, "test author forgot to call done_div/done_elem");
}
if (typeof(style) != "string") {
ok(false, "test author forgot to pass argument");
}
if (!document.getElementById("display")) {
ok(false, "no 'display' element to append to");
}
gElem = document.createElement(tagname);
gElem.setAttribute("style", style);
gElem.classList.add("target");
document.getElementById("display").appendChild(gElem);
return [ gElem, getComputedStyle(gElem, "") ];
}
function listen() {
if (!gElem) {
ok(false, "test author forgot to call new_div before listen");
}
gEventsReceived = [];
function listener(event) {
gEventsReceived.push(event);
}
gElem.addEventListener("animationstart", listener, false);
gElem.addEventListener("animationiteration", listener, false);
gElem.addEventListener("animationend", listener, false);
}
function check_events(eventsExpected, desc) {
// This function checks that the list of eventsExpected matches
// the received events -- but it only checks the properties that
// are present on eventsExpected.
is(gEventsReceived.length, gEventsReceived.length,
"number of events received for " + desc);
for (var i = 0,
i_end = Math.min(eventsExpected.length, gEventsReceived.length);
i != i_end; ++i) {
var exp = eventsExpected[i];
var rec = gEventsReceived[i];
for (var prop in exp) {
if (prop == "elapsedTime") {
// Allow floating point error.
ok(Math.abs(rec.elapsedTime - exp.elapsedTime) < 0.000002,
"events[" + i + "]." + prop + " for " + desc +
" received=" + rec.elapsedTime + " expected=" + exp.elapsedTime);
} else {
is(rec[prop], exp[prop],
"events[" + i + "]." + prop + " for " + desc);
}
}
}
for (var i = eventsExpected.length; i < gEventsReceived.length; ++i) {
ok(false, "unexpected " + gEventsReceived[i].type + " event for " + desc);
}
gEventsReceived = [];
}
function done_element() {
if (!gElem) {
ok(false, "test author called done_element/done_div without matching"
+ " call to new_element/new_div");
}
gElem.remove();
gElem = null;
if (gEventsReceived.length) {
ok(false, "caller should have called check_events");
}
}
[ new_div
, new_element
, listen
, check_events
, done_element ]
.forEach(function(fn) {
window[fn.name] = fn;
});
window.done_div = done_element;
})();
function px_to_num(str)
{
return Number(String(str).match(/^([\d.]+)px$/)[1]);

View File

@ -165,73 +165,12 @@ is(e.elapsedTime, 0.5);
is(e.pseudoElement, "pseudo");
is(e.isTrusted, false)
function advance_clock(milliseconds) {
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
}
var display = document.getElementById("display");
var div = null;
var cs = null;
var events_received = [];
function new_div(style) {
return new_element("div", style);
}
function new_element(tagname, style) {
if (div != null || cs != null) {
ok(false, "test author forgot to call done_div");
}
if (typeof(style) != "string") {
ok(false, "test author forgot to pass argument");
}
div = document.createElement(tagname);
div.setAttribute("style", style);
display.appendChild(div);
cs = getComputedStyle(div, "");
}
function listen() {
events_received = [];
function listener(event) {
events_received.push(event);
}
div.addEventListener("animationstart", listener, false);
div.addEventListener("animationiteration", listener, false);
div.addEventListener("animationend", listener, false);
}
function check_events(events_expected, desc) {
// This function checks that the list of events_expected matches
// the received events -- but it only checks the properties that
// are present on events_expected.
is(events_received.length, events_expected.length,
"number of events received for " + desc);
for (var i = 0,
i_end = Math.min(events_expected.length, events_received.length);
i != i_end; ++i) {
var exp = events_expected[i];
var rec = events_received[i];
for (var prop in exp) {
if (prop == "elapsedTime") {
// Allow floating point error.
ok(Math.abs(rec.elapsedTime - exp.elapsedTime) < 0.000002,
"events[" + i + "]." + prop + " for " + desc +
" received=" + rec.elapsedTime + " expected=" + exp.elapsedTime);
} else {
is(rec[prop], exp[prop], "events[" + i + "]." + prop + " for " + desc);
}
}
}
for (var i = events_expected.length; i < events_received.length; ++i) {
ok(false, "unexpected " + events_received[i].type + " event for " + desc);
}
events_received = [];
}
function done_div() {
display.removeChild(div);
div = null;
cs = null;
if (events_received.length) {
ok(false, "caller should have called check_events");
}
}
// Shortcut new_div to update div, cs
var div, cs;
var originalNewDiv = window.new_div;
window.new_div = function(style) {
[ div, cs ] = originalNewDiv(style);
};
// take over the refresh driver right from the start.
advance_clock(0);
@ -820,7 +759,9 @@ is_approx(px_to_num(cs.marginRight), 100 * gTF.ease_in(0.3), 0.01,
"animation-iteration-count test 1 at 8.1s");
done_div();
new_div("animation: anim2 ease-in 10s 0.3, anim3 ease-out 20s 1.2 alternate forwards, anim4 ease-in-out 5s 1.6 forwards");
new_div("animation: anim2 ease-in 10s 0.3"
+ ", anim3 ease-out 20s 1.2 alternate forwards"
+ ", anim4 ease-in-out 5s 1.6 forwards");
is(cs.marginRight, "0px", "animation-iteration-count test 2 at 0s");
is(cs.marginTop, "0px", "animation-iteration-count test 3 at 0s");
is(cs.marginBottom, "0px", "animation-iteration-count test 4 at 0s");
@ -1378,10 +1319,12 @@ done_div();
// This test depends on forms.css having a rule
// select { line-height: !important }
// If that rule changes, we should rewrite it to depend on a different rule.
new_element("select", "");
var select;
[ select, cs ] = new_element("select", "");
var default_line_height = cs.lineHeight;
done_div();
new_element("select", "animation: uaoverride 2s linear infinite");
done_element();
[ select, cs ] = new_element("select",
"animation: uaoverride 2s linear infinite");
is(cs.lineHeight, default_line_height,
"animations should not override UA !important at 0ms");
is(cs.marginTop, "20px",
@ -1391,14 +1334,15 @@ is(cs.lineHeight, default_line_height,
"animations should not override UA !important at 200ms");
is(cs.marginTop, "40px",
"rest of animation should still work when UA !important present at 200ms");
done_div();
done_element();
// Test that author !important rules override animations, but
// that animations override regular author rules.
new_div("animation: always_fifty 1s linear infinite; margin-left: 200px");
is(cs.marginLeft, "50px", "animations override regular author rules");
done_div();
new_div("animation: always_fifty 1s linear infinite; margin-left: 200px ! important;");
new_div("animation: always_fifty 1s linear infinite;"
+ " margin-left: 200px ! important;");
is(cs.marginLeft, "200px", "important author rules override animations");
done_div();
@ -1515,11 +1459,17 @@ done_div();
// start animations.
// note: anim2 animates margin-right from 0 to 100px
// note: anim3 animates margin-top from 0 to 100px
new_div("animation-name: anim2, anim3; animation-duration: 1s; animation-timing-function: linear; animation-delay: -250ms, -250ms, -750ms, -500ms;");
new_div("animation-name: anim2, anim3;"
+ " animation-duration: 1s;"
+ " animation-timing-function: linear;"
+ " animation-delay: -250ms, -250ms, -750ms, -500ms;");
is(cs.marginRight, "25px", "animation-name list length is the length that matters");
is(cs.marginTop, "25px", "animation-name list length is the length that matters");
done_div();
new_div("animation-name: anim2, anim3, anim2; animation-duration: 1s; animation-timing-function: linear; animation-delay: -250ms, -250ms, -750ms, -500ms;");
new_div("animation-name: anim2, anim3, anim2;"
+ " animation-duration: 1s;"
+ " animation-timing-function: linear;"
+ " animation-delay: -250ms, -250ms, -750ms, -500ms;");
is(cs.marginRight, "75px", "animation-name list length is the length that matters, and the last occurrence of a name wins");
is(cs.marginTop, "25px", "animation-name list length is the length that matters");
done_div();
@ -1652,7 +1602,8 @@ check_events([]);
done_div();
// Test with animation-direction reverse
new_div("margin-right: 200px; animation: anim2 0s 1s both reverse");
new_div("margin-right: 200px;"
+ " animation: anim2 0s 1s both reverse");
advance_clock(0);
is(cs.getPropertyValue("margin-right"), "100px",
"margin-right during backwards fill of reversed zero-duration animation");
@ -1693,8 +1644,8 @@ is(cs.getPropertyValue("margin-right"), "100px",
done_div();
// Test with animation-direction alternate and non-integral number of iterations
new_div("margin-right: 200px; " +
"animation: anim2 0s 1s both alternate 7.3 linear");
new_div("margin-right: 200px;"
+ " animation: anim2 0s 1s both alternate 7.3 linear");
advance_clock(0);
is(cs.getPropertyValue("margin-right"), "0px",
"margin-right during backwards fill of alternating zero-duration " +
@ -1743,8 +1694,8 @@ is(cs.getPropertyValue("margin-right"), "0px",
done_div();
// Test with infinite iteration count and alternate-reverse direction
new_div("margin-right: 200px; " +
"animation: anim2 0s 1s alternate-reverse infinite both");
new_div("margin-right: 200px;"
+ " animation: anim2 0s 1s alternate-reverse infinite both");
advance_clock(0);
is(cs.getPropertyValue("margin-right"), "100px",
"margin-right during backwards fill of infinitely repeating and " +
@ -1756,8 +1707,8 @@ is(cs.getPropertyValue("margin-right"), "100px",
done_div();
// Test with negative delay
new_div("margin-right: 200px; " +
"animation: anim2 0s -1s both reverse 12.7 linear");
new_div("margin-right: 200px;"
+ " animation: anim2 0s -1s both reverse 12.7 linear");
listen();
advance_clock(0);
is(cs.getPropertyValue("margin-right"), "30px",

View File

@ -168,9 +168,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=964646
/** Test for css3-animations running on the compositor thread (Bug 964646) **/
// Global state
var gDisplay = document.getElementById("display"),
gDiv = null,
gEventsReceived = [];
var gDisplay = document.getElementById("display")
, gDiv = null;
// Shortcut omta_is and friends by filling in the initial 'elem' argument
// with gDiv.
@ -185,6 +184,17 @@ var gDisplay = document.getElementById("display"),
};
});
// Shortcut new_div and done_div to update gDiv
var originalNewDiv = window.new_div;
window.new_div = function(style) {
[ gDiv ] = originalNewDiv(style);
};
var originalDoneDiv = window.done_div;
window.done_div = function() {
originalDoneDiv();
gDiv = null;
};
SimpleTest.waitForExplicitFinish();
runOMTATest(function() {
var onAbort = function() {
@ -2073,73 +2083,5 @@ addAsyncAnimTest(function *() {
visitedLink.remove();
});
//----------------------------------------------------------------------
//
// Helper functions from test_animations.html
//
//----------------------------------------------------------------------
function new_div(style) {
if (gDiv !== null) {
ok(false, "test author forgot to call done_div");
}
if (typeof(style) != "string") {
ok(false, "test author forgot to pass style argument");
}
gDiv = document.createElement("div");
gDiv.classList.add("target");
gDiv.setAttribute("style", style);
gDisplay.appendChild(gDiv);
}
function done_div() {
if (gDiv === null) {
ok(false, "test author forgot to call new_div");
}
gDisplay.removeChild(gDiv);
gDiv = null;
}
function listen() {
gEventsReceived = [];
function listener(event) {
gEventsReceived.push(event);
}
gDiv.addEventListener("animationstart", listener, false);
gDiv.addEventListener("animationiteration", listener, false);
gDiv.addEventListener("animationend", listener, false);
}
function check_events(events_expected, desc) {
// This function checks that the list of events_expected matches
// the received events -- but it only checks the properties that
// are present on events_expected.
is(gEventsReceived.length, events_expected.length,
"number of events received for " + desc);
for (var i = 0,
i_end = Math.min(events_expected.length, gEventsReceived.length);
i != i_end; ++i) {
var exp = events_expected[i];
var rec = gEventsReceived[i];
for (var prop in exp) {
if (prop == "elapsedTime") {
// Allow floating point error.
ok(Math.abs(rec.elapsedTime - exp.elapsedTime) < 0.000002,
"events[" + i + "]." + prop + " for " + desc +
" received=" + rec.elapsedTime + " expected=" + exp.elapsedTime);
} else {
is(rec[prop], exp[prop], "events[" + i + "]." + prop + " for " + desc);
}
}
}
for (i = events_expected.length; i < gEventsReceived.length; ++i) {
ok(false, "unexpected " + gEventsReceived[i].type + " event for " + desc);
}
gEventsReceived = [];
}
function advance_clock(milliseconds) {
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
}
</script>
</html>

View File

@ -63,34 +63,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=696253
/** Test for flex-grow and flex-shrink animation (Bug 696253) **/
function advance_clock(milliseconds) {
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
}
var display = document.getElementById("display");
var div = null;
var cs = null;
function new_div(style) {
return new_element("div", style);
}
function new_element(tagname, style) {
if (div != null || cs != null) {
ok(false, "test author forgot to call done_div");
}
if (typeof(style) != "string") {
ok(false, "test author forgot to pass argument");
}
div = document.createElement(tagname);
div.setAttribute("style", style);
display.appendChild(div);
cs = getComputedStyle(div, "");
}
function done_div() {
display.removeChild(div);
div = null;
cs = null;
}
// take over the refresh driver
advance_clock(0);
@ -98,7 +70,7 @@ advance_clock(0);
// --------------------------------------------
// flexGrowTwoToThree: 2.0 at 0%, 2.5 at 50%, 10 after animation is over
new_div("animation: flexGrowTwoToThree linear 1s");
var [ div, cs ] = new_div("animation: flexGrowTwoToThree linear 1s");
is_approx(cs.flexGrow, 2, 0.01, "flexGrowTwoToThree at 0.0s");
advance_clock(500);
is_approx(cs.flexGrow, 2.5, 0.01, "flexGrowTwoToThree at 0.5s");
@ -107,7 +79,7 @@ is(cs.flexGrow, 10, "flexGrowTwoToThree at 1.5s");
done_div();
// flexShrinkTwoToThree: 2.0 at 0%, 2.5 at 50%, 20 after animation is over
new_div("animation: flexShrinkTwoToThree linear 1s");
[ div, cs ] = new_div("animation: flexShrinkTwoToThree linear 1s");
is_approx(cs.flexShrink, 2, 0.01, "flexShrinkTwoToThree at 0.0s");
advance_clock(500);
is_approx(cs.flexShrink, 2.5, 0.01, "flexShrinkTwoToThree at 0.5s");
@ -116,7 +88,7 @@ is(cs.flexShrink, 20, "flexShrinkTwoToThree at 1.5s");
done_div();
// flexGrowZeroToZero: 0 at 0%, 0 at 50%, 10 after animation is over
new_div("animation: flexGrowZeroToZero linear 1s");
[ div, cs ] = new_div("animation: flexGrowZeroToZero linear 1s");
is(cs.flexGrow, 0, "flexGrowZeroToZero at 0.0s");
advance_clock(500);
is(cs.flexGrow, 0, "flexGrowZeroToZero at 0.5s");
@ -125,7 +97,7 @@ is(cs.flexGrow, 10, "flexGrowZeroToZero at 1.5s");
done_div();
// flexShrinkZeroToZero: 0 at 0%, 0 at 50%, 20 after animation is over
new_div("animation: flexShrinkZeroToZero linear 1s");
[ div, cs ] = new_div("animation: flexShrinkZeroToZero linear 1s");
is(cs.flexShrink, 0, "flexShrinkZeroToZero at 0.0s");
advance_clock(500);
is(cs.flexShrink, 0, "flexShrinkZeroToZero at 0.5s");
@ -139,7 +111,7 @@ done_div();
// allowed to animate between 0 and other values. But now that's allowed.)
// flexGrowZeroToOne: 0 at 0%, 0.5 at 50%, 10 after animation is over.
new_div("animation: flexGrowZeroToOne linear 1s");
[ div, cs ] = new_div("animation: flexGrowZeroToOne linear 1s");
is(cs.flexGrow, 0, "flexGrowZeroToOne at 0.0s");
advance_clock(500);
is(cs.flexGrow, 0.5, "flexGrowZeroToOne at 0.5s");
@ -148,7 +120,7 @@ is(cs.flexGrow, 10, "flexGrowZeroToOne at 1.5s");
done_div();
// flexShrinkZeroToOne: 0 at 0%, 0.5 at 50%, 20 after animation is over.
new_div("animation: flexShrinkZeroToOne linear 1s");
[ div, cs ] = new_div("animation: flexShrinkZeroToOne linear 1s");
is(cs.flexShrink, 0, "flexShrinkZeroToOne at 0.0s");
advance_clock(500);
is(cs.flexShrink, 0.5, "flexShrinkZeroToOne at 0.5s");
@ -157,7 +129,7 @@ is(cs.flexShrink, 20, "flexShrinkZeroToOne at 1.5s");
done_div();
// flexGrowOneToZero: 1 at 0%, 0.5 at 50%, 10 after animation is over.
new_div("animation: flexGrowOneToZero linear 1s");
[ div, cs ] = new_div("animation: flexGrowOneToZero linear 1s");
is(cs.flexGrow, 1, "flexGrowOneToZero at 0.0s");
advance_clock(500);
is(cs.flexGrow, 0.5, "flexGrowOneToZero at 0.5s");
@ -166,7 +138,7 @@ is(cs.flexGrow, 10, "flexGrowOneToZero at 1.5s");
done_div();
// flexShrinkOneToZero: 1 at 0%, 0.5 at 50%, 20 after animation is over.
new_div("animation: flexShrinkOneToZero linear 1s");
[ div, cs ] = new_div("animation: flexShrinkOneToZero linear 1s");
is(cs.flexShrink, 1, "flexShrinkOneToZero at 0.0s");
advance_clock(500);
is(cs.flexShrink, 0.5, "flexShrinkOneToZero at 0.5s");