Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / image / test / mochitest / animationPolling.js
blobb582df337e685fa49b3b895ec7334497054ed365
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 var currentTest;
3 var gIsRefImageLoaded = false;
4 const gShouldOutputDebugInfo = false;
6 function pollForSuccess()
8   if (!currentTest.isTestFinished) {
9     if (!currentTest.reusingReferenceImage || (currentTest.reusingReferenceImage
10         && gRefImageLoaded)) {
11       currentTest.checkImage();
12     }
14     setTimeout(pollForSuccess, currentTest.pollFreq);
15   }
18 function referencePoller()
20   currentTest.takeReferenceSnapshot();
23 function reuseImageCallback()
25   gIsRefImageLoaded = true;
28 function failTest()
30   if (currentTest.isTestFinished || currentTest.closeFunc) {
31     return;
32   }
34   ok(false, "timing out after " + currentTest.timeout + "ms.  "
35      + "Animated image still doesn't look correct, after poll #"
36      + currentTest.pollCounter);
37   currentTest.wereFailures = true;
39   if (currentTest.currentSnapshotDataURI) {
40     currentTest.outputDebugInfo("Snapshot #" + currentTest.pollCounter,
41                                 "snapNum" + currentTest.pollCounter,
42                                 currentTest.currentSnapshotDataURI);
43   }
45   currentTest.enableDisplay(document.getElementById(currentTest.debugElementId));
47   currentTest.cleanUpAndFinish();
50 /**
51  * Create a new AnimationTest object.
52  *
53  * @param pollFreq The amount of time (in ms) to wait between consecutive
54  *        snapshots if the reference image and the test image don't match.
55  * @param timeout The total amount of time (in ms) to wait before declaring the
56  *        test as failed.
57  * @param referenceElementId The id attribute of the reference image element, or
58  *        the source of the image to change to, once the reference snapshot has
59  *        been successfully taken. This latter option could be used if you don't
60  *        want the image to become invisible at any time during the test.
61  * @param imageElementId The id attribute of the test image element.
62  * @param debugElementId The id attribute of the div where links should be
63  *        appended if the test fails.
64  * @param cleanId The id attribute of the div or element to use as the 'clean'
65  *        test. This element is only enabled when we are testing to verify that
66  *        the reference image has been loaded. It can be undefined.
67  * @param srcAttr The location of the source of the image, for preloading. This
68  *        is usually not required, but it useful for preloading reference
69  *        images.
70  * @param xulTest A boolean value indicating whether or not this is a XUL test
71  *        (uses hidden=true/false rather than display: none to hide/show
72  *        elements).
73  * @param closeFunc A function that should be called when this test is finished.
74  *        If null, then cleanUpAndFinish() will be called. This can be used to
75  *        chain tests together, so they are all finished exactly once.
76  * @returns {AnimationTest}
77  */
78 function AnimationTest(pollFreq, timeout, referenceElementId, imageElementId,
79                        debugElementId, cleanId, srcAttr, xulTest, closeFunc)
81   // We want to test the cold loading behavior, so clear cache in case an
82   // earlier test got our image in there already.
83   clearImageCache();
85   this.wereFailures = false;
86   this.pollFreq = pollFreq;
87   this.timeout = timeout;
88   this.imageElementId = imageElementId;
89   this.referenceElementId = referenceElementId;
91   if (!document.getElementById(referenceElementId)) {
92     // In this case, we're assuming the user passed in a string that
93     // indicates the source of the image they want to change to,
94     // after the reference image has been taken.
95     this.reusingImageAsReference = true;
96   }
98   this.srcAttr = srcAttr;
99   this.debugElementId = debugElementId;
100   this.referenceSnapshot = ""; // value will be set in takeReferenceSnapshot()
101   this.pollCounter = 0;
102   this.isTestFinished = false;
103   this.numRefsTaken = 0;
104   this.blankWaitTime = 0;
106   this.cleanId = cleanId ? cleanId : '';
107   this.xulTest = xulTest ? xulTest : '';
108   this.closeFunc = closeFunc ? closeFunc : '';
111 AnimationTest.prototype.preloadImage = function()
113   if (this.srcAttr) {
114     this.myImage = new Image();
115     this.myImage.onload = function() { currentTest.continueTest(); };
116     this.myImage.src = this.srcAttr;
117   } else {
118     this.continueTest();
119   }
122 AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
124   if (!gShouldOutputDebugInfo) {
125     return;
126   }
127   var debugElement = document.getElementById(this.debugElementId);
128   var newDataUriElement = document.createElement("a");
129   newDataUriElement.setAttribute("id", id);
130   newDataUriElement.setAttribute("href", dataUri);
131   newDataUriElement.appendChild(document.createTextNode(message));
132   debugElement.appendChild(newDataUriElement);
133   var brElement = document.createElement("br");
134   debugElement.appendChild(brElement);
135   todo(false, "Debug (" + id + "): " + message + " " + dataUri);
138 AnimationTest.prototype.isFinished = function()
140   return this.isTestFinished;
143 AnimationTest.prototype.takeCleanSnapshot = function()
145   var cleanElement;
146   if (this.cleanId) {
147     cleanElement = document.getElementById(this.cleanId);
148   }
150   // Enable clean page comparison element
151   if (cleanElement) {
152     this.enableDisplay(cleanElement);
153   }
155   // Take a snapshot of the initial (clean) page
156   this.cleanSnapshot = snapshotWindow(window, false);
158   // Disable the clean page comparison element
159   if (cleanElement) {
160     this.disableDisplay(cleanElement);
161   }
163   var dataString1 = "Clean Snapshot";
164   this.outputDebugInfo(dataString1, 'cleanSnap',
165                        this.cleanSnapshot.toDataURL());
168 AnimationTest.prototype.takeBlankSnapshot = function()
170   // Take a snapshot of the initial (essentially blank) page
171   this.blankSnapshot = snapshotWindow(window, false);
173   var dataString1 = "Initial Blank Snapshot";
174   this.outputDebugInfo(dataString1, 'blank1Snap',
175                        this.blankSnapshot.toDataURL());
179  * Begin the AnimationTest. This will utilize the information provided in the
180  * constructor to invoke a mochitest on animated images. It will automatically
181  * fail if allowed to run past the timeout. This will attempt to preload an
182  * image, if applicable, and then asynchronously call continueTest(), or if not
183  * applicable, synchronously trigger a call to continueTest().
184  */
185 AnimationTest.prototype.beginTest = function()
187   SimpleTest.waitForExplicitFinish();
189   currentTest = this;
190   this.preloadImage();
194  * This is the second part of the test. It is triggered (eventually) from
195  * beginTest() either synchronously or asynchronously, as an image load
196  * callback.
197  */
198 AnimationTest.prototype.continueTest = function()
200   // In case something goes wrong, fail earlier than mochitest timeout,
201   // and with more information.
202   setTimeout(failTest, this.timeout);
204   if (!this.reusingImageAsReference) {
205     this.disableDisplay(document.getElementById(this.imageElementId));
206   }
208   this.takeReferenceSnapshot();
209   this.setupPolledImage();
210   SimpleTest.executeSoon(pollForSuccess);
213 AnimationTest.prototype.setupPolledImage = function ()
215   // Make sure the image is visible
216   if (!this.reusingImageAsReference) {
217     this.enableDisplay(document.getElementById(this.imageElementId));
218     var currentSnapshot = snapshotWindow(window, false);
219     var result = compareSnapshots(currentSnapshot,
220                                   this.referenceSnapshot, true);
222     this.currentSnapshotDataURI = currentSnapshot.toDataURL();
224     if (result[0]) {
225       // SUCCESS!
226       ok(true, "Animated image looks correct, at poll #"
227          + this.pollCounter);
229       this.cleanUpAndFinish();
230     }
231   } else {
232     if (!gIsRefImageLoaded) {
233       this.myImage = new Image();
234       this.myImage.onload = reuseImageCallback;
235       document.getElementById(this.imageElementId).setAttribute('src',
236         this.referenceElementId);
237     }
238   }
241 AnimationTest.prototype.checkImage = function ()
243   if (this.isTestFinished) {
244     return;
245   }
247   this.pollCounter++;
249   // We need this for some tests, because we need to force the
250   // test image to be visible.
251   if (!this.reusingImageAsReference) {
252     this.enableDisplay(document.getElementById(this.imageElementId));
253   }
255   var currentSnapshot = snapshotWindow(window, false);
256   var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
258   this.currentSnapshotDataURI = currentSnapshot.toDataURL();
260   if (result[0]) {
261     // SUCCESS!
262     ok(true, "Animated image looks correct, at poll #"
263        + this.pollCounter);
265     this.cleanUpAndFinish();
266   }
269 AnimationTest.prototype.takeReferenceSnapshot = function ()
271   this.numRefsTaken++;
273   // Test to make sure the reference image doesn't match a clean snapshot
274   if (!this.cleanSnapshot) {
275     this.takeCleanSnapshot();
276   }
278   // Used later to verify that the reference div disappeared
279   if (!this.blankSnapshot) {
280     this.takeBlankSnapshot();
281   }
283   if (this.reusingImageAsReference) {
284     // Show reference elem (which is actually our image), & take a snapshot
285     var referenceElem = document.getElementById(this.imageElementId);
286     this.enableDisplay(referenceElem);
288     this.referenceSnapshot = snapshotWindow(window, false);
290     var snapResult = compareSnapshots(this.cleanSnapshot,
291                                       this.referenceSnapshot, false);
292     if (!snapResult[0]) {
293       if (this.blankWaitTime > 2000) {
294         // if it took longer than two seconds to load the image, we probably
295         // have a problem.
296         this.wereFailures = true;
297         ok(snapResult[0],
298            "Reference snapshot shouldn't match clean (non-image) snapshot");
299       } else {
300         this.blankWaitTime += currentTest.pollFreq;
301         // let's wait a bit and see if it clears up
302         setTimeout(referencePoller, currentTest.pollFreq);
303         return;
304       }
305     }
307     ok(snapResult[0],
308        "Reference snapshot shouldn't match clean (non-image) snapshot");
310     var dataString = "Reference Snapshot #" + this.numRefsTaken;
311     this.outputDebugInfo(dataString, 'refSnapId',
312                          this.referenceSnapshot.toDataURL());
313   } else {
314     // Make sure the animation section is hidden
315     this.disableDisplay(document.getElementById(this.imageElementId));
317     // Show reference div, & take a snapshot
318     var referenceDiv = document.getElementById(this.referenceElementId);
319     this.enableDisplay(referenceDiv);
321     this.referenceSnapshot = snapshotWindow(window, false);
322     var snapResult = compareSnapshots(this.cleanSnapshot,
323                                       this.referenceSnapshot, false);
324     if (!snapResult[0]) {
325       if (this.blankWaitTime > 2000) {
326         // if it took longer than two seconds to load the image, we probably
327         // have a problem.
328         this.wereFailures = true;
329         ok(snapResult[0],
330            "Reference snapshot shouldn't match clean (non-image) snapshot");
331       } else {
332         this.blankWaitTime += 20;
333         // let's wait a bit and see if it clears up
334         setTimeout(referencePoller, 20);
335         return;
336       }
337     }
339     ok(snapResult[0],
340        "Reference snapshot shouldn't match clean (non-image) snapshot");
342     var dataString = "Reference Snapshot #" + this.numRefsTaken;
343     this.outputDebugInfo(dataString, 'refSnapId',
344                          this.referenceSnapshot.toDataURL());
346     // Re-hide reference div, and take another snapshot to be sure it's gone
347     this.disableDisplay(referenceDiv);
348     this.testBlankCameBack();
349   }
352 AnimationTest.prototype.enableDisplay = function(element)
354   if (!element) {
355     return;
356   }
358   if (!this.xulTest) {
359     element.style.display = '';
360   } else {
361     element.setAttribute('hidden', 'false');
362   }
365 AnimationTest.prototype.disableDisplay = function(element)
367   if (!element) {
368     return;
369   }
371   if (!this.xulTest) {
372     element.style.display = 'none';
373   } else {
374     element.setAttribute('hidden', 'true');
375   }
378 AnimationTest.prototype.testBlankCameBack = function()
380   var blankSnapshot2 = snapshotWindow(window, false);
381   var result = compareSnapshots(this.blankSnapshot, blankSnapshot2, true);
382   ok(result[0], "Reference image should disappear when it becomes display:none");
384   if (!result[0]) {
385     this.wereFailures = true;
386     var dataString = "Second Blank Snapshot";
387     this.outputDebugInfo(dataString, 'blank2SnapId', result[2]);
388   }
391 AnimationTest.prototype.cleanUpAndFinish = function ()
393   // On the off chance that failTest and checkImage are triggered
394   // back-to-back, use a flag to prevent multiple calls to SimpleTest.finish.
395   if (this.isTestFinished) {
396     return;
397   }
399   this.isTestFinished = true;
401   // Call our closing function, if one exists
402   if (this.closeFunc) {
403     this.closeFunc();
404     return;
405   }
407   if (this.wereFailures) {
408     document.getElementById(this.debugElementId).style.display = 'block';
409   }
411   SimpleTest.finish();
412   document.getElementById(this.debugElementId).style.display = "";