Merge pull request #310 from thisandagain/bugfix/coverage

Improve Test Coverage
This commit is contained in:
Andrew Sliwinski 2016-10-24 15:56:04 -04:00 committed by GitHub
commit e35a46fdf1
8 changed files with 342 additions and 18 deletions

View file

@ -4,3 +4,4 @@ node_modules/*
playground/* playground/*
vm.js vm.js
vm.min.js vm.min.js
coverage/*

View file

@ -18,9 +18,8 @@
"prepublish": "npm run build", "prepublish": "npm run build",
"prepublish-watch": "npm run watch", "prepublish-watch": "npm run watch",
"start": "./node_modules/.bin/webpack-dev-server", "start": "./node_modules/.bin/webpack-dev-server",
"tap-integration": "./node_modules/.bin/tap ./test/integration/*.js", "tap": "./node_modules/.bin/tap ./test/{unit,integration}/*.js",
"tap-unit": "./node_modules/.bin/tap ./test/unit/*.js", "test": "npm run lint && npm run tap",
"test": "npm run lint && npm run tap-unit && npm run tap-integration",
"watch": "./node_modules/.bin/webpack --progress --colors --watch", "watch": "./node_modules/.bin/webpack --progress --colors --watch",
"version": "./node_modules/.bin/json -f package.json -I -e \"this.repository.sha = '$(git log -n1 --pretty=format:%H)'\"" "version": "./node_modules/.bin/json -f package.json -I -e \"this.repository.sha = '$(git log -n1 --pretty=format:%H)'\""
}, },

View file

@ -18,6 +18,7 @@ var Keyboard = function (runtime) {
* Convert a Scratch key name to a DOM keyCode. * Convert a Scratch key name to a DOM keyCode.
* @param {Any} keyName Scratch key argument. * @param {Any} keyName Scratch key argument.
* @return {number} Key code corresponding to a DOM event. * @return {number} Key code corresponding to a DOM event.
* @private
*/ */
Keyboard.prototype._scratchKeyToKeyCode = function (keyName) { Keyboard.prototype._scratchKeyToKeyCode = function (keyName) {
if (typeof keyName === 'number') { if (typeof keyName === 'number') {
@ -37,6 +38,12 @@ Keyboard.prototype._scratchKeyToKeyCode = function (keyName) {
return keyString.toUpperCase().charCodeAt(0); return keyString.toUpperCase().charCodeAt(0);
}; };
/**
* Convert a DOM keyCode into a Scratch key name.
* @param {number} keyCode Key code from DOM event.
* @return {Any} Scratch key argument.
* @private
*/
Keyboard.prototype._keyCodeToScratchKey = function (keyCode) { Keyboard.prototype._keyCodeToScratchKey = function (keyCode) {
if (keyCode >= 48 && keyCode <= 90) { if (keyCode >= 48 && keyCode <= 90) {
// Standard letter. // Standard letter.
@ -52,6 +59,10 @@ Keyboard.prototype._keyCodeToScratchKey = function (keyCode) {
return null; return null;
}; };
/**
* Keyboard DOM event handler.
* @param {object} data Data from DOM event.
*/
Keyboard.prototype.postData = function (data) { Keyboard.prototype.postData = function (data) {
if (data.keyCode) { if (data.keyCode) {
var index = this._keysPressed.indexOf(data.keyCode); var index = this._keysPressed.indexOf(data.keyCode);
@ -74,6 +85,11 @@ Keyboard.prototype.postData = function (data) {
} }
}; };
/**
* Get key down state for a specified Scratch key name.
* @param {Any} key Scratch key argument.
* @return {boolean} Is the specified key down?
*/
Keyboard.prototype.getKeyIsDown = function (key) { Keyboard.prototype.getKeyIsDown = function (key) {
if (key === 'any') { if (key === 'any') {
return this._keysPressed.length > 0; return this._keysPressed.length > 0;

View file

@ -12,21 +12,12 @@ var Mouse = function (runtime) {
this.runtime = runtime; this.runtime = runtime;
}; };
Mouse.prototype.postData = function (data) { /**
if (data.x) { * Activate "event_whenthisspriteclicked" hats if needed.
this._x = data.x - (data.canvasWidth / 2); * @param {number} x X position to be sent to the renderer.
} * @param {number} y Y position to be sent to the renderer.
if (data.y) { * @private
this._y = data.y - (data.canvasHeight / 2); */
}
if (typeof data.isDown !== 'undefined') {
this._isDown = data.isDown;
if (this._isDown) {
this._activateClickHats(data.x, data.y);
}
}
};
Mouse.prototype._activateClickHats = function (x, y) { Mouse.prototype._activateClickHats = function (x, y) {
if (this.runtime.renderer) { if (this.runtime.renderer) {
var drawableID = this.runtime.renderer.pick(x, y); var drawableID = this.runtime.renderer.pick(x, y);
@ -42,14 +33,45 @@ Mouse.prototype._activateClickHats = function (x, y) {
} }
}; };
/**
* Mouse DOM event handler.
* @param {object} data Data from DOM event.
*/
Mouse.prototype.postData = function (data) {
if (data.x) {
this._x = data.x - data.canvasWidth / 2;
}
if (data.y) {
this._y = data.y - data.canvasHeight / 2;
}
if (typeof data.isDown !== 'undefined') {
this._isDown = data.isDown;
if (this._isDown) {
this._activateClickHats(data.x, data.y);
}
}
};
/**
* Get the X position of the mouse.
* @return {number} Clamped X position of the mouse cursor.
*/
Mouse.prototype.getX = function () { Mouse.prototype.getX = function () {
return MathUtil.clamp(this._x, -240, 240); return MathUtil.clamp(this._x, -240, 240);
}; };
/**
* Get the Y position of the mouse.
* @return {number} Clamped Y position of the mouse cursor.
*/
Mouse.prototype.getY = function () { Mouse.prototype.getY = function () {
return MathUtil.clamp(-this._y, -180, 180); return MathUtil.clamp(-this._y, -180, 180);
}; };
/**
* Get the down state of the mouse.
* @return {boolean} Is the mouse down?
*/
Mouse.prototype.getIsDown = function () { Mouse.prototype.getIsDown = function () {
return this._isDown; return this._isDown;
}; };

130
test/unit/blocks_control.js Normal file
View file

@ -0,0 +1,130 @@
var test = require('tap').test;
var Control = require('../../src/blocks/scratch3_control');
var Runtime = require('../../src/engine/runtime');
test('getPrimitives', function (t) {
var rt = new Runtime();
var c = new Control(rt);
t.type(c.getPrimitives(), 'object');
t.end();
});
test('repeat', function (t) {
var rt = new Runtime();
var c = new Control(rt);
// Test harness (mocks `util`)
var i = 0;
var repeat = 10;
var util = {
stackFrame: Object.create(null),
startBranch: function () {
i++;
c.repeat({TIMES: repeat}, util);
}
};
// Execute test
c.repeat({TIMES: 10}, util);
t.strictEqual(util.stackFrame.loopCounter, -1);
t.strictEqual(i, repeat);
t.end();
});
test('repeatUntil', function (t) {
var rt = new Runtime();
var c = new Control(rt);
// Test harness (mocks `util`)
var i = 0;
var repeat = 10;
var util = {
stackFrame: Object.create(null),
startBranch: function () {
i++;
c.repeatUntil({CONDITION: (i === repeat)}, util);
}
};
// Execute test
c.repeatUntil({CONDITION: (i === repeat)}, util);
t.strictEqual(i, repeat);
t.end();
});
test('forever', function (t) {
var rt = new Runtime();
var c = new Control(rt);
// Test harness (mocks `util`)
var i = 0;
var util = {
startBranch: function (branchNum, isLoop) {
i++;
t.strictEqual(branchNum, 1);
t.strictEqual(isLoop, true);
}
};
// Execute test
c.forever(null, util);
t.strictEqual(i, 1);
t.end();
});
test('if / ifElse', function (t) {
var rt = new Runtime();
var c = new Control(rt);
// Test harness (mocks `util`)
var i = 0;
var util = {
startBranch: function (branchNum) {
i += branchNum;
}
};
// Execute test
c.if({CONDITION: true}, util);
t.strictEqual(i, 1);
c.if({CONDITION: false}, util);
t.strictEqual(i, 1);
c.ifElse({CONDITION: true}, util);
t.strictEqual(i, 2);
c.ifElse({CONDITION: false}, util);
t.strictEqual(i, 4);
t.end();
});
test('stop', function (t) {
var rt = new Runtime();
var c = new Control(rt);
// Test harness (mocks `util`)
var state = {
stopAll: 0,
stopOtherTargetThreads: 0,
stopThread: 0
};
var util = {
stopAll: function () {
state.stopAll++;
},
stopOtherTargetThreads: function () {
state.stopOtherTargetThreads++;
},
stopThread: function () {
state.stopThread++;
}
};
// Execute test
c.stop({STOP_OPTION: 'all'}, util);
c.stop({STOP_OPTION: 'other scripts in sprite'}, util);
c.stop({STOP_OPTION: 'other scripts in stage'}, util);
c.stop({STOP_OPTION: 'this script'}, util);
t.strictEqual(state.stopAll, 1);
t.strictEqual(state.stopOtherTargetThreads, 2);
t.strictEqual(state.stopThread, 1);
t.end();
});

34
test/unit/io_clock.js Normal file
View file

@ -0,0 +1,34 @@
var test = require('tap').test;
var Clock = require('../../src/io/clock');
var Runtime = require('../../src/engine/runtime');
test('spec', function (t) {
var rt = new Runtime();
var c = new Clock(rt);
t.type(Clock, 'function');
t.type(c, 'object');
t.type(c.projectTimer, 'function');
t.type(c.pause, 'function');
t.type(c.resume, 'function');
t.type(c.resetProjectTimer, 'function');
t.end();
});
test('cycle', function (t) {
var rt = new Runtime();
var c = new Clock(rt);
t.ok(c.projectTimer() <= 0.1);
setTimeout(function () {
c.resetProjectTimer();
setTimeout(function () {
t.ok(c.projectTimer() > 0);
c.pause();
t.ok(c.projectTimer() > 0);
c.resume();
t.ok(c.projectTimer() > 0);
t.end();
}, 100);
}, 100);
});

73
test/unit/io_keyboard.js Normal file
View file

@ -0,0 +1,73 @@
var test = require('tap').test;
var Keyboard = require('../../src/io/keyboard');
var Runtime = require('../../src/engine/runtime');
test('spec', function (t) {
var rt = new Runtime();
var k = new Keyboard(rt);
t.type(k, 'object');
t.type(k.postData, 'function');
t.type(k.getKeyIsDown, 'function');
t.end();
});
test('space', function (t) {
var rt = new Runtime();
var k = new Keyboard(rt);
k.postData({
keyCode: 32,
isDown: true
});
t.strictDeepEquals(k._keysPressed, [32]);
t.strictEquals(k.getKeyIsDown('space'), true);
t.strictEquals(k.getKeyIsDown('any'), true);
t.end();
});
test('letter', function (t) {
var rt = new Runtime();
var k = new Keyboard(rt);
k.postData({
keyCode: 65,
isDown: true
});
t.strictDeepEquals(k._keysPressed, [65]);
t.strictEquals(k.getKeyIsDown('a'), true);
t.strictEquals(k.getKeyIsDown('any'), true);
t.end();
});
test('number', function (t) {
var rt = new Runtime();
var k = new Keyboard(rt);
k.postData({
keyCode: 49,
isDown: true
});
t.strictDeepEquals(k._keysPressed, [49]);
t.strictEquals(k.getKeyIsDown(49), true);
t.strictEquals(k.getKeyIsDown('any'), true);
t.end();
});
test('keyup', function (t) {
var rt = new Runtime();
var k = new Keyboard(rt);
k.postData({
keyCode: 37,
isDown: true
});
k.postData({
keyCode: 37,
isDown: false
});
t.strictDeepEquals(k._keysPressed, []);
t.strictEquals(k.getKeyIsDown(37), false);
t.strictEquals(k.getKeyIsDown('any'), false);
t.end();
});

49
test/unit/io_mouse.js Normal file
View file

@ -0,0 +1,49 @@
var test = require('tap').test;
var Mouse = require('../../src/io/mouse');
var Runtime = require('../../src/engine/runtime');
test('spec', function (t) {
var rt = new Runtime();
var m = new Mouse(rt);
t.type(m, 'object');
t.type(m.postData, 'function');
t.type(m.getX, 'function');
t.type(m.getY, 'function');
t.type(m.getIsDown, 'function');
t.end();
});
test('mouseUp', function (t) {
var rt = new Runtime();
var m = new Mouse(rt);
m.postData({
x: 1,
y: 10,
isDown: false,
canvasWidth: 480,
canvasHeight: 360
});
t.strictEquals(m.getX(), -239);
t.strictEquals(m.getY(), 170);
t.strictEquals(m.getIsDown(), false);
t.end();
});
test('mouseDown', function (t) {
var rt = new Runtime();
var m = new Mouse(rt);
m.postData({
x: 10,
y: 100,
isDown: true,
canvasWidth: 480,
canvasHeight: 360
});
t.strictEquals(m.getX(), -230);
t.strictEquals(m.getY(), 80);
t.strictEquals(m.getIsDown(), true);
t.end();
});