Skip to content

Commit

Permalink
refactor(core): improve tests, fixtures, and refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
JamieMason committed Oct 28, 2018
1 parent 2684490 commit 7ff66d4
Show file tree
Hide file tree
Showing 33 changed files with 805 additions and 436 deletions.
1 change: 1 addition & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import 'expect-more-jest';
60 changes: 60 additions & 0 deletions src/fix-mismatches.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { readJsonSync } from 'fs-extra';
import mock = require('mock-fs');
import { getFixture, getMockCommander } from '../test/helpers';
import { run } from './fix-mismatches';
import { IManifest } from './typings';

describe('fix-mismatches', () => {
let spyConsole: any;

afterAll(() => {
mock.restore();
});

beforeAll(async () => {
const [one, two, three] = getFixture('exact').data as IManifest[];
const sources = [
'/path/1/package.json',
'/path/2/package.json',
'/path/3/package.json'
];
const program = getMockCommander(sources);
mock({
'/path/1/package.json': JSON.stringify(one),
'/path/2/package.json': JSON.stringify(two),
'/path/3/package.json': JSON.stringify(three)
});
const noop = () => undefined;
spyConsole = jest.spyOn(console, 'log').mockImplementation(noop);
await run(program);
});

it('sets the version of dependencies with different versions to the newest of those versions found', () => {
expect(readJsonSync('/path/1/package.json')).toEqual(
expect.objectContaining({
dependencies: { chalk: '2.3.0', commander: '2.13.0' },
devDependencies: {
jest: '22.1.4',
prettier: '1.10.2',
rimraf: '2.6.2'
},
peerDependencies: { gulp: '*' }
})
);
expect(readJsonSync('/path/2/package.json')).toEqual(
expect.objectContaining({
dependencies: { chalk: '2.3.0' },
devDependencies: { jest: '22.1.4' }
})
);
expect(readJsonSync('/path/3/package.json')).toEqual(
expect.objectContaining({
devDependencies: {
npm: 'https://github.com/npm/npm.git',
prettier: '1.10.2'
},
peerDependencies: { gulp: '*' }
})
);
});
});
38 changes: 19 additions & 19 deletions src/fix-mismatches.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import chalk from 'chalk';
import { CommanderStatic } from 'commander';
import { writeJson } from 'fs-extra';
import _ = require('lodash');
import { relative } from 'path';
import {
Expand All @@ -13,9 +13,9 @@ import { getDependencyTypes } from './lib/get-dependency-types';
import { getPackages } from './lib/get-packages';
import { getMismatchedVersionsByName } from './lib/get-versions-by-name';
import { getNewest } from './lib/version';
import { writeJson } from './lib/write-json';
import { CommanderApi } from './typings';

export const run = async (program: CommanderStatic) => {
export const run = async (program: CommanderApi) => {
program
.option(OPTION_SOURCES.spec, OPTION_SOURCES.description, collect)
.option(OPTIONS_PROD.spec, OPTIONS_PROD.description)
Expand All @@ -32,25 +32,25 @@ export const run = async (program: CommanderStatic) => {

Object.entries(mismatchedVersionsByName).forEach(([name, versions]) => {
const newest = getNewest(versions);
if (typeof newest === 'string') {
pkgs.forEach(({ data, path }) => {
dependencyTypes.forEach((type) => {
if (data[type] && data[type][name] && data[type][name] !== newest) {
console.log(
relative(process.cwd(), path),
name,
data[type][name],
'->',
newest
);
data[type][name] = newest;
}
});
pkgs.forEach(({ data, path }) => {
dependencyTypes.forEach((type) => {
if (data[type] && data[type][name] && data[type][name] !== newest) {
console.log(
relative(process.cwd(), path),
name,
data[type][name],
'->',
newest
);
data[type][name] = newest;
}
});
}
});
});

await Promise.all(pkgs.map(({ data, path }) => writeJson(path, data)));
await Promise.all(
pkgs.map(({ data, path }) => writeJson(path, data, { spaces: 2 }))
);

_.each(pkgs, (pkg) => {
console.log(chalk.blue(`./${relative('.', pkg.path)}`));
Expand Down
133 changes: 67 additions & 66 deletions src/format.spec.ts
Original file line number Diff line number Diff line change
@@ -1,107 +1,108 @@
import { getUntidyManifest } from '../test/fixtures';
import { shuffleObject } from '../test/helpers';
import { readJsonSync } from 'fs-extra';
import mock = require('mock-fs');
import { getFixture, getMockCommander, shuffleObject } from '../test/helpers';
import { SORT_FIRST } from './constants';
import { run } from './format';
import { IManifest } from './typings';
import { manifestData } from './manifests/manifest-data';

describe('format', () => {
let results: IManifest[];
beforeAll(() => {
results = manifestData.format([
shuffleObject(getUntidyManifest()) as IManifest
let minimal: IManifest;
let untidy: IManifest;

beforeAll(async () => {
const program = getMockCommander([
'/minimal/package.json',
'/untidy/package.json'
]);
mock({
'/minimal/package.json': JSON.stringify({
name: 'minimal',
version: '0.0.0'
}),
'/untidy/package.json': getFixture('untidy', shuffleObject).json
});
await run(program);
minimal = readJsonSync('/minimal/package.json');
untidy = readJsonSync('/untidy/package.json');
mock.restore();
});

it('sorts specified keys to the top of package.json', () => {
results.forEach((result) => {
expect(Object.keys(result).slice(0, SORT_FIRST.length)).toEqual(
SORT_FIRST
);
});
expect(Object.keys(untidy).slice(0, SORT_FIRST.length)).toEqual(SORT_FIRST);
});

it('sorts remaining keys alphabetically', () => {
results.forEach((result) => {
expect(Object.keys(result).slice(SORT_FIRST.length - 1)).toEqual([
'author',
'bin',
'bugs',
'dependencies',
'devDependencies',
'files',
'homepage',
'keywords',
'license',
'main',
'peerDependencies',
'repository',
'scripts'
]);
});
expect(Object.keys(untidy).slice(SORT_FIRST.length - 1)).toEqual([
'author',
'bin',
'bugs',
'dependencies',
'devDependencies',
'files',
'homepage',
'keywords',
'license',
'main',
'peerDependencies',
'repository',
'scripts'
]);
});

it('sorts "dependencies" alphabetically', () => {
results.forEach((result) => {
expect(result.dependencies).toEqual({
arnold: '5.0.0',
dog: '2.13.0',
guybrush: '7.1.1',
mango: '2.3.0'
});
expect(minimal).not.toHaveProperty('dependencies');
expect(untidy.dependencies).toEqual({
arnold: '5.0.0',
dog: '2.13.0',
guybrush: '7.1.1',
mango: '2.3.0'
});
});

it('sorts "devDependencies" alphabetically', () => {
results.forEach((result) => {
expect(result.devDependencies).toEqual({
stroopwafel: '4.4.2',
waldorf: '22.1.4'
});
expect(minimal).not.toHaveProperty('devDependencies');
expect(untidy.devDependencies).toEqual({
stroopwafel: '4.4.2',
waldorf: '22.1.4'
});
});

it('sorts "files" alphabetically', () => {
results.forEach((result) => {
expect(result.files).toEqual(['assets', 'dist']);
});
expect(minimal).not.toHaveProperty('files');
expect(untidy.files).toEqual(['assets', 'dist']);
});

it('sorts "keywords" alphabetically', () => {
results.forEach((result) => {
expect(result.keywords).toEqual(['thing', 'those', 'whatsits']);
});
expect(minimal).not.toHaveProperty('keywords');
expect(untidy.keywords).toEqual(['thing', 'those', 'whatsits']);
});

it('sorts "peerDependencies" alphabetically', () => {
results.forEach((result) => {
expect(result.peerDependencies).toEqual({
giftwrap: '0.1.2',
jambalaya: '6.1.4',
zoolander: '1.4.25'
});
expect(minimal).not.toHaveProperty('peerDependencies');
expect(untidy.peerDependencies).toEqual({
giftwrap: '0.1.2',
jambalaya: '6.1.4',
zoolander: '1.4.25'
});
});

it('sorts "scripts" alphabetically', () => {
results.forEach((result) => {
expect(result.scripts).toEqual({
build: 'tsc',
format: 'prettier',
lint: 'tslint',
test: 'jest'
});
expect(minimal).not.toHaveProperty('scripts');
expect(untidy.scripts).toEqual({
build: 'tsc',
format: 'prettier',
lint: 'tslint',
test: 'jest'
});
});

it('uses shorthand "bugs"', () => {
results.forEach((result) => {
expect(result.bugs).toEqual('https://github.com/JaneDoe/do-it/issues');
});
expect(minimal).not.toHaveProperty('bugs');
expect(untidy.bugs).toEqual('https://github.com/JaneDoe/do-it/issues');
});

it('uses shorthand "repository"', () => {
results.forEach((result) => {
expect(result.repository).toEqual('JaneDoe/do-it');
});
expect(minimal).not.toHaveProperty('repository');
expect(untidy.repository).toEqual('JaneDoe/do-it');
});
});
48 changes: 14 additions & 34 deletions src/format.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,23 @@
import chalk from 'chalk';
import { CommanderStatic } from 'commander';
import { writeJson } from 'fs-extra';
import _ = require('lodash');
import { relative } from 'path';
import { OPTION_SOURCES, SORT_AZ, SORT_FIRST } from './constants';
import { collect } from './lib/collect';
import { getPackages } from './lib/get-packages';
import { writeJson } from './lib/write-json';
import { IManifest } from './typings';
import { CommanderApi, IManifest } from './typings';

export const run = async (program: CommanderStatic) => {
export const run = async (program: CommanderApi) => {
const shortenBugs = (manifest: IManifest): IManifest => {
if (
manifest.bugs &&
typeof manifest.bugs === 'object' &&
manifest.bugs.url
) {
return {
...manifest,
bugs: manifest.bugs.url
};
}
return manifest;
const bugsUrl = _.get(manifest, 'bugs.url') as string;
return bugsUrl ? { ...manifest, bugs: bugsUrl } : manifest;
};

const shortenRepository = (manifest: IManifest): IManifest => {
if (
manifest.repository &&
typeof manifest.repository === 'object' &&
manifest.repository.url &&
manifest.repository.url.indexOf('github.com') !== -1
) {
return {
...manifest,
repository: manifest.repository.url.split('github.com/')[1]
};
}
return manifest;
const repoUrl = _.get(manifest, 'repository.url', '') as string;
return repoUrl.includes('github.com')
? { ...manifest, repository: repoUrl.split('github.com/')[1] }
: manifest;
};

const sortObject = (obj: IManifest) =>
Expand Down Expand Up @@ -82,12 +64,10 @@ export const run = async (program: CommanderStatic) => {
const pkgs = await getPackages(program);

await Promise.all(
pkgs.map(({ data, path }) =>
writeJson(path, sortManifest(shortenBugs(shortenRepository(data))))
)
pkgs.map(({ data, path }) => {
console.log(chalk.blue(`./${relative('.', path)}`));
const nextData = sortManifest(shortenBugs(shortenRepository(data)));
return writeJson(path, nextData, { spaces: 2 });
})
);

_.each(pkgs, (pkg) => {
console.log(chalk.blue(`./${relative('.', pkg.path)}`));
});
};
5 changes: 2 additions & 3 deletions src/lib/get-dependency-types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { CommanderStatic } from 'commander';
import { DEPENDENCY_TYPES } from '../constants';
import { IManifestKey } from '../typings';
import { CommanderApi, IManifestKey } from '../typings';

export type GetDependencyTypes = (program: CommanderStatic) => IManifestKey[];
export type GetDependencyTypes = (program: CommanderApi) => IManifestKey[];

export const getDependencyTypes: GetDependencyTypes = (program) =>
program.prod || program.dev || program.peer
Expand Down
7 changes: 3 additions & 4 deletions src/lib/get-packages.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { CommanderStatic } from 'commander';
import fs = require('fs-extra');
import globby = require('globby');
import { OPTION_SOURCES } from '../constants';
import { IManifestDescriptor } from '../typings';
import { CommanderApi, IManifestDescriptor } from '../typings';

export const getSources = (program: CommanderStatic): string[] =>
export const getSources = (program: CommanderApi): string[] =>
program.source && program.source.length
? program.source
: OPTION_SOURCES.default;

export const getPackages = async (
program: CommanderStatic
program: CommanderApi
): Promise<IManifestDescriptor[]> =>
Promise.all(
(await globby(getSources(program))).map(async (filePath) => ({
Expand Down

0 comments on commit 7ff66d4

Please sign in to comment.