mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-07-09 04:24:04 -04:00
Merge pull request #782 from kchadha/list-typed-variable
List typed variable
This commit is contained in:
commit
1e27d21b15
13 changed files with 194 additions and 105 deletions
src
blocks
engine
serialization
test
|
@ -52,8 +52,8 @@ class Scratch3DataBlocks {
|
|||
// If it is, report contents joined together with no separator.
|
||||
// If it's not, report contents joined together with a space.
|
||||
let allSingleLetters = true;
|
||||
for (let i = 0; i < list.contents.length; i++) {
|
||||
const listItem = list.contents[i];
|
||||
for (let i = 0; i < list.value.length; i++) {
|
||||
const listItem = list.value[i];
|
||||
if (!((typeof listItem === 'string') &&
|
||||
(listItem.length === 1))) {
|
||||
allSingleLetters = false;
|
||||
|
@ -61,73 +61,73 @@ class Scratch3DataBlocks {
|
|||
}
|
||||
}
|
||||
if (allSingleLetters) {
|
||||
return list.contents.join('');
|
||||
return list.value.join('');
|
||||
}
|
||||
return list.contents.join(' ');
|
||||
return list.value.join(' ');
|
||||
|
||||
}
|
||||
|
||||
addToList (args, util) {
|
||||
const list = util.target.lookupOrCreateList(args.LIST);
|
||||
list.contents.push(args.ITEM);
|
||||
list.value.push(args.ITEM);
|
||||
}
|
||||
|
||||
deleteOfList (args, util) {
|
||||
const list = util.target.lookupOrCreateList(args.LIST);
|
||||
const index = Cast.toListIndex(args.INDEX, list.contents.length);
|
||||
const index = Cast.toListIndex(args.INDEX, list.value.length);
|
||||
if (index === Cast.LIST_INVALID) {
|
||||
return;
|
||||
} else if (index === Cast.LIST_ALL) {
|
||||
list.contents = [];
|
||||
list.value = [];
|
||||
return;
|
||||
}
|
||||
list.contents.splice(index - 1, 1);
|
||||
list.value.splice(index - 1, 1);
|
||||
}
|
||||
|
||||
insertAtList (args, util) {
|
||||
const item = args.ITEM;
|
||||
const list = util.target.lookupOrCreateList(args.LIST);
|
||||
const index = Cast.toListIndex(args.INDEX, list.contents.length + 1);
|
||||
const index = Cast.toListIndex(args.INDEX, list.value.length + 1);
|
||||
if (index === Cast.LIST_INVALID) {
|
||||
return;
|
||||
}
|
||||
list.contents.splice(index - 1, 0, item);
|
||||
list.value.splice(index - 1, 0, item);
|
||||
}
|
||||
|
||||
replaceItemOfList (args, util) {
|
||||
const item = args.ITEM;
|
||||
const list = util.target.lookupOrCreateList(args.LIST);
|
||||
const index = Cast.toListIndex(args.INDEX, list.contents.length);
|
||||
const index = Cast.toListIndex(args.INDEX, list.value.length);
|
||||
if (index === Cast.LIST_INVALID) {
|
||||
return;
|
||||
}
|
||||
list.contents.splice(index - 1, 1, item);
|
||||
list.value.splice(index - 1, 1, item);
|
||||
}
|
||||
|
||||
getItemOfList (args, util) {
|
||||
const list = util.target.lookupOrCreateList(args.LIST);
|
||||
const index = Cast.toListIndex(args.INDEX, list.contents.length);
|
||||
const index = Cast.toListIndex(args.INDEX, list.value.length);
|
||||
if (index === Cast.LIST_INVALID) {
|
||||
return '';
|
||||
}
|
||||
return list.contents[index - 1];
|
||||
return list.value[index - 1];
|
||||
}
|
||||
|
||||
lengthOfList (args, util) {
|
||||
const list = util.target.lookupOrCreateList(args.LIST);
|
||||
return list.contents.length;
|
||||
return list.value.length;
|
||||
}
|
||||
|
||||
listContainsItem (args, util) {
|
||||
const item = args.ITEM;
|
||||
const list = util.target.lookupOrCreateList(args.LIST);
|
||||
if (list.contents.indexOf(item) >= 0) {
|
||||
if (list.value.indexOf(item) >= 0) {
|
||||
return true;
|
||||
}
|
||||
// Try using Scratch comparison operator on each item.
|
||||
// (Scratch considers the string '123' equal to the number 123).
|
||||
for (let i = 0; i < list.contents.length; i++) {
|
||||
if (Cast.compare(list.contents[i], item) === 0) {
|
||||
for (let i = 0; i < list.value.length; i++) {
|
||||
if (Cast.compare(list.value[i], item) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,10 @@ const domToBlock = function (blockDOM, blocks, isTopBlock, parent) {
|
|||
id: fieldId,
|
||||
value: fieldData
|
||||
};
|
||||
const fieldVarType = xmlChild.attribs.variabletype;
|
||||
if (typeof fieldVarType === 'string') {
|
||||
block.fields[fieldName].variableType = fieldVarType;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'value':
|
||||
|
|
|
@ -260,7 +260,7 @@ class Blocks {
|
|||
// If not, create it on the stage.
|
||||
// TODO create global and local variables when UI provides a way.
|
||||
if (!optRuntime.getEditingTarget().lookupVariableById(e.varId)) {
|
||||
stage.createVariable(e.varId, e.varName);
|
||||
stage.createVariable(e.varId, e.varName, e.varType);
|
||||
}
|
||||
break;
|
||||
case 'var_rename':
|
||||
|
@ -310,7 +310,7 @@ class Blocks {
|
|||
case 'field':
|
||||
// Update block value
|
||||
if (!block.fields[args.name]) return;
|
||||
if (args.name === 'VARIABLE') {
|
||||
if (args.name === 'VARIABLE' || args.name === 'LIST') {
|
||||
// Get variable name using the id in args.value.
|
||||
const variable = optRuntime.getEditingTarget().lookupVariableById(args.value);
|
||||
if (variable) {
|
||||
|
@ -499,11 +499,20 @@ class Blocks {
|
|||
for (const field in block.fields) {
|
||||
if (!block.fields.hasOwnProperty(field)) continue;
|
||||
const blockField = block.fields[field];
|
||||
xmlString += `<field name="${blockField.name}"`;
|
||||
const fieldId = blockField.id;
|
||||
if (fieldId) {
|
||||
xmlString += ` id="${fieldId}"`;
|
||||
}
|
||||
const varType = blockField.variableType;
|
||||
if (typeof varType === 'string') {
|
||||
xmlString += ` variabletype="${varType}"`;
|
||||
}
|
||||
let value = blockField.value;
|
||||
if (typeof value === 'string') {
|
||||
value = xmlEscape(blockField.value);
|
||||
}
|
||||
xmlString += `<field name="${blockField.name}">${value}</field>`;
|
||||
xmlString += `>${value}</field>`;
|
||||
}
|
||||
// Add blocks connected to the next connection.
|
||||
if (block.next) {
|
||||
|
|
|
@ -157,7 +157,7 @@ const execute = function (sequencer, thread) {
|
|||
// Add all fields on this block to the argValues.
|
||||
for (const fieldName in fields) {
|
||||
if (!fields.hasOwnProperty(fieldName)) continue;
|
||||
if (fieldName === 'VARIABLE') {
|
||||
if (fieldName === 'VARIABLE' || fieldName === 'LIST') {
|
||||
argValues[fieldName] = fields[fieldName].id;
|
||||
} else {
|
||||
argValues[fieldName] = fields[fieldName].value;
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Object representing a Scratch list.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {!string} name Name of the list.
|
||||
* @param {Array} contents Contents of the list, as an array.
|
||||
* @constructor
|
||||
*/
|
||||
class List {
|
||||
constructor (name, contents) {
|
||||
this.name = name;
|
||||
this.contents = contents;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = List;
|
|
@ -2,7 +2,6 @@ const EventEmitter = require('events');
|
|||
|
||||
const Blocks = require('./blocks');
|
||||
const Variable = require('../engine/variable');
|
||||
const List = require('../engine/list');
|
||||
const uid = require('../util/uid');
|
||||
const {Map} = require('immutable');
|
||||
|
||||
|
@ -88,7 +87,7 @@ class Target extends EventEmitter {
|
|||
const variable = this.lookupVariableById(id);
|
||||
if (variable) return variable;
|
||||
// No variable with this name exists - create it locally.
|
||||
const newVariable = new Variable(id, name, 0, false);
|
||||
const newVariable = new Variable(id, name, Variable.SCALAR_TYPE, false);
|
||||
this.variables[id] = newVariable;
|
||||
return newVariable;
|
||||
}
|
||||
|
@ -117,24 +116,16 @@ class Target extends EventEmitter {
|
|||
/**
|
||||
* Look up a list object for this target, and create it if one doesn't exist.
|
||||
* Search begins for local lists; then look for globals.
|
||||
* @param {!string} id Id of the list.
|
||||
* @param {!string} name Name of the list.
|
||||
* @return {!List} List object.
|
||||
*/
|
||||
lookupOrCreateList (name) {
|
||||
// If we have a local copy, return it.
|
||||
if (this.lists.hasOwnProperty(name)) {
|
||||
return this.lists[name];
|
||||
}
|
||||
// If the stage has a global copy, return it.
|
||||
if (this.runtime && !this.isStage) {
|
||||
const stage = this.runtime.getTargetForStage();
|
||||
if (stage.lists.hasOwnProperty(name)) {
|
||||
return stage.lists[name];
|
||||
}
|
||||
}
|
||||
// No list with this name exists - create it locally.
|
||||
const newList = new List(name, []);
|
||||
this.lists[name] = newList;
|
||||
lookupOrCreateList (id, name) {
|
||||
const list = this.lookupVariableById(id);
|
||||
if (list) return list;
|
||||
// No variable with this name exists - create it locally.
|
||||
const newList = new Variable(id, name, Variable.LIST_TYPE, false);
|
||||
this.variables[id] = newList;
|
||||
return newList;
|
||||
}
|
||||
|
||||
|
@ -143,11 +134,11 @@ class Target extends EventEmitter {
|
|||
* dictionary of variables.
|
||||
* @param {string} id Id of variable
|
||||
* @param {string} name Name of variable.
|
||||
* @param {string} type Type of variable, '' or 'list'
|
||||
*/
|
||||
createVariable (id, name) {
|
||||
createVariable (id, name, type) {
|
||||
if (!this.variables.hasOwnProperty(id)) {
|
||||
const newVariable = new Variable(id, name, 0,
|
||||
false);
|
||||
const newVariable = new Variable(id, name, type, false);
|
||||
this.variables[id] = newVariable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,19 +9,47 @@ class Variable {
|
|||
/**
|
||||
* @param {string} id Id of the variable.
|
||||
* @param {string} name Name of the variable.
|
||||
* @param {(string|number)} value Value of the variable.
|
||||
* @param {string} type Type of the variable, one of '' or 'list'
|
||||
* @param {boolean} isCloud Whether the variable is stored in the cloud.
|
||||
* @constructor
|
||||
*/
|
||||
constructor (id, name, value, isCloud) {
|
||||
constructor (id, name, type, isCloud) {
|
||||
this.id = id || uid();
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
this.isCloud = isCloud;
|
||||
switch (this.type) {
|
||||
case Variable.SCALAR_TYPE:
|
||||
this.value = 0;
|
||||
break;
|
||||
case Variable.LIST_TYPE:
|
||||
this.value = [];
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid variable type: ${this.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
toXML () {
|
||||
return `<variable type="" id="${this.id}">${this.name}</variable>`;
|
||||
return `<variable type="${this.type}" id="${this.id}">${this.name}</variable>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type representation for scalar variables.
|
||||
* This is currently represented as ''
|
||||
* for compatibility with blockly.
|
||||
* @const {string}
|
||||
*/
|
||||
static get SCALAR_TYPE () {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Type representation for list variables.
|
||||
* @const {string}
|
||||
*/
|
||||
static get LIST_TYPE () {
|
||||
return 'list';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ const log = require('../util/log');
|
|||
const uid = require('../util/uid');
|
||||
const specMap = require('./sb2_specmap');
|
||||
const Variable = require('../engine/variable');
|
||||
const List = require('../engine/list');
|
||||
|
||||
const {loadCostume} = require('../import/load-costume.js');
|
||||
const {loadSound} = require('../import/load-sound.js');
|
||||
|
@ -235,9 +234,10 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) {
|
|||
const newVariable = new Variable(
|
||||
getVariableId(variable.name),
|
||||
variable.name,
|
||||
variable.value,
|
||||
Variable.SCALAR_TYPE,
|
||||
variable.isPersistent
|
||||
);
|
||||
newVariable.value = variable.value;
|
||||
target.variables[newVariable.id] = newVariable;
|
||||
}
|
||||
}
|
||||
|
@ -251,10 +251,14 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) {
|
|||
for (let k = 0; k < object.lists.length; k++) {
|
||||
const list = object.lists[k];
|
||||
// @todo: monitor properties.
|
||||
target.lists[list.listName] = new List(
|
||||
const newVariable = new Variable(
|
||||
getVariableId(list.listName),
|
||||
list.listName,
|
||||
list.contents
|
||||
Variable.LIST_TYPE,
|
||||
false
|
||||
);
|
||||
newVariable.value = list.contents;
|
||||
target.variables[newVariable.id] = newVariable;
|
||||
}
|
||||
}
|
||||
if (object.hasOwnProperty('scratchX')) {
|
||||
|
@ -486,10 +490,14 @@ const parseBlock = function (sb2block, getVariableId, extensions) {
|
|||
value: providedArg
|
||||
};
|
||||
|
||||
if (expectedArg.fieldName === 'VARIABLE') {
|
||||
if (expectedArg.fieldName === 'VARIABLE' || expectedArg.fieldName === 'LIST') {
|
||||
// Add `id` property to variable fields
|
||||
activeBlock.fields[expectedArg.fieldName].id = getVariableId(providedArg);
|
||||
}
|
||||
const varType = expectedArg.variableType;
|
||||
if (typeof varType === 'string') {
|
||||
activeBlock.fields[expectedArg.fieldName].variableType = varType;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Special cases to generate mutations.
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
* Finally, I filled in the expected arguments as below.
|
||||
*/
|
||||
|
||||
const Variable = require('../engine/variable');
|
||||
|
||||
/**
|
||||
* @typedef {object} SB2SpecMap_blockInfo
|
||||
* @property {string} opcode - the Scratch 3.0 block opcode. Use 'extensionID.opcode' for extension opcodes.
|
||||
|
@ -1201,7 +1203,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'VARIABLE'
|
||||
fieldName: 'VARIABLE',
|
||||
variableType: Variable.SCALAR_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1210,7 +1213,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'VARIABLE'
|
||||
fieldName: 'VARIABLE',
|
||||
variableType: Variable.SCALAR_TYPE
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
|
@ -1224,7 +1228,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'VARIABLE'
|
||||
fieldName: 'VARIABLE',
|
||||
variableType: Variable.SCALAR_TYPE
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
|
@ -1238,7 +1243,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'VARIABLE'
|
||||
fieldName: 'VARIABLE',
|
||||
variableType: Variable.SCALAR_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1247,16 +1253,18 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'VARIABLE'
|
||||
fieldName: 'VARIABLE',
|
||||
variableType: Variable.SCALAR_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
'contentsOfList:': {
|
||||
opcode: 'data_list',
|
||||
opcode: 'data_listcontents',
|
||||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1270,7 +1278,8 @@ const specMap = {
|
|||
},
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1284,7 +1293,8 @@ const specMap = {
|
|||
},
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1303,7 +1313,8 @@ const specMap = {
|
|||
},
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1317,7 +1328,8 @@ const specMap = {
|
|||
},
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
|
@ -1336,7 +1348,8 @@ const specMap = {
|
|||
},
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1345,7 +1358,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1354,7 +1368,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
|
@ -1368,7 +1383,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1377,7 +1393,8 @@ const specMap = {
|
|||
argMap: [
|
||||
{
|
||||
type: 'field',
|
||||
fieldName: 'LIST'
|
||||
fieldName: 'LIST',
|
||||
variableType: Variable.LIST_TYPE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -8,7 +8,6 @@ const vmPackage = require('../../package.json');
|
|||
const Blocks = require('../engine/blocks');
|
||||
const Sprite = require('../sprites/sprite');
|
||||
const Variable = require('../engine/variable');
|
||||
const List = require('../engine/list');
|
||||
|
||||
const {loadCostume} = require('../import/load-costume.js');
|
||||
const {loadSound} = require('../import/load-sound.js');
|
||||
|
@ -125,22 +124,13 @@ const parseScratchObject = function (object, runtime, extensions) {
|
|||
const newVariable = new Variable(
|
||||
variable.id,
|
||||
variable.name,
|
||||
variable.value,
|
||||
variable.type,
|
||||
variable.isPersistent
|
||||
);
|
||||
newVariable.value = variable.value;
|
||||
target.variables[newVariable.id] = newVariable;
|
||||
}
|
||||
}
|
||||
if (object.hasOwnProperty('lists')) {
|
||||
for (let k = 0; k < object.lists.length; k++) {
|
||||
const list = object.lists[k];
|
||||
// @todo: monitor properties.
|
||||
target.lists[list.listName] = new List(
|
||||
list.listName,
|
||||
list.contents
|
||||
);
|
||||
}
|
||||
}
|
||||
if (object.hasOwnProperty('x')) {
|
||||
target.x = object.x;
|
||||
}
|
||||
|
|
2
test/fixtures/demo.json
vendored
2
test/fixtures/demo.json
vendored
File diff suppressed because one or more lines are too long
|
@ -16,7 +16,8 @@ test('complex', t => {
|
|||
const threads = JSON.parse(e.threads);
|
||||
t.ok(threads.length === 0);
|
||||
|
||||
const results = vm.runtime.targets[0].lists.results.contents;
|
||||
const resultKey = Object.keys(vm.runtime.targets[0].variables)[0];
|
||||
const results = vm.runtime.targets[0].variables[resultKey].value;
|
||||
t.deepEqual(results, ['3', '2', '1', 'stage']);
|
||||
|
||||
t.end();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const test = require('tap').test;
|
||||
const Target = require('../../src/engine/target');
|
||||
const Variable = require('../../src/engine/variable');
|
||||
|
||||
test('spec', t => {
|
||||
const target = new Target();
|
||||
|
@ -23,13 +24,14 @@ test('spec', t => {
|
|||
// Create Variable tests.
|
||||
test('createVariable', t => {
|
||||
const target = new Target();
|
||||
target.createVariable('foo', 'bar');
|
||||
target.createVariable('foo', 'bar', Variable.SCALAR_TYPE);
|
||||
|
||||
const variables = target.variables;
|
||||
t.equal(Object.keys(variables).length, 1);
|
||||
const variable = variables[Object.keys(variables)[0]];
|
||||
t.equal(variable.id, 'foo');
|
||||
t.equal(variable.name, 'bar');
|
||||
t.equal(variable.type, Variable.SCALAR_TYPE);
|
||||
t.equal(variable.value, 0);
|
||||
t.equal(variable.isCloud, false);
|
||||
|
||||
|
@ -39,8 +41,8 @@ test('createVariable', t => {
|
|||
// Create Same Variable twice.
|
||||
test('createVariable2', t => {
|
||||
const target = new Target();
|
||||
target.createVariable('foo', 'bar');
|
||||
target.createVariable('foo', 'bar');
|
||||
target.createVariable('foo', 'bar', Variable.SCALAR_TYPE);
|
||||
target.createVariable('foo', 'bar', Variable.SCALAR_TYPE);
|
||||
|
||||
const variables = target.variables;
|
||||
t.equal(Object.keys(variables).length, 1);
|
||||
|
@ -48,10 +50,38 @@ test('createVariable2', t => {
|
|||
t.end();
|
||||
});
|
||||
|
||||
// Create a list
|
||||
test('createListVariable creates a list', t => {
|
||||
const target = new Target();
|
||||
target.createVariable('foo', 'bar', Variable.LIST_TYPE);
|
||||
|
||||
const variables = target.variables;
|
||||
t.equal(Object.keys(variables).length, 1);
|
||||
const variable = variables[Object.keys(variables)[0]];
|
||||
t.equal(variable.id, 'foo');
|
||||
t.equal(variable.name, 'bar');
|
||||
t.equal(variable.type, Variable.LIST_TYPE);
|
||||
t.assert(variable.value instanceof Array, true);
|
||||
t.equal(variable.value.length, 0);
|
||||
t.equal(variable.isCloud, false);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('createVariable throws when given invalid type', t => {
|
||||
const target = new Target();
|
||||
t.throws(
|
||||
(() => target.createVariable('foo', 'bar', 'baz')),
|
||||
new Error('Invalid variable type: baz')
|
||||
);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
// Rename Variable tests.
|
||||
test('renameVariable', t => {
|
||||
const target = new Target();
|
||||
target.createVariable('foo', 'bar');
|
||||
target.createVariable('foo', 'bar', Variable.SCALAR_TYPE);
|
||||
target.renameVariable('foo', 'bar2');
|
||||
|
||||
const variables = target.variables;
|
||||
|
@ -80,7 +110,7 @@ test('renameVariable2', t => {
|
|||
// Expect no change.
|
||||
test('renameVariable3', t => {
|
||||
const target = new Target();
|
||||
target.createVariable('foo1', 'foo');
|
||||
target.createVariable('foo1', 'foo', Variable.SCALAR_TYPE);
|
||||
target.renameVariable('foo', 'bar2');
|
||||
|
||||
const variables = target.variables;
|
||||
|
@ -95,7 +125,7 @@ test('renameVariable3', t => {
|
|||
// Delete Variable tests.
|
||||
test('deleteVariable', t => {
|
||||
const target = new Target();
|
||||
target.createVariable('foo', 'bar');
|
||||
target.createVariable('foo', 'bar', Variable.SCALAR_TYPE);
|
||||
target.deleteVariable('foo');
|
||||
|
||||
const variables = target.variables;
|
||||
|
@ -114,3 +144,32 @@ test('deleteVariable2', t => {
|
|||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('lookupOrCreateList creates a list if var with given id does not exist', t => {
|
||||
const target = new Target();
|
||||
const variables = target.variables;
|
||||
|
||||
t.equal(Object.keys(variables).length, 0);
|
||||
const listVar = target.lookupOrCreateList('foo', 'bar');
|
||||
t.equal(Object.keys(variables).length, 1);
|
||||
t.equal(listVar.id, 'foo');
|
||||
t.equal(listVar.name, 'bar');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('lookupOrCreateList returns list if one with given id exists', t => {
|
||||
const target = new Target();
|
||||
const variables = target.variables;
|
||||
|
||||
t.equal(Object.keys(variables).length, 0);
|
||||
target.createVariable('foo', 'bar', Variable.LIST_TYPE);
|
||||
t.equal(Object.keys(variables).length, 1);
|
||||
|
||||
const listVar = target.lookupOrCreateList('foo', 'bar');
|
||||
t.equal(Object.keys(variables).length, 1);
|
||||
t.equal(listVar.id, 'foo');
|
||||
t.equal(listVar.name, 'bar');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue