mirror of
https://github.com/scratchfoundation/scratch-analysis.git
synced 2025-03-28 05:30:15 -04:00
Merge pull request #63 from scratchfoundation/develop
Release: 2024-11-07
This commit is contained in:
commit
8227b37697
16 changed files with 29247 additions and 30 deletions
1
.github/CODEOWNERS.md
vendored
Normal file
1
.github/CODEOWNERS.md
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@scratchfoundation/scratch-engineering
|
25
.github/workflows/build.yml
vendored
Normal file
25
.github/workflows/build.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
name: build-scratch-analysis
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
jobs:
|
||||||
|
setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Run Tests
|
||||||
|
run: npm test
|
||||||
|
- name: Semantic Release
|
||||||
|
if: github.ref_name == 'master'
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: npx --no -- semantic-release
|
||||||
|
|
||||||
|
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,7 +4,6 @@
|
||||||
## NPM
|
## NPM
|
||||||
/node_modules
|
/node_modules
|
||||||
npm-*
|
npm-*
|
||||||
package-lock.json
|
|
||||||
|
|
||||||
## Code Coverage
|
## Code Coverage
|
||||||
.nyc_output/
|
.nyc_output/
|
||||||
|
|
1
.nvmrc
Normal file
1
.nvmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
v18
|
21
.travis.yml
21
.travis.yml
|
@ -1,21 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 16
|
|
||||||
- lts/*
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- node_modules
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- stage: release
|
|
||||||
node_js: 16
|
|
||||||
script: echo deploying...
|
|
||||||
deploy:
|
|
||||||
- provider: script
|
|
||||||
script: npx semantic-release --branches develop
|
|
||||||
on:
|
|
||||||
branch: develop
|
|
||||||
stages:
|
|
||||||
- test
|
|
||||||
- name: release
|
|
||||||
if: type != pull_request AND branch = develop
|
|
24
lib/sb2.js
24
lib/sb2.js
|
@ -67,6 +67,28 @@ const extract = function (project, attribute, id, hash) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract summary information about backdrops including
|
||||||
|
* count, list of backdrop names and list of backdrop hashes.
|
||||||
|
* Backdrops are a subset of all costumes.
|
||||||
|
* Backdrops are a costumes from the stage object.
|
||||||
|
* @param {object} project Project object (SB2 format)
|
||||||
|
* @return {object} Summary information
|
||||||
|
*/
|
||||||
|
const backdrops = function (project) {
|
||||||
|
let stageCostumes = project.costumes;
|
||||||
|
|
||||||
|
if (!Array.isArray(stageCostumes)) {
|
||||||
|
return {count: 0, id: [], hash: []};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
count: stageCostumes.length,
|
||||||
|
id: stageCostumes.map((sc) => sc.costumeName),
|
||||||
|
hash: stageCostumes.map((sc) => sc.baseLayerMD5)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract number of sprites from a project object. Will attempt to ignore
|
* Extract number of sprites from a project object. Will attempt to ignore
|
||||||
* "children" which are not sprites.
|
* "children" which are not sprites.
|
||||||
|
@ -227,6 +249,8 @@ module.exports = function (project, callback) {
|
||||||
costumes: extract(project, 'costumes', 'costumeName', 'baseLayerMD5')
|
costumes: extract(project, 'costumes', 'costumeName', 'baseLayerMD5')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
meta.backdrops = backdrops(project);
|
||||||
|
|
||||||
meta.cloud = cloud(project, meta.variables.id);
|
meta.cloud = cloud(project, meta.variables.id);
|
||||||
|
|
||||||
// Sprites
|
// Sprites
|
||||||
|
|
47
lib/sb3.js
47
lib/sb3.js
|
@ -16,6 +16,31 @@ const scripts = function (targets) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const costumes = function (targets) {
|
||||||
|
// Storage objects
|
||||||
|
let occurrences = 0;
|
||||||
|
let nameList = [];
|
||||||
|
let hashList = [];
|
||||||
|
|
||||||
|
for (let t in targets) {
|
||||||
|
for (let a in targets[t].costumes) {
|
||||||
|
const costume = targets[t].costumes[a];
|
||||||
|
occurrences++;
|
||||||
|
nameList.push(costume.name);
|
||||||
|
|
||||||
|
let hash = costume.md5ext || `${costume.assetId}.${costume.dataFormat}`;
|
||||||
|
hashList.push(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// field are named this way to keep backward compatibility
|
||||||
|
return {
|
||||||
|
count: occurrences,
|
||||||
|
id: nameList,
|
||||||
|
hash: hashList
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const variables = function (targets, attribute) {
|
const variables = function (targets, attribute) {
|
||||||
// Storage objects
|
// Storage objects
|
||||||
let occurrences = 0;
|
let occurrences = 0;
|
||||||
|
@ -92,10 +117,22 @@ const blocks = function (targets) {
|
||||||
for (let t in targets) {
|
for (let t in targets) {
|
||||||
for (let a in targets[t].blocks) {
|
for (let a in targets[t].blocks) {
|
||||||
const block = targets[t].blocks[a];
|
const block = targets[t].blocks[a];
|
||||||
|
let opcode = block.opcode;
|
||||||
|
|
||||||
|
// Check for primitive blocks which don't have the opcode field
|
||||||
|
if (typeof opcode === 'undefined') {
|
||||||
|
switch (block[0]) {
|
||||||
|
case (12):
|
||||||
|
opcode = 'data_variable';
|
||||||
|
break;
|
||||||
|
case (13):
|
||||||
|
opcode = 'data_listcontents';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get opcode and check variable manipulation for the presence of
|
// Get opcode and check variable manipulation for the presence of
|
||||||
// cloud variables
|
// cloud variables
|
||||||
let opcode = block.opcode;
|
|
||||||
if (opcode === 'data_setvariableto' || opcode === 'data_changevariableby') {
|
if (opcode === 'data_setvariableto' || opcode === 'data_changevariableby') {
|
||||||
if (isArgCloudVar(block.fields.VARIABLE[1])) {
|
if (isArgCloudVar(block.fields.VARIABLE[1])) {
|
||||||
opcode += '_cloud';
|
opcode += '_cloud';
|
||||||
|
@ -133,6 +170,10 @@ const metadata = function (meta) {
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const stageTargets = function (targets) {
|
||||||
|
return targets.filter((target) => target.isStage);
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = function (project, callback) {
|
module.exports = function (project, callback) {
|
||||||
const meta = {
|
const meta = {
|
||||||
scripts: scripts(project.targets),
|
scripts: scripts(project.targets),
|
||||||
|
@ -141,7 +182,9 @@ module.exports = function (project, callback) {
|
||||||
lists: variables(project.targets, 'lists'),
|
lists: variables(project.targets, 'lists'),
|
||||||
comments: extract(project.targets, 'comments'),
|
comments: extract(project.targets, 'comments'),
|
||||||
sounds: extract(project.targets, 'sounds', 'name', 'md5ext'),
|
sounds: extract(project.targets, 'sounds', 'name', 'md5ext'),
|
||||||
costumes: extract(project.targets, 'costumes', 'name', 'md5ext'),
|
costumes: costumes(project.targets),
|
||||||
|
// backdrops are costumes on the stage target
|
||||||
|
backdrops: costumes(stageTargets(project.targets)),
|
||||||
sprites: sprites(project.targets),
|
sprites: sprites(project.targets),
|
||||||
blocks: blocks(project.targets),
|
blocks: blocks(project.targets),
|
||||||
extensions: extensions(project.extensions),
|
extensions: extensions(project.extensions),
|
||||||
|
|
28841
package-lock.json
generated
Normal file
28841
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -21,6 +21,7 @@
|
||||||
"@babel/eslint-parser": "^7.5.4",
|
"@babel/eslint-parser": "^7.5.4",
|
||||||
"eslint": "^8.16.0",
|
"eslint": "^8.16.0",
|
||||||
"eslint-config-scratch": "^7.0.0",
|
"eslint-config-scratch": "^7.0.0",
|
||||||
|
"scratch-semantic-release-config": "1.0.8",
|
||||||
"tap": "^16.2.0"
|
"tap": "^16.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
release.config.js
Normal file
9
release.config.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: 'scratch-semantic-release-config',
|
||||||
|
branches: [
|
||||||
|
{
|
||||||
|
name: 'master'
|
||||||
|
// default channel
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
23
test/fixtures/sb2/invalid-costumes.json
vendored
Normal file
23
test/fixtures/sb2/invalid-costumes.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"objName": "Stage",
|
||||||
|
"sounds": [{
|
||||||
|
"soundName": "pop",
|
||||||
|
"soundID": -1,
|
||||||
|
"md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
|
||||||
|
"sampleCount": 258,
|
||||||
|
"rate": 11025,
|
||||||
|
"format": ""
|
||||||
|
}],
|
||||||
|
"costumes": {
|
||||||
|
"invalid": "This should be an array but is an object instead"
|
||||||
|
},
|
||||||
|
"currentCostumeIndex": 0,
|
||||||
|
"penLayerMD5": "5c81a336fab8be57adc039a8a2b33ca9.png",
|
||||||
|
"penLayerID": -1,
|
||||||
|
"children": [],
|
||||||
|
"info": {
|
||||||
|
"videoOn": false,
|
||||||
|
"scriptCount": 0,
|
||||||
|
"spriteCount": 0
|
||||||
|
}
|
||||||
|
}
|
8
test/fixtures/sb3/default.json
vendored
8
test/fixtures/sb3/default.json
vendored
|
@ -69,6 +69,14 @@
|
||||||
"dataFormat": "svg",
|
"dataFormat": "svg",
|
||||||
"rotationCenterX": 46,
|
"rotationCenterX": 46,
|
||||||
"rotationCenterY": 53
|
"rotationCenterY": 53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"assetId": "d27716e022fb5f747d7b09fe6eeeca06",
|
||||||
|
"name": "costume_without_md5ext",
|
||||||
|
"bitmapResolution": 1,
|
||||||
|
"dataFormat": "svg",
|
||||||
|
"rotationCenterX": 71,
|
||||||
|
"rotationCenterY": 107
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sounds": [
|
"sounds": [
|
||||||
|
|
BIN
test/fixtures/sb3/default.sb3
vendored
BIN
test/fixtures/sb3/default.sb3
vendored
Binary file not shown.
136
test/fixtures/sb3/primitiveVariableAndListBlocks.json
vendored
Normal file
136
test/fixtures/sb3/primitiveVariableAndListBlocks.json
vendored
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
{
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"isStage": true,
|
||||||
|
"name": "Stage",
|
||||||
|
"variables": {
|
||||||
|
"T1[{JjfXy_y{K@EQkA?1": [
|
||||||
|
"my_variable",
|
||||||
|
"0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lists": {
|
||||||
|
"HewanSoehucCjFovU@^H": [
|
||||||
|
"my_list",
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"broadcasts": {},
|
||||||
|
"blocks": {},
|
||||||
|
"comments": {},
|
||||||
|
"currentCostume": 0,
|
||||||
|
"costumes": [
|
||||||
|
{
|
||||||
|
"assetId": "cd21514d0531fdffb22204e0ec5ed84a",
|
||||||
|
"name": "backdrop1",
|
||||||
|
"md5ext": "cd21514d0531fdffb22204e0ec5ed84a.svg",
|
||||||
|
"dataFormat": "svg",
|
||||||
|
"rotationCenterX": 240,
|
||||||
|
"rotationCenterY": 180
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sounds": [
|
||||||
|
{
|
||||||
|
"assetId": "83a9787d4cb6f3b7632b4ddfebf74367",
|
||||||
|
"name": "pop",
|
||||||
|
"dataFormat": "wav",
|
||||||
|
"format": "",
|
||||||
|
"rate": 44100,
|
||||||
|
"sampleCount": 1032,
|
||||||
|
"md5ext": "83a9787d4cb6f3b7632b4ddfebf74367.wav"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"volume": 100,
|
||||||
|
"layerOrder": 0,
|
||||||
|
"tempo": 60,
|
||||||
|
"videoTransparency": 50,
|
||||||
|
"videoState": "on",
|
||||||
|
"textToSpeechLanguage": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isStage": false,
|
||||||
|
"name": "Sprite1",
|
||||||
|
"variables": {},
|
||||||
|
"lists": {},
|
||||||
|
"broadcasts": {},
|
||||||
|
"blocks": {
|
||||||
|
"wS7V(|TE2G9v@AX8BYK~": [
|
||||||
|
13,
|
||||||
|
"my_list",
|
||||||
|
"HewanSoehucCjFovU@^H",
|
||||||
|
713,
|
||||||
|
604
|
||||||
|
],
|
||||||
|
"|#CTw):^,.,NSY)[Tnb?": {
|
||||||
|
"opcode": "motion_changexby",
|
||||||
|
"next": null,
|
||||||
|
"parent": "^m#)|6_G10cLNp(ZlZv(",
|
||||||
|
"inputs": {
|
||||||
|
"DX": [
|
||||||
|
3,
|
||||||
|
[
|
||||||
|
12,
|
||||||
|
"my_variable",
|
||||||
|
"T1[{JjfXy_y{K@EQkA?1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
"10"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fields": {},
|
||||||
|
"shadow": false,
|
||||||
|
"topLevel": false
|
||||||
|
},
|
||||||
|
"2_SCXE]6;tCt$ZcG|GQ(": [
|
||||||
|
12,
|
||||||
|
"my_variable",
|
||||||
|
"T1[{JjfXy_y{K@EQkA?1",
|
||||||
|
322,
|
||||||
|
449
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"comments": {},
|
||||||
|
"currentCostume": 0,
|
||||||
|
"costumes": [
|
||||||
|
{
|
||||||
|
"assetId": "b7853f557e4426412e64bb3da6531a99",
|
||||||
|
"name": "costume1",
|
||||||
|
"bitmapResolution": 1,
|
||||||
|
"md5ext": "b7853f557e4426412e64bb3da6531a99.svg",
|
||||||
|
"dataFormat": "svg",
|
||||||
|
"rotationCenterX": 48,
|
||||||
|
"rotationCenterY": 50
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sounds": [
|
||||||
|
{
|
||||||
|
"assetId": "83c36d806dc92327b9e7049a565c6bff",
|
||||||
|
"name": "Meow",
|
||||||
|
"dataFormat": "wav",
|
||||||
|
"format": "",
|
||||||
|
"rate": 44100,
|
||||||
|
"sampleCount": 37376,
|
||||||
|
"md5ext": "83c36d806dc92327b9e7049a565c6bff.wav"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"volume": 100,
|
||||||
|
"layerOrder": 1,
|
||||||
|
"visible": true,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"size": 100,
|
||||||
|
"direction": 90,
|
||||||
|
"draggable": false,
|
||||||
|
"rotationStyle": "all around"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"monitors": [],
|
||||||
|
"meta": {
|
||||||
|
"semver": "3.0.0",
|
||||||
|
"vm": "0.2.0-prerelease.20181217191056",
|
||||||
|
"agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
|
||||||
|
"origin": "test.scratch.mit.edu"
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,9 @@ const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const test = require('tap').test;
|
const test = require('tap').test;
|
||||||
const analysis = require('../../lib/index');
|
const analysis = require('../../lib/index');
|
||||||
|
// using the sb2 directly to bypass scratch-parser and excersise
|
||||||
|
// logic targeting broken project files
|
||||||
|
const sb2 = require('../../lib/sb2');
|
||||||
|
|
||||||
const defaultObject = fs.readFileSync(
|
const defaultObject = fs.readFileSync(
|
||||||
path.resolve(__dirname, '../fixtures/sb2/default.json')
|
path.resolve(__dirname, '../fixtures/sb2/default.json')
|
||||||
|
@ -13,6 +16,10 @@ const complexBinary = fs.readFileSync(
|
||||||
path.resolve(__dirname, '../fixtures/sb2/complex.sb2')
|
path.resolve(__dirname, '../fixtures/sb2/complex.sb2')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const invalidCostumes = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../fixtures/sb2/invalid-costumes.json')
|
||||||
|
);
|
||||||
|
|
||||||
test('default (object)', t => {
|
test('default (object)', t => {
|
||||||
analysis(defaultObject, (err, result) => {
|
analysis(defaultObject, (err, result) => {
|
||||||
t.ok(typeof err === 'undefined' || err === null);
|
t.ok(typeof err === 'undefined' || err === null);
|
||||||
|
@ -56,6 +63,15 @@ test('default (object)', t => {
|
||||||
'3696356a03a8d938318876a593572843.svg'
|
'3696356a03a8d938318876a593572843.svg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 1);
|
||||||
|
t.same(result.backdrops.id, [
|
||||||
|
'backdrop1'
|
||||||
|
]);
|
||||||
|
t.same(result.backdrops.hash, [
|
||||||
|
'739b5e2a2435f6e1ec2993791b423146.png'
|
||||||
|
]);
|
||||||
|
|
||||||
t.type(result.sprites, 'object');
|
t.type(result.sprites, 'object');
|
||||||
t.equal(result.sprites.count, 1);
|
t.equal(result.sprites.count, 1);
|
||||||
|
|
||||||
|
@ -119,6 +135,15 @@ test('default (binary)', t => {
|
||||||
'6e8bd9ae68fdb02b7e1e3df656a75635.svg'
|
'6e8bd9ae68fdb02b7e1e3df656a75635.svg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 1);
|
||||||
|
t.same(result.backdrops.id, [
|
||||||
|
'backdrop1'
|
||||||
|
]);
|
||||||
|
t.same(result.backdrops.hash, [
|
||||||
|
'739b5e2a2435f6e1ec2993791b423146.png'
|
||||||
|
]);
|
||||||
|
|
||||||
t.type(result.sprites, 'object');
|
t.type(result.sprites, 'object');
|
||||||
t.equal(result.sprites.count, 1);
|
t.equal(result.sprites.count, 1);
|
||||||
|
|
||||||
|
@ -185,6 +210,15 @@ test('complex (binary)', t => {
|
||||||
'6e8bd9ae68fdb02b7e1e3df656a75635.svg'
|
'6e8bd9ae68fdb02b7e1e3df656a75635.svg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 1);
|
||||||
|
t.same(result.backdrops.id, [
|
||||||
|
'backdrop1'
|
||||||
|
]);
|
||||||
|
t.same(result.backdrops.hash, [
|
||||||
|
'5b465b3b07d39019109d8dc6d6ee6593.svg'
|
||||||
|
]);
|
||||||
|
|
||||||
t.type(result.sprites, 'object');
|
t.type(result.sprites, 'object');
|
||||||
t.equal(result.sprites.count, 1);
|
t.equal(result.sprites.count, 1);
|
||||||
|
|
||||||
|
@ -257,3 +291,18 @@ test('complex (binary)', t => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('stage with invalid costumes', t => {
|
||||||
|
const project = JSON.parse(invalidCostumes);
|
||||||
|
|
||||||
|
sb2(project, (err, result) => {
|
||||||
|
t.ok(typeof err === 'undefined' || err === null);
|
||||||
|
t.type(result, 'object');
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 0);
|
||||||
|
t.same(result.backdrops.id, []);
|
||||||
|
t.same(result.backdrops.hash, []);
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -21,6 +21,10 @@ const badExtensions = fs.readFileSync(
|
||||||
path.resolve(__dirname, '../fixtures/sb3/badExtensions.json')
|
path.resolve(__dirname, '../fixtures/sb3/badExtensions.json')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const primitiveVariableAndListBlocks = fs.readFileSync(
|
||||||
|
path.resolve(__dirname, '../fixtures/sb3/primitiveVariableAndListBlocks.json')
|
||||||
|
);
|
||||||
|
|
||||||
test('default (object)', t => {
|
test('default (object)', t => {
|
||||||
analysis(defaultObject, (err, result) => {
|
analysis(defaultObject, (err, result) => {
|
||||||
t.ok(typeof err === 'undefined' || err === null);
|
t.ok(typeof err === 'undefined' || err === null);
|
||||||
|
@ -54,16 +58,27 @@ test('default (object)', t => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
t.type(result.costumes, 'object');
|
t.type(result.costumes, 'object');
|
||||||
t.equal(result.costumes.count, 3);
|
t.equal(result.costumes.count, 4);
|
||||||
t.same(result.costumes.id, [
|
t.same(result.costumes.id, [
|
||||||
'backdrop1',
|
'backdrop1',
|
||||||
'costume1',
|
'costume1',
|
||||||
'costume2'
|
'costume2',
|
||||||
|
'costume_without_md5ext'
|
||||||
]);
|
]);
|
||||||
t.same(result.costumes.hash, [
|
t.same(result.costumes.hash, [
|
||||||
'cd21514d0531fdffb22204e0ec5ed84a.svg',
|
'cd21514d0531fdffb22204e0ec5ed84a.svg',
|
||||||
'b7853f557e4426412e64bb3da6531a99.svg',
|
'b7853f557e4426412e64bb3da6531a99.svg',
|
||||||
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg'
|
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg',
|
||||||
|
'd27716e022fb5f747d7b09fe6eeeca06.svg'
|
||||||
|
]);
|
||||||
|
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 1);
|
||||||
|
t.same(result.backdrops.id, [
|
||||||
|
'backdrop1'
|
||||||
|
]);
|
||||||
|
t.same(result.backdrops.hash, [
|
||||||
|
'cd21514d0531fdffb22204e0ec5ed84a.svg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
t.type(result.sprites, 'object');
|
t.type(result.sprites, 'object');
|
||||||
|
@ -118,16 +133,27 @@ test('default (binary)', t => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
t.type(result.costumes, 'object');
|
t.type(result.costumes, 'object');
|
||||||
t.equal(result.costumes.count, 3);
|
t.equal(result.costumes.count, 4);
|
||||||
t.same(result.costumes.id, [
|
t.same(result.costumes.id, [
|
||||||
'backdrop1',
|
'backdrop1',
|
||||||
'costume1',
|
'costume1',
|
||||||
'costume2'
|
'costume2',
|
||||||
|
'costume_without_md5ext'
|
||||||
]);
|
]);
|
||||||
t.same(result.costumes.hash, [
|
t.same(result.costumes.hash, [
|
||||||
'cd21514d0531fdffb22204e0ec5ed84a.svg',
|
'cd21514d0531fdffb22204e0ec5ed84a.svg',
|
||||||
'b7853f557e4426412e64bb3da6531a99.svg',
|
'b7853f557e4426412e64bb3da6531a99.svg',
|
||||||
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg'
|
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg',
|
||||||
|
'd27716e022fb5f747d7b09fe6eeeca06.svg'
|
||||||
|
]);
|
||||||
|
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 1);
|
||||||
|
t.same(result.backdrops.id, [
|
||||||
|
'backdrop1'
|
||||||
|
]);
|
||||||
|
t.same(result.backdrops.hash, [
|
||||||
|
'cd21514d0531fdffb22204e0ec5ed84a.svg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
t.type(result.sprites, 'object');
|
t.type(result.sprites, 'object');
|
||||||
|
@ -199,6 +225,15 @@ test('complex (binary)', t => {
|
||||||
'64208764c777be25d34d813dc0b743c7.svg'
|
'64208764c777be25d34d813dc0b743c7.svg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 1);
|
||||||
|
t.same(result.backdrops.id, [
|
||||||
|
'backdrop1'
|
||||||
|
]);
|
||||||
|
t.same(result.backdrops.hash, [
|
||||||
|
'7633d36de03d1df75808f581bbccc742.svg'
|
||||||
|
]);
|
||||||
|
|
||||||
t.type(result.sprites, 'object');
|
t.type(result.sprites, 'object');
|
||||||
t.equal(result.sprites.count, 1);
|
t.equal(result.sprites.count, 1);
|
||||||
|
|
||||||
|
@ -333,6 +368,15 @@ test('regression test IBE-198, a bad list does not break library', t => {
|
||||||
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg'
|
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
t.type(result.backdrops, 'object');
|
||||||
|
t.equal(result.backdrops.count, 1);
|
||||||
|
t.same(result.backdrops.id, [
|
||||||
|
'backdrop1'
|
||||||
|
]);
|
||||||
|
t.same(result.backdrops.hash, [
|
||||||
|
'cd21514d0531fdffb22204e0ec5ed84a.svg'
|
||||||
|
]);
|
||||||
|
|
||||||
t.type(result.sprites, 'object');
|
t.type(result.sprites, 'object');
|
||||||
t.equal(result.sprites.count, 1);
|
t.equal(result.sprites.count, 1);
|
||||||
|
|
||||||
|
@ -351,3 +395,37 @@ test('regression test IBE-198, a bad list does not break library', t => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('correctly handling primitve reporter blocks: list and variable', t => {
|
||||||
|
analysis(primitiveVariableAndListBlocks, (err, result) => {
|
||||||
|
t.ok(typeof err === 'undefined' || err === null);
|
||||||
|
t.type(result, 'object');
|
||||||
|
|
||||||
|
t.type(result.variables, 'object');
|
||||||
|
t.equal(result.variables.count, 1);
|
||||||
|
t.same(result.variables.id, [
|
||||||
|
'my_variable'
|
||||||
|
]);
|
||||||
|
|
||||||
|
t.type(result.lists, 'object');
|
||||||
|
t.equal(result.lists.count, 1);
|
||||||
|
t.same(result.lists.id, [
|
||||||
|
'my_list'
|
||||||
|
]);
|
||||||
|
|
||||||
|
t.type(result.blocks, 'object');
|
||||||
|
t.equal(result.blocks.count, 3);
|
||||||
|
t.equal(result.blocks.unique, 3);
|
||||||
|
t.same(result.blocks.id, [
|
||||||
|
'data_listcontents',
|
||||||
|
'motion_changexby',
|
||||||
|
'data_variable'
|
||||||
|
]);
|
||||||
|
t.same(result.blocks.frequency, {
|
||||||
|
data_listcontents: 1,
|
||||||
|
motion_changexby: 1,
|
||||||
|
data_variable: 1
|
||||||
|
});
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue