import { expect } from 'chai';
import { stub, assert, spy, match } from 'sinon';
import proxyquire from 'proxyquire';
import path from 'path';

describe('npm-dir', () => {

  let NpmDir, fs, io, spawned, handlers;
  beforeEach(() => {
    handlers = {};

    spawned = {
      on: spy(function (name, handler) {
        handlers[name] = handler;
      })
    }

    fs = {
      writeJsonSync: stub(),
      existsSync: stub().returns(true)
    }

    io = {
      spawnPromise: stub().returns(Promise.resolve({}))
    }

    NpmDir = proxyquire('../../../lib/npm/npm-dir', {

      'fs-extra': fs,
      '../io': io,
      'readline': {
        createInterface: stub().returns({
          on: stub()
        })
      },
      '../file-helper': {
        removeFiles: stub()
      }
    }).default;
  });

  describe('constructor', () => {

    it('has rootDir', () => {
      let dir = new NpmDir(__dirname);
      expect(dir.rootDir).to.eql(__dirname);
    });
  });

  describe('install', () => {

    let dir;
    beforeEach(() => {
      dir = new NpmDir(__dirname);
      dir._exists = stub();
    });

    it('writes package.json when installing', (done) => {

      withCloseHandler(() => {
        dir.install({})
          .then(() => {
            assert.calledWith(fs.writeJsonSync, path.join(__dirname, 'package.json'), match.object);
            done();
          })
          .catch(done);
      });
    });

    it('calls \'npm install\' in a child_process', (done) => {
      withCloseHandler(() => {
        dir.install({})
          .then(() => {
            assert.calledWith(io.spawnPromise, 'npm', __dirname, ['install'], false);
            done();
          })
          .catch(done);
      });
    });
  });

  let withCloseHandler = (bodyFn) => {
    bodyFn();
    let close = () => {
      if (handlers.close) {
        handlers.close(0);
      } else {
        setTimeout(close);
      }
    }
    close();
  }

  describe('ls', () => {

    let dir;

    let call = (firstExistsSyncResult, done) => {
      dir = new NpmDir(__dirname);
      fs.existsSync
        .onFirstCall().returns(firstExistsSyncResult)
        .onSecondCall().returns(true);

      dir._spawnPromise = stub().returns(Promise.resolve({ stdout: '{}' }));
      dir._install = stub().returns(Promise.resolve());
      dir.ls()
        .then(done.bind(null, null))
        .catch(done);
    }

    describe('when installed', () => {

      beforeEach((done) => {
        call(true, done);
      });

      it('does not call _install', () => {
        assert.notCalled(dir._install);
      });

      it('calls _spawnPromise', () => {
        assert.calledWith(dir._spawnPromise, ['ls', '--json'], true);
      });
    });

    describe('when not installed', () => {

      beforeEach((done) => {
        call(false, done);
      });

      it('calls _install', () => {
        assert.called(dir._install);
      });

      it('calls _spawnPromise', () => {
        assert.calledWith(dir._spawnPromise, ['ls', '--json'], true);
      });
    });
  });
});
@@ -1153,58 +1153,27 @@
 ', (
-done
 ) =%3E %7B%0A
-%0A
       
-withCloseHandler(() =%3E %7B%0A       
+return
  dir
@@ -1185,34 +1185,32 @@
 all(%7B%7D)%0A        
-  
 .then(() =%3E %7B%0A  
@@ -1199,34 +1199,32 @@
   .then(() =%3E %7B%0A
-  
           assert
@@ -1312,63 +1312,8 @@
 ;%0A  
-          done();%0A          %7D)%0A          .catch(done);%0A
     
@@ -1379,20 +1379,16 @@
 cess', (
-done
 ) =%3E %7B%0A 
@@ -1396,40 +1396,14 @@
     
-withCloseHandler(() =%3E %7B%0A       
+return
  dir
@@ -1419,26 +1419,24 @@
 %7B%7D)%0A        
-  
 .then(() =%3E 
@@ -1429,34 +1429,32 @@
   .then(() =%3E %7B%0A
-  
           assert
@@ -1533,286 +1533,26 @@
     
-    done();%0A          %7D)%0A          .catch(done);%0A      %7D);%0A    %7D);%0A  %7D);%0A%0A  let withCloseHandler = (bodyFn) =%3E %7B%0A    bodyFn();%0A    let close = () =%3E %7B%0A      if (handlers.close) %7B%0A        handlers.close(0);%0A      %7D else %7B%0A        setTimeout(close);%0A      %7D%0A    %7D%0A    close();%0A  %7D
+%7D);%0A    %7D);%0A  %7D);%0A
 %0A%0A  

Add catalog app type `-a catalog` feat(cli): Add `--createArchive` option