From 051e1e477887b56f4471cc07d450442d78a39b5b Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Wed, 19 Feb 2014 20:11:08 -0700 Subject: [PATCH 01/10] bringing the Scratch html5 project under test --- .gitignore | 7 ++ README.md | 46 ++++++++++++ config/karma.conf.js | 37 +++++++++ index.html | 51 +++++++------ js/Scratch.js | 4 +- package.json | 13 ++++ scripts/test.sh | 9 +++ test/artifacts/io-artifact.js | 9 +++ test/artifacts/scratch-artifact.js | 117 +++++++++++++++++++++++++++++ test/lib/.git-keep | 0 test/unit/ioSpec.js | 47 ++++++++++++ test/unit/scratchSpec.js | 25 ++++++ 12 files changed, 340 insertions(+), 25 deletions(-) create mode 100644 .gitignore create mode 100644 config/karma.conf.js create mode 100644 package.json create mode 100755 scripts/test.sh create mode 100644 test/artifacts/io-artifact.js create mode 100644 test/artifacts/scratch-artifact.js create mode 100644 test/lib/.git-keep create mode 100644 test/unit/ioSpec.js create mode 100644 test/unit/scratchSpec.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca4d940 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.swp +test/lib/* + +logs + +npm-debug.log +node_modules diff --git a/README.md b/README.md index 5777743..909bf5c 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,49 @@ Running the HTML5 player on your own website, or locally, you will need to have PHP so that the `proxy.php` file can be used to load assets from the same domain. This is done to be compatible with Javascript security models in today's browsers. To test the HTML5 player against the Flash player you can use the compare.html web page. See the file `TESTING.md` for more details. + + +Unit Tests +---------- +The tests are written using Karma and there should be a 100% passing rate in order to commit any code to the project. + +The expectation is to add a unit test for any code that you contribute to the project. + + +Install Node (NPM) (https://npmjs.org/) +--------------------------------------- + +Brew: +``` +$ brew install npm +``` + +Mac Ports: +``` +$ port install npm +``` + +``` +$ npm install +``` + +Local copy of jQuery and mock-ajax +---------------------------------- + +``` +$ cd test/lib +$ curl http://code.jquery.com/jquery-1.11.0.min.js > jquery-1.11.0.min.js +$ curl http://cloud.github.com/downloads/pivotal/jasmine-ajax/mock-ajax.js > mock-ajax.js +``` + +To Run the tests +---------------- + +``` +$ ./scripts/test.sh +``` + + +To configure the unit tests +--------------------------- +The karam.conf.js file is location in the config directory diff --git a/config/karma.conf.js b/config/karma.conf.js new file mode 100644 index 0000000..312a8a6 --- /dev/null +++ b/config/karma.conf.js @@ -0,0 +1,37 @@ +module.exports = function(config){ + config.set({ + basePath : '../', + + files : [ + 'test/artifacts/**/*.js', + 'test/lib/mock-ajax.js', + 'test/unit/**/*.js', + 'test/lib/jquery-1.11.0.min.js', + 'js/sound/SoundDecoder.js', + 'js/sound/**/*.js', + 'js/util/**/*.js', + 'js/**/*.js' + ], + + exclude : [ + ], + + autoWatch : true, + + frameworks: ['jasmine'], + + browsers : ['Chrome'], + + plugins : [ + 'karma-junit-reporter', + 'karma-chrome-launcher', + 'karma-firefox-launcher', + 'karma-jasmine' + ], + + junitReporter : { + outputFile: 'test_out/unit.xml', + suite: 'unit' + } + +})} diff --git a/index.html b/index.html index 8f25615..71f68b2 100755 --- a/index.html +++ b/index.html @@ -12,31 +12,12 @@ - - - - - - - - - - - - - - - - - - - - - - -
@@ -68,3 +49,27 @@

Scratch HTML5 player

The Scratch HTML5 player is still in development. Feedback is welcome! Please report any bugs (or differences from the Flash player) on Github.

+ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/Scratch.js b/js/Scratch.js index dc817f6..653796f 100644 --- a/js/Scratch.js +++ b/js/Scratch.js @@ -23,7 +23,7 @@ 'use strict'; var runtime, interp, io, iosAudioActive = false; -$(function() { +function Scratch(project_id) { runtime = new Runtime(); runtime.init(); @@ -151,4 +151,4 @@ $(function() { // Load the requested project and go! io = new IO(); io.loadProject(project_id); -}); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..732b5b2 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "scratch-html5", + "description": "HTML 5 based Scratch project player", + "repository": "https://github.com/LLK/scratch-html5", + "devDependencies": { + "phantomjs" : "~1.9", + "karma" : "~0.10", + "karma-junit-reporter" : "~0.1", + "karma-jasmine" : "~0.1", + "karma-ng-scenario" : "~0.1", + "jquery" : "~1.11.0" + } +} diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..972001f --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +BASE_DIR=`dirname $0` + +echo "" +echo "Starting Karma Server (http://karma-runner.github.io)" +echo "-------------------------------------------------------------------" + +$BASE_DIR/../node_modules/karma/bin/karma start $BASE_DIR/../config/karma.conf.js $* diff --git a/test/artifacts/io-artifact.js b/test/artifacts/io-artifact.js new file mode 100644 index 0000000..53ac670 --- /dev/null +++ b/test/artifacts/io-artifact.js @@ -0,0 +1,9 @@ +'use strict'; + +var io_base = 'proxy.php?resource=internalapi/'; +var project_base = io_base + 'project/'; +var project_suffix = '/get/'; +var asset_base = io_base + 'asset/'; +var asset_suffix = '/get/'; +var soundbank_base = 'soundbank/'; +var spriteLayerCount = 0; diff --git a/test/artifacts/scratch-artifact.js b/test/artifacts/scratch-artifact.js new file mode 100644 index 0000000..60e17a1 --- /dev/null +++ b/test/artifacts/scratch-artifact.js @@ -0,0 +1,117 @@ +'use strict'; + +var project_id = 123456789; + +var returnData = { + "objName": "Stage", + "sounds": [{ + "soundName": "pop", + "soundID": -1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + }], + "costumes": [{ + "costumeName": "Scene 1", + "baseLayerID": -1, + "baseLayerMD5": "510da64cf172d53750dffd23fbf73563.png", + "rotationCenterX": 240, + "rotationCenterY": 180, + "spritesHiddenInScene": null + }], + "currentCostumeIndex": 0, + "penLayerMD5": "279467d0d49e152706ed66539b577c00.png", + "tempoBPM": 60, + "children": [{ + "objName": "Sprite1", + "scripts": [[283, + 151, + [["whenClicked"], + ["clearPenTrails"], + ["penColor:", 10485886], + ["putPenDown"], + ["doForever", + [["gotoX:y:", ["randomFrom:to:", -240, 240], ["randomFrom:to:", -180, 180]], ["changePenShadeBy:", 10]]]]]], + "sounds": [{ + "soundName": "pop", + "soundID": -1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + }], + "costumes": [{ + "costumeName": "Costume1", + "baseLayerID": -1, + "baseLayerMD5": "cce61b6e9ad98ea8c8c2e9556a94b7ab.png", + "rotationCenterX": 47, + "rotationCenterY": 55, + "spritesHiddenInScene": null + }, + { + "costumeName": "Costume2", + "baseLayerID": -1, + "baseLayerMD5": "51f6fa1871f17de1a21cdfead7aad574.png", + "rotationCenterX": 47, + "rotationCenterY": 55, + "spritesHiddenInScene": null + }], + "currentCostumeIndex": 0, + "scratchX": 120, + "scratchY": -101, + "scale": 1, + "direction": 90, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 0, + "visible": true + }, + { + "objName": "fish31", + "scripts": [[181, 138, [["whenClicked"], ["nextCostume"]]]], + "sounds": [{ + "soundName": "pop", + "soundID": -1, + "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav", + "sampleCount": 258, + "rate": 11025, + "format": "" + }], + "costumes": [{ + "costumeName": "fish3", + "baseLayerID": -1, + "baseLayerMD5": "5ab571cf8c6e6bcf0ee2443b5df17dcb.png", + "rotationCenterX": 90, + "rotationCenterY": 79, + "spritesHiddenInScene": null + }, + { + "costumeName": "crab1-a", + "baseLayerID": -1, + "baseLayerMD5": "110bf75ed212eb072acec2fa2c39456d.png", + "rotationCenterX": 92, + "rotationCenterY": 62, + "spritesHiddenInScene": null + }, + { + "costumeName": "ballerina-a", + "baseLayerID": -1, + "baseLayerMD5": "4c789664cc6f69d1ef4678ac8b4cb812.png", + "rotationCenterX": 51, + "rotationCenterY": 84, + "spritesHiddenInScene": null + }], + "currentCostumeIndex": 2, + "scratchX": 108, + "scratchY": -28, + "scale": 1, + "direction": 90, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 0, + "visible": true + }], + "info": { + } +}; diff --git a/test/lib/.git-keep b/test/lib/.git-keep new file mode 100644 index 0000000..e69de29 diff --git a/test/unit/ioSpec.js b/test/unit/ioSpec.js new file mode 100644 index 0000000..f986bc8 --- /dev/null +++ b/test/unit/ioSpec.js @@ -0,0 +1,47 @@ +'use strict'; + +/* jasmine specs for IO.js go here */ + +describe('IO', function(){ + var io; + + beforeEach(function() { + io = new IO(); + }); + + it('should have "null" data', function() { + expect(io.data).toBe(null); + }); + + it('should have "null" data', function() { + expect(io.data).toBe(null); + }); + + it('should have a base', function() { + expect(io.base).toBe(io_base); + }); + + it('should have a project_base', function() { + expect(io.project_base).toBe(project_base); + }); + + it('should have a project_suffix', function() { + expect(io.project_suffix).toBe(project_suffix); + }); + + it('should have an asset_base', function() { + expect(io.asset_base).toBe(asset_base); + }); + + it('should have an asset_suffix', function() { + expect(io.asset_suffix).toBe(asset_suffix); + }); + + it('should have an soundbank_base', function() { + expect(io.soundbank_base).toBe(soundbank_base); + }); + + it('should have a spriteLayerCount', function() { + expect(io.spriteLayerCount).toBe(spriteLayerCount); + }); +}); diff --git a/test/unit/scratchSpec.js b/test/unit/scratchSpec.js new file mode 100644 index 0000000..29db9cc --- /dev/null +++ b/test/unit/scratchSpec.js @@ -0,0 +1,25 @@ +'use strict'; + +/* jasmine specs for Scratch.js go here */ + +describe('Scratch', function(){ + var getScript, request, scratch; + var uri = "http://getScript.example.com"; + var callBack = jasmine.createSpy('onSuccess'); + var testResponseText = 'This is a script'; + + var TestResponses = { status: 200, responseText: returnData}; + + beforeEach(function() { + jasmine.Ajax.useMock(); + scratch = Scratch; + scratch(project_id); + request = mostRecentAjaxRequest(); + request.promise(TestResponses, callBack); + }); + + it('should call the internalapi project', function() { + expect(request.url).toBe("proxy.php?resource=internalapi/project/" + project_id + "/get/"); + expect(callBack).toHaveBeenCalled(); + }); +}); From 66998640977bede1a48a8876e639e5648ed4a02e Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Wed, 19 Feb 2014 20:33:55 -0700 Subject: [PATCH 02/10] oops didn't think about updating the compare.html file --- compare.html | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/compare.html b/compare.html index 61ef77c..b538775 100644 --- a/compare.html +++ b/compare.html @@ -8,35 +8,17 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + From 23cc21b7d99ab0015999122e2e84be9d3358789c Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Tue, 4 Mar 2014 21:48:22 -0700 Subject: [PATCH 03/10] updates to bring more of the Scratch project under test ... still baby-steps --- config/karma.conf.js | 25 +++++++------ package.json | 9 ++--- test/unit/scratchSpec.js | 76 ++++++++++++++++++++++++++++++---------- 3 files changed, 72 insertions(+), 38 deletions(-) diff --git a/config/karma.conf.js b/config/karma.conf.js index 312a8a6..9fa12c0 100644 --- a/config/karma.conf.js +++ b/config/karma.conf.js @@ -4,18 +4,22 @@ module.exports = function(config){ files : [ 'test/artifacts/**/*.js', - 'test/lib/mock-ajax.js', + 'test/lib/**/*.js', 'test/unit/**/*.js', - 'test/lib/jquery-1.11.0.min.js', 'js/sound/SoundDecoder.js', 'js/sound/**/*.js', 'js/util/**/*.js', - 'js/**/*.js' + 'js/**/*.js', + 'node_modules/jasmine-jquery/lib/jasmine-jquery.js' ], exclude : [ ], + preprocessors: { + '*.html': ['html2js'] + }, + autoWatch : true, frameworks: ['jasmine'], @@ -23,15 +27,10 @@ module.exports = function(config){ browsers : ['Chrome'], plugins : [ - 'karma-junit-reporter', + 'karma-jasmine', + 'jasmine-jquery', + 'karma-html2js-preprocessor', 'karma-chrome-launcher', - 'karma-firefox-launcher', - 'karma-jasmine' - ], - - junitReporter : { - outputFile: 'test_out/unit.xml', - suite: 'unit' - } - + 'karma-firefox-launcher' + ] })} diff --git a/package.json b/package.json index 732b5b2..e746327 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,8 @@ "description": "HTML 5 based Scratch project player", "repository": "https://github.com/LLK/scratch-html5", "devDependencies": { - "phantomjs" : "~1.9", - "karma" : "~0.10", - "karma-junit-reporter" : "~0.1", - "karma-jasmine" : "~0.1", - "karma-ng-scenario" : "~0.1", - "jquery" : "~1.11.0" + "karma" : "~0.10", + "jasmine-jquery" : "1.3.3", + "karma-html2js-preprocessor" : "~0.1.0" } } diff --git a/test/unit/scratchSpec.js b/test/unit/scratchSpec.js index 29db9cc..0f35ca2 100644 --- a/test/unit/scratchSpec.js +++ b/test/unit/scratchSpec.js @@ -1,25 +1,63 @@ -'use strict'; - /* jasmine specs for Scratch.js go here */ -describe('Scratch', function(){ - var getScript, request, scratch; - var uri = "http://getScript.example.com"; - var callBack = jasmine.createSpy('onSuccess'); - var testResponseText = 'This is a script'; +describe ('Scratch', function() { + describe('Scratch - Load Project', function(){ + var getScript, request, scratch; + var uri = "http://getScript.example.com"; + var callBack = jasmine.createSpy('onSuccess'); + var testResponseText = 'This is a script'; - var TestResponses = { status: 200, responseText: returnData}; + var TestResponses = { status: 200, responseText: returnData}; - beforeEach(function() { - jasmine.Ajax.useMock(); - scratch = Scratch; - scratch(project_id); - request = mostRecentAjaxRequest(); - request.promise(TestResponses, callBack); - }); + beforeEach(function() { + jasmine.Ajax.useMock(); + scratch = Scratch; + scratch(project_id); + request = mostRecentAjaxRequest(); + request.promise(TestResponses, callBack); + }); - it('should call the internalapi project', function() { - expect(request.url).toBe("proxy.php?resource=internalapi/project/" + project_id + "/get/"); - expect(callBack).toHaveBeenCalled(); - }); + it('should call the internalapi project', function() { + expect(request.url).toBe("proxy.php?resource=internalapi/project/" + project_id + "/get/"); + expect(callBack).toHaveBeenCalled(); + }); + }); + + describe('Scratch - Click Green Flag', function(){ + beforeEach(function() { + setFixtures('
'); + scratch = Scratch; + scratch(project_id); + }); + + it('should not click on the green flag if the project is loading', function() { + runtime.projectLoaded = false; + spyOn(runtime, 'greenFlag'); + $('#trigger-green-flag').click(); + expect(runtime.greenFlag).not.toHaveBeenCalled(); + expect($('#overlay').css('display')).toBe('block'); + }); + + it('should click on the green flag if the project is loaded', function() { + runtime.projectLoaded = true; + spyOn(runtime, 'greenFlag'); + $('#trigger-green-flag').click(); + expect(runtime.greenFlag).toHaveBeenCalled(); + expect($('#overlay').css('display')).toBe('none'); + }); + }); + + describe('Scratch - Click Stop', function(){ + beforeEach(function() { + setFixtures(''); + scratch = Scratch; + scratch(project_id); + }); + + it('should not click on the green flag if the project is loading', function() { + spyOn(runtime, 'stopAll'); + $('#trigger-stop').click(); + expect(runtime.stopAll).toHaveBeenCalled(); + }); + }); }); From 3842832e52c5e16b33b6542b95f3d9cd4ad19bda Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Fri, 7 Mar 2014 10:47:50 -0700 Subject: [PATCH 04/10] additional tests in preparation to adding the "ask" functionality --- config/karma.conf.js | 15 +++--- package.json | 3 +- test/artifacts/InterpreterMock.js | 26 ++++++++++ test/artifacts/TargetMock.js | 8 +++ test/artifacts/ask-artifact.js | 55 +++++++++++++++++++++ test/unit/looksPrimitiveSpec.js | 23 +++++++++ test/unit/scratchSpec.js | 4 +- test/unit/sensingPrimitiveSpec.js | 81 +++++++++++++++++++++++++++++++ 8 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 test/artifacts/InterpreterMock.js create mode 100644 test/artifacts/TargetMock.js create mode 100644 test/artifacts/ask-artifact.js create mode 100644 test/unit/looksPrimitiveSpec.js create mode 100644 test/unit/sensingPrimitiveSpec.js diff --git a/config/karma.conf.js b/config/karma.conf.js index 9fa12c0..5c66717 100644 --- a/config/karma.conf.js +++ b/config/karma.conf.js @@ -10,7 +10,8 @@ module.exports = function(config){ 'js/sound/**/*.js', 'js/util/**/*.js', 'js/**/*.js', - 'node_modules/jasmine-jquery/lib/jasmine-jquery.js' + 'node_modules/jasmine-jquery/lib/jasmine-jquery.js', + 'node_modules/underscore/underscore.js' ], exclude : [ @@ -27,10 +28,10 @@ module.exports = function(config){ browsers : ['Chrome'], plugins : [ - 'karma-jasmine', - 'jasmine-jquery', - 'karma-html2js-preprocessor', - 'karma-chrome-launcher', - 'karma-firefox-launcher' - ] + 'karma-jasmine', + 'jasmine-jquery', + 'karma-html2js-preprocessor', + 'karma-chrome-launcher', + 'karma-firefox-launcher' + ] })} diff --git a/package.json b/package.json index e746327..7a6ba49 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "devDependencies": { "karma" : "~0.10", "jasmine-jquery" : "1.3.3", - "karma-html2js-preprocessor" : "~0.1.0" + "karma-html2js-preprocessor" : "~0.1.0", + "underscore" : "~1.6.0" } } diff --git a/test/artifacts/InterpreterMock.js b/test/artifacts/InterpreterMock.js new file mode 100644 index 0000000..7144e37 --- /dev/null +++ b/test/artifacts/InterpreterMock.js @@ -0,0 +1,26 @@ +'use strict'; + +var interpreterMock = function() { + var args = createArgs(arguments); + + function getArgs(argKey) { + return ((argKey in args) ? args[argKey] : null); + } + + function createArgs(methodArgs) { + var args = {}; + if (methodArgs.length) { + _.each(methodArgs, function(newObject) { + _.each(newObject, function(value, key) { + args[key] = value; + }); + }); + } + return args; + } + + return { + 'targetSprite' : function() { return getArgs('targetSprite'); }, + 'arg': function(block, index) { return getArgs('arg');} + } +}; diff --git a/test/artifacts/TargetMock.js b/test/artifacts/TargetMock.js new file mode 100644 index 0000000..9121a00 --- /dev/null +++ b/test/artifacts/TargetMock.js @@ -0,0 +1,8 @@ +'use strict'; + +var targetMock = function() { + return { + 'showBubble' : function() {} + }; + +} diff --git a/test/artifacts/ask-artifact.js b/test/artifacts/ask-artifact.js new file mode 100644 index 0000000..4f0852a --- /dev/null +++ b/test/artifacts/ask-artifact.js @@ -0,0 +1,55 @@ +'use strict'; + +var sensingData = { + "objName": "Stage", + "costumes": [{ + "costumeName": "backdrop1", + "baseLayerID": -1, + "baseLayerMD5": "b61b1077b0ea1931abee9dbbfa7903ff.png", + "bitmapResolution": 2, + "rotationCenterX": 480, + "rotationCenterY": 360 + }], + "currentCostumeIndex": 0, + "penLayerMD5": "5c81a336fab8be57adc039a8a2b33ca9.png", + "tempoBPM": 60, + "videoAlpha": 0.5, + "children": [{ + "objName": "Sprite1", + "scripts": [[42, 40.5, [["whenGreenFlag"], ["doAsk", "What's your name?"]]], + [44.5, + 155.5, + [["whenGreenFlag"], + ["say:", "Hello!"], + ["doIf", ["=", ["timeAndDate", "minute"], "60"], [["say:", ["timestamp"]]]]]]], + "costumes": [{ + "costumeName": "costume1", + "baseLayerID": -1, + "baseLayerMD5": "f9a1c175dbe2e5dee472858dd30d16bb.svg", + "bitmapResolution": 1, + "rotationCenterX": 47, + "rotationCenterY": 55 + }], + "currentCostumeIndex": 0, + "scratchX": 0, + "scratchY": 0, + "scale": 1, + "direction": 90, + "rotationStyle": "normal", + "isDraggable": false, + "indexInLibrary": 1, + "visible": true, + "spriteInfo": { + } + }], + "info": { + "projectID": "18926654", + "spriteCount": 1, + "flashVersion": "MAC 12,0,0,70", + "swfVersion": "v396", + "userAgent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10.9; rv:27.0) Gecko\/20100101 Firefox\/27.0", + "videoOn": false, + "scriptCount": 2, + "hasCloudData": false + } +}; diff --git a/test/unit/looksPrimitiveSpec.js b/test/unit/looksPrimitiveSpec.js new file mode 100644 index 0000000..cadbc6e --- /dev/null +++ b/test/unit/looksPrimitiveSpec.js @@ -0,0 +1,23 @@ +/* jasmine specs for primitives/LooksPrims.js go here */ + +describe ('LooksPrims', function() { + var looksPrims; + beforeEach(function() { + looksPrims = LooksPrims; + }); + + describe('showBubble', function(){ + var sayBlock, targetSpriteMock; + beforeEach(function() { + sayBlock = {'args': ['what to say']}; + targetSpriteMock = targetMock(); + interp = interpreterMock({'targetSprite': targetSpriteMock }, {'arg': sayBlock}); + + }); + it('should return do something', function() { + spyOn(targetSpriteMock, "showBubble"); + showBubble(sayBlock, "say"); + expect(targetSpriteMock.showBubble).toHaveBeenCalled; + }); + }); +}); diff --git a/test/unit/scratchSpec.js b/test/unit/scratchSpec.js index 0f35ca2..0852e46 100644 --- a/test/unit/scratchSpec.js +++ b/test/unit/scratchSpec.js @@ -2,10 +2,8 @@ describe ('Scratch', function() { describe('Scratch - Load Project', function(){ - var getScript, request, scratch; - var uri = "http://getScript.example.com"; + var request, scratch; var callBack = jasmine.createSpy('onSuccess'); - var testResponseText = 'This is a script'; var TestResponses = { status: 200, responseText: returnData}; diff --git a/test/unit/sensingPrimitiveSpec.js b/test/unit/sensingPrimitiveSpec.js new file mode 100644 index 0000000..b75eda1 --- /dev/null +++ b/test/unit/sensingPrimitiveSpec.js @@ -0,0 +1,81 @@ +/* jasmine specs for primitives/SensingPrims.js go here */ + +describe ('SensingPrims', function() { + var sensingPrims; + beforeEach(function() { + sensingPrims = SensingPrims; + realDate = Date; + }); + + afterEach(function () { + Date = realDate; + }); + + describe('primTimestamp', function(){ + beforeEach(function() { + /* MonkeyPatching the built-in Javascript Date */ + var epochDate = new Date(2000, 0, 1); + var nowDate = new Date(2014, 5, 16); + Date = function () { + return (arguments.length ? epochDate : nowDate); + }; + }); + + it('should return the days since 2000', function() { + expect(sensingPrims.prototype.primTimestamp()).toEqual(5280.25); + }); + }); + + describe('primTimeDate', function(){ + beforeEach(function() { + /* MonkeyPatching the built-in Javascript Date */ + Date = function () { + return { + 'getFullYear' : function() { return 2014;}, + 'getMonth' : function() { return 4;}, + 'getDate' : function() { return 16;}, + 'getDay' : function() { return 4;}, + 'getHours' : function() { return 9;}, + 'getMinutes' : function() { return 18;}, + 'getSeconds' : function() { return 36;}, + 'getTime' : function() {} + }; + }; + }); + + it('should return the year', function() { + var block = {'args' : ['year']}; + expect(sensingPrims.prototype.primTimeDate(block)).toEqual(2014); + }); + + it('should return the month of the year', function() { + var block = {'args' : ['month']}; + expect(sensingPrims.prototype.primTimeDate(block)).toEqual(5); + }); + + it('should return the day of the week', function() { + var block = {'args' : ['day of week']}; + expect(sensingPrims.prototype.primTimeDate(block)).toEqual(5); + }); + + it('should return the hour of the day', function() { + var block = {'args' : ['hour']}; + expect(sensingPrims.prototype.primTimeDate(block)).toEqual(9); + }); + + it('should return the minute of the hour', function() { + var block = {'args' : ['minute']}; + expect(sensingPrims.prototype.primTimeDate(block)).toEqual(18); + }); + + it('should return the second of the minute', function() { + var block = {'args' : ['second']}; + expect(sensingPrims.prototype.primTimeDate(block)).toEqual(36); + }); + + it('should return the 0 on year', function() { + var block = {'args' : ['anythingElse']}; + expect(sensingPrims.prototype.primTimeDate(block)).toEqual(0); + }); + }); +}); From 1beed456ccaeb68095572081ab7d3cb84952c257 Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Sat, 8 Mar 2014 00:46:59 -0700 Subject: [PATCH 05/10] updates to add "ask" functionality --- .gitignore | 1 + img/ask-bottom.png | Bin 0 -> 909 bytes img/ask-button.png | Bin 0 -> 1933 bytes img/playerStartFlag.png | Bin 8076 -> 4829 bytes js/Reporter.js | 11 +- js/Sprite.js | 70 +++++- js/Stage.js | 1 + js/primitives/LooksPrims.js | 14 ++ player.css | 47 ++++- test/artifacts/IOMock.js | 25 +++ test/artifacts/TargetMock.js | 4 +- test/artifacts/ask-artifact.js | 16 +- test/artifacts/reporterValues.js | 91 ++++++++ test/unit/looksPrimitiveSpec.js | 54 ++++- test/unit/reporterSpec.js | 96 +++++++++ test/unit/spriteSpec.js | 352 +++++++++++++++++++++++++++++++ test/unit/stageSpec.js | 51 +++++ 17 files changed, 809 insertions(+), 24 deletions(-) create mode 100644 img/ask-bottom.png create mode 100644 img/ask-button.png create mode 100644 test/artifacts/IOMock.js create mode 100644 test/artifacts/reporterValues.js create mode 100644 test/unit/reporterSpec.js create mode 100644 test/unit/spriteSpec.js create mode 100644 test/unit/stageSpec.js diff --git a/.gitignore b/.gitignore index ca4d940..1d5cbb2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.swp test/lib/* +.DS_Store logs diff --git a/img/ask-bottom.png b/img/ask-bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..9823a430aa3477e626d124c5d8fa0e78997a1875 GIT binary patch literal 909 zcmV;819JR{P)gI?43$MNhv*Wb|8N$>B7-$7ve*Mj`=g}92J0E^AoO=EZ zLmnW2SX2er8L?@6^Zn2N6HpB@ysQk4vOF|#;LUeG8BPN2IrZWj!?!>G7`RxN;Bq=5 z91QHtj12ZNJPZH<#DdF!0ssNTf-5vHzWxqon@DhiG*J|Kr(S*sr@IFq ze=$5p3q2J9b_O*;HU@iOV8B8T8vqC(7Hpxp?fxe)Tb!GP?9jaS77}`(wD~^XmF6Zo^soVd077x-*_Yq{gF*!a?=Gp16BFp)!Ko_UxDS{PlmTY{s2Q0HS~;up$BrL6)^NRb jvvB~apA3T#00bBSHz77eF$;b_00000NkvXXu0mjf{(^|| literal 0 HcmV?d00001 diff --git a/img/ask-button.png b/img/ask-button.png new file mode 100644 index 0000000000000000000000000000000000000000..713927add0c1ba49aef6172c49b7243b04106660 GIT binary patch literal 1933 zcmW+%X;f1O7Jk_Sc}PScL8zoGg0ek~R%Sqw00I#NiW^dD5=?-4ViiP%F&IKLqNWN{ zhGj&O3U!yovC1ZSF``f?Fk{`S4um3FM>avt_THP=ANSrL_nhzC@80u$_jp=Lf|KJ? zM*skv_=$1p_UiE|sAPM-`^V9p_Cn0%ZR7z!OW#`3i9bFy3)g29ZrYPmcu-Uz0eIp) z*%B6iwPA@GD+=vKsuhr3X2)e{w!``hoykB{L(ZjkJ;3FdfFW znXIRc!yK~ef&gV_kuD=2Cn!oUXPUAh@L6Vj{JquMUqcJoI6T$hvURztJy#&FS!Y|= zhE5IZz!|wuunB#|F$~M;NvO>_3>3WG!$N@9&)6-8f4<__`hgUiS7%9ar_@vB@f*C-Yt8Q`7a2YWZ ze;sfgf=BR_6~2BMdZswMyvIDZ)?huOQRJJxdLE;Gq4~Z})Y!@LBya&m$YSBn>wiO# znX)T;Je9tB}7f%14;+7UttenSas zK**d3_%g*^r%@gdb>)h-gM*)A7Dg zwcLgp_P%)<(CYPRPaWnt#>mSGHMsz}HL7j0c-QZO6=mW9fwsPy9u(Wy0V!`no&;K8 zb}5`#b(U9lvd+kXjvlby+3~y6g!yvWZo2MxJeP{9Y|gw+zW_h{+Myvb8lWaK%__PzfE>$Xt2^U zYSjrQ%y+A*Y%0#stJ-k;n>*%@8bhE53ZIC~v&R&kwU@a1j`2qfRWB?)wD9zxY7g8r zgnwtnbRdS}W661;R68KeuO3q>UwcBK+>U>qtaD&Kl7hGm&q2}3sIjU-^kFJFR5()9 zw=X;o@9Wj{?Tg!Cpwor_hCe4vIxlY(acQM`(hVF_EcYmS%8DjYS*`we;H-HQ+s~j_ zom9XMk08)G#34J#!p|MHzFt1i3**Gk67x&HpYI76_1JK_TLSnWaCPMPb zVC{`X;HdxFXm*iQc5knFDvZq6uD5ZMQhIE9$T&_>CBb9L48ZXmCNwB65!D!m_QHCb zMxPu{{}V8zt!8rKi^U?*SdN9Z*-Clq6QAZt$Sm@%?Ka%f2_vi)Mk{E&--=^8cg@Hp z!fe&~-FqPf_v3CYiKB3Zrb~OE%JH3h(_C=J81?~`wAzWQC2k$Jb`;HRAJaef2D!SJ zx4B~cq+7fyas~^p`mDH@g$s@ey=`@9-UQD9j?3s|GmvM(1Y8^9sk}&!RJK&#rD!=k z3FDK@OYntLZFa)`5sCZ0uAayio93q?pKM`$r{)rBQ6wha5fA7BK5U@`~sKDv0n6*?Iq54cE=H zx0tnl(I=Hvj^*T37+>a$i6zlPCTw(up*h@lR${q=EU=+o9BpI#a_xFJ*!j*_7Acue zw|O%A<)!&>AIo>JU+5E7^l;PHw#t*8rn(s&3jFSxz6@ud(uHmfs}PE9+devEa5D#H zJGKwZ4*phR{mE7r;0+&rkt($NUNsfdN|s!76;hTCIY=Xzd>Yh#`S?2G(k;Z`;|CGo z{Gdi#;NWQY;KoywzkC?h$-9EZrZQwrobz;-Rb~9O@gP{!AQ!jKPtptl+F{d^?aa+_ z?aT!~v&W$LD6{@yoJWJqv{+`-Kl_(jUAxhz6v%E$=%TS;;BEDVu`gB!&e;Dcz+ayd J*Bm1(`#-kDcuoKS literal 0 HcmV?d00001 diff --git a/img/playerStartFlag.png b/img/playerStartFlag.png index 11a8e72b970d14beda936bcd68e7acb1be7da02a..f2211d1ddad2a80ee4c4ad703a8df910fdbe2c2b 100644 GIT binary patch literal 4829 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 literal 8076 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' + this.label + '
'); + this.el = $('
' + this.determineReporterLabel() + '
'); this.valueEl = $('
null
'); this.el.append(this.valueEl); if (this.mode == 3) { diff --git a/js/Sprite.js b/js/Sprite.js index 026d17e..07d7621 100644 --- a/js/Sprite.js +++ b/js/Sprite.js @@ -73,7 +73,14 @@ var Sprite = function(data) { this.talkBubbleStyler = null; this.talkBubbleOn = false; + // HTML element for the ask bubbles + this.askInput = null; + this.askInputField = null; + this.askInputButton = null; + this.askInputOn = false; + // Internal variables used for rendering meshes. + this.askAnswer = null; //this is a private variable this.textures = []; this.materials = []; this.geometries = []; @@ -142,14 +149,26 @@ Sprite.prototype.attach = function(scene) { this.updateVisible(); this.updateTransform(); - this.talkBubble = $('
'); - this.talkBubble.css('display', 'none'); - this.talkBubbleBox = $('
'); - this.talkBubbleStyler = $('
'); - this.talkBubble.append(this.talkBubbleBox); - this.talkBubble.append(this.talkBubbleStyler); + if (! this.isStage) { + this.talkBubble = $('
'); + this.talkBubble.css('display', 'none'); + this.talkBubbleBox = $('
'); + this.talkBubbleStyler = $('
'); + this.talkBubble.append(this.talkBubbleBox); + this.talkBubble.append(this.talkBubbleStyler); + } + + this.askInput = $('
'); + this.askInput.css('display', 'none'); + this.askInputField = $('
'); + this.askInputTextField = $(''); + this.askInputField.append(this.askInputTextField); + this.askInputButton = $('
'); + this.askInput.append(this.askInputField); + this.askInput.append(this.askInputButton); runtime.scene.append(this.talkBubble); + runtime.scene.append(this.askInput); }; // Load sounds from the server and buffer them @@ -254,20 +273,22 @@ Sprite.prototype.onClick = function(evt) { }; Sprite.prototype.setVisible = function(v) { + if (v === true || v === false) { this.visible = v; this.updateVisible(); + } }; Sprite.prototype.updateLayer = function() { $(this.mesh).css('z-index', this.z); - if (this.talkBubble) this.talkBubble.css('z-index', this.z); + if (this.talkBubble) $(this.talkBubble).css('z-index', this.z); + if (this.askInput) this.askInput.css('z-index', this.z); }; Sprite.prototype.updateVisible = function() { $(this.mesh).css('display', this.visible ? 'inline' : 'none'); - if (this.talkBubbleOn) { - this.talkBubble.css('display', this.visible ? 'inline-block' : 'none'); - } + if (this.talkBubbleOn) this.talkBubble.css('display', this.visible ? 'inline-block' : 'none'); + if (this.askInputOn) this.askInput.css('display', this.visible ? 'inline-block' : 'none'); }; Sprite.prototype.updateTransform = function() { @@ -347,13 +368,21 @@ Sprite.prototype.showBubble = function(text, type) { this.talkBubble.css('left', xy[0] + 'px'); this.talkBubble.css('top', xy[1] + 'px'); - + this.talkBubble.removeClass('say-think-border'); + this.talkBubble.removeClass('ask-border'); + this.talkBubbleStyler.removeClass('bubble-say'); this.talkBubbleStyler.removeClass('bubble-think'); + this.talkBubbleStyler.removeClass('bubble-ask'); if (type == 'say') { + this.talkBubbleBox.addClass('say-think-border'); this.talkBubbleStyler.addClass('bubble-say'); } else if (type == 'think') { + this.talkBubbleBox.addClass('say-think-border'); this.talkBubbleStyler.addClass('bubble-think'); + } else if (type == 'doAsk') { + this.talkBubbleBox.addClass('ask-border'); + this.talkBubbleStyler.addClass('bubble-ask'); } if (this.visible) { @@ -367,6 +396,25 @@ Sprite.prototype.hideBubble = function() { this.talkBubble.css('display', 'none'); }; +Sprite.prototype.showAsk = function() { + this.askInputOn = true; + this.askInput.css('z-index', this.z); + this.askInput.css('left', '15px'); + this.askInput.css('right', '15px'); + this.askInput.css('bottom', '7px'); + this.askInput.css('height', '25px'); + + if (this.visible) { + this.askInput.css('display', 'inline-block'); + this.askInputTextField.focus(); + } +}; + +Sprite.prototype.hideAsk = function() { + this.askInputOn = false; + this.askInput.css('display', 'none'); +}; + Sprite.prototype.setXY = function(x, y) { this.scratchX = x; this.scratchY = y; diff --git a/js/Stage.js b/js/Stage.js index c425e10..8146e93 100644 --- a/js/Stage.js +++ b/js/Stage.js @@ -33,6 +33,7 @@ var Stage = function(data) { this.lineCanvas.width = 480; this.lineCanvas.height = 360; this.lineCache = this.lineCanvas.getContext('2d'); + this.isStage = true; Sprite.call(this, data); }; diff --git a/js/primitives/LooksPrims.js b/js/primitives/LooksPrims.js index e56f646..b63c7f2 100644 --- a/js/primitives/LooksPrims.js +++ b/js/primitives/LooksPrims.js @@ -43,6 +43,9 @@ LooksPrims.prototype.addPrimsTo = function(primTable) { primTable['setGraphicEffect:to:'] = this.primSetEffect; primTable['filterReset'] = this.primClearEffects; + primTable['doAsk'] = this.primDoAsk; + primTable['answer'] = this.primAnswer; + primTable['say:'] = function(b) { showBubble(b, 'say'); }; primTable['say:duration:elapsed:from:'] = function(b) { showBubbleAndWait(b, 'say'); }; primTable['think:'] = function(b) { showBubble(b, 'think'); }; @@ -170,6 +173,17 @@ LooksPrims.prototype.primClearEffects = function(b) { s.updateFilters(); }; +LooksPrims.prototype.primDoAsk= function(b) { + showBubble(b, "doAsk"); + var s = interp.targetSprite(); + if (s != null) s.showAsk(); +}; + +LooksPrims.prototype.primAnswer = function() { + var s = interp.targetSprite(); + return ((s != null) ? s.answer : undefined); +}; + var showBubble = function(b, type) { var s = interp.targetSprite(); if (s != null) s.showBubble(interp.arg(b, 0), type); diff --git a/player.css b/player.css index 3fcff6c..40ca47e 100644 --- a/player.css +++ b/player.css @@ -398,7 +398,7 @@ button#trigger-stop:hover { } /* Say/think bubble styles */ - .bubble-container { +.bubble-container { position: absolute; } .bubble { @@ -407,7 +407,6 @@ button#trigger-stop:hover { max-width: 120px; min-width: 40px; padding: 6px 11px 6px 11px; - border: 3px solid rgb(160, 160, 160); border-radius: 10px; background: #fff; font-family: sans-serif; @@ -416,6 +415,20 @@ button#trigger-stop:hover { color: #000; text-align: center; } +.bubble.say-think-border { + border: 3px solid rgb(160, 160, 160); +} +.bubble.ask-border, .ask-container { + border: 3px solid rgb(74, 173, 222); +} +.bubble-ask { + position: absolute; + margin-top: -3px; + margin-left: 8px; + width: 44px; + height: 18px; + background: url(img/ask-bottom.png) transparent no-repeat; +} .bubble-say { position: absolute; margin-top: -3px; @@ -432,3 +445,33 @@ button#trigger-stop:hover { height: 19px; background: url(img/think-bottom.png) transparent no-repeat; } +.ask-container { + position: absolute; + display: inline-block; + padding: 5px 0px 0px 5px; + border-radius: 5px; + background: #fff; + font-family: sans-serif; + font-weight: bold; + font-size: 14px; + color: #000; +} +.ask-container .ask-field .ask-text-field { + width: 405px; + height: 16px; + font-family: sans-serif; + font-weight: light; + font-size: 12px; + background: #EAEAEA; +} + +.ask-container .ask-button { + position: absolute; + right: 2px; + top: 2px; + width: 25px; + height: 25px; + background: url(img/ask-button.png) transparent no-repeat; +} + + diff --git a/test/artifacts/IOMock.js b/test/artifacts/IOMock.js new file mode 100644 index 0000000..6a7a118 --- /dev/null +++ b/test/artifacts/IOMock.js @@ -0,0 +1,25 @@ +'use strict'; + +var ioMock = function() { + var args = createArgs(arguments); + + function getArgs(argKey) { + return ((argKey in args) ? args[argKey] : null); + } + + function createArgs(methodArgs) { + var args = {}; + if (methodArgs.length) { + _.each(methodArgs, function(newObject) { + _.each(newObject, function(value, key) { + args[key] = value; + }); + }); + } + return args; + } + + return { + 'getCount' : function() { return getArgs('getCount'); } + } +}; diff --git a/test/artifacts/TargetMock.js b/test/artifacts/TargetMock.js index 9121a00..8071a39 100644 --- a/test/artifacts/TargetMock.js +++ b/test/artifacts/TargetMock.js @@ -2,7 +2,9 @@ var targetMock = function() { return { - 'showBubble' : function() {} + 'showBubble' : function() {}, + 'showAsk' : function() {}, + 'answer' : 22 }; } diff --git a/test/artifacts/ask-artifact.js b/test/artifacts/ask-artifact.js index 4f0852a..654a07d 100644 --- a/test/artifacts/ask-artifact.js +++ b/test/artifacts/ask-artifact.js @@ -1,7 +1,10 @@ -'use strict'; - var sensingData = { "objName": "Stage", + "variables": [{ + "name": "myAnswer", + "value": 0, + "isPersistent": false + }], "costumes": [{ "costumeName": "backdrop1", "baseLayerID": -1, @@ -16,6 +19,15 @@ var sensingData = { "videoAlpha": 0.5, "children": [{ "objName": "Sprite1", + "variables": [{ + "name": "myAnswer2", + "value": 0, + "isPersistent": false + }, { + "name": "answer", + "value": 0, + "isPersistent": false + }], "scripts": [[42, 40.5, [["whenGreenFlag"], ["doAsk", "What's your name?"]]], [44.5, 155.5, diff --git a/test/artifacts/reporterValues.js b/test/artifacts/reporterValues.js new file mode 100644 index 0000000..484b990 --- /dev/null +++ b/test/artifacts/reporterValues.js @@ -0,0 +1,91 @@ +'use Strict;' + +var ReporterValues = function() { + return { + 'getStageVariables': function() { + return { + 'cmd' : "getVar:", + 'color' : 15629590, + 'isDiscrete' : true, + 'mode' : 1, + 'param' : "myAnswer", + 'sliderMax' : 100, + 'sliderMin' : 0, + 'target' : "Stage", + 'visible' : true, + 'x' : 5, + 'y' : 5, + }; + } + } +}; +/* +cmd + "getVar:" + +color + 15629590 + +isDiscrete + true + +mode + 1 + +param + "myAnswer2" + +sliderMax + 100 + +sliderMin + 0 + +target + "Sprite1" + +visible + true + +x + 5 + +y + 32 +*/ + +/* + +cmd + "getVar:" + +color + 15629590 + +isDiscrete + true + +mode + 1 + +param + "answer" + +sliderMax + 100 + +sliderMin + 0 + +target + "Sprite1" + +visible + true + +x + 5 + +y + 59 +*/ diff --git a/test/unit/looksPrimitiveSpec.js b/test/unit/looksPrimitiveSpec.js index cadbc6e..a46f747 100644 --- a/test/unit/looksPrimitiveSpec.js +++ b/test/unit/looksPrimitiveSpec.js @@ -1,23 +1,65 @@ /* jasmine specs for primitives/LooksPrims.js go here */ describe ('LooksPrims', function() { - var looksPrims; + var looksPrims, targetSpriteMock; beforeEach(function() { looksPrims = LooksPrims; + targetSpriteMock = targetMock(); }); - describe('showBubble', function(){ - var sayBlock, targetSpriteMock; + describe('showBubble for Say', function(){ + var sayBlock; beforeEach(function() { sayBlock = {'args': ['what to say']}; - targetSpriteMock = targetMock(); interp = interpreterMock({'targetSprite': targetSpriteMock }, {'arg': sayBlock}); - }); - it('should return do something', function() { + + it('should call the showBubble method on the targetedSprite', function() { spyOn(targetSpriteMock, "showBubble"); showBubble(sayBlock, "say"); expect(targetSpriteMock.showBubble).toHaveBeenCalled; }); }); + + describe('showBubble for Think', function(){ + var thinkBlock; + beforeEach(function() { + thinkBlock = {'args': ['what to think']}; + interp = interpreterMock({'targetSprite': targetSpriteMock }, {'arg': thinkBlock}); + }); + + it('should call the showBubble method on the targetedSprite', function() { + spyOn(targetSpriteMock, "showBubble"); + showBubble(thinkBlock, "think"); + expect(targetSpriteMock.showBubble).toHaveBeenCalled; + }); + }); + + + describe('showBubble for Ask', function(){ + var askBlock; + beforeEach(function() { + askBlock = {'args': 'what to ask'}; + interp = interpreterMock({'targetSprite': targetSpriteMock }, {'arg': askBlock}); + + }); + + it('should call the showBubble method on the targetedSprite', function() { + spyOn(targetSpriteMock, "showBubble"); + spyOn(targetSpriteMock, "showAsk"); + looksPrims.prototype.primDoAsk(askBlock); + expect(targetSpriteMock.showBubble).toHaveBeenCalled; + expect(targetSpriteMock.showAsk).toHaveBeenCalled; + }); + }); + + describe('primAnswer', function(){ + beforeEach(function() { + interp = interpreterMock({'targetSprite': targetSpriteMock }); + }); + + it('should return the answer variable from the targetedSprite', function() { + expect(looksPrims.prototype.primAnswer()).toBe(22); + }); + }); }); diff --git a/test/unit/reporterSpec.js b/test/unit/reporterSpec.js new file mode 100644 index 0000000..c879f58 --- /dev/null +++ b/test/unit/reporterSpec.js @@ -0,0 +1,96 @@ +/* jasmine specs for Reporter.js go here */ + +describe ('Reporter', function() { + var reporter, reporterValues; + + beforeEach(function() { + reporter = Reporter; + reporterValues = new ReporterValues(); + }); + + describe('Instantization variables', function() { + var initReporter; + beforeEach(function() { + io = new ioMock({'getCount': 4}); + initReporter = new reporter(reporterValues.getStageVariables()); + }); + + describe('Reporter Variables', function() { + it('should have a cmd variable', function() { + expect(initReporter.cmd).toBe('getVar:'); + }); + + it('should have a color variable', function() { + expect(initReporter.color).toBe(15629590); + }); + + it('should have a isDiscrete variable', function() { + expect(initReporter.isDiscrete).toBe(true); + }); + + it('should have a mode variable', function() { + expect(initReporter.mode).toBe(1); + }); + + it('should have a param variable', function() { + expect(initReporter.param).toBe('myAnswer'); + }); + + it('should have a sliderMax variable', function() { + expect(initReporter.sliderMax).toBe(100); + }); + + it('should have a sliderMin variable', function() { + expect(initReporter.sliderMin).toBe(0); + }); + + it('should have a target variable', function() { + expect(initReporter.target).toBe('Stage'); + }); + + it('should have a visible variable', function() { + expect(initReporter.visible).toBe(true); + }); + + it('should have a x variable', function() { + expect(initReporter.x).toBe(5); + }); + + it('should have a y variable', function() { + expect(initReporter.y).toBe(5); + }); + + it('should have a z variable', function() { + expect(initReporter.z).toBe(4); + }); + + it('should have an el variable', function() { + expect(initReporter.el).toBe(null); + }); + + it('should have an valueEl variable', function() { + expect(initReporter.valueEl).toBe(null); + }); + + it('should have an slider variable', function() { + expect(initReporter.slider).toBe(null); + }); + }); + }); + describe('determineReporterLabel', function() { + + it('should return a stage variable', function() { + reporter.prototype.target = "Stage"; + reporter.prototype.param = "myAnswer"; + expect(reporter.prototype.determineReporterLabel()).toBe('myAnswer'); + }); + + it('should return a sprite variable', function() { + reporter.prototype.target = "Sprite 1"; + reporter.prototype.param = "localAnswer"; + expect(reporter.prototype.determineReporterLabel()).toBe('Sprite 1: localAnswer'); + + }); + + }); +}); diff --git a/test/unit/spriteSpec.js b/test/unit/spriteSpec.js new file mode 100644 index 0000000..feeb11c --- /dev/null +++ b/test/unit/spriteSpec.js @@ -0,0 +1,352 @@ +/* jasmine specs for Sprite.js go here */ + +describe ('Sprite', function() { + var sprite; + + + beforeEach(function() { + sprite = Sprite; + }); + + describe('Instantization variables', function() { + var initSprite; + beforeEach(function() { + var spriteObject = sensingData.children[0]; + initSprite = new sprite(spriteObject); + }); + + describe('Sprite Variables', function() { + it('should have a visible variable', function() { + expect(initSprite.visible).toBe(true); + }); + }); + + describe('Pen Variables', function() { + it('should have a penIsDown variable', function() { + expect(initSprite.penIsDown).toBe(false); + }); + + it('should have a penWidth variable', function() { + expect(initSprite.penWidth).toBe(1); + }); + + it('should have a penHue variable', function() { + expect(initSprite.penHue).toBe(120); + }); + + it('should have a penShade variable', function() { + expect(initSprite.penShade).toBe(50); + }); + + it('should have a penColorCache variable', function() { + expect(initSprite.penColorCache).toBe(0x0000FF); + }); + }); + + describe('Ask Bubble', function() { + it('should have an askInput variable', function() { + expect(initSprite.askInput).toBe(null); + }); + + it('should have an askInputBox variable', function() { + expect(initSprite.askInputField).toBe(null); + }); + + it('should have an askInputStyler variable', function() { + expect(initSprite.askInputButton).toBe(null); + }); + + it('should have an askInputOn variable', function() { + expect(initSprite.askInputOn).toBe(false); + }); + + it('should have an answer variable', function() { + expect(initSprite.askAnswer).toBe(null); + }); + }); + }) + + describe('showBubble', function() { + var spriteProto; + beforeEach(function() { + spriteProto = sprite.prototype; + spriteProto.visible = true; + setFixtures('
'); + spriteProto.talkBubble = $('.bubble-container'); + spriteProto.talkBubble.css('display', 'none'); + spriteProto.talkBubbleBox = $('
'); + spriteProto.talkBubbleStyler = $('
'); + spriteProto.talkBubble.append(spriteProto.talkBubbleBox); + spriteProto.talkBubble.append(spriteProto.talkBubbleStyler); + }); + + describe('Say', function(){ + it('should call the showBubble method on the Sprite', function() { + var text = "What to say"; + spyOn(spriteProto, "getTalkBubbleXY").andReturn([50,50]);; + spriteProto.showBubble(text, "say"); + expect($('.bubble').html()).toBe(text); + expect($('.bubble-say').hasClass('bubble-say')).toBe(true); + expect($('.bubble').hasClass('say-think-border')).toBe(true); + expect($('.bubble-container').css('display')).toBe('inline-block'); + }); + }); + + describe('Think', function(){ + it('should call the showBubble method on the Sprite', function() { + var text = "What to think"; + spyOn(spriteProto, "getTalkBubbleXY").andReturn([50,50]);; + spriteProto.showBubble(text, "think"); + expect($('.bubble').html()).toBe(text); + expect($('.bubble-think').hasClass('bubble-think')).toBe(true); + expect($('.bubble').hasClass('say-think-border')).toBe(true); + expect($('.bubble-container').css('display')).toBe('inline-block'); + }); + }); + + describe('Ask', function(){ + it('should call the showBubble method on the Sprite', function() { + var text = "What to Ask"; + spyOn(spriteProto, "getTalkBubbleXY").andReturn([50,50]);; + spriteProto.showBubble(text, "doAsk"); + expect($('.bubble').html()).toBe(text); + expect($('.bubble-ask').hasClass('bubble-ask')).toBe(true); + expect($('.bubble').hasClass('ask-border')).toBe(true); + expect($('.bubble-container').css('display')).toBe('inline-block'); + }); + }); + + describe('Any Bubble with visible false', function(){ + it('should call the showBubble method on the Sprite and not display it', function() { + spriteProto.visible = false; + var text = "What to Ask"; + spyOn(spriteProto, "getTalkBubbleXY").andReturn([50,50]);; + spriteProto.showBubble(text, "doAsk"); + expect($('.bubble').html()).toBe(text); + expect($('.bubble-ask').hasClass('bubble-ask')).toBe(true); + expect($('.bubble').hasClass('ask-border')).toBe(true); + expect($('.bubble-container').css('display')).toBe('none'); + }); + }); + }); + + describe('hideBubble', function() { + var spriteProto; + beforeEach(function() { + spriteProto = sprite.prototype; + setFixtures('
'); + spriteProto.talkBubble = $('.bubble-container'); + spriteProto.talkBubble.css('display', 'inline'); + }); + + it('should hide the bubble', function() { + spriteProto.hideBubble(); + expect($('.bubble-container').css('display')).toBe('none'); + expect(spriteProto.talkBubbleOn).toBe(false); + + }); + }); + + describe('showAsk', function() { + var spriteProto; + beforeEach(function() { + spriteProto = sprite.prototype; + spriteProto.visible = true; + spriteProto.z = 22; + setFixtures('
'); + spriteProto.askInput= $('.ask-container'); + spriteProto.askInput.css('display','none'); + spriteProto.askInput.css('position','relative'); + spriteProto.askInputField = $('
'); + spriteProto.askInputTextField = $(''); + spriteProto.askInputField.append(spriteProto.askInputTextField); + spriteProto.askInputButton = $('
'); + spriteProto.askInput.append(spriteProto.askInputField); + spriteProto.askInput.append(spriteProto.askInputButton); + }); + + it('should show the ask input if visible is true', function() { + spriteProto.showAsk(); + expect($('.ask-container').css('display')).toBe('inline-block'); + expect($('.ask-container').css('z-index')).toBe('22'); + expect($('.ask-container').css('left')).toBe('15px'); + expect($('.ask-container').css('right')).toBe('15px'); + expect($('.ask-container').css('bottom')).toBe('7px'); + expect($('.ask-container').css('height')).toBe('25px'); + expect($('.ask-container').css('height')).toBe('25px'); + expect($('.ask-text-field').is(':focus')).toBe(true); + expect(spriteProto.askInputOn).toBe(true); + }); + + it('should not show the ask input if visible is false', function() { + spriteProto.visible = false; + spriteProto.showAsk(); + expect($('.ask-container').css('display')).toBe('none'); + expect($('.ask-text-field').is(':focus')).toBe(false); + }); + }); + + describe('hideAsk', function() { + var spriteProto; + beforeEach(function() { + spriteProto = sprite.prototype; + setFixtures('
'); + spriteProto.askInput = $('.ask-container'); + spriteProto.askInput.css('display', 'inline'); + }); + + it('should hide the ask input', function() { + spriteProto.hideAsk(); + expect($('.ask-container').css('display')).toBe('none'); + expect(spriteProto.askInputOn).toBe(false); + + }); + }); + + describe('updateLayer', function() { + var spriteProto; + beforeEach(function() { + spriteProto = sprite.prototype; + setFixtures('
'); + spriteProto.talkBubble = $('.bubble-container'); + spriteProto.talkBubble.css('position', 'relative'); + spriteProto.askInput = $('.ask-container'); + spriteProto.askInput.css('position', 'relative'); + spriteProto.mesh = $('.mesh'); + spriteProto.mesh.css('position', 'relative'); + spriteProto.z = 22; + }); + + it('should update the mesh z-index', function() { + expect($('.mesh').css('z-index')).toBe('auto'); + spriteProto.updateLayer(); + expect($('.mesh').css('z-index')).toBe('22'); + }); + + it('should update the talkBubble z-index', function() { + expect($('.bubble-container').css('z-index')).toBe('auto'); + spriteProto.updateLayer(); + expect($('.bubble-container').css('z-index')).toBe('22'); + }); + + it('should update the askInput z-index', function() { + expect($('.ask-container').css('z-index')).toBe('auto'); + spriteProto.updateLayer(); + expect($('.ask-container').css('z-index')).toBe('22'); + }); + }); + + describe('updateVisible', function() { + var spriteProto; + beforeEach(function() { + spriteProto = sprite.prototype; + setFixtures('
'); + spriteProto.talkBubble = $('.bubble-container'); + spriteProto.talkBubble.css('display', 'none'); + spriteProto.askInput = $('.ask-container'); + spriteProto.askInput.css('display', 'none'); + spriteProto.mesh = $('.mesh'); + spriteProto.mesh.css('display', 'none'); + }); + + describe('mesh', function() { + it('should update the mesh display on false', function() { + expect($('.mesh').css('display')).toBe('none'); + spriteProto.visible = false; + spriteProto.updateVisible(); + expect($('.mesh').css('display')).toBe('none'); + }); + + it('should update the mesh display on true', function() { + expect($('.mesh').css('display')).toBe('none'); + spriteProto.visible = true; + spriteProto.updateVisible(); + expect($('.mesh').css('display')).toBe('inline'); + }); + + }); + + describe('talkBubble', function() { + it('should update the talkBubble on talkBubble true and visible true', function() { + expect($('.bubble-container').css('display')).toBe('none'); + spriteProto.talkBubbleOn = true; + spriteProto.visible = true; + spriteProto.updateVisible(); + expect($('.bubble-container').css('display')).toBe('inline-block'); + }); + + it('should update the talkBubble on talkBubble false and visible true', function() { + expect($('.bubble-container').css('display')).toBe('none'); + spriteProto.talkBubbleOn = false; + spriteProto.visible = true; + spriteProto.updateVisible(); + expect($('.bubble-container').css('display')).toBe('none'); + }); + + it('should update the talkBubble on talkBubble true and visible false', function() { + expect($('.bubble-container').css('display')).toBe('none'); + spriteProto.talkBubbleOn = true; + spriteProto.visible = false; + spriteProto.updateVisible(); + expect($('.bubble-container').css('display')).toBe('none'); + }); + }); + + describe('askContainer', function() { + it('should update the askInput on askInput true and visible true', function() { + expect($('.ask-container').css('display')).toBe('none'); + spriteProto.askInputOn = true; + spriteProto.visible = true; + spriteProto.updateVisible(); + expect($('.ask-container').css('display')).toBe('inline-block'); + }); + + it('should update the askInput on askInput false and visible true', function() { + expect($('.ask-container').css('display')).toBe('none'); + spriteProto.askInputOn = false; + spriteProto.visible = true; + spriteProto.updateVisible(); + expect($('.ask-container').css('display')).toBe('none'); + }); + + it('should update the askInput on askInput true and visible false', function() { + expect($('.ask-container').css('display')).toBe('none'); + spriteProto.askInputOn = true; + spriteProto.visible = false; + spriteProto.updateVisible(); + expect($('.ask-container').css('display')).toBe('none'); + }); + }); + + }); + + describe('setVisible', function() { + var spriteProto; + beforeEach(function() { + spriteProto = sprite.prototype; + spyOn(spriteProto, "updateVisible"); + }); + + it('should set visible to true', function() { + expect(spriteProto.visible).toBe(false); + spriteProto.setVisible(true); + expect(spriteProto.visible).toBe(true); + expect(spriteProto.updateVisible).toHaveBeenCalled(); + }); + + it('should set visible to false', function() { + spriteProto.visible = true; + spriteProto.setVisible(false); + expect(spriteProto.visible).toBe(false); + expect(spriteProto.updateVisible).toHaveBeenCalled(); + }); + + it('should set take no action on an invalid character', function() { + spriteProto.visible = true; + spriteProto.setVisible('hello'); + expect(spriteProto.visible).toBe(true); + expect(spriteProto.updateVisible).not.toHaveBeenCalled(); + }); + + }); +}); diff --git a/test/unit/stageSpec.js b/test/unit/stageSpec.js new file mode 100644 index 0000000..330a451 --- /dev/null +++ b/test/unit/stageSpec.js @@ -0,0 +1,51 @@ +/* jasmine specs for Stage.js go here */ + +describe ('Stage', function() { + var stage; + + beforeEach(function() { + stage = Stage; + }); + + describe('Instantization variables', function() { + var initStage, lineCanvas; + beforeEach(function() { + spyOn(Sprite, "call"); + initStage = new stage(sensingData); + }); + + describe('Stage Variables', function() { + it('should have a z variable', function() { + expect(initStage.z).toBe(-2); + }); + + it('should have a penLayerLoaded variable', function() { + expect(initStage.penLayerLoaded).toBe(false); + }); + + it('should have a lineCanvas element', function() { + expect(initStage.lineCanvas).toBeDefined(); + }); + + it('should have a lineCanvas width', function() { + expect(initStage.lineCanvas.width).toBe(480); + }); + + it('should have a lineCanvas height', function() { + expect(initStage.lineCanvas.height).toBe(360); + }); + + it('should have a lineCache variable', function() { + expect(initStage.lineCache).toBeDefined(); + }); + + it('should have a isStage variable', function() { + expect(initStage.isStage).toBe(true); + }); + + it('should have called Sprite.call', function() { + expect(Sprite.call).toHaveBeenCalled(); + }); + }); + }); +}); From 6f54f52f3c99516ad64769159333ae48260c87c8 Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Sat, 8 Mar 2014 09:41:01 -0700 Subject: [PATCH 06/10] Added functionality to hide the doAsk prompt on a stopAll call with tests --- js/Runtime.js | 13 ++-- test/artifacts/InterpreterMock.js | 3 +- test/artifacts/RuntimeMock.js | 29 ++++++++ test/artifacts/SpriteMock.js | 27 ++++++++ test/artifacts/StageMock.js | 25 +++++++ test/artifacts/ThreadMock.js | 24 +++++++ test/unit/runTimeSpec.js | 107 ++++++++++++++++++++++++++++++ 7 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 test/artifacts/RuntimeMock.js create mode 100644 test/artifacts/SpriteMock.js create mode 100644 test/artifacts/StageMock.js create mode 100644 test/artifacts/ThreadMock.js create mode 100644 test/unit/runTimeSpec.js diff --git a/js/Runtime.js b/js/Runtime.js index b222af9..2b59751 100644 --- a/js/Runtime.js +++ b/js/Runtime.js @@ -88,19 +88,14 @@ Runtime.prototype.stopAll = function() { interp.activeThread = new Thread(null); interp.threads = []; stopAllSounds(); - // Hide reporters + // Hide sprite bubbles, resetFilters and doAsk prompts for (var s = 0; s < runtime.sprites.length; s++) { - if (runtime.sprites[s].hideBubble) { - runtime.sprites[s].hideBubble(); - } + if (runtime.sprites[s].hideBubble) runtime.sprites[s].hideBubble(); + if (runtime.sprites[s].resetFilters) runtime.sprites[s].resetFilters(); + if (runtime.sprites[s].hideAsk) runtime.sprites[s].hideAsk(); } // Reset graphic effects runtime.stage.resetFilters(); - for (var s = 0; s < runtime.sprites.length; s++) { - if (runtime.sprites[s].resetFilters) { - runtime.sprites[s].resetFilters(); - } - } }; // Step method for execution - called every 33 milliseconds diff --git a/test/artifacts/InterpreterMock.js b/test/artifacts/InterpreterMock.js index 7144e37..f48749e 100644 --- a/test/artifacts/InterpreterMock.js +++ b/test/artifacts/InterpreterMock.js @@ -21,6 +21,7 @@ var interpreterMock = function() { return { 'targetSprite' : function() { return getArgs('targetSprite'); }, - 'arg': function(block, index) { return getArgs('arg');} + 'arg': function(block, index) { return getArgs('arg');}, + 'activeThread': undefined } }; diff --git a/test/artifacts/RuntimeMock.js b/test/artifacts/RuntimeMock.js new file mode 100644 index 0000000..16200c0 --- /dev/null +++ b/test/artifacts/RuntimeMock.js @@ -0,0 +1,29 @@ +'use strict'; + +var runtimeMock = function() { + var args = createArgs(arguments); + + function getArgs(argKey) { + return ((argKey in args) ? args[argKey] : null); + } + + function createArgs(methodArgs) { + var args = {}; + if (methodArgs.length) { + _.each(methodArgs, function(newObject) { + _.each(newObject, function(value, key) { + args[key] = value; + }); + }); + } + return args; + } + + return { + 'sprites' : [ + new spriteMock() + ], + 'stage': new stageMock() + + } +}; diff --git a/test/artifacts/SpriteMock.js b/test/artifacts/SpriteMock.js new file mode 100644 index 0000000..935fe9d --- /dev/null +++ b/test/artifacts/SpriteMock.js @@ -0,0 +1,27 @@ +'use strict'; + +var spriteMock = function() { + var args = createArgs(arguments); + + function getArgs(argKey) { + return ((argKey in args) ? args[argKey] : null); + } + + function createArgs(methodArgs) { + var args = {}; + if (methodArgs.length) { + _.each(methodArgs, function(newObject) { + _.each(newObject, function(value, key) { + args[key] = value; + }); + }); + } + return args; + } + + return { + 'hideBubble' : function() { return getArgs('hideBubble'); }, + 'hideAsk': function() { return getArgs('hideAsk');}, + 'resetFilters': function() { return getArgs('resetFilters');} + } +}; diff --git a/test/artifacts/StageMock.js b/test/artifacts/StageMock.js new file mode 100644 index 0000000..3b76ced --- /dev/null +++ b/test/artifacts/StageMock.js @@ -0,0 +1,25 @@ +'use strict'; + +var stageMock = function() { + var args = createArgs(arguments); + + function getArgs(argKey) { + return ((argKey in args) ? args[argKey] : null); + } + + function createArgs(methodArgs) { + var args = {}; + if (methodArgs.length) { + _.each(methodArgs, function(newObject) { + _.each(newObject, function(value, key) { + args[key] = value; + }); + }); + } + return args; + } + + return { + 'resetFilters' : function() { return getArgs('resetFilters'); } + } +}; diff --git a/test/artifacts/ThreadMock.js b/test/artifacts/ThreadMock.js new file mode 100644 index 0000000..2d8dd30 --- /dev/null +++ b/test/artifacts/ThreadMock.js @@ -0,0 +1,24 @@ +'use strict'; + +var threadMock = function() { + var args = createArgs(arguments); + + function getArgs(argKey) { + return ((argKey in args) ? args[argKey] : null); + } + + function createArgs(methodArgs) { + var args = {}; + if (methodArgs.length) { + _.each(methodArgs, function(newObject) { + _.each(newObject, function(value, key) { + args[key] = value; + }); + }); + } + return args; + } + + return { + } +}; diff --git a/test/unit/runTimeSpec.js b/test/unit/runTimeSpec.js new file mode 100644 index 0000000..906247b --- /dev/null +++ b/test/unit/runTimeSpec.js @@ -0,0 +1,107 @@ +/* jasmine specs for Runtime.js go here */ + +describe ('Runtime', function() { + var runtimeObj; + + beforeEach(function() { + runtimeObj = Runtime; + }); + + describe('Instantization variables', function() { + var initRuntime, lineCanvas; + beforeEach(function() { + initRuntime = new runtimeObj(); + }); + + describe('Runtime Variables', function() { + it('should have a scene variable', function() { + expect(initRuntime.scene).toBe(null); + }); + + it('should have a sprites array', function() { + expect(initRuntime.sprites).toEqual([]); + }); + + it('should have a reporters array', function() { + expect(initRuntime.reporters).toEqual([]); + }); + + it('should have a keysDown array', function() { + expect(initRuntime.keysDown).toEqual([]); + }); + + it('should have a mouseDown variable', function() { + expect(initRuntime.mouseDown).toBe(false); + }); + + it('should have a mousePos array', function() { + expect(initRuntime.mousePos).toEqual([0,0]); + }); + + it('should have an audioContext variable', function() { + expect(initRuntime.audioContext).toBe(null); + }); + + it('should have an audoGain variable', function() { + expect(initRuntime.audioGain).toBe(null); + }); + + it('should have an audioPlaying array', function() { + expect(initRuntime.audioPlaying).toEqual([]); + }); + + it('should have a notesPlaying array', function() { + expect(initRuntime.notesPlaying).toEqual([]); + }); + + it('should have a projectLoaded variable', function() { + expect(initRuntime.projectLoaded).toBe(false); + }); + }); + }); + + describe('Stop All', function() { + beforeEach(function() { + runtime = new runtimeMock + spyOn(window, "stopAllSounds"); + spyOn(runtime.stage, "resetFilters"); + spyOn(runtime.sprites[0], "hideBubble"); + spyOn(runtime.sprites[0], "resetFilters"); + spyOn(runtime.sprites[0], "hideAsk"); + Thread = threadMock; + interp = new interpreterMock(); + }); + + it('should call a new Thread Object', function() { + runtimeObj.prototype.stopAll(); + expect(interp.activeThread).toEqual({}); + }); + + it('should call a blank thread array ', function() { + runtimeObj.prototype.stopAll(); + expect(interp.activeThread).toEqual([]); + }); + + it('should call stopAllSounds', function() { + runtimeObj.prototype.stopAll(); + expect(window.stopAllSounds).toHaveBeenCalled(); + }); + + it('should call sprites.hideBubble', function() { + runtimeObj.prototype.stopAll(); + expect(runtime.sprites[0].hideBubble).toHaveBeenCalled(); + }); + + it('should call sprites.resetFilters', function() { + runtimeObj.prototype.stopAll(); + expect(runtime.sprites[0].resetFilters).toHaveBeenCalled(); + }); + + it('should call sprites.hideAsk', function() { + runtimeObj.prototype.stopAll(); + expect(runtime.sprites[0].hideAsk).toHaveBeenCalled(); + }); + + }); + +}); From e59b279be11bd20bdfce0b7cb4a8578d838f8102 Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Sun, 9 Mar 2014 11:59:38 -0600 Subject: [PATCH 07/10] updates to finish doAsk --- js/Interpreter.js | 14 +++++ js/Reporter.js | 12 +++- js/Sprite.js | 23 ++++++-- js/Stage.js | 1 + js/primitives/LooksPrims.js | 18 +----- js/primitives/SensingPrims.js | 18 ++++++ test/artifacts/InterpreterMock.js | 3 +- test/artifacts/StageMock.js | 3 +- test/artifacts/TargetMock.js | 2 +- test/artifacts/TestHelpers.js | 5 ++ test/artifacts/ThreadMock.js | 1 + test/unit/interpreterSpec.js | 94 +++++++++++++++++++++++++++++++ test/unit/looksPrimitiveSpec.js | 24 ++------ test/unit/reporterSpec.js | 14 ++++- test/unit/runTimeSpec.js | 10 +++- test/unit/sensingPrimitiveSpec.js | 31 ++++++++++ test/unit/spriteSpec.js | 76 ++++++++++++++++++++----- test/unit/stageSpec.js | 4 ++ test/unit/threadSpec.js | 50 ++++++++++++++++ 19 files changed, 341 insertions(+), 62 deletions(-) create mode 100644 test/artifacts/TestHelpers.js create mode 100644 test/unit/interpreterSpec.js create mode 100644 test/unit/threadSpec.js diff --git a/js/Interpreter.js b/js/Interpreter.js index c566e0f..310599f 100644 --- a/js/Interpreter.js +++ b/js/Interpreter.js @@ -40,6 +40,7 @@ var Thread = function(block, target) { this.tmp = null; // used for thread operations like Timer this.tmpObj = []; // used for Sprite operations like glide this.firstTime = true; + this.paused = false; }; var Interpreter = function() { @@ -126,6 +127,13 @@ Interpreter.prototype.stepThreads = function() { } }; +Interpreter.prototype.pauseActiveThread = function() { + var self = this; + var timeoutId = setTimeout(function () { + (self.activeThread.paused) ? self.pauseActiveThread() : clearTimeout(timeoutId); + }, 1000); +} + Interpreter.prototype.stepActiveThread = function() { // Run the active thread until it yields. if (typeof(this.activeThread) == 'undefined') { @@ -135,6 +143,8 @@ Interpreter.prototype.stepActiveThread = function() { if (b == null) return; this.yield = false; while (true) { + if (this.activeThread.paused) return; + ++this.opCount; // Advance the "program counter" to the next block before running the primitive. // Control flow primitives (e.g. if) may change activeThread.nextBlock. @@ -247,6 +257,10 @@ Interpreter.prototype.targetSprite = function() { return this.activeThread.target; }; +Interpreter.prototype.targetStage = function() { + return runtime.stage; +}; + // Timer Interpreter.prototype.startTimer = function(secs) { var waitMSecs = 1000 * secs; diff --git a/js/Reporter.js b/js/Reporter.js index c55f0d2..f0f58f6 100644 --- a/js/Reporter.js +++ b/js/Reporter.js @@ -29,14 +29,19 @@ var Reporter = function(data) { this.y = data.y; this.z = io.getCount(); + //Set the label after hydrating the cmd and param variables + this.label = this.determineReporterLabel(); + this.el = null; // jQuery Element for the outer box this.valueEl = null; // jQ element containing the reporter value this.slider = null; // slider jQ element }; Reporter.prototype.determineReporterLabel = function() { - if (this.target === 'Stage') { + if (this.target === 'Stage' && this.cmd === "getVar:") { return this.param; + } else if (this.target === 'Stage' && this.param === null) { + return this.cmd; } else { return this.target + ': ' + this.param; } @@ -46,7 +51,7 @@ Reporter.prototype.attach = function(scene) { switch (this.mode) { case 1: // Normal case 3: // Slider - this.el = $('
' + this.determineReporterLabel() + '
'); + this.el = $('
' + this.label + '
'); this.valueEl = $('
null
'); this.el.append(this.valueEl); if (this.mode == 3) { @@ -84,6 +89,9 @@ Reporter.prototype.update = function() { var newValue = ''; var target = runtime.spriteNamed(this.target); switch (this.cmd) { + case 'answer': + newValue = target.askAnswer; + break; case 'getVar:': newValue = target.variables[this.param]; break; diff --git a/js/Sprite.js b/js/Sprite.js index 07d7621..b00065d 100644 --- a/js/Sprite.js +++ b/js/Sprite.js @@ -80,7 +80,6 @@ var Sprite = function(data) { this.askInputOn = false; // Internal variables used for rendering meshes. - this.askAnswer = null; //this is a private variable this.textures = []; this.materials = []; this.geometries = []; @@ -161,9 +160,10 @@ Sprite.prototype.attach = function(scene) { this.askInput = $('
'); this.askInput.css('display', 'none'); this.askInputField = $('
'); - this.askInputTextField = $(''); + this.askInputTextField = $(''); this.askInputField.append(this.askInputTextField); this.askInputButton = $('
'); + this.bindDoAskButton(); this.askInput.append(this.askInputField); this.askInput.append(this.askInputButton); @@ -368,8 +368,8 @@ Sprite.prototype.showBubble = function(text, type) { this.talkBubble.css('left', xy[0] + 'px'); this.talkBubble.css('top', xy[1] + 'px'); - this.talkBubble.removeClass('say-think-border'); - this.talkBubble.removeClass('ask-border'); + this.talkBubbleBox.removeClass('say-think-border'); + this.talkBubbleBox.removeClass('ask-border'); this.talkBubbleStyler.removeClass('bubble-say'); this.talkBubbleStyler.removeClass('bubble-think'); @@ -412,9 +412,24 @@ Sprite.prototype.showAsk = function() { Sprite.prototype.hideAsk = function() { this.askInputOn = false; + this.askInputTextField.val(''); this.askInput.css('display', 'none'); }; +Sprite.prototype.bindDoAskButton = function() { + var self = this; + this.askInputButton.on("keypress click", function(e){ + var eType = e.type; + if (eType === 'click' || (eType === 'keypress' && e.which === 13)) { + var stage = interp.targetStage(); + stage.askAnswer = $(self.askInputTextField).val(); + self.hideBubble(); + self.hideAsk(); + interp.activeThread.paused = false; + } + }); +}; + Sprite.prototype.setXY = function(x, y) { this.scratchX = x; this.scratchY = y; diff --git a/js/Stage.js b/js/Stage.js index 8146e93..e433955 100644 --- a/js/Stage.js +++ b/js/Stage.js @@ -34,6 +34,7 @@ var Stage = function(data) { this.lineCanvas.height = 360; this.lineCache = this.lineCanvas.getContext('2d'); this.isStage = true; + this.askAnswer = ""; //this is a private variable and should be blank Sprite.call(this, data); }; diff --git a/js/primitives/LooksPrims.js b/js/primitives/LooksPrims.js index b63c7f2..47a7823 100644 --- a/js/primitives/LooksPrims.js +++ b/js/primitives/LooksPrims.js @@ -43,9 +43,6 @@ LooksPrims.prototype.addPrimsTo = function(primTable) { primTable['setGraphicEffect:to:'] = this.primSetEffect; primTable['filterReset'] = this.primClearEffects; - primTable['doAsk'] = this.primDoAsk; - primTable['answer'] = this.primAnswer; - primTable['say:'] = function(b) { showBubble(b, 'say'); }; primTable['say:duration:elapsed:from:'] = function(b) { showBubbleAndWait(b, 'say'); }; primTable['think:'] = function(b) { showBubble(b, 'think'); }; @@ -173,25 +170,14 @@ LooksPrims.prototype.primClearEffects = function(b) { s.updateFilters(); }; -LooksPrims.prototype.primDoAsk= function(b) { - showBubble(b, "doAsk"); - var s = interp.targetSprite(); - if (s != null) s.showAsk(); -}; - -LooksPrims.prototype.primAnswer = function() { - var s = interp.targetSprite(); - return ((s != null) ? s.answer : undefined); -}; - var showBubble = function(b, type) { var s = interp.targetSprite(); - if (s != null) s.showBubble(interp.arg(b, 0), type); + if (s !== null) s.showBubble(interp.arg(b, 0), type); }; var showBubbleAndWait = function(b, type) { var s = interp.targetSprite(); - if (s == null) return; + if (s === null) return; if (interp.activeThread.firstTime) { var text = interp.arg(b, 0); var secs = interp.numarg(b, 1); diff --git a/js/primitives/SensingPrims.js b/js/primitives/SensingPrims.js index 81e0414..325cbb5 100644 --- a/js/primitives/SensingPrims.js +++ b/js/primitives/SensingPrims.js @@ -22,6 +22,9 @@ SensingPrims.prototype.addPrimsTo = function(primTable) { primTable['touchingColor:'] = this.primTouchingColor; primTable['color:sees:'] = this.primColorTouchingColor; + primTable['doAsk'] = this.primDoAsk; + primTable['answer'] = this.primAnswer; + primTable['keyPressed:'] = this.primKeyPressed; primTable['mousePressed'] = function(b) { return runtime.mouseDown; }; primTable['mouseX'] = function(b) { return runtime.mousePos[0]; }; @@ -174,6 +177,21 @@ var stageColorByColorHitTest = function(target, myColor, otherColor) { return false; }; +SensingPrims.prototype.primDoAsk= function(b) { + showBubble(b, "doAsk"); + var s = interp.targetSprite(); + if (s !== null) { + interp.activeThread.paused = true; + s.showAsk(); + } +}; + +SensingPrims.prototype.primAnswer = function(b) { + var s = interp.targetStage(); + return (s !== null ? s.askAnswer : undefined); +}; + + SensingPrims.prototype.primKeyPressed = function(b) { var key = interp.arg(b, 0); var ch = key.charCodeAt(0); diff --git a/test/artifacts/InterpreterMock.js b/test/artifacts/InterpreterMock.js index f48749e..bd2058f 100644 --- a/test/artifacts/InterpreterMock.js +++ b/test/artifacts/InterpreterMock.js @@ -22,6 +22,7 @@ var interpreterMock = function() { return { 'targetSprite' : function() { return getArgs('targetSprite'); }, 'arg': function(block, index) { return getArgs('arg');}, - 'activeThread': undefined + 'activeThread': new threadMock(), + 'targetStage': function() { var rtMock = new runtimeMock(); return rtMock.stage} } }; diff --git a/test/artifacts/StageMock.js b/test/artifacts/StageMock.js index 3b76ced..2db827a 100644 --- a/test/artifacts/StageMock.js +++ b/test/artifacts/StageMock.js @@ -20,6 +20,7 @@ var stageMock = function() { } return { - 'resetFilters' : function() { return getArgs('resetFilters'); } + 'resetFilters' : function() { return getArgs('resetFilters'); }, + 'askAnswer' : 12 } }; diff --git a/test/artifacts/TargetMock.js b/test/artifacts/TargetMock.js index 8071a39..e017a9d 100644 --- a/test/artifacts/TargetMock.js +++ b/test/artifacts/TargetMock.js @@ -4,7 +4,7 @@ var targetMock = function() { return { 'showBubble' : function() {}, 'showAsk' : function() {}, - 'answer' : 22 + 'askAnswer' : 22 }; } diff --git a/test/artifacts/TestHelpers.js b/test/artifacts/TestHelpers.js new file mode 100644 index 0000000..d6fe08f --- /dev/null +++ b/test/artifacts/TestHelpers.js @@ -0,0 +1,5 @@ +'use strict'; + +var deepCopy = function(object) { + return jQuery.extend(true, {}, object); +} diff --git a/test/artifacts/ThreadMock.js b/test/artifacts/ThreadMock.js index 2d8dd30..fe506c3 100644 --- a/test/artifacts/ThreadMock.js +++ b/test/artifacts/ThreadMock.js @@ -20,5 +20,6 @@ var threadMock = function() { } return { + 'paused' : getArgs('paused') } }; diff --git a/test/unit/interpreterSpec.js b/test/unit/interpreterSpec.js new file mode 100644 index 0000000..802db99 --- /dev/null +++ b/test/unit/interpreterSpec.js @@ -0,0 +1,94 @@ +/* jasmine specs for Interpreter.js go here */ + +describe ('Interpreter', function() { + var interp; + + beforeEach(function() { + interp = Interpreter; + }); + + describe('Instantization variables', function() { + var initInterp, realThread, realTimer; + beforeEach(function() { + realThread = Thread; + realTimer = Timer; + Thread = threadMock; + Timer = function() {}; + initInterp = new interp(); + }); + + afterEach(function() { + Thread = realThread; + Timer = realTimer; + }); + + describe('Interpreter Variables', function() { + it('should have a primitiveTable collection', function() { + expect(initInterp.primitiveTable).toEqual({}); + }); + + it('should have a variables collection', function() { + expect(initInterp.variables).toEqual({}); + }); + + it('should have a threads array', function() { + expect(initInterp.threads).toEqual([]); + }); + + it('should have an activeThread variable', function() { + expect(initInterp.activeThread).toEqual(threadMock()); + }); + + it('should have a WorkTime variable', function() { + expect(initInterp.WorkTime).toBe(30); + }); + + it('should have a currentMSecs variable', function() { + expect(initInterp.currentMSecs).toBe(null); + }); + + it('should have a timer variable', function() { + expect(initInterp.timer).toEqual({}); + }); + + it('should have a yield variable', function() { + expect(initInterp.yield).toBe(false); + }); + + it('should have a doRedraw variable', function() { + expect(initInterp.doRedraw).toBe(false); + }); + + it('should have an opCount variable', function() { + expect(initInterp.opCount).toBe(0); + }); + + it('should have a debugOps variable', function() { + expect(initInterp.debugOps).toBe(false); + }); + + it('should have a debugFunc variable', function() { + expect(initInterp.debugFunc).toBe(null); + }); + + it('should have an opCount2 variable', function() { + expect(initInterp.opCount2).toBe(0); + }); + }); + }); + + describe('PauseActiveThread', function() { + it('should call clearTimeout', function() { + spyOn(window, "setTimeout"); + interp.prototype.pauseActiveThread(); + expect(window.setTimeout).toHaveBeenCalled(); + }); + }); + + describe('TargetStage', function() { + it('should return the target.stage object', function() { + runtime = new runtimeMock(); + expect(interp.prototype.targetStage()).toEqual(runtime.stage); + }); + }); +}); diff --git a/test/unit/looksPrimitiveSpec.js b/test/unit/looksPrimitiveSpec.js index a46f747..fab10d5 100644 --- a/test/unit/looksPrimitiveSpec.js +++ b/test/unit/looksPrimitiveSpec.js @@ -17,7 +17,7 @@ describe ('LooksPrims', function() { it('should call the showBubble method on the targetedSprite', function() { spyOn(targetSpriteMock, "showBubble"); showBubble(sayBlock, "say"); - expect(targetSpriteMock.showBubble).toHaveBeenCalled; + expect(targetSpriteMock.showBubble).toHaveBeenCalledWith({args:['what to say']}, 'say'); }); }); @@ -31,35 +31,21 @@ describe ('LooksPrims', function() { it('should call the showBubble method on the targetedSprite', function() { spyOn(targetSpriteMock, "showBubble"); showBubble(thinkBlock, "think"); - expect(targetSpriteMock.showBubble).toHaveBeenCalled; + expect(targetSpriteMock.showBubble).toHaveBeenCalledWith({args:['what to think']}, 'think'); }); }); - describe('showBubble for Ask', function(){ var askBlock; beforeEach(function() { - askBlock = {'args': 'what to ask'}; + askBlock = {'args': ['what to ask']}; interp = interpreterMock({'targetSprite': targetSpriteMock }, {'arg': askBlock}); - }); it('should call the showBubble method on the targetedSprite', function() { spyOn(targetSpriteMock, "showBubble"); - spyOn(targetSpriteMock, "showAsk"); - looksPrims.prototype.primDoAsk(askBlock); - expect(targetSpriteMock.showBubble).toHaveBeenCalled; - expect(targetSpriteMock.showAsk).toHaveBeenCalled; - }); - }); - - describe('primAnswer', function(){ - beforeEach(function() { - interp = interpreterMock({'targetSprite': targetSpriteMock }); - }); - - it('should return the answer variable from the targetedSprite', function() { - expect(looksPrims.prototype.primAnswer()).toBe(22); + showBubble(askBlock, "ask"); + expect(targetSpriteMock.showBubble).toHaveBeenCalledWith({args:['what to ask']}, 'ask'); }); }); }); diff --git a/test/unit/reporterSpec.js b/test/unit/reporterSpec.js index c879f58..7a51ebd 100644 --- a/test/unit/reporterSpec.js +++ b/test/unit/reporterSpec.js @@ -64,6 +64,10 @@ describe ('Reporter', function() { expect(initReporter.z).toBe(4); }); + it('should have a label variable', function() { + expect(initReporter.label).toBe('myAnswer'); + }); + it('should have an el variable', function() { expect(initReporter.el).toBe(null); }); @@ -77,19 +81,27 @@ describe ('Reporter', function() { }); }); }); - describe('determineReporterLabel', function() { + describe('determineReporterLabel', function() { it('should return a stage variable', function() { reporter.prototype.target = "Stage"; reporter.prototype.param = "myAnswer"; + reporter.prototype.cmd = "getVar:"; expect(reporter.prototype.determineReporterLabel()).toBe('myAnswer'); }); it('should return a sprite variable', function() { reporter.prototype.target = "Sprite 1"; reporter.prototype.param = "localAnswer"; + reporter.prototype.cmd = "getVar:"; expect(reporter.prototype.determineReporterLabel()).toBe('Sprite 1: localAnswer'); + }); + it('should return a stage answer variable', function() { + reporter.prototype.target = "Stage"; + reporter.prototype.param = null; + reporter.prototype.cmd = "answer"; + expect(reporter.prototype.determineReporterLabel()).toBe('answer'); }); }); diff --git a/test/unit/runTimeSpec.js b/test/unit/runTimeSpec.js index 906247b..e30f600 100644 --- a/test/unit/runTimeSpec.js +++ b/test/unit/runTimeSpec.js @@ -61,6 +61,7 @@ describe ('Runtime', function() { }); describe('Stop All', function() { + var realThread; beforeEach(function() { runtime = new runtimeMock spyOn(window, "stopAllSounds"); @@ -68,18 +69,23 @@ describe ('Runtime', function() { spyOn(runtime.sprites[0], "hideBubble"); spyOn(runtime.sprites[0], "resetFilters"); spyOn(runtime.sprites[0], "hideAsk"); + realThread = Thread; Thread = threadMock; interp = new interpreterMock(); }); + afterEach(function() { + Thread = realThread; + }); + it('should call a new Thread Object', function() { runtimeObj.prototype.stopAll(); - expect(interp.activeThread).toEqual({}); + expect(interp.activeThread).toEqual(new threadMock()); }); it('should call a blank thread array ', function() { runtimeObj.prototype.stopAll(); - expect(interp.activeThread).toEqual([]); + expect(interp.activeThread).toEqual(new threadMock()); }); it('should call stopAllSounds', function() { diff --git a/test/unit/sensingPrimitiveSpec.js b/test/unit/sensingPrimitiveSpec.js index b75eda1..4b3ac4d 100644 --- a/test/unit/sensingPrimitiveSpec.js +++ b/test/unit/sensingPrimitiveSpec.js @@ -78,4 +78,35 @@ describe ('SensingPrims', function() { expect(sensingPrims.prototype.primTimeDate(block)).toEqual(0); }); }); + + describe('primAnswer', function(){ + beforeEach(function() { + interp = interpreterMock({'targetSprite': new targetMock()}); + }); + + it('should return the answer variable from the targetedSprite', function() { + expect(sensingPrims.prototype.primAnswer()).toBe(12); + }); + }); + + describe('primDoAsk', function(){ + var askBlock, targetSpriteMock; + beforeEach(function() { + targetSpriteMock = targetMock(); + askBlock = {'args': 'what to ask'}; + interp = interpreterMock({'targetSprite': targetSpriteMock}, {'arg': askBlock}); + + }); + + it('should call the showBubble method on the targetedSprite', function() { + spyOn(window, "showBubble"); + spyOn(targetSpriteMock, "showAsk"); + sensingPrims.prototype.primDoAsk(askBlock); + expect(window.showBubble).toHaveBeenCalledWith({args:'what to ask'}, 'doAsk'); + expect(targetSpriteMock.showAsk).toHaveBeenCalled; + expect(interp.activeThread.paused).toBe(true); + }); + }); + + }); diff --git a/test/unit/spriteSpec.js b/test/unit/spriteSpec.js index feeb11c..5d5016d 100644 --- a/test/unit/spriteSpec.js +++ b/test/unit/spriteSpec.js @@ -3,7 +3,6 @@ describe ('Sprite', function() { var sprite; - beforeEach(function() { sprite = Sprite; }); @@ -59,17 +58,13 @@ describe ('Sprite', function() { it('should have an askInputOn variable', function() { expect(initSprite.askInputOn).toBe(false); }); - - it('should have an answer variable', function() { - expect(initSprite.askAnswer).toBe(null); - }); }); }) describe('showBubble', function() { var spriteProto; beforeEach(function() { - spriteProto = sprite.prototype; + spriteProto = deepCopy(sprite.prototype); spriteProto.visible = true; setFixtures('
'); spriteProto.talkBubble = $('.bubble-container'); @@ -133,7 +128,7 @@ describe ('Sprite', function() { describe('hideBubble', function() { var spriteProto; beforeEach(function() { - spriteProto = sprite.prototype; + spriteProto = deepCopy(sprite.prototype); setFixtures('
'); spriteProto.talkBubble = $('.bubble-container'); spriteProto.talkBubble.css('display', 'inline'); @@ -150,7 +145,7 @@ describe ('Sprite', function() { describe('showAsk', function() { var spriteProto; beforeEach(function() { - spriteProto = sprite.prototype; + spriteProto = deepCopy(sprite.prototype); spriteProto.visible = true; spriteProto.z = 22; setFixtures('
'); @@ -158,7 +153,7 @@ describe ('Sprite', function() { spriteProto.askInput.css('display','none'); spriteProto.askInput.css('position','relative'); spriteProto.askInputField = $('
'); - spriteProto.askInputTextField = $(''); + spriteProto.askInputTextField = $(''); spriteProto.askInputField.append(spriteProto.askInputTextField); spriteProto.askInputButton = $('
'); spriteProto.askInput.append(spriteProto.askInputField); @@ -189,9 +184,11 @@ describe ('Sprite', function() { describe('hideAsk', function() { var spriteProto; beforeEach(function() { - spriteProto = sprite.prototype; + spriteProto = deepCopy(sprite.prototype); setFixtures('
'); spriteProto.askInput = $('.ask-container'); + spriteProto.askInputTextField = $(''); + spriteProto.askInputTextField.val("Delete Me"); spriteProto.askInput.css('display', 'inline'); }); @@ -199,14 +196,63 @@ describe ('Sprite', function() { spriteProto.hideAsk(); expect($('.ask-container').css('display')).toBe('none'); expect(spriteProto.askInputOn).toBe(false); + expect(spriteProto.askInputTextField.val()).toBe(''); + }); + }); + describe('bindAsk', function() { + beforeEach(function() { + spriteProto = deepCopy(sprite.prototype); + spriteProto.askInputTextField = $(''); + spriteProto.askInputButton = $('
'); + spyOn(spriteProto, "hideBubble"); + spyOn(spriteProto, "hideAsk"); + }); + + it('should bind to the askInputButton and handle a click', function() { + interp = new interpreterMock(); + spyOn(interp, "targetStage").andCallThrough(); + $(spriteProto.askInputTextField).val('Hellow World'); + spriteProto.bindDoAskButton(); + $(spriteProto.askInputButton).click(); + expect(interp.targetStage).toHaveBeenCalled(); + }); + + it('should bind to the askInputButton and handle a enter/return', function() { + interp = new interpreterMock(); + spyOn(interp, "targetStage").andCallThrough(); + spriteProto.bindDoAskButton(); + var e = $.Event( "keypress", { which: 13 } ); + $(spriteProto.askInputButton).trigger(e); + expect(interp.targetStage).toHaveBeenCalled(); + }); + + + it('should call hideBubble', function() { + spriteProto.bindDoAskButton(); + $(spriteProto.askInputButton).click(); + expect(spriteProto.hideBubble).toHaveBeenCalled(); + expect(spriteProto.hideAsk).toHaveBeenCalled(); + }); + + it('should call hideAsk', function() { + spriteProto.bindDoAskButton(); + $(spriteProto.askInputButton).click(); + expect(spriteProto.hideAsk).toHaveBeenCalled(); + }); + + it('should have interp.activeThread.paused be false', function() { + interp = new interpreterMock(); + spriteProto.bindDoAskButton(); + $(spriteProto.askInputButton).click(); + expect(interp.activeThread.paused).toBe(false); }); }); describe('updateLayer', function() { var spriteProto; beforeEach(function() { - spriteProto = sprite.prototype; + spriteProto = deepCopy(sprite.prototype); setFixtures('
'); spriteProto.talkBubble = $('.bubble-container'); spriteProto.talkBubble.css('position', 'relative'); @@ -239,7 +285,7 @@ describe ('Sprite', function() { describe('updateVisible', function() { var spriteProto; beforeEach(function() { - spriteProto = sprite.prototype; + spriteProto = deepCopy(sprite.prototype); setFixtures('
'); spriteProto.talkBubble = $('.bubble-container'); spriteProto.talkBubble.css('display', 'none'); @@ -323,12 +369,12 @@ describe ('Sprite', function() { describe('setVisible', function() { var spriteProto; beforeEach(function() { - spriteProto = sprite.prototype; + spriteProto = deepCopy(sprite.prototype); spyOn(spriteProto, "updateVisible"); }); it('should set visible to true', function() { - expect(spriteProto.visible).toBe(false); + expect(spriteProto.visible).toBe(undefined); spriteProto.setVisible(true); expect(spriteProto.visible).toBe(true); expect(spriteProto.updateVisible).toHaveBeenCalled(); @@ -347,6 +393,6 @@ describe ('Sprite', function() { expect(spriteProto.visible).toBe(true); expect(spriteProto.updateVisible).not.toHaveBeenCalled(); }); - }); + }); diff --git a/test/unit/stageSpec.js b/test/unit/stageSpec.js index 330a451..32a7d2e 100644 --- a/test/unit/stageSpec.js +++ b/test/unit/stageSpec.js @@ -43,6 +43,10 @@ describe ('Stage', function() { expect(initStage.isStage).toBe(true); }); + it('should have an askAnswer variable', function() { + expect(initStage.askAnswer).toBe(""); + }); + it('should have called Sprite.call', function() { expect(Sprite.call).toHaveBeenCalled(); }); diff --git a/test/unit/threadSpec.js b/test/unit/threadSpec.js new file mode 100644 index 0000000..ab7f24b --- /dev/null +++ b/test/unit/threadSpec.js @@ -0,0 +1,50 @@ +/* jasmine specs for Interpreter.js -> Thread go here */ + +describe ('Thread', function() { + var thread; + + beforeEach(function() { + thread = Thread; + }); + + describe('Instantization variables', function() { + var initThread; + beforeEach(function() { + initThread = new thread('block', 'target'); + }); + + describe('Thread Variables', function() { + it('should have a nextBlock variable', function() { + expect(initThread.nextBlock).toBe('block'); + }); + + it('should have a firstBlock variable', function() { + expect(initThread.firstBlock).toBe('block'); + }); + + it('should have a stack variable', function() { + expect(initThread.stack).toEqual([]); + }); + + it('should have a target variable', function() { + expect(initThread.target).toBe('target'); + }); + + it('should have a tmp variable', function() { + expect(initThread.tmp).toBe(null); + }); + + it('should have a tmpObj variable', function() { + expect(initThread.tmpObj).toEqual([]); + }); + + it('should have a firstTime variable', function() { + expect(initThread.firstTime).toBe(true); + }); + + it('should have a paused variable', function() { + expect(initThread.paused).toBe(false); + }); + }); + }); +}); From b6e9ecf0b5c2ece5c6ff54491dbe5f5c743c3464 Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Sun, 9 Mar 2014 12:00:49 -0600 Subject: [PATCH 08/10] oops forgot to delete an unneeded method --- js/Interpreter.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/js/Interpreter.js b/js/Interpreter.js index 310599f..077ba16 100644 --- a/js/Interpreter.js +++ b/js/Interpreter.js @@ -127,13 +127,6 @@ Interpreter.prototype.stepThreads = function() { } }; -Interpreter.prototype.pauseActiveThread = function() { - var self = this; - var timeoutId = setTimeout(function () { - (self.activeThread.paused) ? self.pauseActiveThread() : clearTimeout(timeoutId); - }, 1000); -} - Interpreter.prototype.stepActiveThread = function() { // Run the active thread until it yields. if (typeof(this.activeThread) == 'undefined') { From 365e93f16a31d757f10a8c406971703013e8d0ea Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Mon, 10 Mar 2014 10:16:31 -0600 Subject: [PATCH 09/10] some final touches to the doAsk/answer project --- README.md | 2 ++ test/unit/interpreterSpec.js | 8 -------- todo.txt | 2 -- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 909bf5c..45474e9 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ Mac Ports: $ port install npm ``` +In your local scratch directory + ``` $ npm install ``` diff --git a/test/unit/interpreterSpec.js b/test/unit/interpreterSpec.js index 802db99..7ad7ed4 100644 --- a/test/unit/interpreterSpec.js +++ b/test/unit/interpreterSpec.js @@ -77,14 +77,6 @@ describe ('Interpreter', function() { }); }); - describe('PauseActiveThread', function() { - it('should call clearTimeout', function() { - spyOn(window, "setTimeout"); - interp.prototype.pauseActiveThread(); - expect(window.setTimeout).toHaveBeenCalled(); - }); - }); - describe('TargetStage', function() { it('should return the target.stage object', function() { runtime = new runtimeMock(); diff --git a/todo.txt b/todo.txt index 856d91f..c8bf282 100644 --- a/todo.txt +++ b/todo.txt @@ -15,8 +15,6 @@ To do: -Trigger hats (e.g. When Scene Starts?) - -Ask block - -SVGs/Clicks/Correct collisions and bounce (see Chromium bug https://code.google.com/p/chromium/issues/detail?id=249037). From 6e6524e4813131293c5d385383b86ec2cb7e3a08 Mon Sep 17 00:00:00 2001 From: Brian Pilati Date: Mon, 10 Mar 2014 21:04:56 -0600 Subject: [PATCH 10/10] updates to elevate my code to scratch standards --- README.md | 5 +- compare.html | 2 +- js/Sprite.js | 8 ++- test/artifacts/reporterValues.js | 90 ++++++++----------------------- test/unit/interpreterSpec.js | 4 +- test/unit/ioSpec.js | 4 -- test/unit/looksPrimitiveSpec.js | 8 +-- test/unit/reporterSpec.js | 4 +- test/unit/runTimeSpec.js | 8 +-- test/unit/scratchSpec.js | 35 ++++++------ test/unit/sensingPrimitiveSpec.js | 2 +- test/unit/spriteSpec.js | 12 +---- test/unit/stageSpec.js | 4 +- test/unit/threadSpec.js | 4 +- 14 files changed, 68 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 45474e9..099de17 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,12 @@ In your local scratch directory $ npm install ``` -Local copy of jQuery and mock-ajax ----------------------------------- +Local copy of jQuery +-------------------- ``` $ cd test/lib $ curl http://code.jquery.com/jquery-1.11.0.min.js > jquery-1.11.0.min.js -$ curl http://cloud.github.com/downloads/pivotal/jasmine-ajax/mock-ajax.js > mock-ajax.js ``` To Run the tests diff --git a/compare.html b/compare.html index b538775..0f3a26a 100644 --- a/compare.html +++ b/compare.html @@ -9,7 +9,7 @@ -