Merge pull request #214 from juliandescottes/feature-add-tests

Feature add tests
This commit is contained in:
Julian Descottes 2014-08-26 23:57:45 +02:00
commit 913ef272cf
49 changed files with 1164 additions and 182 deletions

View file

@ -1,6 +1,6 @@
language: node_js
node_js:
- 0.8
- 0.10
before_install:
- npm update -g npm
- npm install -g grunt-cli

View file

@ -10,27 +10,48 @@
* If you run this task locally, it may require some env set up first.
*/
var SOURCE_FOLDER = "src";
module.exports = function(grunt) {
var dateFormat = require('dateformat');
var now = new Date();
var version = '-' + dateFormat(now, "yyyy-mm-dd-hh-MM");
var mapToSrcFolder = function (path) {return [SOURCE_FOLDER, path].join('/');};
var mapToSrcFolder = function (path) {
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 getGhostConfig = function (delay) {
var mapToCasperFolder = function (path) {
return "test/casperjs/" + path;
};
var casperEnvironments = {
'local' : {
suite : './test/casperjs/LocalTestSuite.js',
delay : 50
},
'travis' : {
suite : './test/casperjs/TravisTestSuite.js',
delay : 5000
}
};
var getCasperConfig = function (env) {
var conf = casperEnvironments[env];
var tests = require(conf.suite).tests.map(mapToCasperFolder);
return {
filesSrc : ['test/integration/casperjs/*_test.js'],
filesSrc : tests,
options : {
args : {
baseUrl : 'http://localhost:' + '<%= connect.test.options.port %>/src/',
baseUrl : 'http://localhost:' + '<%= express.test.options.port %>/',
mode : '?debug',
delay : delay
delay : conf.delay
},
async : false,
direct : false,
logLevel : 'info',
printCommand : false,
@ -39,6 +60,23 @@ module.exports = function(grunt) {
};
};
var getExpressConfig = function (source, port, host) {
var bases;
if (typeof source === 'string') {
bases = [source];
} else if (Array.isArray(source)) {
bases = source;
}
return {
options: {
port: port,
hostname : host || 'localhost',
bases: bases
}
};
};
grunt.initConfig({
clean: {
before: ['dest'],
@ -62,29 +100,10 @@ module.exports = function(grunt) {
'!src/js/lib/**/*.js' // Exclude lib folder (note the leading !)
]
},
connect : {
test : {
options : {
base : '.',
port : 4321
}
}
},
express: {
regular: {
options: {
port: 9001,
hostname : 'localhost',
bases: ['dest']
}
},
debug: {
options: {
port: 9901,
hostname : 'localhost',
bases: ['src']
}
}
test: getExpressConfig(['src', 'test'], 9991),
regular: getExpressConfig('dest', 9001),
debug: getExpressConfig(['src', 'test'], 9901)
},
open : {
regular : {
@ -105,8 +124,8 @@ module.exports = function(grunt) {
}
},
ghost : {
'default' : getGhostConfig(5000),
local : getGhostConfig(50)
'travis' : getCasperConfig('travis'),
'local' : getCasperConfig('local')
},
concat : {
js : {
@ -236,6 +255,11 @@ module.exports = function(grunt) {
dest: 'build/closure/closure_compiled_binary.js'
}
},
karma: {
unit: {
configFile: 'karma.conf.js'
}
},
nodewebkit: {
options: {
build_dir: './dest/desktop/', // destination folder of releases.
@ -262,7 +286,6 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-closure-tools');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
@ -271,6 +294,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-replace');
grunt.loadNpmTasks('grunt-ghost');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-leading-indent');
grunt.loadNpmTasks('grunt-node-webkit-builder');
grunt.loadNpmTasks('grunt-contrib-copy');
@ -278,11 +302,17 @@ module.exports = function(grunt) {
// Validate
grunt.registerTask('lint', ['leadingIndent:jsFiles', 'leadingIndent:cssFiles', 'jshint']);
// Validate & Test
grunt.registerTask('test', ['lint', 'compile', 'connect:test', 'ghost:default']);
// karma/unit-tests task
grunt.registerTask('unit-test', ['karma']);
// Validate & Test
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', 'connect:test', 'ghost:local']);
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']);

67
karma.conf.js Normal file
View file

@ -0,0 +1,67 @@
// Karma configuration
// Generated on Tue Jul 22 2014 23:49:26 GMT+0200 (Romance Daylight Time)
module.exports = function(config) {
var mapToSrcFolder = function (path) {return ['src', path].join('/');};
var piskelScripts = require('./src/piskel-script-list.js').scripts.map(mapToSrcFolder);
piskelScripts.push('test/js/**/*.js');
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: piskelScripts,
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
};

View file

@ -12,34 +12,14 @@ SETLOCAL
set APP_BIN="%PISKEL_HOME%\dest\desktop\cache\win\0.9.2"
set MISC_FOLDER=%PISKEL_HOME%\misc
set RELEASES_FOLDER=%PISKEL_HOME%\dest\desktop\releases
set DEST_FOLDER=%RELEASES_FOLDER%\win
set DEST_FOLDER=%RELEASES_FOLDER%\piskel\win\piskel
ECHO "Building Piskel executable for Windows ..."
ECHO "Creating release directory ..."
MKDIR "%DEST_FOLDER%"
ECHO "DONE"
ECHO "Packaging executable ..."
COPY /b "%APP_BIN%\nw.exe"+"%RELEASES_FOLDER%\piskel\piskel.nw" "%DEST_FOLDER%\piskel-raw.exe"
ECHO "DONE"
ECHO "COPYing dependencies ..."
COPY "%APP_BIN%\*.dll" "%DEST_FOLDER%\"
COPY "%APP_BIN%\nw.pak" "%DEST_FOLDER%\"
ECHO "DONE"
ECHO "Updating Piskel icon -- Using Resource Hacker"
%RESOURCE_HACKER_PATH%\ResHacker -addoverwrite "%DEST_FOLDER%\piskel-raw.exe", "%DEST_FOLDER%\piskel-exploded.exe", "%MISC_FOLDER%\desktop\logo.ico", ICONGROUP, IDR_MAINFRAME, 1033
DEL "%DEST_FOLDER%\piskel-raw.exe"
%RESOURCE_HACKER_PATH%\ResHacker -addoverwrite "%DEST_FOLDER%\piskel.exe", "%DEST_FOLDER%\piskel-logo.exe", "%MISC_FOLDER%\desktop\logo.ico", ICONGROUP, IDR_MAINFRAME, 1033
DEL "%DEST_FOLDER%\piskel.exe"
ECHO "DONE"
ECHO "Boxing application to single file -- Using Enigma Virtual Box"
%VBOX_PATH%\enigmavbconsole "%MISC_FOLDER%\desktop\package-piskel.evb"
DEL "%DEST_FOLDER%\*.dll"
DEL "%DEST_FOLDER%\nw.pak"
DEL "%DEST_FOLDER%\piskel-exploded.exe"
ECHO "DONE"
PAUSE
explorer "%DEST_FOLDER%\"

View file

@ -3,7 +3,7 @@
"name": "piskel",
"main": "./dest/index.html",
"description": "Web based 2d animations editor",
"version": "0.1.0",
"version": "0.2.0",
"homepage": "http://github.com/juliandescottes/piskel",
"repository": {
"type": "git",
@ -14,23 +14,27 @@
"start": "nodewebkit"
},
"devDependencies": {
"grunt": "~0.4.1",
"dateformat": "1.0.8-1.2.3",
"grunt": "~0.4.5",
"grunt-closure-tools": "~0.9.7",
"grunt-contrib-clean": "0.5.0",
"grunt-contrib-connect": "0.3.0",
"grunt-contrib-concat": "0.1.2",
"grunt-contrib-concat": "0.5.0",
"grunt-contrib-copy": "0.5.0",
"grunt-contrib-jshint": "0.5.4",
"grunt-contrib-uglify": "0.2.2",
"grunt-contrib-jshint": "0.10.0",
"grunt-contrib-uglify": "0.5.0",
"grunt-contrib-watch": "0.6.1",
"grunt-express": "1.0",
"grunt-replace": "0.7.8",
"grunt-ghost": "1.0.12",
"grunt-open": "0.2.3",
"grunt-express": "1.4.1",
"grunt-ghost": "1.1.0",
"grunt-leading-indent": "0.1.0",
"grunt-closure-tools": "~0.8.3",
"grunt-node-webkit-builder": "0.1.19",
"nodewebkit": "0.8.4",
"dateformat" : "1.0.8-1.2.3"
"grunt-node-webkit-builder": "0.1.21",
"grunt-open": "0.2.3",
"grunt-replace": "0.7.8",
"grunt-karma": "~0.8.2",
"karma": "0.12.17",
"karma-chrome-launcher": "^0.1.4",
"karma-phantomjs-launcher": "^0.1.4",
"karma-jasmine": "^0.1.5",
"nodewebkit": "~0.10.1"
},
"window": {
"title": "Piskel",

View file

@ -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
DRAWING_TEST_FOLDER : 'drawing'
};

View file

@ -2,6 +2,8 @@
var Events = {
TOOL_SELECTED : "TOOL_SELECTED",
SELECT_TOOL : "SELECT_TOOL",
TOOL_RELEASED : "TOOL_RELEASED",
SELECT_PRIMARY_COLOR: "SELECT_PRIMARY_COLOR",
SELECT_SECONDARY_COLOR: "SELECT_SECONDARY_COLOR",
@ -47,5 +49,12 @@ var Events = {
ZOOM_CHANGED : "ZOOM_CHANGED",
CURRENT_COLORS_UPDATED : "CURRENT_COLORS_UPDATED"
CURRENT_COLORS_UPDATED : "CURRENT_COLORS_UPDATED",
MOUSE_EVENT : "MOUSE_EVENT",
// Tests
TEST_RECORD_END : "TEST_RECORD_END",
TEST_CASE_END : "TEST_CASE_END",
TEST_SUITE_END : "TEST_SUITE_END"
};

View file

@ -29,8 +29,8 @@
var layer = new pskl.model.Layer("Layer 1");
var frame = new pskl.model.Frame(size.width, size.height);
layer.addFrame(frame);
layer.addFrame(frame);
piskel.addLayer(layer);
this.corePiskelController = new pskl.controller.piskel.PiskelController(piskel);
@ -115,7 +115,6 @@
}
this.storageService.init();
var drawingLoop = new pskl.rendering.DrawingLoop();
drawingLoop.addCallback(this.render, this);
drawingLoop.start();
@ -126,6 +125,10 @@
if (piskelData && piskelData.piskel) {
this.loadPiskel_(piskelData.piskel, piskelData.descriptor, piskelData.fps);
}
if (pskl.devtools) {
pskl.devtools.init();
}
},
loadPiskel_ : function (serializedPiskel, descriptor, fps) {

View file

@ -134,8 +134,9 @@
* @private
*/
ns.DrawingController.prototype.onMousedown_ = function (event) {
$.publish(Events.MOUSE_EVENT, [event, this]);
var frame = this.piskelController.getCurrentFrame();
var coords = this.renderer.getCoordinates(event.clientX, event.clientY);
var coords = this.getSpriteCoordinates(event.clientX, event.clientY);
if (event.button === Constants.MIDDLE_BUTTON) {
if (frame.containsPixel(coords.x, coords.y)) {
@ -204,10 +205,11 @@
};
ns.DrawingController.prototype.moveTool_ = function (x, y, event) {
var coords = this.renderer.getCoordinates(x, y);
var coords = this.getSpriteCoordinates(x, y);
var currentFrame = this.piskelController.getCurrentFrame();
if (this.isClicked) {
$.publish(Events.MOUSE_EVENT, [event, this]);
// Warning : do not call setCurrentButton here
// mousemove do not have the correct mouse button information on all browsers
this.currentToolBehavior.moveToolAt(
@ -248,6 +250,7 @@
*/
ns.DrawingController.prototype.onMouseup_ = function (event) {
if(this.isClicked) {
$.publish(Events.MOUSE_EVENT, [event, this]);
// A mouse button was clicked on the drawing canvas before this mouseup event,
// the user was probably drawing on the canvas.
// Note: The mousemove movement (and the mouseup) may end up outside
@ -256,7 +259,7 @@
this.isClicked = false;
this.setCurrentButton(event);
var coords = this.renderer.getCoordinates(event.clientX, event.clientY);
var coords = this.getSpriteCoordinates(event.clientX, event.clientY);
this.currentToolBehavior.releaseToolAt(
coords.x,
coords.y,
@ -280,6 +283,10 @@
return this.renderer.getCoordinates(screenX, screenY);
};
ns.DrawingController.prototype.getScreenCoordinates = function(spriteX, spriteY) {
return this.renderer.reverseCoordinates(spriteX, spriteY);
};
ns.DrawingController.prototype.setCurrentButton = function (event) {
this.currentMouseButton_ = event.button;
};

View file

@ -38,6 +38,8 @@
this.selectTool_(this.tools[0]);
// Activate listener on tool panel:
$("#tool-section").mousedown($.proxy(this.onToolIconClicked_, this));
$.subscribe(Events.SELECT_TOOL, this.onSelectToolEvent_.bind(this));
};
/**
@ -54,6 +56,13 @@
stage.data("selected-tool-class", tool.instance.toolId);
};
ns.ToolController.prototype.onSelectToolEvent_ = function(event, toolId) {
var tool = this.getToolById_(toolId);
if (tool) {
this.selectTool_(tool);
}
};
/**
* @private
*/

View file

@ -47,17 +47,6 @@
this.duplicateFrameAt(this.getCurrentFrameIndex());
};
ns.PublicPiskelController.prototype.raiseSaveStateEvent_ = function (fn, args) {
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.REPLAY_NO_SNAPSHOT,
scope : this,
replay : {
fn : fn,
args : args
}
});
};
ns.PublicPiskelController.prototype.replay = function (frame, replayData) {
replayData.fn.apply(this.piskelController, replayData.args);
};
@ -141,4 +130,15 @@
return this.piskelController.piskel;
};
ns.PublicPiskelController.prototype.raiseSaveStateEvent_ = function (fn, args) {
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.REPLAY_NO_SNAPSHOT,
scope : this,
replay : {
fn : fn,
args : args
}
});
};
})();

View file

@ -39,7 +39,10 @@
};
ns.ImportController.prototype.onOpenPiskelChange_ = function (evt) {
this.openPiskelFile_();
var files = this.hiddenOpenPiskelInput.get(0).files;
if (files.length == 1) {
this.openPiskelFile_(files[0]);
}
};
ns.ImportController.prototype.onOpenPiskelClick_ = function (evt) {
@ -51,19 +54,14 @@
this.closeDrawer_();
};
ns.ImportController.prototype.openPiskelFile_ = function () {
var files = this.hiddenOpenPiskelInput.get(0).files;
if (files.length == 1) {
var file = files[0];
if (this.isPiskel_(file)){
pskl.utils.PiskelFileUtils.loadFromFile(file, function (piskel, descriptor, fps) {
piskel.setDescriptor(descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(fps);
});
this.closeDrawer_();
}
ns.ImportController.prototype.openPiskelFile_ = function (file) {
if (this.isPiskel_(file)){
pskl.utils.PiskelFileUtils.loadFromFile(file, function (piskel, descriptor, fps) {
piskel.setDescriptor(descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(fps);
});
this.closeDrawer_();
}
};

View file

@ -30,7 +30,8 @@
for (var i = 0; i < this.piskelController.getFrameCount(); i++) {
var frame = this.piskelController.getFrameAt(i);
var canvas = this.getFrameAsCanvas_(frame);
var filename = "sprite_" + (i+1) + ".png";
var basename = document.getElementById("zip-file-name").value || "sprite_";
var filename = basename + (i+1) + ".png";
zip.file(filename, pskl.CanvasUtils.getBase64FromCanvas(canvas) + '\n', {base64: true});
}
@ -85,4 +86,4 @@
}
return url;
};
})();
})();

View file

@ -0,0 +1,147 @@
(function () {
var ns = $.namespace('pskl.devtools');
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.DrawingTestPlayer.DEFAULT_STEP = 50;
ns.DrawingTestPlayer.prototype.start = function () {
this.setupInitialState_();
this.createMouseShim_();
this.regenerateReferencePng().then(function () {
this.playEvent_(0);
}.bind(this));
};
ns.DrawingTestPlayer.prototype.setupInitialState_ = function () {
var size = this.initialState.size;
var piskel = this.createPiskel_(size.width, size.height);
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.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");
var frame = new pskl.model.Frame(width, height);
layer.addFrame(frame);
piskel.addLayer(layer);
return piskel;
};
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];
if (recordEvent.type === 'mouse-event') {
this.playMouseEvent_(recordEvent);
} else if (recordEvent.type === 'color-event') {
this.playColorEvent_(recordEvent);
} else if (recordEvent.type === 'tool-event') {
this.playToolEvent_(recordEvent);
} else if (recordEvent.type === 'instrumented-event') {
this.playInstrumentedEvent_(recordEvent);
}
if (this.events[index+1]) {
this.playEvent_(index+1);
} else {
this.onTestEnd_();
}
}.bind(this), this.step);
};
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;
event.clientY = screenCoordinates.y;
if (event.type == 'mousedown') {
pskl.app.drawingController.onMousedown_(event);
} else if (event.type == 'mouseup') {
pskl.app.drawingController.onMouseup_(event);
} else if (event.type == 'mousemove') {
pskl.app.drawingController.onMousemove_(event);
}
};
ns.DrawingTestPlayer.prototype.playColorEvent_ = function (recordEvent) {
if (recordEvent.isPrimary) {
$.publish(Events.SELECT_PRIMARY_COLOR, [recordEvent.color]);
} else {
$.publish(Events.SELECT_SECONDARY_COLOR, [recordEvent.color]);
}
};
ns.DrawingTestPlayer.prototype.playToolEvent_ = function (recordEvent) {
$.publish(Events.SELECT_TOOL, [recordEvent.toolId]);
};
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);
};
})();

