Skip to content

Commit

Permalink
Merge branch 'issue-8'
Browse files Browse the repository at this point in the history
  • Loading branch information
thomrick committed Aug 6, 2017
2 parents 7b4728a + 0fdc792 commit 848fb87
Show file tree
Hide file tree
Showing 16 changed files with 445 additions and 25 deletions.
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
coverage/
node_modules/
src/
scripts/

.gitignore
.travis.yml
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
"scripts": {
"build": "npm run -s build:src && npm run -s build:assets",
"build:src": "tsc",
"build:assets": "cp -R src/assets bin/assets",
"clean": "rm -rf bin/* && rm -rf coverage/*",
"build:assets": "ts-node scripts/copy.script.ts src/assets bin/assets",
"clean": "ts-node scripts/clean.script.ts bin/* && ts-node scripts/clean.script.ts coverage/*",
"clean:build": "npm run -s clean && npm run -s build",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"prepare": "npm run clean:build",
"test": "nyc --require ts-node/register mocha src/**/*.spec.ts --reporter spec"
"prepublishOnly": "npm run clean:build",
"test": "npm run -s test:src && npm run -s test:scripts",
"test:src": "nyc mocha src/**/*.spec.ts --require ts-node/register --reporter spec",
"test:scripts": "mocha scripts/**/*.spec.ts --require ts-node/register --reporter spec"
},
"repository": {
"type": "git",
Expand Down
10 changes: 10 additions & 0 deletions scripts/clean.script.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Clean} from './lib/clean';

console.log('Start to clean...');
Clean.execute(process.argv)
.then(() => {
console.log('Succeed to clean');
})
.catch(error => {
console.log('Failed to clean with error\n', error);
});
10 changes: 10 additions & 0 deletions scripts/copy.script.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Copy} from './lib/copy';

console.log('Start to copy...');
Copy.execute(process.argv)
.then(() => {
console.log('Succeed to copy');
})
.catch(error => {
console.log('Failed to copy with error\n', error);
});
39 changes: 39 additions & 0 deletions scripts/lib/clean.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {FileSystemUtils} from '../../src/core/utils/file-system.utils';
import * as os from 'os';
import * as path from 'path';

export class Clean {
public static execute(args: string[]): Promise<void[]> {
return this.extractFileNames(args)
.then(fileNames => Promise.all(fileNames.map(filename => this.clean(filename))));
}

private static extractFileNames(args: string[]): Promise<string[]> {
if (os.platform() === 'win32')
return this.extractWin32PlatformFiles(args);
else
return Promise.resolve(args.slice(2, args.length));
}

private static extractWin32PlatformFiles(args: string[]): Promise<string[]> {
const dirname: string = args[2].replace('*', '');
return FileSystemUtils.readdir(dirname)
.then(fileNames => fileNames.map(filename => path.join(dirname, filename)));
}

private static clean(filename: string): Promise<void> {
return FileSystemUtils.stat(filename)
.then(fileStat => {
if (fileStat.isFile())
return FileSystemUtils.rm(filename);
else
return FileSystemUtils.rmdir(filename);
})
.then(() => {
console.log(` ${ filename } deleted`);
})
.catch(error => {
console.log(` ${ filename } not be deleted`);
});
}
}
44 changes: 44 additions & 0 deletions scripts/lib/copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as fs from 'fs';
import {ReadStream, WriteStream} from 'fs';
import {FileSystemUtils} from '../../src/core/utils/file-system.utils';
import * as path from 'path';

export class Copy {
public static execute(argv: string[]): Promise<void> {
const origin: string = argv[2];
const destination: string = argv[3];
return this.copy(origin, destination);
}

private static copy(origin: string, destination: string) {
return FileSystemUtils.stat(origin)
.then(fileStat => {
if (fileStat.isFile())
return this.copyFile(origin, destination);
else
return this.copyDirectory(origin, destination);
});
}

private static copyFile(origin: string, destination: string): Promise<void> {
console.log(` copy ${ origin } \n to ${ destination }`);
return new Promise<void>((resolve, reject) => {
const reader: ReadStream = fs.createReadStream(origin);
const writer: WriteStream = fs.createWriteStream(destination);
reader.pipe(writer);
reader.on('end', resolve);
reader.on('error', reject);
});
}

private static copyDirectory(origin: string, destination: string): Promise<void> {
return FileSystemUtils.readdir(origin)
.then(files => {
return FileSystemUtils.mkdir(destination)
.then(() => Promise.all(
files.map(file => this.copy(path.join(origin, file), path.join(destination, file)))
));
})
.then(() => {});
}
}
114 changes: 114 additions & 0 deletions scripts/lib/tests/clean.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import * as sinon from 'sinon';
import {FileSystemUtils} from '../../../src/core/utils/file-system.utils';
import {Clean} from '../clean';
import * as os from 'os';
import * as path from 'path';

describe('Clean', () => {
let sandbox: sinon.SinonSandbox;
beforeEach(() => sandbox = sinon.sandbox.create());
afterEach(() => sandbox.restore());

let statStub: sinon.SinonStub;
let rmStub: sinon.SinonStub;
let rmdirStub: sinon.SinonStub;
let readdirStub: sinon.SinonStub;
let platformStub: sinon.SinonStub;
beforeEach(() => {
statStub = sandbox.stub(FileSystemUtils, 'stat');
rmStub = sandbox.stub(FileSystemUtils, 'rm');
rmdirStub = sandbox.stub(FileSystemUtils, 'rmdir');
readdirStub = sandbox.stub(FileSystemUtils, 'readdir');
platformStub = sandbox.stub(os, 'platform');
});

describe('#execute()', () => {
context('Unix platform', () => {
const argv: string[] = [ 'node_process_call', 'script_call', 'filename1', 'filename2', 'filename3' ];

beforeEach(() => {
platformStub.callsFake(() => 'unix');
});

it('should call stat per file', () => {
statStub.callsFake(() => Promise.resolve({
isFile: () => true
}));
return Clean.execute(argv)
.then(() => {
sinon.assert.calledThrice(statStub);
sinon.assert.calledWith(statStub, 'filename1');
sinon.assert.calledWith(statStub, 'filename2');
sinon.assert.calledWith(statStub, 'filename3');
});
});

it('should call rm on files', () => {
statStub.callsFake(() => Promise.resolve({
isFile: () => true
}));
rmStub.callsFake(() => Promise.resolve());
return Clean.execute(argv)
.then(() => {
sinon.assert.calledThrice(rmStub);
sinon.assert.calledWith(rmStub, 'filename1');
sinon.assert.calledWith(rmStub, 'filename2');
sinon.assert.calledWith(rmStub, 'filename3');
});
});

it('should call rmdir on directories', () => {
rmdirStub.callsFake(() => Promise.resolve());
statStub.callsFake(() => Promise.resolve({
isFile: () => false
}));
return Clean.execute(argv)
.then(() => {
sinon.assert.calledThrice(rmdirStub);
sinon.assert.calledWith(rmdirStub, 'filename1');
sinon.assert.calledWith(rmdirStub, 'filename2');
sinon.assert.calledWith(rmdirStub, 'filename3');
});
});

});

context('win32 platform', () => {
const argv: string[] = [ 'node_process_call', 'script_call', 'directory/*' ];
beforeEach(() => {
platformStub.callsFake(() => 'win32');
rmdirStub.callsFake(() => Promise.resolve());
rmStub.callsFake(() => Promise.resolve());
readdirStub.callsFake(() => Promise.resolve([
'filename1',
'filename2',
'filename3'
]));
});

it('should extract files from directory', () => {
statStub.callsFake(() => Promise.resolve({
isFile: () => false
}));
return Clean.execute(argv)
.then(() => {
sinon.assert.called(readdirStub);
});
});

it('should remove * on win32 platform', () => {
statStub.callsFake(() => Promise.resolve({
isFile: () => true
}));

return Clean.execute(argv)
.then(() => {
sinon.assert.calledThrice(statStub);
sinon.assert.calledWith(statStub, path.join('directory', 'filename1'));
sinon.assert.calledWith(statStub, path.join('directory', 'filename2'));
sinon.assert.calledWith(statStub, path.join('directory', 'filename3'));
});
});
});
});
});
144 changes: 144 additions & 0 deletions scripts/lib/tests/copy.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import {Copy} from '../copy';
import * as sinon from 'sinon';
import * as fs from 'fs';
import {PassThrough} from 'stream';
import {FileSystemUtils} from '../../../src/core/utils/file-system.utils';
import * as path from 'path';

