mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-06-03 09:04:40 -04: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
src
test
|
@ -871,15 +871,17 @@ const parseScratchObject = function (object, runtime, extensions, zip) {
|
||||||
* @param {object} json - JSON representation of a VM runtime.
|
* @param {object} json - JSON representation of a VM runtime.
|
||||||
* @param {Runtime} runtime - Runtime instance
|
* @param {Runtime} runtime - Runtime instance
|
||||||
* @param {JSZip} zip - Sb3 file describing this project (to load assets from)
|
* @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
|
* @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 = {
|
const extensions = {
|
||||||
extensionIDs: new Set(),
|
extensionIDs: new Set(),
|
||||||
extensionURLs: new Map()
|
extensionURLs: new Map()
|
||||||
};
|
};
|
||||||
return Promise.all(
|
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 => ({
|
).then(targets => ({
|
||||||
targets,
|
targets,
|
||||||
extensions
|
extensions
|
||||||
|
|
|
@ -385,6 +385,7 @@ class VirtualMachine extends EventEmitter {
|
||||||
* @return {!Promise} Promise that resolves after targets are installed.
|
* @return {!Promise} Promise that resolves after targets are installed.
|
||||||
*/
|
*/
|
||||||
addSprite (input) {
|
addSprite (input) {
|
||||||
|
const errorPrefix = 'Sprite Upload Error:';
|
||||||
if (typeof input === 'object' && !(input instanceof ArrayBuffer) &&
|
if (typeof input === 'object' && !(input instanceof ArrayBuffer) &&
|
||||||
!ArrayBuffer.isView(input)) {
|
!ArrayBuffer.isView(input)) {
|
||||||
// If the input is an object and not any ArrayBuffer
|
// If the input is an object and not any ArrayBuffer
|
||||||
|
@ -411,47 +412,47 @@ class VirtualMachine extends EventEmitter {
|
||||||
.then(validatedInput => {
|
.then(validatedInput => {
|
||||||
const projectVersion = validatedInput[0].projectVersion;
|
const projectVersion = validatedInput[0].projectVersion;
|
||||||
if (projectVersion === 2) {
|
if (projectVersion === 2) {
|
||||||
return this.addSprite2(validatedInput[0], validatedInput[1]);
|
return this._addSprite2(validatedInput[0], validatedInput[1]);
|
||||||
}
|
}
|
||||||
if (projectVersion === 3) {
|
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 => {
|
.catch(error => {
|
||||||
// Intentionally rejecting here (want errors to be handled by caller)
|
// Intentionally rejecting here (want errors to be handled by caller)
|
||||||
if (error.hasOwnProperty('validationError')) {
|
if (error.hasOwnProperty('validationError')) {
|
||||||
return Promise.reject(JSON.stringify(error));
|
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.
|
* 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
|
* @param {?ArrayBuffer} zip Optional zip of assets being referenced by json
|
||||||
* @returns {Promise} Promise that resolves after the sprite is added
|
* @returns {Promise} Promise that resolves after the sprite is added
|
||||||
*/
|
*/
|
||||||
addSprite2 (json, zip) {
|
_addSprite2 (sprite, zip) {
|
||||||
// Validate & parse
|
// Validate & parse
|
||||||
|
|
||||||
return sb2.deserialize(json, this.runtime, true, zip)
|
return sb2.deserialize(sprite, this.runtime, true, zip)
|
||||||
.then(({targets, extensions}) =>
|
.then(({targets, extensions}) =>
|
||||||
this.installTargets(targets, extensions, false));
|
this.installTargets(targets, extensions, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single sb3 sprite.
|
* 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
|
* @param {?ArrayBuffer} zip Optional zip of assets being referenced by target json
|
||||||
* @returns {Promise} Promise that resolves after the sprite is added
|
* @returns {Promise} Promise that resolves after the sprite is added
|
||||||
*/
|
*/
|
||||||
addSprite3 (target, zip) {
|
_addSprite3 (sprite, zip) {
|
||||||
// Validate & parse
|
// Validate & parse
|
||||||
|
|
||||||
return sb3
|
return sb3
|
||||||
.deserialize(target, this.runtime, zip)
|
.deserialize(sprite, this.runtime, zip, true)
|
||||||
.then(({targets, extensions}) => this.installTargets(targets, extensions, false));
|
.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
|
// Add sprite
|
||||||
vm.addSprite2(sprite);
|
vm.addSprite(sprite);
|
||||||
|
|
||||||
// Add backdrop
|
// Add backdrop
|
||||||
vm.addBackdrop(
|
vm.addBackdrop(
|
||||||
|
|
|
@ -15,7 +15,7 @@ test('interface', t => {
|
||||||
t.type(vm.postIOData, 'function');
|
t.type(vm.postIOData, 'function');
|
||||||
|
|
||||||
t.type(vm.loadProject, 'function');
|
t.type(vm.loadProject, 'function');
|
||||||
t.type(vm.addSprite2, 'function');
|
t.type(vm.addSprite, 'function');
|
||||||
t.type(vm.addCostume, 'function');
|
t.type(vm.addCostume, 'function');
|
||||||
t.type(vm.addBackdrop, 'function');
|
t.type(vm.addBackdrop, 'function');
|
||||||
t.type(vm.addSound, 'function');
|
t.type(vm.addSound, 'function');
|
||||||
|
|
|
@ -2,6 +2,15 @@ const test = require('tap').test;
|
||||||
const VirtualMachine = require('../../src/virtual-machine.js');
|
const VirtualMachine = require('../../src/virtual-machine.js');
|
||||||
const Sprite = require('../../src/sprites/sprite.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 => {
|
test('renameSprite throws when there is no sprite with that id', t => {
|
||||||
const vm = new VirtualMachine();
|
const vm = new VirtualMachine();
|
||||||
vm.runtime.getTargetById = () => null;
|
vm.runtime.getTargetById = () => null;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue