Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow ignoring unknown files + tests #7

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module.exports = function (grunt) {
options: {
reporter: 'spec',
},
src: ['test/spec.js'],
src: ['test/*[s|S]pec.js'],
},
},
});
Expand Down
52 changes: 31 additions & 21 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,60 @@ const semver = require('semver');
const inquirer = require('inquirer');
const shellQuote = require('shell-quote');

const ERRORS = require('./errors');

// this is moved here to allow it being overridden for testing purposes...
// still not sure if this is the way to go as the module should probably
// be refactored for easier testing
let run = command => execSync(command, {encoding: 'utf8'}); // eslint-disable-line prefer-const

// this is moved here to allow it being overridden for testing purposes...
// still not sure if this is the way to go as the module should probably
// be refactored for easier testing
let writePackageJson = configObject => // eslint-disable-line prefer-const
fs.writeFileSync(getPackageJsonPath(),
`${ JSON.stringify(configObject, null, 2) }\n`);

// this is moved here to allow the parent method (writePackageJson)
// being overridden for testing purposes...
// still not sure if this is the way to go as the module should probably
// be refactored for easier testing
const getPackageJsonPath = () => `${ process.cwd() }/${ getRootPath() }package.json`;

// this is moved here to allow the parent method (getPackageJsonPath)
// being overridden for testing purposes...
// still not sure if this is the way to go as the module should probably
// be refactored for easier testing
const getRootPath = () => run('git rev-parse --show-cdup').trim();

const createNpmBump = (remoteName, branch) => {
remoteName = remoteName || 'origin';
branch = branch || 'master';

const UsageError = class extends Error {
constructor(message) {
super(message);
this.name = 'UsageError';
}
};

return releaseType => {
const isPrerelease = ['major', 'minor', 'patch'].indexOf(releaseType) === -1;

const getHashFor = branchName => {
try {
return run(`git rev-parse --verify ${ quote(branchName) }`).trim();
} catch (error) {
throw new UsageError(`Git couldn't find the branch: "${ branchName
}"; please ensure it exists`);
throw ERRORS.unknownBranch(branchName);
}
};

const ensureCleanBranch = () => {
if (getHashFor('HEAD') !== getHashFor(branch)) {
throw new UsageError(`You need to be on the "${ branch
}" branch to run this script`);
throw ERRORS.invalidBranch(branch);
}
if (getHashFor(branch) !== getHashFor(`${ remoteName }/${ branch }`)) {
throw new UsageError('You need to push your changes first');
throw ERRORS.notCurrentBranch(branch);
}
if (run('git status -s').length) {
throw new UsageError(
'You have uncommited changes! Commit them before running this script');
if (run('git status -s').split('\n').filter(line => line.indexOf('??') !== 0).length) {
throw ERRORS.uncommittedChanges(branch);
}
};

const getRootPath = () => run('git rev-parse --show-cdup').trim();
const getPackageJsonPath = () => `${ process.cwd() }/${ getRootPath() }package.json`;
const quote = string => shellQuote.quote([string]);
const run = command => execSync(command, {encoding: 'utf8'});
const writePackageJson = configObject =>
fs.writeFileSync(getPackageJsonPath(),
`${ JSON.stringify(configObject, null, 2) }\n`);

const doBump = () => {
const packageJson = require(getPackageJsonPath());
Expand Down
41 changes: 41 additions & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict';

const UsageError = class extends Error {
constructor(message) {
super(message);
this.name = 'UsageError';
}
};

// todo is use sprintf or suchlike

const ERROR_UNKNOWN_BRANCH = 'Git couldn\'t find the branch: "%branch%"; please ensure it exists';

const ERROR_INVALID_BRANCH = 'You need to be on the "%branch%" branch to run this script';

// can contain branch name but is bc
const ERROR_BRANCH_IS_NOT_CURRENT = 'You need to push your changes first';

const ERROR_UNCOMMITTED_CHANGES =
'You have uncommited changes! Commit them before running this script';

module.exports = {
UsageError,
ERROR_UNKNOWN_BRANCH,
ERROR_INVALID_BRANCH,
ERROR_BRANCH_IS_NOT_CURRENT,
ERROR_UNCOMMITTED_CHANGES,

unknownBranch: branch => new UsageError(
ERROR_UNKNOWN_BRANCH.replace('%branch%', branch)),

invalidBranch: branch => new UsageError(
ERROR_INVALID_BRANCH.replace('%branch%', branch)),

notCurrentBranch: branch => new UsageError(
ERROR_BRANCH_IS_NOT_CURRENT.replace('%branch%', branch)),

uncommittedChanges: branch => new UsageError(
ERROR_UNCOMMITTED_CHANGES.replace('%branch%', branch)),

};
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@
"shell-quote": "^1.6.1"
},
"devDependencies": {
"chai": "^3.5.0",
"eslint-config-mgol": "0.0.24",
"grunt": "1.0.1",
"grunt-cli": "1.2.0",
"grunt-eslint": "19.0.0",
"grunt-mocha-test": "0.12.7",
"load-grunt-tasks": "3.5.0",
"mocha": "3.0.2",
"mockery": "^1.7.0",
"rewire": "^2.5.2",
"time-grunt": "1.4.0"
},
"scripts": {
Expand Down
86 changes: 86 additions & 0 deletions test/allowIgnoringUnknownFilesSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use strict';

const assert = require('chai').assert;
const rewire = require('rewire');
const mockery = require('mockery');

const ERROR_UNCOMMITTED_CHANGES = require('../lib/errors').ERROR_UNCOMMITTED_CHANGES;

describe('allow ignoring unknown files', () => {

// ////////////////////////////////////////////////////////////////////////////////////////////
// setup the tests .. should possibly be in a before..

// ignore inquirer prompts..
mockery.enable();
mockery.warnOnUnregistered(false);
mockery.registerMock('inquirer', {
prompt() {
return Promise.resolve(''); // resolving an empty string removes the prompt output...
},
});

// after mockery we can require our libraries..
// though via rewire as the module requires a complete refactor for testing

const npmBump = rewire('../lib/cli');
npmBump.__set__('writePackageJson', () => {
// do nothing; else would be modifying the package.json
});

// for these test to work we need to rewire the cmd answers...
let cmdOutput = { // eslint-disable-line prefer-const
'git rev-parse --verify HEAD': '',
'git rev-parse --verify unknown': '',
'git rev-parse --verify test/unknown': '',
'git rev-parse --verify other': '',
'git rev-parse --verify test/other': '',
'git rev-parse --verify mixed': '',
'git rev-parse --verify test/mixed': '',
'git rev-parse --show-cdup': '',
};
npmBump.__set__('run', cmd => {
if (cmdOutput[cmd] !== undefined) {
return cmdOutput[cmd];
}
return 'ERROR'; // otherwise deliver an unknown response
});

// ////////////////////////////////////////////////////////////////////////////////////////////
// so now start some tests... ;-)

/**
* "git status -s" output uses "?? rel-path" for unknown resources
*/
it('should ignore unknown files (prefixed by ??)', () => {
cmdOutput['git status -s'] = '?? 123\n?? 456\r\f?? 789';

npmBump.custom('test', 'unknown')('patch');
});

/**
* "git status -s" output uses "XX rel-path" for other resources (XX is M/D/etc)
*/
it('should NOT ignore known files (prefixed by M etc)', () => {
assert.throws(
() => {
cmdOutput['git status -s'] = ' M 123\n M 456\n D 789';

npmBump.custom('test', 'other')('patch');
},
ERROR_UNCOMMITTED_CHANGES
);
});

it('should NOT ignore other files when unknown files are present', () => {
assert.throws(
() => {
cmdOutput['git status -s'] = ' M 123\n M 456\r\f?? 789\n D 123';

npmBump.custom('test', 'mixed')('patch');
},
ERROR_UNCOMMITTED_CHANGES
);
});

});