describe('Copy', () => {
let sandbox: sinon.SinonSandbox;
beforeEach(() => sandbox = sinon.sandbox.create());
afterEach(() => sandbox.restore());

let statStub: sinon.SinonStub;
let createReadStreamStub: sinon.SinonStub;
let createWriteStreamStub: sinon.SinonStub;
let pipeSpy: sinon.SinonSpy;
let readdirStub: sinon.SinonStub;
let mkdirStub: sinon.SinonStub;
beforeEach(() => {
statStub = sandbox.stub(FileSystemUtils, 'stat');
createReadStreamStub = sandbox.stub(fs, 'createReadStream').callsFake(() => {
const reader = new PassThrough();
reader.end();
return reader;
});
createWriteStreamStub = sandbox.stub(fs, 'createWriteStream').callsFake(() => new PassThrough());
pipeSpy = sandbox.spy(PassThrough.prototype, 'pipe');
readdirStub = sandbox.stub(FileSystemUtils, 'readdir');
mkdirStub = sandbox.stub(FileSystemUtils, 'mkdir').callsFake(() => Promise.resolve());
});

describe('#execute()', () => {
const argv: string[] = [ 'node_process_call', 'script_call', 'origin', 'destination' ];

it('should evaluate if origin is a file', () => {
statStub.callsFake(() => Promise.resolve({
isFile: () => true
}));
return Copy.execute(argv)
.then(() => {
sinon.assert.calledWith(statStub, 'origin');
});
});

context('origin is a file', () => {
beforeEach(() => {
statStub.callsFake(() => Promise.resolve({
isFile: () => true
}));
});

it('should open an input stream on origin file', () => {
return Copy.execute(argv)
.then(() => {
sinon.assert.calledWith(createReadStreamStub, 'origin');
});
});

it('should open an output stream to destination file', () => {
return Copy.execute(argv)
.then(() => {
sinon.assert.calledWith(createWriteStreamStub, 'destination');
});
});

it('should pipe origin to destination', () => {
return Copy.execute(argv)
.then(() => {
sinon.assert.called(pipeSpy);
});
});
});

context('origin is directory', () => {
beforeEach(() => {
statStub.callsFake(filename => {
if (filename === 'origin')
return Promise.resolve({
isFile: () => false
});
else
return Promise.resolve({
isFile: () => true
});
});
readdirStub.callsFake(() => Promise.resolve([
'filename1',
'filename2',
'filename3',
]));
});

it('should read the directory', () => {
return Copy.execute(argv)
.then(() => {
sinon.assert.calledWith(readdirStub, 'origin');
});
});

it('should copy each files in the directory to the destination', () => {
return Copy.execute(argv)
.then(() => {
sinon.assert.calledThrice(createReadStreamStub);
sinon.assert.calledWith(createReadStreamStub, path.join('origin', 'filename1'));
sinon.assert.calledWith(createReadStreamStub, path.join('origin', 'filename2'));
sinon.assert.calledWith(createReadStreamStub, path.join('origin', 'filename3'));
sinon.assert.calledThrice(createWriteStreamStub);
sinon.assert.calledWith(createWriteStreamStub, path.join('destination', 'filename1'));
sinon.assert.calledWith(createWriteStreamStub, path.join('destination', 'filename2'));
sinon.assert.calledWith(createWriteStreamStub, path.join('destination', 'filename3'));
sinon.assert.calledThrice(pipeSpy);
});
});
});

context('origin contains sub directories', () => {
beforeEach(() => {
statStub.callsFake(filename => {
if (filename === 'origin' || filename === 'origin/directory')
return Promise.resolve({
isFile: () => false
});
else
return Promise.resolve({
isFile: () => true
});
});
readdirStub.callsFake(filename => {
if (filename === 'origin')
return Promise.resolve([ 'directory' ]);
else
return Promise.resolve([ 'filename']);
});
});

it('create the intermediate directory before copy file', () => {
return Copy.execute(argv)
.then(() => {
sinon.assert.called(mkdirStub);
});
});
});
});
});
Loading

0 comments on commit 848fb87

Please sign in to comment.