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

test(roc-plugin-repo): Add semver utilities tests #12

Open
wants to merge 7 commits into
base: master
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
3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"plugins": [
"prettier"
],
"env": {
"jest": true
},
"rules": {
"prettier/prettier": ["error", { "trailingComma": "all", "singleQuote": true }],
"no-underscore-dangle": "off",
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ cache:
node_js:
- 6.9
before_script:
- git fetch --unshallow # needed to perform tests correctly
- npm start bootstrap
1 change: 1 addition & 0 deletions extensions/roc-plugin-repo/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function fetchProjects(command) {
return command(invokeHook('get-projects'));
}

// eslint-disable-next-line import/no-unresolved
const jestOptions = require('jest-cli/build/cli/args').options;

Object.keys(jestOptions).forEach(key => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const conventionalChangelog = require.requireActual('conventional-changelog');

export default function(options, context, gitRawCommitsOpts) {
// lock down "to" commits to make results predictable
const to = '84fe778a213bea560ca30bb8f085d8d6652eb455';
return conventionalChangelog(options, context, {
...gitRawCommitsOpts,
to,
});
}
9 changes: 9 additions & 0 deletions extensions/roc-plugin-repo/src/semver/__mocks__/roc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const executeSync = command => {
if (command.includes('commit-hash-some-directory')) {
return 'some-directory/some-folder/roc-plugin-hadron-collider';
}
return '';
};

// eslint-disable-next-line import/prefer-default-export
export { executeSync };
347 changes: 347 additions & 0 deletions extensions/roc-plugin-repo/src/semver/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,347 @@
/* eslint-disable import/first */
jest.mock('conventional-changelog');
jest.mock('roc');

import {
getLatestCommitsSinceRelease,
conventionalChangelogOptions,
getNextVersions,
createVersionsDoesNotMatch,
getMultiScopes,
getAutoScopes,
} from './utils';

describe('Semver utilities', () => {
describe('to get latest commits since release', () => {
it('should return information for current monorepo', async () => {
const projects = [];
const from = '';
const isMonorepo = true;

const result = await getLatestCommitsSinceRelease(
'angular',
from,
projects,
isMonorepo,
);

expect(Object.keys(result).sort()).toEqual([
'roc-plugin-repo',
'roc-plugin-repo-react',
'roc-plugin-repo-roc',
]);
expect(result['roc-plugin-repo'].release.subject).toBe('0.0.27');
expect(result['roc-plugin-repo-react'].release.subject).toBe('0.0.5');
expect(result['roc-plugin-repo-roc'].release.subject).toBe('0.0.1');
});
});

describe('to generate Conventional Changelog options', () => {
it('should set correct scope when commit is a revert', done => {
const project = {
path: '/',
};
const isMonorepo = false;

const options = conventionalChangelogOptions('angular', isMonorepo, [])(
project,
);
const commit = {
type: 'revert',
subject: "feat(@whole/world): Hey, what's the worst that could happen?",
scope: 'this should be changed',
};

options.transform(commit, () => {
expect(commit.scope).toBe('@whole/world');
done();
});
});

it('should not make changes to a commit if we are not using monorepo', done => {
const project = {
path: '/',
};
const isMonorepo = false;

const options = conventionalChangelogOptions('angular', isMonorepo, [])(
project,
);
const commit = {
type: 'release',
};

options.transform(commit, () => {
expect(commit).toEqual(commit);
done();
});
});

describe('should remove commit scope if we are using monorepo', () => {
it('when the scope is the same as the project name', done => {
const name = 'roc-plugin-hadron-collider';
const project = {
name,
path: '/',
};
const isMonorepo = true;

const options = conventionalChangelogOptions('angular', isMonorepo, [])(
project,
);
const commit = {
type: 'release',
scope: name,
notes: [],
};

options.transform(commit, () => {
expect(commit.scope).toBe(null);
done();
});
});

it('when the scope is the same as the project name', done => {
const name = 'roc-plugin-hadron-collider';
const project = {
name,
path: '/',
};
const isMonorepo = true;

const options = conventionalChangelogOptions('angular', isMonorepo, [])(
project,
);
const commit = {
type: 'release',
scope: name,
notes: [],
};

options.transform(commit, () => {
expect(commit.scope).toBe(null);
done();
});
});

it('when the scope affects all projects', done => {
const project = {
name: 'roc-plugin-hadron-collider',
path: '/',
};
const isMonorepo = true;

const options = conventionalChangelogOptions('angular', isMonorepo, [])(
project,
);
const commit = {
type: 'release',
scope: 'all',
notes: [],
};

options.transform(commit, () => {
expect(commit.scope).toBe(null);
done();
});
});

it('when project is included in a multi scope', done => {
const name = 'roc-plugin-hadron-collider';
const project = {
name,
path: '/',
};
const isMonorepo = true;

const options = conventionalChangelogOptions('angular', isMonorepo, [])(
project,
);
const commit = {
type: 'multi',
scope: 'multi',
notes: [
{
title: 'scopes',
text: `roc-plugin-skynet, ${name}`,
},
],
};

options.transform(commit, () => {
expect(commit.scope).toBe(null);
done();
});
});
});
});

describe('to get next versions', () => {
it('should return correct next versions for projects', () => {
const hadron = 'roc-plugin-hadron-collider';
const hadronNewVersion = '1.2.3';
const skynet = 'roc-plugin-skynet';
const skynetVersion = '0.1.4';
const status = {
[hadron]: {
newVersion: hadronNewVersion,
},
};
const projects = [
{
name: hadron,
packageJSON: {
version: '0.0.0',
},
},
{
name: skynet,
packageJSON: {
version: skynetVersion,
},
},
];

const projectsWithNextVersions = getNextVersions(status, projects);

expect(projectsWithNextVersions[hadron].version).toBe(hadronNewVersion);
expect(projectsWithNextVersions[skynet].version).toBe(skynetVersion);
});
});

describe('to match version numbers', () => {
it('should match when semver is ignored', () => {
const ignoreSemver = true;
const name = 'roc-plugin-hadron-collider';
const projectsWithVersions = {
[name]: {},
};
const dependencies = {};

const versionsDoesNotMatch = createVersionsDoesNotMatch(
projectsWithVersions,
dependencies,
ignoreSemver,
);
expect(versionsDoesNotMatch(name)).toBe(false);
});

it('should match when dependency is declared as latest', () => {
const ignoreSemver = false;
const name = 'roc-plugin-hadron-collider';
const projectsWithVersions = {
[name]: {},
};
const dependencies = {
[name]: 'latest',
};

const versionsDoesNotMatch = createVersionsDoesNotMatch(
projectsWithVersions,
dependencies,
ignoreSemver,
);
expect(versionsDoesNotMatch(name)).toBe(false);
});

it('should not match when dependency satisfies semver range', () => {
const ignoreSemver = false;
const name = 'roc-plugin-hadron-collider';
const projectsWithVersions = {
[name]: {
version: '1.2.4',
},
};
const dependencies = {
[name]: '^2.0.0',
};

const versionsDoesNotMatch = createVersionsDoesNotMatch(
projectsWithVersions,
dependencies,
ignoreSemver,
);
expect(versionsDoesNotMatch(name)).toBe(true);
});
});

describe('to get notes for multi scope commits', () => {
it('should ignore non-monorepo commits', () => {
const isMonorepo = false;
const commit = {
scope: 'multi',
notes: [
{
title: 'scopes',
text: 'I should not see that',
},
],
};

expect(getMultiScopes(commit, isMonorepo)).toEqual([]);
});

it('should extract text from monorepo commits', () => {
const isMonorepo = true;
const text = 'I should see that';
const commit = {
scope: 'multi',
notes: [
{
title: 'scopes',
text,
},
],
};

expect(getMultiScopes(commit, isMonorepo)).toEqual([text]);
});
});

describe('to get notes from affected files', () => {
it('should ignore non-monorepo commits', () => {
const isMonorepo = false;
const commit = {
scope: '*',
};
const projects = [];

expect(getAutoScopes(commit, isMonorepo, projects)).toEqual([]);
});

it('should ignore commits that did not affect any files', () => {
const isMonorepo = true;
const commit = {
hash: 'commit-hash-nothing',
scope: '*',
};
const projects = [];

expect(getAutoScopes(commit, isMonorepo, projects)).toEqual([]);
});

it('should return scope of commits that did affect some files', () => {
const isMonorepo = true;
const hadron = 'roc-plugin-hadron-collider';
const commit = {
hash: 'commit-hash-some-directory',
scope: '*',
};
const projects = [
{
name: hadron,
directory: 'some-directory',
folder: 'some-folder',
},
{
name: 'roc-plugin-skynet',
directory: 'other-directory',
folder: 'other-folder',
},
];

expect(getAutoScopes(commit, isMonorepo, projects)).toEqual([hadron]);
});
});
});
/* eslint-enable import/first */