From caebce5ec880d2146b71ba3c3158fde4873b7d79 Mon Sep 17 00:00:00 2001 From: jdescottes Date: Sat, 23 Aug 2014 22:45:52 +0200 Subject: [PATCH] added test suite runner, removed tests from travis build --- Gruntfile.js | 37 ++++-- src/js/Constants.js | 5 +- src/js/Events.js | 5 +- src/js/app.js | 23 +--- ...stRecordPlayer.js => DrawingTestPlayer.js} | 108 +++++++++++------- ...TestRecorder.js => DrawingTestRecorder.js} | 22 ++-- src/js/devtools/DrawingTestRunner.js | 22 +--- src/js/devtools/DrawingTestSuiteController.js | 77 +++++++++++++ src/js/devtools/DrawingTestSuiteRunner.js | 63 ++++++++++ src/js/devtools/TestRecordController.js | 4 +- src/js/devtools/init.js | 34 ++++++ src/js/service/AppEngineStorageService.js | 57 ++++----- src/js/service/ImageUploadService.js | 25 ++-- src/js/utils/Xhr.js | 46 ++++++++ src/piskel-script-list.js | 12 +- test/integration/casperjs/TravisTestSuite.js | 4 + .../casperjs/drawing-records/TestSuite.json | 5 + 17 files changed, 391 insertions(+), 158 deletions(-) rename src/js/devtools/{TestRecordPlayer.js => DrawingTestPlayer.js} (62%) rename src/js/devtools/{TestRecorder.js => DrawingTestRecorder.js} (78%) create mode 100644 src/js/devtools/DrawingTestSuiteController.js create mode 100644 src/js/devtools/DrawingTestSuiteRunner.js create mode 100644 src/js/devtools/init.js create mode 100644 src/js/utils/Xhr.js create mode 100644 test/integration/casperjs/TravisTestSuite.js create mode 100644 test/integration/casperjs/drawing-records/TestSuite.json diff --git a/Gruntfile.js b/Gruntfile.js index 624806c..b9834ea 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -20,22 +20,36 @@ module.exports = function(grunt) { return "src/" + path; }; - var piskelScripts = require('./src/piskel-script-list.js').scripts.map(mapToSrcFolder); + var piskelScripts = require('./src/piskel-script-list.js').scripts.map(mapToSrcFolder).filter(function (path) { + return path.indexOf('devtools') === -1; + }); var piskelStyles = require('./src/piskel-style-list.js').styles.map(mapToSrcFolder); var mapToCasperFolder = function (path) { return "test/integration/casperjs/" + path; }; - var casperTests = require('./test/integration/casperjs/TestSuite.js').tests.map(mapToCasperFolder); - var getCasperConfig = function (delay) { + var casperEnvironments = { + 'local' : { + suite : './test/integration/casperjs/TestSuite.js', + delay : 50 + }, + 'travis' : { + suite : './test/integration/casperjs/TravisTestSuite.js', + delay : 5000 + } + }; + + var getCasperConfig = function (env) { + var conf = casperEnvironments[env]; + var tests = require(conf.suite).tests.map(mapToCasperFolder); return { - filesSrc : casperTests, + filesSrc : tests, options : { args : { baseUrl : 'http://localhost:' + '<%= express.test.options.port %>/', mode : '?debug', - delay : delay + delay : conf.delay }, async : false, direct : false, @@ -110,8 +124,8 @@ module.exports = function(grunt) { } }, ghost : { - 'default' : getCasperConfig(5000), - 'local' : getCasperConfig(50) + 'travis' : getCasperConfig('travis'), + 'local' : getCasperConfig('local') }, concat : { js : { @@ -292,10 +306,13 @@ module.exports = function(grunt) { grunt.registerTask('unit-test', ['karma']); // Validate & Test - grunt.registerTask('test', ['lint', 'compile', 'unit-test','express:test', 'ghost:default']); - + grunt.registerTask('test-travis', ['lint', 'compile', 'unit-test', 'express:test', 'ghost:travis']); // Validate & Test (faster version) will NOT work on travis !! - grunt.registerTask('precommit', ['lint', 'compile', 'express:test', 'ghost:default']); + grunt.registerTask('test-local', ['lint', 'compile', 'unit-test', 'express:test', 'ghost:local']); + + grunt.registerTask('test', ['test-travis']); + grunt.registerTask('precommit', ['test-local']); + // Compile JS code (eg verify JSDoc annotation and types, no actual minified code generated). grunt.registerTask('compile', ['closureCompiler:compile', 'clean:after']); diff --git a/src/js/Constants.js b/src/js/Constants.js index 713724d..ae7823c 100644 --- a/src/js/Constants.js +++ b/src/js/Constants.js @@ -69,5 +69,8 @@ var Constants = { MOUSEMOVE_THROTTLING : 10, ABSTRACT_FUNCTION : function () {throw 'abstract method should be implemented';}, - EMPTY_FUNCTION : function () {} + EMPTY_FUNCTION : function () {}, + + // TESTS + BASE_TEST_FOLDER : 'integration/casperjs/drawing-records' }; \ No newline at end of file diff --git a/src/js/Events.js b/src/js/Events.js index 31d1d0e..5b9d110 100644 --- a/src/js/Events.js +++ b/src/js/Events.js @@ -54,6 +54,7 @@ var Events = { MOUSE_EVENT : "MOUSE_EVENT", // Tests - - TEST_RECORD_END : "TEST_RECORD_END" + TEST_RECORD_END : "TEST_RECORD_END", + TEST_CASE_END : "TEST_CASE_END", + TEST_SUITE_END : "TEST_SUITE_END" }; \ No newline at end of file diff --git a/src/js/app.js b/src/js/app.js index 4d39ee5..90477e9 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -115,25 +115,6 @@ } this.storageService.init(); - - var href = document.location.href.toLowerCase(); - // test tools - var testModeOn = href.indexOf('test=true') !== -1; - if (testModeOn) { - this.testRecorder = new pskl.devtools.TestRecorder(this.piskelController); - this.testRecorder.init(); - - this.testRecordController = new pskl.devtools.TestRecordController(this.testRecorder); - this.testRecordController.init(); - } - - // test tools - var runTestModeOn = href.indexOf('test-run=') !== -1; - if (runTestModeOn) { - var testName = href.split('test-run=')[1]; - this.testRunner = new pskl.devtools.DrawingTestRunner(testName); - } - var drawingLoop = new pskl.rendering.DrawingLoop(); drawingLoop.addCallback(this.render, this); drawingLoop.start(); @@ -145,8 +126,8 @@ this.loadPiskel_(piskelData.piskel, piskelData.descriptor, piskelData.fps); } - if (this.testRunner) { - this.testRunner.start(); + if (pskl.devtools) { + pskl.devtools.init(); } }, diff --git a/src/js/devtools/TestRecordPlayer.js b/src/js/devtools/DrawingTestPlayer.js similarity index 62% rename from src/js/devtools/TestRecordPlayer.js rename to src/js/devtools/DrawingTestPlayer.js index 27071bd..82dfbf3 100644 --- a/src/js/devtools/TestRecordPlayer.js +++ b/src/js/devtools/DrawingTestPlayer.js @@ -1,42 +1,36 @@ (function () { var ns = $.namespace('pskl.devtools'); - ns.TestRecordPlayer = function (testRecord) { + ns.DrawingTestPlayer = function (testRecord, step) { this.initialState = testRecord.initialState; this.events = testRecord.events; this.referencePng = testRecord.png; + this.step = step || ns.DrawingTestPlayer.DEFAULT_STEP; + this.callbacks = []; this.shim = null; }; - ns.TestRecordPlayer.STEP = 40; + ns.DrawingTestPlayer.DEFAULT_STEP = 50; - ns.TestRecordPlayer.prototype.start = function () { + ns.DrawingTestPlayer.prototype.start = function () { this.setupInitialState_(); this.createMouseShim_(); - this.playEvent_(0); + this.regenerateReferencePng().then(function () { + this.playEvent_(0); + }.bind(this)); }; - ns.TestRecordPlayer.prototype.setupInitialState_ = function () { + ns.DrawingTestPlayer.prototype.setupInitialState_ = function () { var size = this.initialState.size; var piskel = this.createPiskel_(size.width, size.height); - pskl.app.piskelController.setPiskel(piskel, true); + pskl.app.piskelController.setPiskel(piskel); $.publish(Events.SELECT_PRIMARY_COLOR, [this.initialState.primaryColor]); $.publish(Events.SELECT_SECONDARY_COLOR, [this.initialState.secondaryColor]); $.publish(Events.SELECT_TOOL, [this.initialState.selectedTool]); }; - ns.TestRecordPlayer.prototype.createMouseShim_ = function () { - this.shim = document.createElement('DIV'); - this.shim.style.cssText = 'position:fixed;top:0;left:0;right:0;left:0;bottom:0;z-index:15000'; - this.shim.addEventListener('mousemove', function (e) { - e.stopPropagation(); - e.preventDefault(); - }); - document.body.appendChild(this.shim); - }; - - ns.TestRecordPlayer.prototype.createPiskel_ = function (width, height) { + ns.DrawingTestPlayer.prototype.createPiskel_ = function (width, height) { var descriptor = new pskl.model.piskel.Descriptor('TestPiskel', ''); var piskel = new pskl.model.Piskel(width, height, descriptor); var layer = new pskl.model.Layer("Layer 1"); @@ -48,7 +42,39 @@ return piskel; }; - ns.TestRecordPlayer.prototype.playEvent_ = function (index) { + ns.DrawingTestPlayer.prototype.regenerateReferencePng = function () { + var image = new Image(); + var then = function () {}; + + image.onload = function () { + this.referencePng = pskl.CanvasUtils.createFromImage(image).toDataURL(); + then(); + }.bind(this); + image.src = this.referencePng; + + return { + then : function (cb) { + then = cb; + } + }; + }; + + ns.DrawingTestPlayer.prototype.createMouseShim_ = function () { + this.shim = document.createElement('DIV'); + this.shim.style.cssText = 'position:fixed;top:0;left:0;right:0;left:0;bottom:0;z-index:15000'; + this.shim.addEventListener('mousemove', function (e) { + e.stopPropagation(); + e.preventDefault(); + }, true); + document.body.appendChild(this.shim); + }; + + ns.DrawingTestPlayer.prototype.removeMouseShim_ = function () { + this.shim.parentNode.removeChild(this.shim); + this.shim = null; + }; + + ns.DrawingTestPlayer.prototype.playEvent_ = function (index) { this.timer = window.setTimeout(function () { var recordEvent = this.events[index]; @@ -67,29 +93,10 @@ } else { this.onTestEnd_(); } - }.bind(this), ns.TestRecordPlayer.STEP); + }.bind(this), this.step); }; - ns.TestRecordPlayer.prototype.onTestEnd_ = function () { - var renderer = new pskl.rendering.PiskelRenderer(pskl.app.piskelController); - var png = renderer.renderAsCanvas().toDataURL(); - - var image = new Image(); - image.onload = function () { - var canvas = pskl.CanvasUtils.createFromImage(image); - var referencePng = canvas.toDataURL(); - var success = png === referencePng; - - this.shim.parentNode.removeChild(this.shim); - this.shim = null; - - $.publish(Events.TEST_RECORD_END, [success, png + ' vs ' + referencePng]); - }.bind(this); - image.src = this.referencePng; - - }; - - ns.TestRecordPlayer.prototype.playMouseEvent_ = function (recordEvent) { + ns.DrawingTestPlayer.prototype.playMouseEvent_ = function (recordEvent) { var event = recordEvent.event; var screenCoordinates = pskl.app.drawingController.getScreenCoordinates(recordEvent.coords.x, recordEvent.coords.y); event.clientX = screenCoordinates.x; @@ -103,7 +110,7 @@ } }; - ns.TestRecordPlayer.prototype.playColorEvent_ = function (recordEvent) { + ns.DrawingTestPlayer.prototype.playColorEvent_ = function (recordEvent) { if (recordEvent.isPrimary) { $.publish(Events.SELECT_PRIMARY_COLOR, [recordEvent.color]); } else { @@ -111,13 +118,30 @@ } }; - ns.TestRecordPlayer.prototype.playToolEvent_ = function (recordEvent) { + ns.DrawingTestPlayer.prototype.playToolEvent_ = function (recordEvent) { $.publish(Events.SELECT_TOOL, [recordEvent.toolId]); }; - ns.TestRecordPlayer.prototype.playInstrumentedEvent_ = function (recordEvent) { + ns.DrawingTestPlayer.prototype.playInstrumentedEvent_ = function (recordEvent) { pskl.app.piskelController[recordEvent.methodName].apply(pskl.app.piskelController, recordEvent.args); }; + ns.DrawingTestPlayer.prototype.onTestEnd_ = function () { + this.removeMouseShim_(); + + var renderer = new pskl.rendering.PiskelRenderer(pskl.app.piskelController); + var png = renderer.renderAsCanvas().toDataURL(); + + var success = png === this.referencePng; + + $.publish(Events.TEST_RECORD_END, [success, png, this.referencePng]); + this.callbacks.forEach(function (callback) { + callback(success, png, this.referencePng); + }); + }; + + ns.DrawingTestPlayer.prototype.addEndTestCallback = function (callback) { + this.callbacks.push(callback); + }; })(); \ No newline at end of file diff --git a/src/js/devtools/TestRecorder.js b/src/js/devtools/DrawingTestRecorder.js similarity index 78% rename from src/js/devtools/TestRecorder.js rename to src/js/devtools/DrawingTestRecorder.js index b04b7b9..6597d03 100644 --- a/src/js/devtools/TestRecorder.js +++ b/src/js/devtools/DrawingTestRecorder.js @@ -1,13 +1,13 @@ (function () { var ns = $.namespace('pskl.devtools'); - ns.TestRecorder = function (piskelController) { + ns.DrawingTestRecorder = function (piskelController) { this.piskelController = piskelController; this.isRecording = false; this.reset(); }; - ns.TestRecorder.prototype.init = function () { + ns.DrawingTestRecorder.prototype.init = function () { $.subscribe(Events.MOUSE_EVENT, this.onMouseEvent_.bind(this)); $.subscribe(Events.TOOL_SELECTED, this.onToolEvent_.bind(this)); $.subscribe(Events.PRIMARY_COLOR_SELECTED, this.onColorEvent_.bind(this, true)); @@ -23,7 +23,7 @@ } }; - ns.TestRecorder.prototype.instrumentMethod_ = function (object, methodName) { + ns.DrawingTestRecorder.prototype.instrumentMethod_ = function (object, methodName) { var method = object[methodName]; var testRecorder = this; return function () { @@ -32,12 +32,12 @@ }; }; - ns.TestRecorder.prototype.reset = function () { + ns.DrawingTestRecorder.prototype.reset = function () { this.initialState = {}; this.events = []; }; - ns.TestRecorder.prototype.startRecord = function () { + ns.DrawingTestRecorder.prototype.startRecord = function () { this.isRecording = true; this.initialState = { size : { @@ -50,7 +50,7 @@ }; }; - ns.TestRecorder.prototype.stopRecord = function () { + ns.DrawingTestRecorder.prototype.stopRecord = function () { this.isRecording = false; var renderer = new pskl.rendering.PiskelRenderer(this.piskelController); @@ -67,13 +67,13 @@ return testRecord; }; - ns.TestRecorder.prototype.onMouseEvent_ = function (evt, mouseEvent, originator) { + ns.DrawingTestRecorder.prototype.onMouseEvent_ = function (evt, mouseEvent, originator) { if (this.isRecording) { this.recordMouseEvent_(mouseEvent); } }; - ns.TestRecorder.prototype.onColorEvent_ = function (isPrimary, evt, color) { + ns.DrawingTestRecorder.prototype.onColorEvent_ = function (isPrimary, evt, color) { if (this.isRecording) { var recordEvent = {}; recordEvent.type = 'color-event'; @@ -83,7 +83,7 @@ } }; - ns.TestRecorder.prototype.onToolEvent_ = function (evt, tool) { + ns.DrawingTestRecorder.prototype.onToolEvent_ = function (evt, tool) { if (this.isRecording) { var recordEvent = {}; recordEvent.type = 'tool-event'; @@ -92,7 +92,7 @@ } }; - ns.TestRecorder.prototype.onInstrumentedMethod_ = function (callee, methodName, args) { + ns.DrawingTestRecorder.prototype.onInstrumentedMethod_ = function (callee, methodName, args) { if (this.isRecording) { var recordEvent = {}; recordEvent.type = 'instrumented-event'; @@ -102,7 +102,7 @@ } }; - ns.TestRecorder.prototype.recordMouseEvent_ = function (mouseEvent) { + ns.DrawingTestRecorder.prototype.recordMouseEvent_ = function (mouseEvent) { var coords = pskl.app.drawingController.getSpriteCoordinates(mouseEvent.clientX, mouseEvent.clientY); var recordEvent = new ns.MouseEvent(mouseEvent, coords); var lastEvent = this.events[this.events.length-1]; diff --git a/src/js/devtools/DrawingTestRunner.js b/src/js/devtools/DrawingTestRunner.js index 1d09ada..6f7fc7f 100644 --- a/src/js/devtools/DrawingTestRunner.js +++ b/src/js/devtools/DrawingTestRunner.js @@ -7,29 +7,17 @@ }; ns.DrawingTestRunner.prototype.start = function () { - var testName = this.testName; - var xhr = new XMLHttpRequest(); - xhr.open('GET', testName, true); - - xhr.onload = function(e) { - if (this.status == 200) { - var recordPlayer = new ns.TestRecordPlayer(JSON.parse(this.responseText)); - recordPlayer.start(); - } else { - this.onerror(e); - } - }; - xhr.onerror = function(e) { - console.error('Could not load file : ' + testName); - }; - xhr.send(); + pskl.utils.Xhr.get(this.testName, function (response) { + var res = response.responseText; + var recordPlayer = new ns.DrawingTestPlayer(JSON.parse(res)); + recordPlayer.start(); + }.bind(this)); }; ns.DrawingTestRunner.prototype.onTestRecordEnd_ = function (evt, success, png) { var testResult = document.createElement('div'); testResult.id = 'drawing-test-result'; testResult.setAttribute('data-test-name', this.testName); - // pskl.app.paletteController.setPrimaryColor('rgba(0,255,0,0)'); testResult.innerHTML = success ? 'OK' : ('KO:'+png); document.body.appendChild(testResult); }; diff --git a/src/js/devtools/DrawingTestSuiteController.js b/src/js/devtools/DrawingTestSuiteController.js new file mode 100644 index 0000000..4ab9455 --- /dev/null +++ b/src/js/devtools/DrawingTestSuiteController.js @@ -0,0 +1,77 @@ +(function () { + var ns = $.namespace('pskl.devtools'); + + ns.DrawingTestSuiteController = function (suitePath) { + if (suitePath.indexOf('/') === -1) { + suitePath = [Constants.BASE_TEST_FOLDER, suitePath].join('/'); + } + this.suitePath = suitePath; + this.testSuiteRunner = null; + }; + + ns.DrawingTestSuiteController.prototype.init = function () { + $.subscribe(Events.TEST_CASE_END, this.onTestCaseEnd_.bind(this)); + $.subscribe(Events.TEST_SUITE_END, this.onTestSuiteEnd_.bind(this)); + }; + + ns.DrawingTestSuiteController.prototype.start = function () { + this.reset(); + this.startTime_ = Date.now(); + pskl.utils.Xhr.get(this.suitePath, this.onTestSuiteLoaded_.bind(this)); + + var testSuiteStatus = document.createElement('li'); + testSuiteStatus.innerHTML = pskl.utils.Template.replace( + 'Test Suite [{{path}}]', + {path : this.shortenPath_(this.suitePath)} + ); + this.testListElt.appendChild(testSuiteStatus); + }; + + ns.DrawingTestSuiteController.prototype.reset = function () { + this.domElt = document.createElement('div'); + this.domElt.style.cssText = 'position:absolute;z-index:10000;margin:5px;padding:10px;background:lightgrey'; + + this.testListElt = document.createElement('ul'); + + this.domElt.appendChild(this.testListElt); + + document.body.appendChild(this.domElt); + }; + + ns.DrawingTestSuiteController.prototype.onTestSuiteLoaded_ = function (response) { + var testPaths = JSON.parse(response.responseText).tests; + testPaths = testPaths.map(function (path) { + return this.suitePath.replace(/\/([^\/]+\.json)/i, '/' + path); + }.bind(this)); + this.testSuiteRunner = new ns.DrawingTestSuiteRunner(testPaths); + this.testSuiteRunner.start(); + }; + + ns.DrawingTestSuiteController.prototype.onTestCaseEnd_ = function (evt, testPath, status) { + 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'} + ); + this.testListElt.appendChild(testCaseStatus); + }; + + ns.DrawingTestSuiteController.prototype.onTestSuiteEnd_ = function (evt, status) { + console.log('on test suite end'); + 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} + ); + this.testListElt.appendChild(testSuiteStatus); + }; + + ns.DrawingTestSuiteController.prototype.shortenPath_ = function (path) { + // keep only the part after the last '/' + return path.replace(/^.*\/([^\/]+.json$)/, '$1'); + }; +})(); \ No newline at end of file diff --git a/src/js/devtools/DrawingTestSuiteRunner.js b/src/js/devtools/DrawingTestSuiteRunner.js new file mode 100644 index 0000000..11947c6 --- /dev/null +++ b/src/js/devtools/DrawingTestSuiteRunner.js @@ -0,0 +1,63 @@ +(function () { + var ns = $.namespace('pskl.devtools'); + + ns.DrawingTestSuiteRunner = function (testPaths) { + if (Array.isArray(testPaths)) { + this.testStatus = {}; + this.testPaths = testPaths; + this.status = ns.DrawingTestSuiteRunner.STATUS.NOT_STARTED; + this.currentIndex = -1; + } else { + throw new Error('testPaths should be an array of string (test paths)'); + } + }; + + ns.DrawingTestSuiteRunner.STATUS = { + ERROR : 'ERROR', + FAILED : 'FAILED', + SUCCESS : 'SUCCESS', + ONGOING : 'ONGOING', + NOT_STARTED : 'NOT_STARTED' + }; + + ns.DrawingTestSuiteRunner.prototype.start = function () { + this.status = ns.DrawingTestSuiteRunner.STATUS.ONGOING; + this.runTest(0); + }; + + ns.DrawingTestSuiteRunner.prototype.runTest = function (testIndex) { + this.currentIndex = testIndex; + var path = this.testPaths[testIndex]; + if (path) { + pskl.utils.Xhr.get(path, this.onTestLoaded_.bind(this)); + } else { + this.onTestSuiteEnd_(); + } + }; + + ns.DrawingTestSuiteRunner.prototype.onTestLoaded_ = function (response) { + var testRecord = JSON.parse(response.responseText); + + var testPlayer = new ns.DrawingTestPlayer(testRecord, 10); + + testPlayer.addEndTestCallback(this.onTestEnd_.bind(this)); + testPlayer.start(); + }; + + ns.DrawingTestSuiteRunner.prototype.onTestEnd_ = function (success, png, referencePng) { + var path = this.testPaths[this.currentIndex]; + this.testStatus[path] = success; + $.publish(Events.TEST_CASE_END, [path, success]); + + this.runTest(this.currentIndex + 1); + }; + + ns.DrawingTestSuiteRunner.prototype.onTestSuiteEnd_ = function () { + var success = this.testPaths.every(function (path) { + return this.testStatus[path]; + }.bind(this)); + + this.status = success ? ns.DrawingTestSuiteRunner.STATUS.SUCCESS : ns.DrawingTestSuiteRunner.STATUS.ERROR; + $.publish(Events.TEST_SUITE_END, [this.status]); + }; +})(); \ No newline at end of file diff --git a/src/js/devtools/TestRecordController.js b/src/js/devtools/TestRecordController.js index 22016a1..04581b3 100644 --- a/src/js/devtools/TestRecordController.js +++ b/src/js/devtools/TestRecordController.js @@ -46,8 +46,8 @@ var file =files[0]; pskl.utils.FileUtils.readFile(file, function (content) { var testRecord = JSON.parse(window.atob(content.replace(/data\:.*?\;base64\,/,''))); - var testRecordPlayer = new ns.TestRecordPlayer(testRecord); - testRecordPlayer.start(); + var testPlayer = new ns.DrawingTestPlayer(testRecord); + testPlayer.start(); }.bind(this)); } }; diff --git a/src/js/devtools/init.js b/src/js/devtools/init.js new file mode 100644 index 0000000..64e2737 --- /dev/null +++ b/src/js/devtools/init.js @@ -0,0 +1,34 @@ +(function () { + var ns = $.namespace('pskl.devtools'); + + ns.init = function () { + var href = document.location.href.toLowerCase(); + // test tools + var testModeOn = href.indexOf('test=true') !== -1; + if (testModeOn) { + this.testRecorder = new pskl.devtools.DrawingTestRecorder(this.piskelController); + this.testRecorder.init(); + + this.testRecordController = new pskl.devtools.TestRecordController(this.testRecorder); + this.testRecordController.init(); + } + + // test tools + var runTestModeOn = href.indexOf('test-run=') !== -1; + if (runTestModeOn) { + var testPath = href.split('test-run=')[1]; + this.testRunner = new pskl.devtools.DrawingTestRunner(testPath); + this.testRunner.start(); + } + + // test tools + var runSuiteModeOn = href.indexOf('test-suite=') !== -1; + if (runSuiteModeOn) { + var suitePath = href.split('test-suite=')[1]; + this.testSuiteController = new pskl.devtools.DrawingTestSuiteController(suitePath); + this.testSuiteController.init(); + this.testSuiteController.start(); + } + }; + +})(); \ No newline at end of file diff --git a/src/js/service/AppEngineStorageService.js b/src/js/service/AppEngineStorageService.js index 8c93f23..4d37713 100644 --- a/src/js/service/AppEngineStorageService.js +++ b/src/js/service/AppEngineStorageService.js @@ -8,42 +8,33 @@ ns.AppEngineStorageService.prototype.init = function () {}; ns.AppEngineStorageService.prototype.store = function (callbacks) { - var formData = this.prepareFormData_(); - - var xhr = new XMLHttpRequest(); - xhr.open('POST', Constants.APPENGINE.URL.SAVE, true); - - xhr.onload = function(e) { - if (this.status == 200) { - callbacks.success(); - callbacks.after(); - } else { - this.onerror(e); - } - }; - xhr.onerror = function(e) { - callbacks.error(this.status); - callbacks.after(); - }; - xhr.send(formData); - }; - - ns.AppEngineStorageService.prototype.prepareFormData_ = function () { var piskel = this.piskelController.getPiskel(); var descriptor = piskel.getDescriptor(); - var formData = new FormData(); - formData.append('framesheet', this.piskelController.serialize()); - formData.append('fps', this.piskelController.getFPS()); - formData.append('name', descriptor.name); - formData.append('description', descriptor.description); - if (descriptor.isPublic) { - formData.append('public', true); - } - formData.append('frames', this.piskelController.getFrameCount()); - formData.append('first_frame_as_png', pskl.app.getFirstFrameAsPng()); - formData.append('framesheet_as_png', pskl.app.getFramesheetAsPng()); + var data = { + framesheet : this.piskelController.serialize(), + fps : this.piskelController.getFPS(), + name : descriptor.name, + description : descriptor.description, + frames : this.piskelController.getFrameCount(), + first_frame_as_png : pskl.app.getFirstFrameAsPng(), + framesheet_as_png : pskl.app.getFramesheetAsPng() + }; - return formData; + if (descriptor.isPublic) { + data['public'] = true; + } + + var success = function () { + callbacks.success(); + callbacks.after(); + }; + + var error = function (response) { + callbacks.error(response.status); + callbacks.after(); + }; + + pskl.utils.Xhr.post(Constants.APPENGINE.URL.SAVE, data, success, error); }; })(); \ No newline at end of file diff --git a/src/js/service/ImageUploadService.js b/src/js/service/ImageUploadService.js index e024955..93561f5 100644 --- a/src/js/service/ImageUploadService.js +++ b/src/js/service/ImageUploadService.js @@ -6,23 +6,18 @@ /** * Upload a base64 image data to distant service. If successful, will call provided callback with the image URL as first argument; * @param {String} imageData base64 image data (such as the return value of canvas.toDataUrl()) - * @param {Function} cbSuccess success callback. 1st argument will be the uploaded image URL - * @param {Function} cbError error callback + * @param {Function} success success callback. 1st argument will be the uploaded image URL + * @param {Function} error error callback */ - ns.ImageUploadService.prototype.upload = function (imageData, cbSuccess, cbError) { - var xhr = new XMLHttpRequest(); - var formData = new FormData(); - formData.append('data', imageData); - xhr.open('POST', Constants.IMAGE_SERVICE_UPLOAD_URL, true); - xhr.onload = function (e) { - if (this.status == 200) { - var imageUrl = Constants.IMAGE_SERVICE_GET_URL + this.responseText; - cbSuccess(imageUrl); - } else { - cbError(); - } + ns.ImageUploadService.prototype.upload = function (imageData, success, error) { + var data = { + data : imageData }; - xhr.send(formData); + var wrappedSuccess = function (response) { + success(Constants.IMAGE_SERVICE_GET_URL + response.responseText); + }; + + pskl.utils.Xhr.post(Constants.IMAGE_SERVICE_UPLOAD_URL, data, wrappedSuccess, error); }; })(); diff --git a/src/js/utils/Xhr.js b/src/js/utils/Xhr.js new file mode 100644 index 0000000..6b11189 --- /dev/null +++ b/src/js/utils/Xhr.js @@ -0,0 +1,46 @@ +(function () { + var ns = $.namespace('pskl.utils'); + ns.Xhr = { + get : function (url, success, error) { + var xhr = ns.Xhr.xhr_(url, 'GET', success, error); + xhr.send(); + }, + + post : function (url, data, success, error) { + var xhr = ns.Xhr.xhr_(url, 'POST', success, error); + var formData = new FormData(); + + if (typeof data == 'object') { + for (var key in data) { + if (data.hasOwnProperty(key)) { + formData.append(key, data[key]); + } + } + } + + xhr.send(formData); + }, + + xhr_ : function (url, method, success, error) { + success = success || function (){}; + error = error || function (){}; + + var xhr = new XMLHttpRequest(); + xhr.open(method, url, true); + + xhr.onload = function(e) { + if (this.status == 200) { + success(this); + } else { + this.onerror(this, e); + } + }; + + xhr.onerror = function(e) { + error(e); + }; + + return xhr; + } + }; +})(); \ No newline at end of file diff --git a/src/piskel-script-list.js b/src/piskel-script-list.js index e66c663..bd66a18 100644 --- a/src/piskel-script-list.js +++ b/src/piskel-script-list.js @@ -25,6 +25,7 @@ "js/utils/PiskelFileUtils.js", "js/utils/Template.js", "js/utils/UserSettings.js", + "js/utils/Xhr.js", "js/utils/serialization/Serializer.js", "js/utils/serialization/Deserializer.js", "js/utils/serialization/backward/Deserializer_v0.js", @@ -139,11 +140,14 @@ "js/drawingtools/ColorSwap.js", // Devtools - "js/devtools/MouseEvent.js", - "js/devtools/TestRecorder.js", - "js/devtools/TestRecordPlayer.js", - "js/devtools/TestRecordController.js", + "js/devtools/DrawingTestPlayer.js", + "js/devtools/DrawingTestRecorder.js", "js/devtools/DrawingTestRunner.js", + "js/devtools/DrawingTestSuiteController.js", + "js/devtools/DrawingTestSuiteRunner.js", + "js/devtools/MouseEvent.js", + "js/devtools/TestRecordController.js", + "js/devtools/init.js", // Application controller and initialization "js/app.js", diff --git a/test/integration/casperjs/TravisTestSuite.js b/test/integration/casperjs/TravisTestSuite.js new file mode 100644 index 0000000..eec0f7f --- /dev/null +++ b/test/integration/casperjs/TravisTestSuite.js @@ -0,0 +1,4 @@ +(typeof exports != "undefined" ? exports : pskl_exports).tests = [ + // did not manage to successfully run drawing tests on travis yet ... + 'SmokeTest.js' +]; \ No newline at end of file diff --git a/test/integration/casperjs/drawing-records/TestSuite.json b/test/integration/casperjs/drawing-records/TestSuite.json new file mode 100644 index 0000000..0735c21 --- /dev/null +++ b/test/integration/casperjs/drawing-records/TestSuite.json @@ -0,0 +1,5 @@ +{ "tests" : [ + "SimplePenDrawing1.json", + "ComplexDrawing1.json", + "ComplexDrawing2.json" +]} \ No newline at end of file