View file

@ -0,0 +1,115 @@
(function () {
var ns = $.namespace('pskl.devtools');
ns.DrawingTestRecorder = function (piskelController) {
this.piskelController = piskelController;
this.isRecording = false;
this.reset();
};
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));
$.subscribe(Events.SECONDARY_COLOR_SELECTED, this.onColorEvent_.bind(this, false));
for (var key in this.piskelController) {
if (typeof this.piskelController[key] == 'function') {
var methodTriggersReset = this.piskelController[key].toString().indexOf('Events.PISKEL_RESET') != -1;
if (methodTriggersReset) {
this.piskelController[key] = this.instrumentMethod_(this.piskelController, key);
}
}
}
};
ns.DrawingTestRecorder.prototype.instrumentMethod_ = function (object, methodName) {
var method = object[methodName];
var testRecorder = this;
return function () {
testRecorder.onInstrumentedMethod_(object, methodName, arguments);
return method.apply(this, arguments);
};
};
ns.DrawingTestRecorder.prototype.reset = function () {
this.initialState = {};
this.events = [];
};
ns.DrawingTestRecorder.prototype.startRecord = function () {
this.isRecording = true;
this.initialState = {
size : {
width : this.piskelController.getWidth(),
height : this.piskelController.getHeight()
},
primaryColor : pskl.app.paletteController.getPrimaryColor(),
secondaryColor : pskl.app.paletteController.getSecondaryColor(),
selectedTool : pskl.app.toolController.currentSelectedTool.instance.toolId
};
};
ns.DrawingTestRecorder.prototype.stopRecord = function () {
this.isRecording = false;
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
var png = renderer.renderAsCanvas().toDataURL();
var testRecord = JSON.stringify({
events : this.events,
initialState : this.initialState,
png : png
});
this.reset();
return testRecord;
};
ns.DrawingTestRecorder.prototype.onMouseEvent_ = function (evt, mouseEvent, originator) {
if (this.isRecording) {
this.recordMouseEvent_(mouseEvent);
}
};
ns.DrawingTestRecorder.prototype.onColorEvent_ = function (isPrimary, evt, color) {
if (this.isRecording) {
var recordEvent = {};
recordEvent.type = 'color-event';
recordEvent.color = color;
recordEvent.isPrimary = isPrimary;
this.events.push(recordEvent);
}
};
ns.DrawingTestRecorder.prototype.onToolEvent_ = function (evt, tool) {
if (this.isRecording) {
var recordEvent = {};
recordEvent.type = 'tool-event';
recordEvent.toolId = tool.toolId;
this.events.push(recordEvent);
}
};
ns.DrawingTestRecorder.prototype.onInstrumentedMethod_ = function (callee, methodName, args) {
if (this.isRecording) {
var recordEvent = {};
recordEvent.type = 'instrumented-event';
recordEvent.methodName = methodName;
recordEvent.args = Array.prototype.slice.call(args, 0);
this.events.push(recordEvent);
}
};
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];
if (!recordEvent.equals(lastEvent)) {
this.events.push(recordEvent);
}
};
})();

