text: const should = require('should');
  const sinon = require('sinon');
  const fs = require('fs-extra');
  const common = require('../../../../server/lib/common');
  const manipulator = require('../../../../server/lib/image/manipulator');
  const testUtils = require('../../../utils');
  const sandbox = sinon.sandbox.create();
  
  describe('lib/image: manipulator', function () {
      afterEach(function () {
          sandbox.restore();
          testUtils.unmockNotExistingModule();
      });
  
      describe('cases', function () {
          let sharp, sharpInstance;
  
          beforeEach(function () {
              sandbox.stub(fs, 'readFile').resolves('original');
              sandbox.stub(fs, 'writeFile').resolves();
  
              sharpInstance = {
                  metadata: sandbox.stub(),
                  resize: sandbox.stub(),
                  rotate: sandbox.stub(),
                  toBuffer: sandbox.stub(),
              };
  
              sharp = sandbox.stub().callsFake(() => {
                  return sharpInstance;
              });
  
              sharp.cache = sandbox.stub();
              testUtils.mockNotExistingModule('sharp', sharp);
          });
  
          it('resize image', function () {
              sharpInstance.metadata.resolves({width: 2000, height: 2000});
              sharpInstance.toBuffer.resolves({
                  data: 'manipulated',
                  info: {
                      size: 42
                  }
              });
  
              return manipulator.process({width: 1000})
                  .then(() => {
                      sharp.cache.calledOnce.should.be.true();
                      sharpInstance.metadata.calledOnce.should.be.true();
                      sharpInstance.resize.calledOnce.should.be.true();
                      sharpInstance.rotate.calledOnce.should.be.true();
  
                      fs.writeFile.calledOnce.should.be.true();
                      fs.writeFile.calledWith('manipulated');
                  });
          });
  
          it('skip resizing if image is too small', function () {
              sharpInstance.metadata.resolves({width: 50, height: 50});
              sharpInstance.toBuffer.resolves({
                  data: 'manipulated',
                  info: {
                      size: 42
                  }
              });
  
              return manipulator.process({width: 1000})
                  .then(() => {
                      sharp.cache.calledOnce.should.be.true();
                      sharpInstance.metadata.calledOnce.should.be.true();
                      sharpInstance.resize.calledOnce.should.be.false();
                      sharpInstance.rotate.calledOnce.should.be.true();
  
                      fs.writeFile.calledOnce.should.be.true();
                      fs.writeFile.calledWith('manipulated');
                  });
          });
  
          it('uses original image as an output when the size (bytes) is bigger after manipulation', function () {
              sharpInstance.metadata.resolves({
                  width: 2000,
                  size: 10
              });
  
              sharpInstance.toBuffer.resolves({
                  data: 'manipulated',
                  info: {
                      size: 42
                  }
              });
  
              return manipulator.process({width: 1000})
                  .then(() => {
                      sharp.cache.calledOnce.should.be.true();
                      sharpInstance.metadata.calledOnce.should.be.true();
                      sharpInstance.resize.calledOnce.should.be.true();
                      sharpInstance.rotate.calledOnce.should.be.true();
                      sharpInstance.toBuffer.calledOnce.should.be.true();
  
                      fs.writeFile.calledOnce.should.be.true();
                      fs.writeFile.calledWith('original');
                  });
          });
  
          it('sharp throws error during processing', function () {
              sharpInstance.metadata.resolves({width: 500, height: 500});
              sharpInstance.toBuffer.resolves({
                  data: 'manipulated',
                  info: {
                      size: 42
                  }
              });
  
              fs.writeFile.rejects(new Error('whoops'));
  
              return manipulator.process({width: 2000})
                  .then(() => {
                      '1'.should.eql(1, 'Expected to fail');
                  })
                  .catch((err) => {
                      (err instanceof common.errors.InternalServerError).should.be.true;
                      err.code.should.eql('IMAGE_PROCESSING');
                      sharp.cache.calledOnce.should.be.true;
                      sharpInstance.metadata.calledOnce.should.be.true();
                      sharpInstance.resize.calledOnce.should.be.false();
                      sharpInstance.rotate.calledOnce.should.be.true();
  
                      fs.writeFile.calledOnce.should.be.true();
                  });
          });
      });
  
      describe('installation', function () {
          beforeEach(function () {
              testUtils.mockNotExistingModule('sharp', new Error(), true);
          });
  
          it('sharp was not installed', function () {
              return manipulator.process()
                  .then(() => {
                      '1'.should.eql(1, 'Expected to fail');
                  })
                  .catch((err) => {
                      (err instanceof common.errors.InternalServerError).should.be.true();
                      err.code.should.eql('SHARP_INSTALLATION');
                  });
          });
      });
  });
  