diff --git a/lib/unzip.js b/lib/unzip.js index 0d643111..0c930dfc 100644 --- a/lib/unzip.js +++ b/lib/unzip.js @@ -23,10 +23,18 @@ module.exports = function (input, isGZip, isSprite, callback) { } return JSZip.loadAsync(input) .then(function (zip) { - return zip.file(isSprite ? 'sprite.json' : 'project.json').async('string') - .then(function (project) { - return callback(null, [project, zip]); - }); + // look for json in the list of files, or in a subdirectory + // assumes there is only one sprite or project json in the zipfile + const file = isSprite ? + zip.file(/^([^/]*\/)?sprite\.json$/)[0] : + zip.file(/^([^/]*\/)?project\.json$/)[0]; + if (file) { + return file.async('string') + .then(function (project) { + return callback(null, [project, zip]); + }); + } + return callback(msg + 'missing project or sprite json'); }) .catch(function (err) { return callback(msg + JSON.stringify(err)); diff --git a/test/fixtures/data.js b/test/fixtures/data.js index fef92573..7aebec80 100644 --- a/test/fixtures/data.js +++ b/test/fixtures/data.js @@ -33,14 +33,16 @@ module.exports = { sb: fs.readFileSync(path.resolve(__dirname, './data/_example.sb')), sb2: fs.readFileSync(path.resolve(__dirname, './data/_example.sb2')), json: fs.readFileSync(path.resolve(__dirname, './data/_example.json')), - gzipJson: fs.readFileSync(path.resolve(__dirname, './data/_example.json.gz')) + gzipJson: fs.readFileSync(path.resolve(__dirname, './data/_example.json.gz')), + invalidEmpty: fs.readFileSync(path.resolve(__dirname, './data/invalid/_invalidEmpty.sb2')) }, sprites: { default_cat_sprite2: fs.readFileSync(path.resolve(__dirname, './data/_default_cat.sprite2')), default_cat_sprite2_json: fs.readFileSync(path.resolve(__dirname, './data/_default_cat.sprite2json')), example_sprite2: fs.readFileSync(path.resolve(__dirname, './data/_example_sprite.sprite2')), example_sprite2_json: fs.readFileSync(path.resolve(__dirname, './data/_example_sprite.sprite2json')), - bananas_sprite2: fs.readFileSync(path.resolve(__dirname, './data/_bananas.sprite2')) + bananas_sprite2: fs.readFileSync(path.resolve(__dirname, './data/_bananas.sprite2')), + bananas_nested_sprite2: fs.readFileSync(path.resolve(__dirname, './data/_bananas_nested.sprite2')) }, sb3_comments: { comments: fs.readFileSync(path.resolve(__dirname, './data/_comments.sb3')), diff --git a/test/fixtures/data/_bananas_nested.sprite2 b/test/fixtures/data/_bananas_nested.sprite2 new file mode 100644 index 00000000..cdbafef1 Binary files /dev/null and b/test/fixtures/data/_bananas_nested.sprite2 differ diff --git a/test/fixtures/data/_nestedFolder.sb2 b/test/fixtures/data/_nestedFolder.sb2 new file mode 100644 index 00000000..2395c048 Binary files /dev/null and b/test/fixtures/data/_nestedFolder.sb2 differ diff --git a/test/fixtures/data/invalid/_invalidEmpty.sb2 b/test/fixtures/data/invalid/_invalidEmpty.sb2 new file mode 100644 index 00000000..978903cc Binary files /dev/null and b/test/fixtures/data/invalid/_invalidEmpty.sb2 differ diff --git a/test/integration/example.js b/test/integration/example.js index 7dac9ad4..98e63c30 100644 --- a/test/integration/example.js +++ b/test/integration/example.js @@ -62,3 +62,13 @@ test('gzipped json', function (t) { t.end(); }); }); + +test('invalid empty project archive', function (t) { + var msg = 'Failed to unzip and extract project.json, with error: '; + parser(data.example.invalidEmpty, false, function (err, result) { + t.type(err, 'string'); + t.equal(err.startsWith(msg), true); + t.type(result, 'undefined'); + t.end(); + }); +}); diff --git a/test/integration/sprites.js b/test/integration/sprites.js index dc1ef982..7662dccc 100644 --- a/test/integration/sprites.js +++ b/test/integration/sprites.js @@ -42,6 +42,19 @@ test('banana sprite2, no sounds', function (t) { }); }); +test('nested banana sprite2', function (t) { + parser(data.sprites.bananas_nested_sprite2, true, function (err, result) { + t.equal(err, null); + t.equal(Array.isArray(result), true); + var res = result[0]; + var possibleZip = result[1]; + t.type(res, 'object'); + t.equal(res.projectVersion, 2); + t.equal(possibleZip instanceof JSZip, true); + t.end(); + }); +}); + test('default cat sprite2 json', function (t) { parser(data.sprites.default_cat_sprite2_json, true, function (err, result) { t.equal(err, null); diff --git a/test/unit/unzip.js b/test/unit/unzip.js index 4a0178c5..bc9a2cb2 100644 --- a/test/unit/unzip.js +++ b/test/unit/unzip.js @@ -11,7 +11,8 @@ var fixtures = { zipFakeProjectJSON: path.resolve(__dirname, '../fixtures/data/_zipFakeProjectJson.zip'), zipNoProjectJSON: - path.resolve(__dirname, '../fixtures/data/_zipNoProjectJson.zip') + path.resolve(__dirname, '../fixtures/data/_zipNoProjectJson.zip'), + sb2Nested: path.resolve(__dirname, '../fixtures/data/_nestedFolder.sb2') }; for (var i in fixtures) { @@ -63,6 +64,20 @@ test('gzipped JSON', function (t) { }); }); +test('sb2 with nested folder', function (t) { + var buffer = new Buffer(fixtures.sb2Nested); + unzip(buffer, false, false, function (err, res) { + t.equal(err, null); + t.equal(Array.isArray(res), true); + t.type(res[0], 'string'); + t.doesNotThrow(function () { + JSON.parse(res[0]); + }); + t.equal(res[1] instanceof JSZip, true); + t.end(); + }); +}); + test('zip without project json', function (t) { var buffer = new Buffer(fixtures.zipNoProjectJSON); unzip(buffer, false, false, function (err, res) {