View file

@ -0,0 +1,25 @@
(function () {
var ns = $.namespace('pskl.devtools');
ns.DrawingTestRunner = function (testName) {
this.testName = testName;
$.subscribe(Events.TEST_RECORD_END, this.onTestRecordEnd_.bind(this));
};
ns.DrawingTestRunner.prototype.start = function () {
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);
testResult.innerHTML = success ? 'OK' : ('KO:'+png);
document.body.appendChild(testResult);
};
})();

View file

@ -0,0 +1,77 @@
(function () {
var ns = $.namespace('pskl.devtools');
ns.DrawingTestSuiteController = function (suitePath) {
if (suitePath.indexOf('/') === -1) {
suitePath = [Constants.DRAWING_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(
'<b>Test Suite [{{path}}]</b>',
{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 [Constants.DRAWING_TEST_FOLDER, 'tests', path].join('/');
}.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 : <b style="color:{{color}}">{{status}}</b>',
{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(
'<b>Test finished : {{status}}</b> ({{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');
};
})();

View file

@ -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, 50);
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]);
};
})();

View file

@ -0,0 +1,26 @@
(function () {
var ns = $.namespace('pskl.devtools');
ns.MouseEvent = function (event, coords) {
this.event = {
type : event.type,
button : event.button,
shiftKey : event.shiftKey,
altKey : event.altKey,
ctrlKey : event.ctrlKey
};
this.coords = coords;
this.type = 'mouse-event';
};
ns.MouseEvent.prototype.equals = function (otherEvent) {
if (otherEvent && otherEvent instanceof ns.MouseEvent) {
var sameEvent = JSON.stringify(otherEvent.event) == JSON.stringify(this.event);
var sameCoords = JSON.stringify(otherEvent.coords) == JSON.stringify(this.coords);
return sameEvent && sameCoords;
} else {
return false;
}
};
})();

