mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-06-26 06:10:26 -04:00
Merge pull request #1727 from paulkaplan/add-ext-on-share
Add unloaded extensions on block sharing
This commit is contained in:
commit
4f5aba4fe6
4 changed files with 154 additions and 82 deletions
|
@ -221,3 +221,18 @@ test('deserializeBlocks on already deserialized input', t => {
|
|||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('getExtensionIdForOpcode', t => {
|
||||
t.equal(sb3.getExtensionIdForOpcode('wedo_loopy'), 'wedo');
|
||||
|
||||
// does not consider CORE to be extensions
|
||||
t.false(sb3.getExtensionIdForOpcode('control_loopy'));
|
||||
|
||||
// only considers things before the first underscore
|
||||
t.equal(sb3.getExtensionIdForOpcode('hello_there_loopy'), 'hello');
|
||||
|
||||
// does not return anything for opcodes with no extension
|
||||
t.false(sb3.getExtensionIdForOpcode('hello'));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
|
|
@ -744,28 +744,29 @@ test('shareBlocksToTarget shares global variables without any name changes', t =
|
|||
t.type(stage.blocks.getBlock('a block'), 'undefined');
|
||||
|
||||
// Share the block to the stage
|
||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id);
|
||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id).then(() => {
|
||||
|
||||
// Verify that the block now exists on the target as well as the stage
|
||||
t.type(target.blocks.getBlock('a block'), 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
// Verify that the block now exists on the target as well as the stage
|
||||
t.type(target.blocks.getBlock('a block'), 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
|
||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
|
||||
// Verify that the variables haven't changed, the variable still exists on the
|
||||
// stage, it should still have the same name and value, and there should be
|
||||
// no variables on the target.
|
||||
t.equal(Object.keys(target.variables).length, 0);
|
||||
t.equal(Object.keys(stage.variables).length, 1);
|
||||
t.equal(stage.variables['mock var id'].name, 'a mock variable');
|
||||
t.equal(vm.getVariableValue(stage.id, 'mock var id'), 10);
|
||||
// Verify that the variables haven't changed, the variable still exists on the
|
||||
// stage, it should still have the same name and value, and there should be
|
||||
// no variables on the target.
|
||||
t.equal(Object.keys(target.variables).length, 0);
|
||||
t.equal(Object.keys(stage.variables).length, 1);
|
||||
t.equal(stage.variables['mock var id'].name, 'a mock variable');
|
||||
t.equal(vm.getVariableValue(stage.id, 'mock var id'), 10);
|
||||
|
||||
t.end();
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('shareBlocksToTarget shares a local variable to the stage, creating a global variable with a new name', t => {
|
||||
|
@ -803,36 +804,36 @@ test('shareBlocksToTarget shares a local variable to the stage, creating a globa
|
|||
t.type(stage.blocks.getBlock('a block'), 'undefined');
|
||||
|
||||
// Share the block to the stage
|
||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id);
|
||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id).then(() => {
|
||||
// Verify that the block still exists on the target and remains unchanged
|
||||
t.type(target.blocks.getBlock('a block'), 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
|
||||
// Verify that the block still exists on the target and remains unchanged
|
||||
t.type(target.blocks.getBlock('a block'), 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
||||
|
||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
||||
// Verify that a new global variable was created, the old one still exists on
|
||||
// the target and still has the same name and value, and the new one has
|
||||
// a new name and value 0.
|
||||
t.equal(Object.keys(target.variables).length, 1);
|
||||
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
||||
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
||||
|
||||
// Verify that a new global variable was created, the old one still exists on
|
||||
// the target and still has the same name and value, and the new one has
|
||||
// a new name and value 0.
|
||||
t.equal(Object.keys(target.variables).length, 1);
|
||||
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
||||
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
||||
// Verify that a new variable was created on the stage, with a new name and new id
|
||||
t.equal(Object.keys(stage.variables).length, 1);
|
||||
t.type(stage.variables['mock var id'], 'undefined');
|
||||
const newGlobalVar = Object.values(stage.variables)[0];
|
||||
t.equal(newGlobalVar.name, 'Stage: a mock variable');
|
||||
const newId = newGlobalVar.id;
|
||||
t.notEqual(newId, 'mock var id');
|
||||
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
||||
|
||||
// Verify that a new variable was created on the stage, with a new name and new id
|
||||
t.equal(Object.keys(stage.variables).length, 1);
|
||||
t.type(stage.variables['mock var id'], 'undefined');
|
||||
const newGlobalVar = Object.values(stage.variables)[0];
|
||||
t.equal(newGlobalVar.name, 'Stage: a mock variable');
|
||||
const newId = newGlobalVar.id;
|
||||
t.notEqual(newId, 'mock var id');
|
||||
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
||||
|
||||
t.end();
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('shareBlocksToTarget chooses a fresh name for a new global variable checking for conflicts on all sprites', t => {
|
||||
|
@ -877,36 +878,65 @@ test('shareBlocksToTarget chooses a fresh name for a new global variable checkin
|
|||
otherTarget.createVariable('a different var', 'Stage: a mock variable', Variable.SCALAR_TYPE);
|
||||
|
||||
// Share the block to the stage
|
||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id);
|
||||
vm.shareBlocksToTarget([target.blocks.getBlock('a block')], stage.id, target.id).then(() => {
|
||||
// Verify that the block still exists on the target and remains unchanged
|
||||
t.type(target.blocks.getBlock('a block'), 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
|
||||
// Verify that the block still exists on the target and remains unchanged
|
||||
t.type(target.blocks.getBlock('a block'), 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(target.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(target.blocks.getBlock('a block').fields.VARIABLE.id, 'mock var id');
|
||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
||||
|
||||
t.type(stage.blocks.getBlock('a block'), 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields, 'object');
|
||||
t.type(stage.blocks.getBlock('a block').fields.VARIABLE, 'object');
|
||||
t.equal(stage.blocks.getBlock('a block').fields.VARIABLE.id, 'StageVarFromLocal_mock var id');
|
||||
// Verify that a new global variable was created, the old one still exists on
|
||||
// the target and still has the same name and value, and the new one has
|
||||
// a new name and value 0.
|
||||
t.equal(Object.keys(target.variables).length, 1);
|
||||
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
||||
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
||||
|
||||
// Verify that a new global variable was created, the old one still exists on
|
||||
// the target and still has the same name and value, and the new one has
|
||||
// a new name and value 0.
|
||||
t.equal(Object.keys(target.variables).length, 1);
|
||||
t.equal(target.variables['mock var id'].name, 'a mock variable');
|
||||
t.equal(vm.getVariableValue(target.id, 'mock var id'), 10);
|
||||
// Verify that a new variable was created on the stage, with a new name and new id
|
||||
t.equal(Object.keys(stage.variables).length, 1);
|
||||
t.type(stage.variables['mock var id'], 'undefined');
|
||||
const newGlobalVar = Object.values(stage.variables)[0];
|
||||
t.equal(newGlobalVar.name, 'Stage: a mock variable2');
|
||||
const newId = newGlobalVar.id;
|
||||
t.notEqual(newId, 'mock var id');
|
||||
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
||||
|
||||
// Verify that a new variable was created on the stage, with a new name and new id
|
||||
t.equal(Object.keys(stage.variables).length, 1);
|
||||
t.type(stage.variables['mock var id'], 'undefined');
|
||||
const newGlobalVar = Object.values(stage.variables)[0];
|
||||
t.equal(newGlobalVar.name, 'Stage: a mock variable2');
|
||||
const newId = newGlobalVar.id;
|
||||
t.notEqual(newId, 'mock var id');
|
||||
t.equals(vm.getVariableValue(stage.id, newId), 0);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
t.end();
|
||||
test('shareBlocksToTarget loads extensions that have not yet been loaded', t => {
|
||||
const vm = new VirtualMachine();
|
||||
const runtime = vm.runtime;
|
||||
const spr1 = new Sprite(null, runtime);
|
||||
const stage = spr1.createClone();
|
||||
runtime.targets = [stage];
|
||||
|
||||
const fakeBlocks = [
|
||||
{opcode: 'loaded_fakeblock'},
|
||||
{opcode: 'notloaded_fakeblock'}
|
||||
];
|
||||
|
||||
// Stub the extension manager
|
||||
const loadedIds = [];
|
||||
vm.extensionManager = {
|
||||
isExtensionLoaded: id => id === 'loaded',
|
||||
loadExtensionURL: id => new Promise(resolve => {
|
||||
loadedIds.push(id);
|
||||
resolve();
|
||||
})
|
||||
};
|
||||
|
||||
vm.shareBlocksToTarget(fakeBlocks, stage.id).then(() => {
|
||||
// Verify that only the not-loaded extension gets loaded
|
||||
t.deepEqual(loadedIds, ['notloaded']);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('Setting turbo mode emits events', t => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue