UNPKG

affiance

Version:

A configurable and extendable Git hook manager for node projects

370 lines (302 loc) 14.4 kB
var testHelper = require('../../test_helper'); var fse = require('fs-extra'); var path = require('path'); var expect = testHelper.expect; var sinon = testHelper.sinon; var gitRepo = testHelper.requireSourceModule(module); var utils = testHelper.requireSourceModule(module, 'lib/utils'); var fileUtils = testHelper.requireSourceModule(module, 'lib/fileUtils'); describe('gitRepo', function() { beforeEach('create git repo', function() { this.oldCwd = process.cwd(); this.repoPath = testHelper.tempRepo(); process.chdir(this.repoPath); }); afterEach('reset cwd on process', function() { if(!this.oldCwd) { return; } process.chdir(this.oldCwd); testHelper.cleanupDirectory(this.repoPath); }); describe('.submoduleStatuses', function() { it('returns an empty array when there are no submodules', function() { var submoduleStatuses = gitRepo.submoduleStatuses(); expect(submoduleStatuses).to.be.an('Array'); expect(submoduleStatuses).to.be.empty }); describe('when the repo contains submodules', function() { beforeEach('setup nested submodules', function() { // Create the repo that will be the nested submodule. this.nestedSubmoduleRepo = testHelper.tempRepo(); utils.execSync('git commit --allow-empty -m "Initial commit"', {cwd: this.nestedSubmoduleRepo}); // Create the repo that will be the direct submodule. this.submoduleRepo = testHelper.tempRepo(); utils.execSync( 'git submodule add ' + this.nestedSubmoduleRepo + ' nested-sub 2>&1 > /dev/null', {cwd: this.submoduleRepo} ); utils.execSync('git commit -m "Add nested submodule"', {cwd: this.submoduleRepo}); // Add the direct submodule to the main test repo. utils.execSync('git submodule add ' + this.submoduleRepo + ' sub 2>&1 > /dev/null'); }); afterEach('setup nested submodules', function() { testHelper.cleanupDirectory(this.nestedSubmoduleRepo); testHelper.cleanupDirectory(this.submoduleRepo); }); it('returns submodule statuses for this repo', function() { var submoduleStatuses = gitRepo.submoduleStatuses(); expect(submoduleStatuses).to.have.length(1); expect(submoduleStatuses[0]).to.have.property('path', 'sub'); }); it('includes nested submodules if the recursive flag is provided', function() { var submoduleStatuses = gitRepo.submoduleStatuses({recursive: true}); expect(submoduleStatuses).to.have.length(2); expect(submoduleStatuses[0]).to.have.property('path', 'sub'); expect(submoduleStatuses[1]).to.have.property('path', 'sub/nested-sub'); }); }); }); describe('.extractModifiedLines', function() { beforeEach('setup file', function() { this.fileName = 'file.txt'; this.fileContent = "Hello World\nHow are you?\n"; fse.writeFileSync(this.fileName, this.fileContent); utils.execSync('git add ' + this.fileName); utils.execSync('git commit -m "Initial commit"'); }); it('returns an empty array when no lines are modified', function() { var modifiedLines = gitRepo.extractModifiedLines(this.fileName); expect(modifiedLines).to.be.an('Array'); expect(modifiedLines).to.be.empty }); it('returns the last line if a line is added', function() { var nextLine = 'Hello Again\n'; fse.appendFileSync(this.fileName, nextLine); var modifiedLines = gitRepo.extractModifiedLines(this.fileName); expect(modifiedLines).to.be.an('Array'); expect(modifiedLines).to.have.length(1); expect(modifiedLines[0]).to.equal('3'); }); it('returns an existing line if changed string', function() { fse.writeFileSync(this.fileName, "Hello World\nWho are you?\n"); var modifiedLines = gitRepo.extractModifiedLines(this.fileName); expect(modifiedLines).to.be.an('Array'); expect(modifiedLines).to.have.length(1); expect(modifiedLines[0]).to.equal('2'); }); it('returns an empty string if lines removed', function() { fse.writeFileSync(this.fileName, "Hello World\n"); var modifiedLines = gitRepo.extractModifiedLines(this.fileName); expect(modifiedLines).to.be.an('Array'); expect(modifiedLines).to.be.empty }); }); describe('.modifiedFiles', function() { describe('when the staged option is set', function() { beforeEach('set options', function(){ this.options = {staged: true}; }); it('returns files that are added', function() { fse.ensureFileSync('added.txt'); utils.execSync('git add added.txt'); var modifiedFiles = gitRepo.modifiedFiles(this.options); expect(modifiedFiles).to.be.an('Array'); expect(modifiedFiles).to.have.length(1); expect(modifiedFiles[0]).to.include('added.txt'); }); it('returns files that are renamed', function() { fse.ensureFileSync('file.txt'); utils.execSync('git add file.txt'); utils.execSync('git commit -m "Initial commit"'); utils.execSync('git mv file.txt renamed.txt'); var modifiedFiles = gitRepo.modifiedFiles(this.options); expect(modifiedFiles).to.be.an('Array'); expect(modifiedFiles).to.have.length(1); expect(modifiedFiles[0]).to.include('renamed.txt'); }); it('returns files that are modified', function() { fse.ensureFileSync('file.txt'); utils.execSync('git add file.txt'); utils.execSync('git commit -m "Initial commit"'); fse.appendFileSync('file.txt', "Moar text.\n"); utils.execSync('git add file.txt'); var modifiedFiles = gitRepo.modifiedFiles(this.options); expect(modifiedFiles).to.be.an('Array'); expect(modifiedFiles).to.have.length(1); expect(modifiedFiles[0]).to.include('file.txt'); }); it('does not include deleted files', function() { fse.ensureFileSync('file.txt'); utils.execSync('git add file.txt'); utils.execSync('git commit -m "Initial commit"'); utils.execSync('git rm file.txt'); var modifiedFiles = gitRepo.modifiedFiles(this.options); expect(modifiedFiles).to.be.an('Array'); expect(modifiedFiles).to.be.empty; }); it('does not include submodule name', function() { var submoduleRepo = testHelper.tempRepo(); utils.execSync('git commit --allow-empty -m "Initial commit"', {cwd: submoduleRepo}); utils.execSync('git submodule add ' + submoduleRepo + ' sub 2>&1 > /dev/null'); var modifiedFiles = gitRepo.modifiedFiles(this.options); expect(modifiedFiles).to.be.an('Array'); expect(modifiedFiles).to.have.length(1); expect(modifiedFiles[0]).to.not.include('sub'); testHelper.cleanupDirectory(submoduleRepo); }); }); }); describe('.listFiles', function() { beforeEach('add initial commit to repo', function() { utils.execSync('git commit --allow-empty -m "Initial commit"'); }); it('does not include submodules', function() { var submoduleRepo = testHelper.tempRepo(); utils.execSync('git commit --allow-empty -m "Initial commit"', {cwd: submoduleRepo}); utils.execSync('git submodule add ' + submoduleRepo + ' sub 2>&1 > /dev/null'); utils.execSync('git commit -m "Add submodule"'); var listFiles = gitRepo.listFiles(); expect(listFiles).to.be.an('Array'); expect(listFiles).to.have.length(1); expect(listFiles[0]).to.not.include('sub'); testHelper.cleanupDirectory(submoduleRepo); }); describe('when listing the contents of a directory', function() { beforeEach('setup the directory', function() { this.dirName = 'some-dir'; this.paths = [this.dirName + path.sep]; fse.ensureDirSync(this.dirName); }); it('returns an empty array if the directory is empty', function() { var listFiles = gitRepo.listFiles(this.paths); expect(listFiles).to.be.an('Array'); expect(listFiles).to.be.empty; }); it('returns files in the directory', function() { var fileName = this.dirName + '/file.txt'; fse.ensureFileSync(fileName); utils.execSync('git add ' + fileName); utils.execSync('git commit -m "Add file"'); var listFiles = gitRepo.listFiles(this.paths); expect(listFiles).to.be.an('Array'); expect(listFiles).to.have.length(1); expect(listFiles[0]).to.equal(path.resolve(fileName)); }); }); }); describe('.isTracked', function() { beforeEach('setup tracked and untracked file', function() { fse.ensureFileSync('untracked'); fse.ensureFileSync('tracked'); utils.execSync('git add tracked'); utils.execSync('git commit -m "Initial commit"'); fse.ensureFileSync('staged'); utils.execSync('git add staged'); }); it('returns false for untracked files', function() { expect(gitRepo.isTracked('untracked')).to.equal(false); }); it('returns true for committed files', function() { expect(gitRepo.isTracked('tracked')).to.equal(true); }); it('returns true for staged files', function() { expect(gitRepo.isTracked('staged')).to.equal(true); }); }); describe('.allFiles', function() { beforeEach('setup repo with files and a submodule', function() { fse.ensureFileSync('untracked'); fse.ensureFileSync('tracked'); utils.execSync('git add tracked'); utils.execSync('git commit -m "Initial commit"'); this.submoduleRepo = testHelper.tempRepo(); utils.execSync('git commit --allow-empty -m "Initial commit"', {cwd: this.submoduleRepo}); utils.execSync('git submodule add ' + this.submoduleRepo + ' sub 2>&1 > /dev/null'); utils.execSync('git commit -m "Add submodule"'); fse.ensureFileSync('staged'); utils.execSync('git add staged'); }); afterEach('clean up submodule repo', function() { if (this.submoduleRepo) { testHelper.cleanupDirectory(this.submoduleRepo); } }); it('includes tracked and staged files', function() { var allFiles = gitRepo.allFiles(); expect(allFiles).to.have.length(3); expect(allFiles).to.include(path.resolve('staged')); expect(allFiles).to.include(path.resolve('tracked')); expect(allFiles).to.include(path.resolve('.gitmodules')); expect(allFiles).to.not.include(path.resolve('sub')); }); }); describe('.isInitialCommit', function() { it('returns true if there are no existing commits in the repo', function() { expect(gitRepo.isInitialCommit()).to.equal(true); }); it('returns true if there are no existing commits in the repo', function() { utils.execSync('git commit --allow-empty -m "Initial commit"'); expect(gitRepo.isInitialCommit()).to.equal(false); }); }); describe('.stagedSubmoduleRemovals', function() { beforeEach('setup submodules', function() { // Create the repo that will be the direct submodule. this.submoduleRepo = testHelper.tempRepo(); utils.execSync('git commit --allow-empty -m "Initial commit"', {cwd: this.submoduleRepo}); // Add the direct submodule to the main test repo. utils.execSync('git submodule add ' + this.submoduleRepo + ' sub-repo 2>&1 > /dev/null'); utils.execSync('git commit -m "Initial commit"'); }); afterEach('cleanup nested submodules', function() { testHelper.cleanupDirectory(this.submoduleRepo); }); it('returns an empty array when no submodules are being removed', function() { var stagedSubmoduleRemovals = gitRepo.stagedSubmoduleRemovals(); expect(stagedSubmoduleRemovals).to.be.an('Array'); expect(stagedSubmoduleRemovals).to.be.empty; }); it('returns an empty array only additions are staged', function() { var additionalSubmoduleRepo = testHelper.tempRepo(); utils.execSync('git commit --allow-empty -m "Another submodule"', {cwd: additionalSubmoduleRepo}); utils.execSync('git submodule add ' + additionalSubmoduleRepo + ' another-sub-repo 2>&1 > /dev/null'); var stagedSubmoduleRemovals = gitRepo.stagedSubmoduleRemovals(); expect(stagedSubmoduleRemovals).to.be.an('Array'); expect(stagedSubmoduleRemovals).to.be.empty; testHelper.cleanupDirectory(additionalSubmoduleRepo); }); it('returns submodules that are staged for removal', function() { utils.execSync('git rm sub-repo'); var stagedSubmoduleRemovals = gitRepo.stagedSubmoduleRemovals(); expect(stagedSubmoduleRemovals).to.be.an('Array'); expect(stagedSubmoduleRemovals).to.have.length(1); expect(stagedSubmoduleRemovals[0]).to.have.property('path', 'sub-repo'); expect(fileUtils.isDirectory(stagedSubmoduleRemovals[0].url)).to.equal(true); }); }); describe('.branchesContainingCommit', function() { beforeEach('setup topic branch', function() { utils.execSync('git checkout -b master > /dev/null 2>&1'); utils.execSync('git commit --allow-empty -m "Initial commit"'); utils.execSync('git checkout -b topic > /dev/null 2>&1'); utils.execSync('git commit --allow-empty -m "Topical commit"'); }); it('returns the branch if the branch name is used', function() { var branchesContainingCommit = gitRepo.branchesContainingCommit('topic'); expect(branchesContainingCommit).to.have.length(1); expect(branchesContainingCommit[0]).to.equal('topic'); }); it('returns the all branches that contain a ref', function() { var branchesContainingCommit = gitRepo.branchesContainingCommit('master'); expect(branchesContainingCommit).to.have.length(2); expect(branchesContainingCommit).to.include('master'); expect(branchesContainingCommit).to.include('topic'); }); it('returns an empty array if not branches currently contain the commit', function() { utils.execSync('git checkout --detach > /dev/null 2>&1'); utils.execSync('git commit --allow-empty -m "Detached HEAD"'); var branchesContainingCommit = gitRepo.branchesContainingCommit('HEAD'); expect(branchesContainingCommit).to.be.an('Array'); expect(branchesContainingCommit).to.be.empty; }); }); });