UNPKG

gulp-tinypng-extended

Version:

TinyPNG API wrapper for compressing PNG & JPG images

366 lines (274 loc) 9.52 kB
process.env.NODE_ENV = 'test'; var fs = require('fs'), spawn = require('child_process').spawn, crypto = require('crypto'), expect = require('chai').expect, nock = require('nock'), Vinyl = require('vinyl'), dry = process.env.PNG_DRY ? true : false, TinyPNG = require('../index'); var key = 'KHOsJMrP6w-X3FVuyXdevV-vCnDDbqo9', cwd = __dirname, TestFile = function(type) { var file = cwd + '/assets/image' + (type ? '_' + type : '') + '.png'; return new Vinyl({ path: 'image.png', contents: fs.readFileSync(file) }); }; if(dry) console.info('dry flag set, skipping API tests...'); describe('tinypng', function() { it('has correct bound object', function() { var struct = ['conf', 'init', 'stream', 'request', 'hasher', 'utils', 'hash', 'stats'], inst = new TinyPNG(key); expect(inst).to.have.all.keys(struct); }); it('transforms key into config object', function() { var inst = new TinyPNG('test_string_0'); expect(inst.conf.options.key).to.equal('test_string_0'); }); it('init hashing object', function() { var struct = ['sigFile', 'sigs', 'calc', 'update', 'compare', 'populate', 'write'], inst = new TinyPNG(key); expect(inst.hash).to.have.all.keys(struct); }); describe('#init', function() { it('sets object configuration', function() { var inst = new TinyPNG({ key: 'test_string_0', sigFile: 'test_string_1' }); expect(inst.conf.options.key).to.equal('test_string_0'); expect(inst.conf.options.sigFile).to.equal('test_string_1'); expect(inst.conf.token).to.equal(Buffer.from('api:test_string_0').toString('base64')); }); it('throws error on missing API key', function() { expect(TinyPNG).to.throw(Error, /missing api key/i); }); }); describe('#request', function() { var struct = ['file', 'upload', 'download', 'handler', 'get'], inst = new TinyPNG(key), image = new TestFile(), empty_image = new TestFile('empty'); it('returns correct object', function() { expect(inst.request()).to.have.all.keys(struct); expect(new inst.request()).to.have.all.keys(struct); }); describe('#upload', function() { it('uploads and returns object', function(done) { this.timeout(20000); if(dry) return done(); inst.request(image).upload(function(err, data) { expect(err).to.not.be.instanceof(Error); expect(data).to.have.all.keys(['url', 'count']); done(); }); }); it('uploads and and tries to retry on bad gateway error', function(done) { this.timeout(20010); var gateway = nock('https://api.tinify.com') .post('/shrink') .reply(502, '<html><head><title>502 Bad Gateway</title></head><body><h1>502 Bad Gateway</h1></body></html>'); inst.request(image).upload(function(err, data) { expect(err).to.be.instanceof(Error); nock.cleanAll(); done(); }); }); it('upload empty file should throw error, skip and not break the plugin', function(done) { this.timeout(2000); inst.request(empty_image).upload(function(err, data) { expect(err).to.be.instanceof(Error); expect(err.message).to.equal('Error: Empty or broken images could not be send image.png'); done(); }); }); }); describe('#download', function() { it('downloads and returns correct buffer', function(done) { this.timeout(20000); inst.request(new TestFile()).download('http://ovh.net/files/1Mb.dat', function(err, data) { expect(err).to.not.be.instanceof(Error); expect(data.toString()).to.equal(fs.readFileSync(cwd + '/assets/download.dat').toString()); done(); }); }); }); describe('#handler', function() { it('returns correct unknown error', function() { var request = new inst.request(new TestFile()); expect(request.handler({ error: 'TestError'}, 500).message).to.equal('TestError (500): No message returned for image.png'); expect(request.handler({ error: 'TestError', message: 'test'}, 500).message).to.equal('TestError (500): test for image.png'); }); }); describe('#get', function() { it('returns compressed image', function(done) { this.timeout(30000); if(dry) return done(); inst.request(image).get(function(err, file) { expect(err).to.not.be.instanceof(Error); expect(file.contents).to.have.length.lessThan(image.contents.length); done(); }); }); }); }); describe('#hasher', function() { var struct = ['sigFile', 'sigs', 'calc', 'update', 'compare', 'populate', 'write'], inst = new TinyPNG(key), hash = new inst.hasher('test/location'); it('returns correct object', function() { expect(inst.hasher()).to.have.all.keys(struct); expect(new inst.hasher()).to.have.all.keys(struct); }); it('sets signature file location', function() { expect(hash).to.have.property('sigFile', 'test/location'); }); describe('#calc', function() { it('returns md5 hash', function(done) { var file = new TestFile(); hash.calc(file, function(md5) { expect(md5).to.equal(crypto.createHash('md5').update(file.contents).digest('hex')); done(); }); }); }); describe('#update', function() { it('updates internal signature cache', function() { var file = new TestFile(), hash = new inst.hasher(); hash.update(file, 'test_hash'); expect(hash.sigs).to.have.property(file.relative, 'test_hash'); expect(hash.changed).to.equal(true); }); }); describe('#compare', function() { it('compares and succeeds', function(done) { var file = new TestFile(), hash = new inst.hasher(); hash.calc(file, function(md5) { hash.update(file, md5); hash.compare(file, function(result, sig) { expect(result).to.equal(true); expect(sig).to.equal(md5); done(); }); }); }); it('compares and fails', function(done) { var file = new TestFile(), hash = new inst.hasher(); hash.calc(file, function(md5) { hash.compare(file, function(result, sig) { expect(result).to.equal(false); expect(sig).to.equal(md5); done(); }); }); }); }); describe('#populate', function() { afterEach(function() { try { fs.unlinkSync('.test'); } catch(err) {} }); it('reads from sig file and populate internal signature cache', function() { fs.writeFileSync('.test', JSON.stringify({'test.png': 'test_hash'})); var hash = new inst.hasher('.test').populate(); expect(hash.sigs).to.have.property('test.png', 'test_hash'); }); it('fails silently on failed read of sig file', function() { var hash = new inst.hasher('.test'); expect(hash.populate()).to.equal(hash); }); it('doesn\'t error on failed JSON parse', function() { var hash = new inst.hasher('/etc/hosts'); expect(hash.populate).to.not.throw(Error); expect(hash.populate()).to.not.be.instanceof(Error); }); }); describe('#write', function() { afterEach(function() { try { fs.unlinkSync('.test'); } catch(err) {} }); it('writes signature file with correct data', function() { var file = new TestFile(), hash = new inst.hasher('.test'); hash.update(file, 'test_hash'); hash.write(); expect(fs.readFileSync('.test').toString()).to.equal(JSON.stringify(hash.sigs)); }); it('fails silently on failed write of sig file', function() { var file = new TestFile(), hash = new inst.hasher(); hash.update(file, 'test_hash'); expect(hash.write()).to.equal(hash); }); }); }); describe('utils', function() { describe('#glob', function() { var inst = new TinyPNG(key); it('returns proper value on correct glob match', function() { var file = new TestFile(); expect(inst.utils.glob(file, '*ge.png')).to.equal(true); expect(inst.utils.glob(file, '*go.png')).to.equal(false); }); }); }); }); describe('tinypng gulp', function() { var target = cwd + '/assets/tmp/image.png'; before(function() { process.env.TINYPNG_SIGS = true; process.env.TINYPNG_KEY = key; }); after(function() { process.env.TINYPNG_SIGS = false; }); afterEach(function() { try { fs.unlinkSync(target); fs.unlinkSync('.sigs'); } catch(err) {} }); it('returns compressed files', function(done) { this.timeout(30000); if(dry) return done(); file = new TestFile(); var sh = spawn('node', ['node_modules/gulp/bin/gulp.js', 'tinypng']); sh.stdout.on('end', function() { expect(fs.existsSync(target)).to.equal(true, 'compressed output file created'); expect(fs.readFileSync(target)).to.have.length.lessThan(file.contents.length); done(); }); }); it('ignores files on the cli', function(done) { this.timeout(30000); var sh = spawn('node', ['node_modules/gulp/bin/gulp.js', 'tinypng', '--ignore', '*ge.png']); sh.stdout.on('end', function() { expect(fs.existsSync(target)).to.equal(false); done(); }); }); it('forces files on the cli', function(done) { this.timeout(30000); if(dry) return done(); var inst = new TinyPNG(key), hash = new inst.hasher('.sigs'), file = new TestFile(); hash.calc(file, function(md5) { hash.update(file, md5); hash.write(); var sh = spawn('node', ['node_modules/gulp/bin/gulp.js', 'tinypng', '--force', '*ge.png']); sh.stdout.on('end', function() { expect(fs.existsSync(target)).to.equal(true, 'compressed output file created'); expect(fs.readFileSync(target)).to.have.length.lessThan(file.contents.length); done(); }); }); }); });