diff --git a/src/js/app.js b/src/js/app.js index ee3bb4d1..9849f0ac 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -152,9 +152,9 @@ document.querySelector('#drawing-canvas-container')); this.fileDropperService.init(); - var drawingLoop = new pskl.rendering.DrawingLoop(); - drawingLoop.addCallback(this.render, this); - drawingLoop.start(); + this.drawingLoop = new pskl.rendering.DrawingLoop(); + this.drawingLoop.addCallback(this.render, this); + this.drawingLoop.start(); this.initTooltips_(); diff --git a/src/js/devtools/DrawingTestPlayer.js b/src/js/devtools/DrawingTestPlayer.js index 2876bbce..2a0940c6 100644 --- a/src/js/devtools/DrawingTestPlayer.js +++ b/src/js/devtools/DrawingTestPlayer.js @@ -8,6 +8,8 @@ this.step = step || this.initialState.step || ns.DrawingTestPlayer.DEFAULT_STEP; this.callbacks = []; this.shim = null; + this.performance = 0; + }; ns.DrawingTestPlayer.DEFAULT_STEP = 50; @@ -15,6 +17,15 @@ ns.DrawingTestPlayer.prototype.start = function () { this.setupInitialState_(); this.createMouseShim_(); + + // Override the main drawing loop to record the time spent rendering. + this.loopBackup = pskl.app.drawingLoop.loop; + pskl.app.drawingLoop.loop = function () { + var before = window.performance.now(); + this.loopBackup.call(pskl.app.drawingLoop); + this.performance += window.performance.now() - before; + }.bind(this); + this.regenerateReferencePng(function () { this.playEvent_(0); }.bind(this)); @@ -76,11 +87,13 @@ this.timer = window.setTimeout(function () { var recordEvent = this.events[index]; + // All events have already been replayed, finish the test. if (!recordEvent) { this.onTestEnd_(); return; } + var before = window.performance.now(); if (recordEvent.type === 'mouse-event') { this.playMouseEvent_(recordEvent); } else if (recordEvent.type === 'keyboard-event') { @@ -97,6 +110,9 @@ this.playInstrumentedEvent_(recordEvent); } + // Record the time spent replaying the event + this.performance += window.performance.now() - before; + this.playEvent_(index + 1); }.bind(this), this.step); }; @@ -155,6 +171,8 @@ ns.DrawingTestPlayer.prototype.onTestEnd_ = function () { this.removeMouseShim_(); + // Restore the original drawing loop. + pskl.app.drawingLoop.loop = this.loopBackup; // Retrieve the imageData corresponding to the spritesheet created by the test. var renderer = new pskl.rendering.PiskelRenderer(pskl.app.piskelController); @@ -175,8 +193,11 @@ $.publish(Events.TEST_RECORD_END, [success]); this.callbacks.forEach(function (callback) { - callback(success); - }); + callback({ + success: success, + performance: this.performance + }); + }.bind(this)); }; ns.DrawingTestPlayer.prototype.addEndTestCallback = function (callback) { diff --git a/src/js/devtools/DrawingTestSuiteController.js b/src/js/devtools/DrawingTestSuiteController.js index 483929bd..30fc1ce7 100644 --- a/src/js/devtools/DrawingTestSuiteController.js +++ b/src/js/devtools/DrawingTestSuiteController.js @@ -47,25 +47,33 @@ this.testSuiteRunner.start(); }; - ns.DrawingTestSuiteController.prototype.onTestCaseEnd_ = function (evt, testPath, status) { + ns.DrawingTestSuiteController.prototype.onTestCaseEnd_ = function (evt, testPath, success, performance) { var testCaseStatus = document.createElement('li'); testCaseStatus.innerHTML = pskl.utils.Template.replace( - '[{{path}}] finished : {{status}}', - {path : this.shortenPath_(testPath), status : status ? 'OK' : 'KO', color : status ? 'green' : 'red'} + '[{{path}}] finished : {{status}} ({{performance}})', + { + path : this.shortenPath_(testPath), + status : success ? 'OK' : 'KO', + color : success ? 'green' : 'red', + performance: performance.toFixed(2) + } ); this.testListElt.appendChild(testCaseStatus); }; - ns.DrawingTestSuiteController.prototype.onTestSuiteEnd_ = function (evt, status) { - console.log('on test suite end'); + ns.DrawingTestSuiteController.prototype.onTestSuiteEnd_ = function (evt, status, performance) { var elapsed = Date.now() - this.startTime_; elapsed = (elapsed / 1000).toFixed(4); var testSuiteStatus = document.createElement('li'); testSuiteStatus.innerHTML = pskl.utils.Template.replace( - 'Test finished : {{status}} ({{elapsed}} seconds)', - {status : status, elapsed : elapsed} + 'Test finished : {{status}} ({{elapsed}}s, performance: {{performance}})', + { + status : status, + elapsed : elapsed, + performance: performance.toFixed(2) + } ); this.testListElt.appendChild(testSuiteStatus); }; diff --git a/src/js/devtools/DrawingTestSuiteRunner.js b/src/js/devtools/DrawingTestSuiteRunner.js index 69e4a02a..b489920c 100644 --- a/src/js/devtools/DrawingTestSuiteRunner.js +++ b/src/js/devtools/DrawingTestSuiteRunner.js @@ -44,20 +44,25 @@ testPlayer.start(); }; - ns.DrawingTestSuiteRunner.prototype.onTestEnd_ = function (success) { + ns.DrawingTestSuiteRunner.prototype.onTestEnd_ = function (data /* {success, performance} */) { var path = this.testPaths[this.currentIndex]; - this.testStatus[path] = success; - $.publish(Events.TEST_CASE_END, [path, success]); + this.testStatus[path] = data; + + $.publish(Events.TEST_CASE_END, [path, data.success, data.performance]); this.runTest(this.currentIndex + 1); }; ns.DrawingTestSuiteRunner.prototype.onTestSuiteEnd_ = function () { var success = this.testPaths.every(function (path) { - return this.testStatus[path]; + return this.testStatus[path].success; }.bind(this)); + var performance = this.testPaths.reduce(function (p, path) { + return this.testStatus[path].performance + p; + }.bind(this), 0); + this.status = success ? ns.DrawingTestSuiteRunner.STATUS.SUCCESS : ns.DrawingTestSuiteRunner.STATUS.ERROR; - $.publish(Events.TEST_SUITE_END, [this.status]); + $.publish(Events.TEST_SUITE_END, [this.status, performance]); }; })(); diff --git a/src/js/rendering/DrawingLoop.js b/src/js/rendering/DrawingLoop.js index ade4e0bc..febea42e 100644 --- a/src/js/rendering/DrawingLoop.js +++ b/src/js/rendering/DrawingLoop.js @@ -15,6 +15,7 @@ scope : scope, args : args }; + this.callbacks.push(callbackObj); return callbackObj; };