veendor
Version:
a tool for stroing your npm dependencies in arbitraty storage
337 lines (269 loc) • 15.6 kB
JavaScript
const _ = require('lodash');
const chai = require('chai');
const sinon = require('sinon');
const chaiAsPromised = require('chai-as-promised');
const assert = chai.assert;
chai.use(chaiAsPromised);
const gitWrapper = require('../../lib/commandWrappers/gitWrapper');
const helpers = require('../../lib/commandWrappers/helpers');
const {notifyAssert, AnError} = require('./helpers');
let config;
describe('gitWrapper', () => {
let sandbox;
beforeEach(() => {
sandbox = sinon.sandbox.create();
});
afterEach(() => {
sandbox.restore();
});
describe('.isGitLfsAvailable', () => {
it('should reject with GitLfsNotAvailableError if `git lfs` returns non-zero', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'lfs') {
return Promise.reject('\'lfs\' is not a git command.\n');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.isGitLfsAvailable();
assert.isRejected(result, gitWrapper.GitLfsNotAvailableError).notify(done);
});
it('should reject with GitLfsNotAvailableError if `git config --list` does not contain `filter.lfs.clean`',
done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'lfs') {
return Promise.resolve('watwat');
} else if (executable === 'git' && args[0] === 'config' && args[1] === '--list') {
return Promise.resolve(
'filter.lfs.smudge=git-lfs smudge -- %f\n' +
'filter.lfs.process=git-lfs filter-process\n' +
'filter.lfs.required=true\n' +
'core.repositoryformatversion=0'
);
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.isGitLfsAvailable();
assert.isRejected(result, gitWrapper.GitLfsNotAvailableError).notify(done);
});
it('should reject with GitLfsNotAvailableError if `git config --list` does not contain `filter.lfs.smudge`',
done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'lfs') {
return Promise.resolve('watwat');
} else if (executable === 'git' && args[0] === 'config' && args[1] === '--list') {
return Promise.resolve(
'filter.lfs.clean=git-lfs clean -- %f\n' +
'filter.lfs.process=git-lfs filter-process\n' +
'filter.lfs.required=true\n' +
'core.repositoryformatversion=0'
);
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.isGitLfsAvailable();
assert.isRejected(result, gitWrapper.GitLfsNotAvailableError).notify(done);
});
it('should reject with GitLfsNotAvailableError if `git config --list` does not contain `filter.lfs.process`',
done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'lfs') {
return Promise.resolve('watwat');
} else if (executable === 'git' && args[0] === 'config' && args[1] === '--list') {
return Promise.resolve(
'filter.lfs.clean=git-lfs clean -- %f\n' +
'filter.lfs.smudge=git-lfs smudge -- %f\n' +
'filter.lfs.required=true\n' +
'core.repositoryformatversion=0'
);
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.isGitLfsAvailable();
assert.isRejected(result, gitWrapper.GitLfsNotAvailableError).notify(done);
});
it('should fulfill with true if `git lfs` is in place and git lfs hooks are installed', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'lfs') {
return Promise.resolve('watwat');
} else if (executable === 'git' && args[0] === 'config' && args[1] === '--list') {
return Promise.resolve(
'filter.lfs.clean=git-lfs clean -- %f\n' +
'filter.lfs.smudge=git-lfs smudge -- %f\n' +
'filter.lfs.process=git-lfs filter-process\n' +
'filter.lfs.required=true\n' +
'core.repositoryformatversion=0'
);
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.isGitLfsAvailable();
assert.isFulfilled(result, true).notify(done);
});
});
describe('.olderRevision', () => {
it('should reject with TooOldRevisionError if file doen\'t have that amount of revisions', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args.some(arg => arg === '--pretty=format:%h')) {
return Promise.resolve('43485c2\n8638279\n12312a\n1231241\n');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.olderRevision(process.cwd(), ['test'], 5);
assert.isRejected(result, gitWrapper.TooOldRevisionError).notify(done);
});
it('should call git show with last line of git log output', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args.some(arg => arg === '--pretty=format:%h')) {
return Promise.resolve('43485c2\n8638279\n');
} else if (executable === 'git' && args[1] === 'show') {
assert.equal(args[2], '8638279:test');
done();
return Promise.resolve('ok');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
gitWrapper.olderRevision(process.cwd(), ['test'], 2);
});
it('should resolve with array of git show outputs', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args.some(arg => arg === '--pretty=format:%h')) {
return Promise.resolve('43485c2\n8638279\n');
} else if (executable === 'git' && args[1] === 'show' && args[2] === '8638279:foo') {
return Promise.resolve('Foo once was like this.\nCan you imagine?\n');
} else if (executable === 'git' && args[1] === 'show' && args[2] === '8638279:bar') {
return Promise.resolve('As a kid, bar looked like this.\n');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.olderRevision(process.cwd(), ['foo', 'bar'], 2);
assert.becomes(result, [
'Foo once was like this.\nCan you imagine?\n',
'As a kid, bar looked like this.\n',
]).notify(done);
});
it('should call git log with all files listed', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[1] === 'log') {
notifyAssert(() => {
assert.equal(args[4], 'test_file');
assert.equal(args[5], 'also_test_file');
assert.equal(args[6], 'foo_bar');
}, done);
return Promise.resolve('43485c2\n8638279\n');
} else if (executable === 'git' && args[1] === 'show') {
return Promise.resolve('this is elder file.\nShow some respect.\n');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
gitWrapper.olderRevision(process.cwd(), ['test_file', 'also_test_file', 'foo_bar'], 2);
});
it('should be null-safe for filenames', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[1] === 'log') {
notifyAssert(() => {
assert.equal(args[4], 'test_file');
assert.equal(args[5], 'foo_bar');
}, done);
return Promise.resolve('43485c2\n8638279\n');
} else if (executable === 'git' && args[1] === 'show') {
return Promise.resolve('this is elder file.\nShow some respect.\n');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
gitWrapper.olderRevision(process.cwd(), ['test_file', null, 'foo_bar'], 2);
});
it('should resolve with null for null-filenames', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[1] === 'log') {
return Promise.resolve('43485c2\n8638279\n');
} else if (executable === 'git' && args[1] === 'show') {
if (args[2] === '8638279:test_file') {
return Promise.resolve('elder test_file');
} else if (args[2] === '8638279:foo_bar') {
return Promise.resolve('elder foo_bar');
}
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.olderRevision(process.cwd(), ['test_file', null, 'foo_bar'], 2);
assert.becomes(result, ['elder test_file', null, 'elder foo_bar']).notify(done);
});
});
describe('tag', () => {
it('should throw RefAlreadyExistsError when git output shows it', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'tag') {
return Promise.reject(new helpers.CommandReturnedNonZeroError(
'Command [git tag] returned 1',
'fatal: tag \'veendor-32097f47c59765895b8b9d2002fe40ddc0de38bf-linux\' already exists'
));
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.tag(process.cwd(), 'veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux');
assert.isRejected(result, gitWrapper.RefAlreadyExistsError).notify(done);
});
});
describe('push', () => {
it('should throw RefAlreadyExistsError when git output shows it', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'push') {
return Promise.reject(new helpers.CommandReturnedNonZeroError(
'Command [git push] returned 1',
'HEAD is now at 7b3abff Initial commit\n' +
'Git LFS: (1 of 1 files) 47.46 MB / 47.46 MB\n' +
'To git@github.com:mutantcornholio/veendor-cache.git\n' +
' ! [rejected] veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux' +
' -> veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux (already exists)\n' +
'error: failed to push some refs to \'git@github.yandex-team.ru:market/veendor-cache.git\'\n' +
'hint: Updates were rejected because the tag already exists in the remote.'
));
}
if (executable === 'git' && args[0] === 'remote') {
return Promise.resolve('origin');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.push(process.cwd(), 'veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux');
assert.isRejected(result, gitWrapper.RefAlreadyExistsError).notify(done);
});
it('should throw RefAlreadyExistsError when git responds with cannot lock ref...reference already exists error',
done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'push') {
return Promise.reject(new helpers.CommandReturnedNonZeroError(
'Command [git push] returned 1',
'HEAD is now at 7b3abff Initial commit\n' +
'Git LFS: (1 of 1 files) 47.46 MB / 47.46 MB\n' +
'To git@github.com:mutantcornholio/veendor-cache.git\n' +
' ! [remote rejected] veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux' +
' -> veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux (cannot lock ref ' +
'\'refs/tags/veendor-3bc8fa1e3e22364e13220fef900aea2d19699c23-linux-48\': ' +
'reference already exists)\n' +
'error: failed to push some refs to ' +
'\'git@github.yandex-team.ru:market/veendor-cache.git\''
));
}
if (executable === 'git' && args[0] === 'remote') {
return Promise.resolve('origin');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.push(process.cwd(), 'veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux');
assert.isRejected(result, gitWrapper.RefAlreadyExistsError).notify(done);
});
it('should throw original generic error from git', done => {
sandbox.stub(helpers, 'getOutput').callsFake((executable, args) => {
if (executable === 'git' && args[0] === 'push') {
return Promise.reject(new AnError('test'));
}
if (executable === 'git' && args[0] === 'remote') {
return Promise.resolve('origin');
}
return Promise.reject(new Error(`mock me, bitch! args: ${args}`));
});
const result = gitWrapper.push(process.cwd(), 'veendor-e00d8185b0bdb7f25d89e79ed779d0b6809bfcd0-linux');
assert.isRejected(result, AnError).notify(done);
});
});
});