View file

@ -0,0 +1,76 @@
(function () {
var ns = $.namespace('pskl.devtools');
ns.TestRecordController = function (testRecorder) {
this.testRecorder = testRecorder;
$.subscribe(Events.TEST_RECORD_END, this.onTestRecordEnd_.bind(this));
};
ns.TestRecordController.prototype.init = function () {
var fileInput = document.createElement('input');
fileInput.setAttribute('type', 'file');
fileInput.addEventListener('change', this.onFileInputChange_.bind(this));
fileInput.style.display = 'none';
var container = document.createElement('div');
container.style.cssText = 'position:absolute;z-index:10000;margin:5px;padding:10px;background:lightgrey';
document.body.appendChild(container);
var loadInput = document.createElement('button');
loadInput.innerHTML = 'Load Test ...';
loadInput.addEventListener('click', this.onLoadInputClick_.bind(this));
var startInput = document.createElement('button');
startInput.innerHTML = 'Start record';
startInput.addEventListener('click', this.onStartInputClick_.bind(this));
var stopInput = document.createElement('button');
stopInput.innerHTML = 'Stop record';
stopInput.addEventListener('click', this.onStopInputClick_.bind(this));
stopInput.setAttribute('disabled','disabled');
this.container = container;
this.fileInput = this.container.appendChild(fileInput);
this.loadInput = this.container.appendChild(loadInput);
this.startInput = this.container.appendChild(startInput);
this.stopInput = this.container.appendChild(stopInput);
};
ns.TestRecordController.prototype.onLoadInputClick_ = function () {
this.fileInput.click();
};
ns.TestRecordController.prototype.onFileInputChange_ = function () {
var files = this.fileInput.files;
if (files.length == 1) {
var file =files[0];
pskl.utils.FileUtils.readFile(file, function (content) {
var testRecord = JSON.parse(window.atob(content.replace(/data\:.*?\;base64\,/,'')));
var testPlayer = new ns.DrawingTestPlayer(testRecord);
testPlayer.start();
}.bind(this));
}
};
ns.TestRecordController.prototype.onStartInputClick_ = function () {
this.testRecorder.startRecord();
this.startInput.setAttribute('disabled','disabled');
this.stopInput.removeAttribute('disabled');
};
ns.TestRecordController.prototype.onStopInputClick_ = function () {
var testRecord = this.testRecorder.stopRecord();
pskl.utils.BlobUtils.stringToBlob(testRecord, function(blob) {
pskl.utils.FileUtils.downloadAsFile(blob, 'record_piskel.json');
}.bind(this), "application/json");
this.startInput.removeAttribute('disabled');
this.stopInput.setAttribute('disabled','disabled');
};
ns.TestRecordController.prototype.onTestRecordEnd_ = function (evt, success) {
window.alert('Test finished : ', success);
};
})();

