diff --git a/.gitignore b/.gitignore index f6e6869..1c6f036 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ test test-output npm-debug.log node_modules +coverage +.idea \ No newline at end of file diff --git a/package.json b/package.json index 652ac4f..16e9189 100644 --- a/package.json +++ b/package.json @@ -10,17 +10,26 @@ "bin": { "jeff": "./bin/jeff" }, + "scripts": { + "test": "NODE_ENV=test mocha --recursive unit-tests", + "istanbul": "istanbul cover _mocha unit-tests/**/*.test.js" + }, "main": "./src/index.js", "dependencies": { - "async": "0.2.10", - "buffer-crc32": "^0.2.5", - "canvas": "1.1.6", - "commander": "2.2.0", - "fs-extra": "0.8.1", - "glob": "4.3.1", - "image-optim": "0.3.0", - "js-beautify": "1.4.2", - "node-pngquant-native": "0.0.12" + "async": "0.2.10", + "buffer-crc32": "^0.2.5", + "canvas": "1.6.11", + "commander": "2.2.0", + "fs-extra": "0.8.1", + "glob": "4.3.1", + "image-optim": "0.3.0", + "js-beautify": "1.4.2", + "node-pngquant-native": "1.0.5" + }, + "devDependencies" : { + "chai": "4.1.2", + "mocha": "5.2.0", + "istanbul": "0.4.5" }, "repository": { "type": "git", @@ -32,4 +41,4 @@ "url": "https://github.com/Wizcorp/jeff/blob/master/LICENSE" } ] -} \ No newline at end of file +} diff --git a/src/SwfObjectProcessor/createSymbols.js b/src/SwfObjectProcessor/createSymbols.js index 9c3fe63..e905cf3 100644 --- a/src/SwfObjectProcessor/createSymbols.js +++ b/src/SwfObjectProcessor/createSymbols.js @@ -4,7 +4,7 @@ var processShape = require('./processShape'); function createSymbol(swfObject) { var symbol = { id: swfObject.id, swfObject: swfObject, parents: {} }; - + switch(swfObject.type) { case 'main': @@ -28,18 +28,16 @@ function createSymbol(swfObject) { case 'shape': var shapes = swfObject.edges; + var nbShapes = shapes.length; var imagesArray = []; - for (var s = 0; s < shapes.length; s += 1) { + for (var s = 0; s < nbShapes; s++) { var shape = shapes[s]; - var fill = shape.leftFill; - var containsImage = fill ? (fill.type ? (fill.type === 'pattern') : false) : false; - if (!containsImage) { - fill = shape.rightFill; - containsImage = fill ? (fill.type ? (fill.type === 'pattern') : false) : false; - } + var isLeftFill = shape && shape.leftFill && shape.leftFill.type === 'pattern'; + var isRightFill = shape && shape.rightFill && shape.rightFill.type === 'pattern'; - if (containsImage) { + if (isLeftFill || isRightFill) { + var fill = isLeftFill ? shape.leftFill : shape.rightFill; var m = fill.matrix; // In case of an image all the components of the matrix have to be divided by 20 @@ -115,7 +113,7 @@ function createSymbol(swfObject) { function createSymbols(swfObjects) { var symbols = []; var nbSymbols = swfObjects.length; - for (var s = 0; s < nbSymbols; s += 1) { + for (var s = 0; s < nbSymbols; s++) { var swfObject = swfObjects[s]; symbols[swfObject.id] = createSymbol(swfObject); } diff --git a/src/SwfObjectProcessor/removeSymbols.js b/src/SwfObjectProcessor/removeSymbols.js index 4ec5885..b5055ad 100644 --- a/src/SwfObjectProcessor/removeSymbols.js +++ b/src/SwfObjectProcessor/removeSymbols.js @@ -1,30 +1,40 @@ 'use strict'; -function removeSymbols(symbols, classSymbols, removeList){ - var nbClassSymbols = classSymbols.length; - for (var s = 0; s < nbClassSymbols; s += 1) { - - var classSymbol = classSymbols[s]; - if (!classSymbol || !classSymbol.children) { - continue; - } - - var children = classSymbol.children; - for (var c = 0; c < children.length; c += 1) { - - var child = children[c]; - var symbol = symbols[child.id]; - if (!symbol.className){ - continue; - } - - var idx = removeList.indexOf(symbol.className); - if (idx !== -1) { - children.splice(c, 1); - c -= 1; - } - } - } +function removeSymbols(symbols, classSymbols, removeList) { + var nbClassSymbols = classSymbols.length; + + for (var s = 0; s < nbClassSymbols; s++) { + var classSymbol = classSymbols[s]; + + if (!classSymbol || !classSymbol.children) { + continue; + } + + var children = classSymbol.children; + + for (var c = 0; c < children.length; c++) { + var child = children[c]; + + if (!child || typeof child.id === "undefined") { + continue; + } + + var symbol = symbols[child.id]; + + if (!symbol || !symbol.className) { + continue; + } + + if (removeList && removeList.length > 0) { + var idx = removeList.indexOf(symbol.className); + + if (idx !== -1) { + children.splice(c, 1); + c -= 1; + } + } + } + } } module.exports = removeSymbols; \ No newline at end of file diff --git a/unit-tests/SwfObjectProcessor/addClassNames.test.js b/unit-tests/SwfObjectProcessor/addClassNames.test.js new file mode 100644 index 0000000..14b1842 --- /dev/null +++ b/unit-tests/SwfObjectProcessor/addClassNames.test.js @@ -0,0 +1,33 @@ +const expect = require('chai').expect; + +const addClassNames = require('../../src/SwfObjectProcessor/addClassNames'); + +describe('Add class names', function () { + it('add one class name', function () { + const symbols = [{}]; + + const classNames = { + test: [0] + }; + + const classNamesKeys = Object.keys(classNames); + + const result = addClassNames(symbols, classNames); + + expect(result[0]).to.exist; + expect(result[0]).to.have.own.property('className'); + expect(result[0].className).to.eql(classNamesKeys[0]); + }); + + it('add no class', function () { + const symbols = []; + + const classNames = { + test: [0] + }; + + const result = addClassNames(symbols, classNames); + + expect(result).to.be.empty; + }); +}); \ No newline at end of file diff --git a/unit-tests/SwfObjectProcessor/createSymbols.test.js b/unit-tests/SwfObjectProcessor/createSymbols.test.js new file mode 100644 index 0000000..c1ddf5b --- /dev/null +++ b/unit-tests/SwfObjectProcessor/createSymbols.test.js @@ -0,0 +1,346 @@ +const expect = require('chai').expect; + +const createSymbols = require('../../src/SwfObjectProcessor/createSymbols'); + +describe('Create Symbols', function () { + it('create symbol from swf object of type \'main\'', function () { + const id = 0; + const frameCount = 1; + + const swfObjects = [{ + id: id, + type: 'main', + frameCount: frameCount + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.have.own.property('isAnimation'); + expect(result[id].isAnimation).to.be.true; + expect(result[id]).to.have.own.property('duration'); + expect(result[id].duration).to.eql(frameCount); + }); + + it('create symbol from swf object of type \'image\'', function () { + const id = 0; + const width = 120; + const height = 120; + + const swfObjects = [{ + id: id, + type: 'image', + width: width, + height: height + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.have.own.property('isGraphic'); + expect(result[id].isGraphic).to.be.true; + expect(result[id]).to.have.own.property('isImage'); + expect(result[id].isImage).to.be.true; + expect(result[id]).to.have.own.property('maxDims'); + expect(result[id].maxDims).to.eql({}); + expect(result[id]).to.have.own.property('bounds'); + expect(result[id].bounds).to.eql([{ + left: 0, + right: width, + top: 0, + bottom: height + }]); + }); + + it('create symbol from swf object of type \'shape\'', function () { + const id = 0; + const imageID = 0; + const length = 20; + + const swfObjects = [{ + id: id, + type: 'shape', + edges: [ + { + leftFill: { + type: 'pattern', + image: { + id: imageID + }, + matrix: { + scaleX: length, + scaleY: length, + skewX: length, + skewY: length, + moveX: length, + moveY: length + } + }, + records: [] + }, + { + rightFill: { + type: 'pattern', + image: { + id: imageID + }, + matrix: { + scaleX: length, + scaleY: length, + skewX: length, + skewY: length, + moveX: length, + moveY: length + } + }, + records: [] + }, + { + leftFill: { + type: 'non-pattern' + }, + records: [] + }, + { + leftFill: {}, + records: [] + }, + { + rightFill: { + type: 'non-pattern' + }, + records: [] + }, + { + rightFill: {}, + records: [] + } + ], + bounds: { + left: length, + right: length, + top: length, + bottom: length + } + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.have.own.property('isGraphic'); + expect(result[id].isGraphic).to.be.true; + expect(result[id]).to.have.own.property('isShape'); + expect(result[id].isShape).to.be.true; + expect(result[id]).to.have.own.property('maxDims'); + expect(result[id].maxDims).to.eql({}); + expect(result[id]).to.have.own.property('bounds'); + expect(result[id].bounds).to.eql([{ + left: length / 20, + right: length / 20, + top: length / 20, + bottom: length / 20 + }]); + expect(result[id]).to.have.own.property('images'); + expect(result[id].images).to.eql([{ + id: imageID, + matrix: [ + length / 20, + length / 20, + length / 20, + length / 20, + length / 20, + length / 20 + ], + image: { + id: imageID + } + }, { + id: imageID, + matrix: [ + length / 20, + length / 20, + length / 20, + length / 20, + length / 20, + length / 20 + ], + image: { + id: imageID + } + }]); + }); + + it('create symbol from swf object of type \'shape\' with no edges', function () { + const id = 0; + const length = 20; + + const swfObjects = [{ + id: id, + type: 'shape', + edges: [], + bounds: { + left: length, + right: length, + top: length, + bottom: length + } + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.have.own.property('bounds'); + expect(result[id].bounds).to.eql([{ + left: length / 20, + right: length / 20, + top: length / 20, + bottom: length / 20 + }]); + }); + + it('create symbol from swf object of type \'morph\'', function () { + const id = 0; + const startLength = 20; + const endLength = 40; + + const swfObjects = [{ + id: id, + type: 'morph', + startBounds: { + left: startLength, + right: startLength, + top: startLength, + bottom: startLength + }, + endBounds: { + left: endLength, + right: endLength, + top: endLength, + bottom: endLength + } + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.have.own.property('isGraphic'); + expect(result[id].isGraphic).to.be.true; + expect(result[id]).to.have.own.property('isMorphing'); + expect(result[id].isMorphing).to.be.true; + expect(result[id]).to.have.own.property('maxDims'); + expect(result[id].maxDims).to.eql({}); + expect(result[id]).to.have.own.property('bounds'); + expect(result[id].bounds).to.eql([{ + left: Math.min(startLength, endLength) / 20, + right: Math.max(startLength, endLength) / 20, + top: Math.min(startLength, endLength) / 20, + bottom: Math.max(startLength, endLength) / 20 + }]); + }); + + it('create symbol from swf object of type \'sprite\'', function () { + const id = 0; + const frameCount = 1; + const length = 20; + + const swfObjects = [{ + id: id, + type: 'sprite', + frameCount: frameCount, + scalingGrid: { + left: length, + right: length, + top: length, + bottom: length + } + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.have.own.property('isAnimation'); + expect(result[id].isAnimation).to.be.true; + expect(result[id]).to.have.own.property('duration'); + expect(result[id].duration).to.eql(frameCount); + expect(result[id]).to.have.own.property('scalingGrid'); + expect(result[id].scalingGrid).to.eql({ + left: length / 20, + right: length / 20, + top: length / 20, + bottom: length / 20 + }); + }); + + it('create symbol from swf object of type \'sprite\' with no scalingGrid', function () { + const id = 0; + const frameCount = 1; + + const swfObjects = [{ + id: id, + type: 'sprite', + frameCount: frameCount + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.have.own.property('isAnimation'); + expect(result[id].isAnimation).to.be.true; + expect(result[id]).to.have.own.property('duration'); + expect(result[id].duration).to.eql(frameCount); + }); + + it('create symbol from swf object of type \'font\'', function () { + const id = 0; + + const swfObjects = [{ + id: id, + type: 'font' + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.eql({ + id: id, + swfObject: swfObjects[0], + parents: {} + }); + }); + + it('create symbol from swf object of type \'text\'', function () { + const id = 0; + + const swfObjects = [{ + id: id, + type: 'text' + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.eql({ + id: id, + swfObject: swfObjects[0], + parents: {} + }); + }); + + it('create symbol from swf object of unknown type', function () { + const id = 0; + + const swfObjects = [{ + id: id, + type: 'null' + }]; + + const result = createSymbols(swfObjects); + + expect(result[id]).to.exist; + expect(result[id]).to.eql({ + id: id, + swfObject: swfObjects[0], + parents: {} + }); + }); +}); \ No newline at end of file diff --git a/unit-tests/SwfObjectProcessor/removeSymbols.test.js b/unit-tests/SwfObjectProcessor/removeSymbols.test.js new file mode 100644 index 0000000..2ee0ee4 --- /dev/null +++ b/unit-tests/SwfObjectProcessor/removeSymbols.test.js @@ -0,0 +1,109 @@ +const expect = require('chai').expect; + +const removeSymbols = require('../../src/SwfObjectProcessor/removeSymbols'); + +describe('Remove Symbols', function () { + const symbols = [{ + className: 'test' + }]; + + const removeList = 'test'; + + it('remove 1 symbol', function () { + const classSymbols = [{ + children: [{ + id: 0 + }] + }]; + + removeSymbols(symbols, classSymbols, removeList); + + expect(classSymbols).to.be.eql([{ + children: [] + }]); + }); + + it('fail removing symbol because className doesn\'t exist in removeList', function () { + const classSymbols = [{ + children: [{ + id: 0 + }] + }]; + + const emptyRemoveList = 'null'; + + removeSymbols(symbols, classSymbols, emptyRemoveList); + + expect(classSymbols).to.be.eql([{ + children: [{ + id: 0 + }] + }]); + }); + + it('fail removing symbol because removeList is null or empty', function () { + const classSymbols = [{ + children: [{ + id: 0 + }] + }]; + + const emptyRemoveList = null; + + removeSymbols(symbols, classSymbols, emptyRemoveList); + + expect(classSymbols).to.be.eql([{ + children: [{ + id: 0 + }] + }]); + }); + + it('fail removing symbol because symbols doesn\'t have className attribute', function () { + const emptySymbols = [{ + empty: '' + }]; + + const classSymbols = [{ + children: [{ + id: 0 + }] + }]; + + removeSymbols(emptySymbols, classSymbols, removeList); + + expect(classSymbols).to.be.eql([{ + children: [{ + id: 0 + }] + }]); + }); + + it('fail removing symbol because classSymbols doesn\'t have children attribute', function () { + const emptyClassSymbols = [{ + empty: '' + }]; + + removeSymbols(symbols, emptyClassSymbols, removeList); + + expect(emptyClassSymbols).to.be.eql([{ + empty: '' + }]); + }); + + it('fail removing symbol because classSymbols\' children doesn\'t have id attribute', function () { + const classSymbols = [{ + children: [{ + empty: '' + }] + }]; + + removeSymbols(symbols, classSymbols, removeList); + + expect(classSymbols).to.be.eql([{ + children: [{ + empty: '' + }] + }]); + }); +}); \ No newline at end of file