chromium/third_party/blink/web_tests/transitions/transition-end-event-helpers.js

'use strict';
var _recordedEvents = new Array();
// Number of events we're supposed to receive.
var _expectedEventCount = 0;
// Function invoked when we've received _expectedEventCount events.
var _endFunction;
// Have we processed the events? This is used to make sure we process the
// events only once.
var _processedEvents = false;

/* Call this function to record manually transition end events:

Function parameters:
    event [required]: the event passed with "webkitTransitionEnd" or "transitionend"

*/
function recordTransitionEndEvent(event)
{
  if (event.type != "webkitTransitionEnd" && event.type != "transitionend" )
    throw("Invalid transition end event!");

  _recordedEvents.push([
    event.propertyName,
    event.target.id,
    Math.round(event.elapsedTime * 1000) / 1000 // round to ms to avoid floating point imprecision
    ]);
  if (_recordedEvents.length == _expectedEventCount)
    _endFunction();
}

/* This is the helper function to run transition end event tests:

Test page requirements:
- The body must contain an empty div with id "result"
- The body must contain a div with with id "container"
- Call this function directly from the <script> inside the test page

Function parameters:
    expected [required]: an array of arrays defining the expected parameter values for the recorded transition end events (see below)
    callback [optional]: a function to be executed just before the test starts (none by default)

    Each sub-array must contain these items in this order:
    - the name of the CSS property that was transitioning
    - the id of the element on which the CSS property was transitioning
    - the elapsed time in seconds at which the CSS property finished transitioning
    - a boolean indicating if an event listener should be automatically added to the element to record the transition end event or if the script calls recordTransitionEndEvent() directly

*/
function runTransitionTest(expected, callback)
{
  _expectedEventCount = expected.length;

  if (window.testRunner) {
    testRunner.dumpAsText();
    testRunner.waitUntilDone();
  }

  function processEndEvents(expected)
  {
    if (_processedEvents)
      return;  // Only need to process events once

    _processedEvents = true;

    function compareEventInfo(e1, e2)
    {
      // Sort by property name then event target id

      // Index 0 is the property name
      if (e1[0]<e2[0]) return -1;
      if (e1[0]>e2[0]) return +1;

      // Index 1 is the target id
      if (e1[1]<e2[1]) return -1;
      if (e1[1]>e2[1]) return +1;

      return 0;
    }

    function examineResults(results, expected)
    {
      // Sort recorded and expected events arrays so they have the same ordering
      expected.sort(compareEventInfo);
      results.sort(compareEventInfo);

      var result = '<p>';
      for (var i=0; i < results.length && i < expected.length; ++i) {
        var pass = expected[i][0] == results[i][0] && expected[i][1] == results[i][1] && expected[i][2] == results[i][2];

        if (pass)
          result += "PASS --- ";
        else
          result += "FAIL --- ";

        result += "[Expected] Property: " + expected[i][0] + " ";
        result += "Target: " + expected[i][1] + " ";
        result += "Elapsed Time: " + expected[i][2];

        if (!pass) {
          result += " --- ";
          result += "[Received] Property: " + results[i][0] + " ";
          result += "Target: " + results[i][1] + " ";
          result += "Elapsed Time: " + results[i][2];
        }

        result += "<br>";
      }
      result += "</p>";

      if (expected.length > results.length) {
        result += "<p>FAIL - Missing events<br>";
        for (i=results.length; i < expected.length; ++i) {
          result += "[Missing] Property: " + expected[i][0] + " ";
          result += "Target: " + expected[i][1] + " ";
          result += "Elapsed Time: " + expected[i][2] + "<br>";
        }
        result += "</p>";
      } else if (expected.length < results.length) {
        result += "<p>FAIL - Unexpected events<br>";
        for (i=expected.length; i < results.length; ++i) {
          result += "[Unexpected] Property: " + results[i][0] + " ";
          result += "Target: " + results[i][1] + " ";
          result += "Elapsed Time: " + results[i][2] + "<br>";
        }
        result += "</p>";
      }

      return result;
    }

    document.body.removeChild(document.getElementById('container'));
    document.getElementById('result').innerHTML = examineResults(_recordedEvents, expected);

    if (window.testRunner)
        testRunner.notifyDone();
  }

  function startTest(expected, callback, maxTime)
  {
    document.body.offsetHeight; // Force style recalc
    if (callback)
      callback();

    if (!maxTime)
        maxTime = 0;

    for (var i=0; i < expected.length; ++i) {
      if (expected[i][3]) {
        var box = document.getElementById(expected[i][1]);
        box.addEventListener("webkitTransitionEnd", recordTransitionEndEvent, false);
      }

      var time = expected[i][2];
      if (time > maxTime)
          maxTime = time;
    }

    _endFunction = function() { processEndEvents(expected); };
    // Add three seconds of fudge. We don't just use the run_web_tests.py timeout
    // because processEndEvents gives more information on what failed.
    window.setTimeout(_endFunction, maxTime * 1000 + 3000);
  }

  window.addEventListener('load', function() { startTest(expected, callback) }, false);
}