mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-22 14:02:37 -05:00
Tests and cleanup of addSprite3 so that .sprite3 format does not need to be nested inside an extra {targets: ...}
This commit is contained in:
parent
9cc34d7406
commit
55352e88b1
7 changed files with 105 additions and 14 deletions
|
@ -871,15 +871,17 @@ const parseScratchObject = function (object, runtime, extensions, zip) {
|
|||
* @param {object} json - JSON representation of a VM runtime.
|
||||
* @param {Runtime} runtime - Runtime instance
|
||||
* @param {JSZip} zip - Sb3 file describing this project (to load assets from)
|
||||
* @param {boolean} isSingleSprite - If true treat as single sprite, else treat as whole project
|
||||
* @returns {Promise.<ImportedProject>} Promise that resolves to the list of targets after the project is deserialized
|
||||
*/
|
||||
const deserialize = function (json, runtime, zip) {
|
||||
const deserialize = function (json, runtime, zip, isSingleSprite) {
|
||||
const extensions = {
|
||||
extensionIDs: new Set(),
|
||||
extensionURLs: new Map()
|
||||
};
|
||||
return Promise.all(
|
||||
(json.targets || []).map(target => parseScratchObject(target, runtime, extensions, zip))
|
||||
((isSingleSprite ? [json] : json.targets) || []).map(target =>
|
||||
parseScratchObject(target, runtime, extensions, zip))
|
||||
).then(targets => ({
|
||||
targets,
|
||||
extensions
|
||||
|
|
|
@ -385,6 +385,7 @@ class VirtualMachine extends EventEmitter {
|
|||
* @return {!Promise} Promise that resolves after targets are installed.
|
||||
*/
|
||||
addSprite (input) {
|
||||
const errorPrefix = 'Sprite Upload Error:';
|
||||
if (typeof input === 'object' && !(input instanceof ArrayBuffer) &&
|
||||
!ArrayBuffer.isView(input)) {
|
||||
// If the input is an object and not any ArrayBuffer
|
||||
|
@ -411,47 +412,47 @@ class VirtualMachine extends EventEmitter {
|
|||
.then(validatedInput => {
|
||||
const projectVersion = validatedInput[0].projectVersion;
|
||||
if (projectVersion === 2) {
|
||||
return this.addSprite2(validatedInput[0], validatedInput[1]);
|
||||
return this._addSprite2(validatedInput[0], validatedInput[1]);
|
||||
}
|
||||
if (projectVersion === 3) {
|
||||
return this.addSprite3(validatedInput[0], validatedInput[1]);
|
||||
return this._addSprite3(validatedInput[0], validatedInput[1]);
|
||||
}
|
||||
return Promise.reject('Unable to verify sprite version.');
|
||||
return Promise.reject(`${errorPrefix} Unable to verify sprite version.`);
|
||||
})
|
||||
.catch(error => {
|
||||
// Intentionally rejecting here (want errors to be handled by caller)
|
||||
if (error.hasOwnProperty('validationError')) {
|
||||
return Promise.reject(JSON.stringify(error));
|
||||
}
|
||||
return Promise.reject(error);
|
||||
return Promise.reject(`${errorPrefix} ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single sprite from the "Sprite2" (i.e., SB2 sprite) format.
|
||||
* @param {string} json JSON string representing the sprite.
|
||||
* @param {object} sprite Object representing 2.0 sprite to be added.
|
||||
* @param {?ArrayBuffer} zip Optional zip of assets being referenced by json
|
||||
* @returns {Promise} Promise that resolves after the sprite is added
|
||||
*/
|
||||
addSprite2 (json, zip) {
|
||||
_addSprite2 (sprite, zip) {
|
||||
// Validate & parse
|
||||
|
||||
return sb2.deserialize(json, this.runtime, true, zip)
|
||||
return sb2.deserialize(sprite, this.runtime, true, zip)
|
||||
.then(({targets, extensions}) =>
|
||||
this.installTargets(targets, extensions, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single sb3 sprite.
|
||||
* @param {string} target JSON string representing the sprite/target.
|
||||
* @param {object} sprite Object rperesenting 3.0 sprite to be added.
|
||||
* @param {?ArrayBuffer} zip Optional zip of assets being referenced by target json
|
||||
* @returns {Promise} Promise that resolves after the sprite is added
|
||||
*/
|
||||
addSprite3 (target, zip) {
|
||||
_addSprite3 (sprite, zip) {
|
||||
// Validate & parse
|
||||
|
||||
return sb3
|
||||
.deserialize(target, this.runtime, zip)
|
||||
.deserialize(sprite, this.runtime, zip, true)
|
||||
.then(({targets, extensions}) => this.installTargets(targets, extensions, false));
|
||||
}
|
||||
|
||||
|
|
BIN
test/fixtures/example_sprite.sprite2
vendored
Normal file
BIN
test/fixtures/example_sprite.sprite2
vendored
Normal file
Binary file not shown.
79
test/integration/addSprite.js
Normal file
79
test/integration/addSprite.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
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/virtual-machine');
|
||||
const RenderedTarget = require('../../src/sprites/rendered-target');
|
||||
|
||||
const projectUri = path.resolve(__dirname, '../fixtures/default.sb2');
|
||||
const project = readFileToBuffer(projectUri);
|
||||
|
||||
const vm = new VirtualMachine();
|
||||
|
||||
test('spec', t => {
|
||||
t.type(vm.addSprite, 'function');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('default cat', t => {
|
||||
// Get default cat from .sprite2
|
||||
const uri = path.resolve(__dirname, '../fixtures/example_sprite.sprite2');
|
||||
const sprite = readFileToBuffer(uri);
|
||||
|
||||
vm.attachStorage(makeTestStorage());
|
||||
|
||||
// Evaluate playground data and exit
|
||||
vm.on('playgroundData', e => {
|
||||
const threads = JSON.parse(e.threads);
|
||||
t.ok(threads.length === 0);
|
||||
t.end();
|
||||
process.nextTick(process.exit);
|
||||
});
|
||||
|
||||
vm.start();
|
||||
vm.clear();
|
||||
vm.setCompatibilityMode(false);
|
||||
vm.setTurboMode(false);
|
||||
t.doesNotThrow(() => {
|
||||
vm.loadProject(project).then(() => {
|
||||
|
||||
t.equal(vm.runtime.targets.length, 2); // stage and default sprite
|
||||
|
||||
// Add another sprite
|
||||
vm.addSprite(sprite).then(() => {
|
||||
const targets = vm.runtime.targets;
|
||||
|
||||
// Test
|
||||
t.type(targets, 'object');
|
||||
t.equal(targets.length, 3);
|
||||
|
||||
const newTarget = targets[2];
|
||||
|
||||
t.ok(newTarget instanceof RenderedTarget);
|
||||
t.type(newTarget.id, 'string');
|
||||
t.type(newTarget.blocks, 'object');
|
||||
t.type(newTarget.variables, 'object');
|
||||
const varIds = Object.keys(newTarget.variables);
|
||||
t.type(varIds.length, 1);
|
||||
const variable = newTarget.variables[varIds[0]];
|
||||
t.equal(variable.name, 'foo');
|
||||
t.equal(variable.value, 0);
|
||||
|
||||
t.equal(newTarget.isOriginal, true);
|
||||
t.equal(newTarget.currentCostume, 0);
|
||||
t.equal(newTarget.isOriginal, true);
|
||||
t.equal(newTarget.isStage, false);
|
||||
t.equal(newTarget.sprite.name, 'Apple');
|
||||
|
||||
vm.greenFlag();
|
||||
|
||||
setTimeout(() => {
|
||||
t.equal(variable.value, 10);
|
||||
vm.getPlaygroundData();
|
||||
vm.stopAll();
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -73,7 +73,7 @@ test('complex', t => {
|
|||
});
|
||||
|
||||
// Add sprite
|
||||
vm.addSprite2(sprite);
|
||||
vm.addSprite(sprite);
|
||||
|
||||
// Add backdrop
|
||||
vm.addBackdrop(
|
||||
|
|
|
@ -15,7 +15,7 @@ test('interface', t => {
|
|||
t.type(vm.postIOData, 'function');
|
||||
|
||||
t.type(vm.loadProject, 'function');
|
||||
t.type(vm.addSprite2, 'function');
|
||||
t.type(vm.addSprite, 'function');
|
||||
t.type(vm.addCostume, 'function');
|
||||
t.type(vm.addBackdrop, 'function');
|
||||
t.type(vm.addSound, 'function');
|
||||
|
|
|
@ -2,6 +2,15 @@ const test = require('tap').test;
|
|||
const VirtualMachine = require('../../src/virtual-machine.js');
|
||||
const Sprite = require('../../src/sprites/sprite.js');
|
||||
|
||||
test('addSprite throws on invalid string', t => {
|
||||
const vm = new VirtualMachine();
|
||||
vm.addSprite('this is not a sprite')
|
||||
.catch(e => {
|
||||
t.equal(e.startsWith('Sprite Upload Error:'), true);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('renameSprite throws when there is no sprite with that id', t => {
|
||||
const vm = new VirtualMachine();
|
||||
vm.runtime.getTargetById = () => null;
|
||||
|
|
Loading…
Reference in a new issue