diff --git a/test/fixtures/comments.sb3 b/test/fixtures/comments.sb3 new file mode 100644 index 000000000..ce937c454 Binary files /dev/null and b/test/fixtures/comments.sb3 differ diff --git a/test/integration/comments_sb3.js b/test/integration/comments_sb3.js new file mode 100644 index 000000000..fd3766622 --- /dev/null +++ b/test/integration/comments_sb3.js @@ -0,0 +1,91 @@ +const path = require('path'); +const test = require('tap').test; +const makeTestStorage = require('../fixtures/make-test-storage'); +const readFileToBuffer = require('../fixtures/readProjectFile').readFileToBuffer; +const VirtualMachine = require('../../src/index'); + +const projectUri = path.resolve(__dirname, '../fixtures/comments.sb3'); +const project = readFileToBuffer(projectUri); + +test('load an sb3 project with comments', t => { + const vm = new VirtualMachine(); + vm.attachStorage(makeTestStorage()); + + // Evaluate playground data and exit + vm.on('playgroundData', e => { + const threads = JSON.parse(e.threads); + t.equal(threads.length, 0); + + const stage = vm.runtime.targets[0]; + const target = vm.runtime.targets[1]; + + const stageComments = Object.values(stage.comments); + + // Stage has 1 comment, and it is minimized. + t.equal(stageComments.length, 1); + t.equal(stageComments[0].minimized, true); + t.equal(stageComments[0].text, 'A minimized stage comment.'); + // The stage comment is a workspace comment + t.equal(stageComments[0].blockId, null); + + // Sprite 1 has 6 Comments, 1 workspace comment, and 5 block comments + const targetComments = Object.values(target.comments); + t.equal(targetComments.length, 6); + const spriteWorkspaceComments = targetComments.filter(comment => comment.blockId === null); + t.equal(spriteWorkspaceComments.length, 1); + t.equal(spriteWorkspaceComments[0].minimized, false); + t.equal(spriteWorkspaceComments[0].text, 'This is a workspace comment.'); + + // Test the sprite block comments + const blockComments = targetComments.filter(comment => !!comment.blockId); + t.equal(blockComments.length, 5); + + t.equal(blockComments[0].minimized, true); + t.equal(blockComments[0].text, '1. Green Flag Comment.'); + const greenFlagBlock = target.blocks.getBlock(blockComments[0].blockId); + t.equal(greenFlagBlock.comment, blockComments[0].id); + t.equal(greenFlagBlock.opcode, 'event_whenflagclicked'); + + t.equal(blockComments[1].minimized, true); + t.equal(blockComments[1].text, '2. Turn 15 Degrees Comment.'); + const turnRightBlock = target.blocks.getBlock(blockComments[1].blockId); + t.equal(turnRightBlock.comment, blockComments[1].id); + t.equal(turnRightBlock.opcode, 'motion_turnright'); + + t.equal(blockComments[2].minimized, false); + t.equal(blockComments[2].text, '3. Comment for a loop.'); + const repeatBlock = target.blocks.getBlock(blockComments[2].blockId); + t.equal(repeatBlock.comment, blockComments[2].id); + t.equal(repeatBlock.opcode, 'control_repeat'); + + t.equal(blockComments[3].minimized, false); + t.equal(blockComments[3].text, '4. Comment for a block nested in a loop.'); + const changeColorBlock = target.blocks.getBlock(blockComments[3].blockId); + t.equal(changeColorBlock.comment, blockComments[3].id); + t.equal(changeColorBlock.opcode, 'looks_changeeffectby'); + + t.equal(blockComments[4].minimized, false); + t.equal(blockComments[4].text, '5. Comment for a block outside of a loop.'); + const stopAllBlock = target.blocks.getBlock(blockComments[4].blockId); + t.equal(stopAllBlock.comment, blockComments[4].id); + t.equal(stopAllBlock.opcode, 'control_stop'); + + t.end(); + process.nextTick(process.exit); + }); + + // Start VM, load project, and run + t.doesNotThrow(() => { + vm.start(); + vm.clear(); + vm.setCompatibilityMode(false); + vm.setTurboMode(false); + vm.loadProject(project).then(() => { + vm.greenFlag(); + setTimeout(() => { + vm.getPlaygroundData(); + vm.stopAll(); + }, 100); + }); + }); +}); diff --git a/test/unit/serialization_sb3.js b/test/unit/serialization_sb3.js index a3be33a7a..4b7723151 100644 --- a/test/unit/serialization_sb3.js +++ b/test/unit/serialization_sb3.js @@ -3,11 +3,12 @@ const path = require('path'); const VirtualMachine = require('../../src/index'); const sb3 = require('../../src/serialization/sb3'); const readFileToBuffer = require('../fixtures/readProjectFile').readFileToBuffer; -const projectPath = path.resolve(__dirname, '../fixtures/clone-cleanup.sb2'); +const exampleProjectPath = path.resolve(__dirname, '../fixtures/clone-cleanup.sb2'); +const commentsSB2ProjectPath = path.resolve(__dirname, '../fixtures/comments.sb2'); test('serialize', t => { const vm = new VirtualMachine(); - vm.loadProject(readFileToBuffer(projectPath)) + vm.loadProject(readFileToBuffer(exampleProjectPath)) .then(() => { const result = sb3.serialize(vm.runtime); // @todo Analyze @@ -24,3 +25,44 @@ test('deserialize', t => { t.end(); }); }); + + +test('serialize sb2 project with comments as sb3', t => { + const vm = new VirtualMachine(); + vm.loadProject(readFileToBuffer(commentsSB2ProjectPath)) + .then(() => { + const result = sb3.serialize(vm.runtime); + + t.type(JSON.stringify(result), 'string'); + t.type(result.targets, 'object'); + t.equal(Array.isArray(result.targets), true); + t.equal(result.targets.length, 2); + + const stage = result.targets[0]; + t.equal(stage.isStage, true); + // The stage has 0 blocks, and 1 workspace comment + t.type(stage.blocks, 'object'); + t.equal(Object.keys(stage.blocks).length, 0); + t.type(stage.comments, 'object'); + t.equal(Object.keys(stage.comments).length, 1); + const stageBlockComments = Object.values(stage.comments).filter(comment => !!comment.blockId); + const stageWorkspaceComments = Object.values(stage.comments).filter(comment => comment.blockId === null); + t.equal(stageBlockComments.length, 0); + t.equal(stageWorkspaceComments.length, 1); + + const sprite = result.targets[1]; + t.equal(sprite.isStage, false); + t.type(sprite.blocks, 'object'); + // Sprite 1 has 6 blocks, 5 block comments, and 1 workspace comment + t.equal(Object.keys(sprite.blocks).length, 6); + t.type(sprite.comments, 'object'); + t.equal(Object.keys(sprite.comments).length, 6); + + const spriteBlockComments = Object.values(sprite.comments).filter(comment => !!comment.blockId); + const spriteWorkspaceComments = Object.values(sprite.comments).filter(comment => comment.blockId === null); + t.equal(spriteBlockComments.length, 5); + t.equal(spriteWorkspaceComments.length, 1); + + t.end(); + }); +});