34
src/js/devtools/init.js Normal file
View file

@ -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(pskl.app.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();
}
};
})();

View file

@ -196,6 +196,28 @@
};
};
ns.FrameRenderer.prototype.reverseCoordinates = function(x, y) {
var cellSize = this.zoom;
x = x * cellSize;
y = y * cellSize;
x = x - this.offset.x * cellSize;
y = y - this.offset.y * cellSize;
x = x + this.margin.x;
y = y + this.margin.y;
var containerOffset = this.container.offset();
x = x + containerOffset.left;
y = y + containerOffset.top;
return {
x : x + (cellSize/2),
y : y + (cellSize/2)
};
};
/**
* @private
*/

View file

@ -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);
};
})();

View file

@ -1,14 +1,13 @@
(function () {
var ns = $.namespace('pskl.service');
var SNAPSHOT_PERIOD = 50;
var LOAD_STATE_INTERVAL = 50;
ns.HistoryService = function (piskelController, shortcutService, deserializer) {
this.piskelController = piskelController || pskl.app.piskelController;
this.shortcutService = shortcutService || pskl.app.shortcutService;
this.deserializer = deserializer || pskl.utils.serialization.Deserializer;
ns.HistoryService = function (piskelController) {
this.piskelController = piskelController;
this.stateQueue = [];
this.currentIndex = -1;
this.saveState__b = this.onSaveStateEvent.bind(this);
this.lastLoadState = -1;
@ -17,6 +16,8 @@
ns.HistoryService.SNAPSHOT = 'SNAPSHOT';
ns.HistoryService.REPLAY = 'REPLAY';
ns.HistoryService.SNAPSHOT_PERIOD = 50;
ns.HistoryService.LOAD_STATE_INTERVAL = 50;
/**
* This event alters the state (frames, layers) of the piskel. The event is triggered before the execution of associated command.
* Don't store snapshots for such events.
@ -24,10 +25,10 @@
ns.HistoryService.REPLAY_NO_SNAPSHOT = 'REPLAY_NO_SNAPSHOT';
ns.HistoryService.prototype.init = function () {
$.subscribe(Events.PISKEL_SAVE_STATE, this.saveState__b);
$.subscribe(Events.PISKEL_SAVE_STATE, this.onSaveStateEvent.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
this.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
this.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
this.saveState({
type : ns.HistoryService.SNAPSHOT
@ -50,7 +51,7 @@
var isSnapshot = stateInfo.type === ns.HistoryService.SNAPSHOT;
var isNoSnapshot = stateInfo.type === ns.HistoryService.REPLAY_NO_SNAPSHOT;
var isAtAutoSnapshotInterval = this.currentIndex % SNAPSHOT_PERIOD === 0 || this.saveNextAsSnapshot;
var isAtAutoSnapshotInterval = this.currentIndex % ns.HistoryService.SNAPSHOT_PERIOD === 0 || this.saveNextAsSnapshot;
if (isNoSnapshot && isAtAutoSnapshotInterval) {
this.saveNextAsSnapshot = true;
} else if (isSnapshot || isAtAutoSnapshotInterval) {
@ -58,10 +59,6 @@
this.saveNextAsSnapshot = false;
}
if (isSnapshot) {
}
this.stateQueue.push(state);
};
@ -74,7 +71,7 @@
};
ns.HistoryService.prototype.isLoadStateAllowed_ = function (index) {
var timeOk = (Date.now() - this.lastLoadState) > LOAD_STATE_INTERVAL;
var timeOk = (Date.now() - this.lastLoadState) > ns.HistoryService.LOAD_STATE_INTERVAL;
var indexInRange = index >= 0 && index < this.stateQueue.length;
return timeOk && indexInRange;
};
@ -97,7 +94,7 @@
}
var serializedPiskel = this.getSnapshotFromState_(snapshotIndex);
var onPiskelLoadedCb = this.onPiskelLoaded_.bind(this, index, snapshotIndex);
pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, onPiskelLoadedCb);
this.deserializer.deserialize(serializedPiskel, onPiskelLoadedCb);
}
} catch (e) {
window.console.error("[CRITICAL ERROR] : Unable to load a history state.");
@ -138,6 +135,7 @@
this.replayState(state);
}
// Should only do this when going backwards
var lastState = this.stateQueue[index+1];
if (lastState) {
this.setupState(lastState);

View file

@ -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);
};
})();

View file

@ -26,6 +26,13 @@
return canvas;
},
createFromImage : function (image) {
var canvas = pskl.CanvasUtils.createCanvas(image.width, image.height);
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
return canvas;
},
/**
* By default, all scaling operations on a Canvas 2D Context are performed using antialiasing.
* Resizing a 32x32 image to 320x320 will lead to a blurry output.

46
src/js/utils/Xhr.js Normal file
View file

@ -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;
}
};
})();

View file

@ -14,13 +14,26 @@ jQuery.namespace = function() {
/**
* Need a polyfill for PhantomJS
*/
if (typeof Function.prototype.bind !== "function") {
Function.prototype.bind = function(scope) {
"use strict";
var _function = this;
return function() {
return _function.apply(scope, arguments);
};
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var bindArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
var args = bindArgs.concat(Array.prototype.slice.call(arguments));
return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, args);
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}

View file

@ -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",
@ -137,6 +138,17 @@
"js/drawingtools/selectiontools/ShapeSelect.js",
"js/drawingtools/ColorPicker.js",
"js/drawingtools/ColorSwap.js",
// Devtools
"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",
// Bonus features !!

View file

@ -7,11 +7,16 @@
<span class="settings-description">PNG with all frames side by side.</span>
<button type="button" class="button button-primary png-download-button">Download PNG</button>
</div>
<div class="settings-title">
Export as ZIP
</div>
<div class="settings-item">
<span class="settings-description">ZIP with one PNG file per frame.</span>
<div>
<button type="button" class="button button-primary zip-generate-button"/>Download ZIP</button>
<span class="settings-description">ZIP with one PNG file per frame. Name will use the prefix above and append the frame index, ex: sprite_1.png</span>
<div class="settings-item">
<label for="zip-file-name">File prefix:</label>
<input id="zip-file-name" type="text" class="textfield" placeholder="sprite_">
</div>
<button type="button" class="button button-primary zip-generate-button"/>Download ZIP</button>
</div>
<div class="settings-title">
Export to Animated GIF
@ -37,4 +42,4 @@
<span class="gif-export-progress-status"></span>
<div class="gif-export-progress-bar"></div>
</div>
</div>
</div>

View file

@ -0,0 +1,42 @@
(function () {
var tests = require('./test/drawing/DrawingTests.casper.js').tests;
var baseUrl = casper.cli.get('baseUrl')+"?debug";
var resultSelector = '#drawing-test-result';
casper.start();
var runTest = function (index) {
var test = 'drawing/tests/' + tests[index];
casper.open(baseUrl + "&test-run=" + test);
casper.then(function () {
this.echo('Running test : ' + test);
this.wait(casper.cli.get('delay'));
});
casper.then(function () {
this.echo('Waiting for test result : ' + resultSelector);
this.waitForSelector(resultSelector, function () {
// then
var result = this.getHTML(resultSelector);
this.echo('Test finished : ' + result);
this.test.assertEquals(result, 'OK');
}, function () {
// onTimeout
this.test.fail('Test timed out');
}, 60*1000);
})
.run(function () {
if (tests[index+1]) {
runTest(index+1);
} else {
this.test.done();
}
});
};
runTest(0);
})();

View file

@ -0,0 +1,4 @@
(typeof exports != "undefined" ? exports : pskl_exports).tests = [
'SmokeTest.js',
'DrawingTest.js'
];

View file

@ -7,7 +7,7 @@ casper
this.echo(casper.cli.get('baseUrl')+"?debug");
// If there was a JS error after the page load, casper won't perform asserts
this.test.assertExists('html', 'Casper JS cannot assert DOM elements. A JS error has probably occured.');
this.test.assertExists('#drawing-canvas-container canvas', 'Check if drawing canvas element is created');
})
.run(function () {

View file

@ -0,0 +1,4 @@
(typeof exports != "undefined" ? exports : pskl_exports).tests = [
// did not manage to successfully run drawing tests on travis yet ...
'SmokeTest.js'
];

View file

@ -0,0 +1,13 @@
{"tests" : [
"pen.drawing.json",
"bucket.drawing.json",
"color.picker.json",
"frames.fun.json",
"layers.fun.json",
"lighten.darken.json",
"move.json",
"pen.secondary.color.json",
"squares.circles.json",
"stroke.json",
"verticalpen.drawing.json"
]}

View file

@ -0,0 +1,11 @@
(typeof exports != "undefined" ? exports : pskl_exports).tests = [
"pen.drawing.json",
"color.picker.json",
"frames.fun.json",
"layers.fun.json",
"move.json",
"pen.secondary.color.json",
"squares.circles.json",
"stroke.json",
"verticalpen.drawing.json"
];

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,48 @@
{"events":[{"type":"tool-event","toolId":"tool-pen"},
{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":0},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":0},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":0},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"},
{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"},
{"type":"color-event","color":"rgb(11, 182, 0)","isPrimary":true},
{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":1},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":1},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":1},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":1},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":1},"type":"mouse-event"},
{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":1},"type":"mouse-event"},
{"type":"color-event","color":"rgb(49, 84, 47)","isPrimary":true},
{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":2},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":2},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":2},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":2},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":2},"type":"mouse-event"},
{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":2},"type":"mouse-event"},
{"type":"tool-event","toolId":"tool-colorpicker"},
{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},
{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},
{"type":"tool-event","toolId":"tool-pen"},
{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":3},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":3},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":3},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":3},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":3},"type":"mouse-event"},
{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":3},"type":"mouse-event"},
{"type":"tool-event","toolId":"tool-colorpicker"},
{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},
{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},
{"type":"tool-event","toolId":"tool-pen"},
{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":4},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":4},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":4},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":4},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":4},"type":"mouse-event"},
{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":4},"type":"mouse-event"},
{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":4},"type":"mouse-event"}],"initialState":{"size":{"width":5,"height":5},"primaryColor":"rgb(182, 177, 0)","secondaryColor":"#80ff00","selectedTool":"tool-move"},"png":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQIW2PctpHhPwMaYOTehkXQMEQfUyXR2gFosQoFS9oVSgAAAABJRU5ErkJggg=="}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"events":[{"type":"tool-event","toolId":"tool-pen"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"},{"type":"color-event","color":"#158d00","isPrimary":true},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"type":"color-event","color":"#6bb25e","isPrimary":true},{"type":"tool-event","toolId":"tool-paint-bucket"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"type":"instrumented-event","methodName":"addFrameAt","args":[1]},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"type":"instrumented-event","methodName":"duplicateFrameAt","args":[0]},{"type":"instrumented-event","methodName":"moveFrame","args":[1,2]},{"type":"instrumented-event","methodName":"setCurrentFrameIndex","args":[2]}],"initialState":{"size":{"width":5,"height":5},"primaryColor":"#8d007c","secondaryColor":"rgba(0, 0, 0, 0)","selectedTool":"tool-move"},"png":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAFCAYAAACaTbYsAAAAPklEQVQYV2PsZaj5z4AG7m16hC7EoOQnhyHGKNrLgKE5TDUOQ+Gq24uwa0ZWDFKESzO6OrDNFGlGdw+xzgYAdtkjkmnNRVEAAAAASUVORK5CYII="}

View file

@ -0,0 +1 @@
{"events":[{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"type":"instrumented-event","methodName":"createLayer","args":[]},{"type":"color-event","color":"#0ea92e","isPrimary":true},{"type":"tool-event","toolId":"tool-rectangle"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},{"type":"instrumented-event","methodName":"createLayer","args":[]},{"type":"color-event","color":"#170ea9","isPrimary":true},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":3},"type":"mouse-event"},{"type":"instrumented-event","methodName":"moveLayerDown","args":[]},{"type":"tool-event","toolId":"tool-move"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":1},"type":"mouse-event"}],"initialState":{"size":{"width":5,"height":5},"primaryColor":"#a9220e","secondaryColor":"rgba(0, 0, 0, 0)","selectedTool":"tool-paint-bucket"},"png":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAM0lEQVQIW2NcqcT3nwENMIIEU9sV4MKzKx8wwAU5U6sZvs9uZQDRGCrhgiC9eW9mw40AAEumFR2KMzAWAAAAAElFTkSuQmCC"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"events":[{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":0},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":0},"type":"mouse-event"},{"type":"color-event","color":"#b00000","isPrimary":true},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":1},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":1},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":1},"type":"mouse-event"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":2},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":2},"type":"mouse-event"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":2},"type":"mouse-event"},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":3},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":3},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":3},"type":"mouse-event"},{"type":"color-event","color":"#03b000","isPrimary":true},{"event":{"type":"mousedown","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":0,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":1,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":2,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":3,"y":4},"type":"mouse-event"},{"event":{"type":"mousemove","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":4},"type":"mouse-event"},{"event":{"type":"mouseup","button":0,"shiftKey":false,"altKey":false,"ctrlKey":false},"coords":{"x":4,"y":4},"type":"mouse-event"}],"initialState":{"size":{"width":5,"height":5},"primaryColor":"#000000","secondaryColor":"rgba(0, 0, 0, 0)","selectedTool":"tool-pen"},"png":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAALUlEQVQIW2NkYGD4D8QogBFdYANQEVwQxAEpCGBgYAQLggRAHJguRuYNmGYCAJ6NCGbAWR+yAAAAAElFTkSuQmCC"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,86 @@
var callFactory = function (method) {
return {
times : function (times) {
var results = [];
for (var i = 0 ; i < times ; i++) {
results.push(method());
}
return results;
},
once : function () {
return method();
}
};
};
describe("History Service suite", function() {
var SERIALIZED_PISKEL = 'serialized-piskel';
var historyService = null;
var getLastState = function () {
return historyService.stateQueue[historyService.currentIndex];
};
var createMockHistoryService = function () {
var mockPiskelController = {
serialize : function () {
return SERIALIZED_PISKEL;
}
};
var mockShortcutService = {
addShortcut : function () {}
};
return new pskl.service.HistoryService(mockPiskelController, mockShortcutService);
};
it("starts at -1", function() {
historyService = createMockHistoryService();
expect(historyService.currentIndex).toBe(-1);
});
it("is at 0 after init", function() {
historyService = createMockHistoryService();
historyService.init();
expect(historyService.currentIndex).toBe(0);
});
var sendSaveEvents = function (type) {
return callFactory (function () {
$.publish(Events.PISKEL_SAVE_STATE, {
type : type,
scope : {},
replay : {}
});
});
};
it("stores a piskel snapshot after 5 SAVE", function () {
// BEFORE
var SNAPSHOT_PERIOD_BACKUP = pskl.service.HistoryService.SNAPSHOT_PERIOD;
pskl.service.HistoryService.SNAPSHOT_PERIOD = 5;
historyService = createMockHistoryService();
historyService.init();
sendSaveEvents(pskl.service.HistoryService.REPLAY).times(5);
expect(historyService.currentIndex).toBe(5);
expect(getLastState().piskel).toBe(SERIALIZED_PISKEL);
sendSaveEvents(pskl.service.HistoryService.REPLAY).times(4);
sendSaveEvents(pskl.service.HistoryService.REPLAY_NO_SNAPSHOT).once();
expect(getLastState().piskel).toBeUndefined();
sendSaveEvents(pskl.service.HistoryService.REPLAY_NO_SNAPSHOT).once();
expect(getLastState().piskel).toBeUndefined();
sendSaveEvents(pskl.service.HistoryService.REPLAY).once();
expect(getLastState().piskel).toBe(SERIALIZED_PISKEL);
// AFTER
pskl.service.HistoryService.SNAPSHOT_PERIOD = SNAPSHOT_PERIOD_BACKUP;
})
});