Skip to content

Commit

Permalink
test: add more tests (#182)
Browse files Browse the repository at this point in the history
* test: increase coverage in format
* test: add unit tests for init.ts
* chore: update package-lock.json
  • Loading branch information
ofrobots committed Jun 28, 2018
1 parent 122fe81 commit b2b5bbd
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 15 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions src/format.ts
Expand Up @@ -18,7 +18,8 @@ import * as path from 'path';
import {Options} from './cli';
import {createProgram} from './lint';

const clangFormat = require('clang-format');
// Exported for testing purposes.
export const clangFormat = require('clang-format');

const BASE_ARGS_FILE = ['-style=file'];
const BASE_ARGS_INLINE =
Expand Down Expand Up @@ -56,7 +57,7 @@ export async function format(
program.getRootFileNames().filter(f => !f.endsWith('.d.ts'));

if (fix) {
return await fixFormat(srcFiles, baseClangFormatArgs);
return fixFormat(srcFiles, baseClangFormatArgs);
} else {
const result = await checkFormat(srcFiles, baseClangFormatArgs);
if (!result) {
Expand Down
18 changes: 9 additions & 9 deletions src/init.ts
Expand Up @@ -45,13 +45,13 @@ export interface PackageJson {
version?: string;
devDependencies?: Bag<string>;
scripts?: Bag<string>;
name: string;
description: string;
main: string;
types: string;
files: string[];
license: string;
keywords: string[];
name?: string;
description?: string;
main?: string;
types?: string;
files?: string[];
license?: string;
keywords?: string[];
}

async function query(
Expand All @@ -72,7 +72,7 @@ async function query(
return answers.query;
}

async function addScripts(
export async function addScripts(
packageJson: PackageJson, options: Options): Promise<boolean> {
let edits = false;
const scripts: Bag<string> = {
Expand Down Expand Up @@ -111,7 +111,7 @@ async function addScripts(
return edits;
}

async function addDependencies(
export async function addDependencies(
packageJson: PackageJson, options: Options): Promise<boolean> {
let edits = false;
const deps: Bag<string> = {'gts': `^${pkg.version}`, 'typescript': '~2.8.0'};
Expand Down
34 changes: 33 additions & 1 deletion test/test-format.ts
Expand Up @@ -37,7 +37,7 @@ const OPTIONS: Options = {
logger: {log: console.log, error: console.error, dir: nop}
};

test.serial('format should return false for well-formatted files', t => {
test.serial('format should return true for well-formatted files', t => {
return withFixtures(
{'tsconfig.json': JSON.stringify({files: ['a.ts']}), 'a.ts': GOOD_CODE},
async () => {
Expand Down Expand Up @@ -178,3 +178,35 @@ test.serial('format should use user provided config', t => {
t.true(result);
});
});

test.serial('format should prefer the files parameter over options', t => {
return withFixtures(
{
'tsconfig.json': JSON.stringify({files: ['a.ts']}),
'a.ts': BAD_CODE,
'good.ts': GOOD_CODE
},
async () => {
const result = await format.format(OPTIONS, ['good.ts'], false);
t.true(result);
});
});

test.serial('format should return error from failed spawn', async t => {
return withFixtures(
{'tsconfig.json': JSON.stringify({files: ['a.ts']}), 'a.ts': GOOD_CODE},
async () => {
const MESSAGE = '🦄';
// Mock clangFormat.
const original = format.clangFormat.spawnClangFormat;
// tslint:disable-next-line:no-any
format.clangFormat.spawnClangFormat = (_: any, cb: Function) => {
setImmediate(() => {
cb(new Error(MESSAGE));
});
};
await t.throws(format.format(OPTIONS, [], true), Error, MESSAGE);
await t.throws(format.format(OPTIONS, [], false), Error, MESSAGE);
format.clangFormat.spawnClangFormat = original;
});
});
150 changes: 150 additions & 0 deletions test/test-init.ts
@@ -0,0 +1,150 @@
/**
* Copyright 2018 Google LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import test from 'ava';
import path from 'path';

import {Options} from '../src/cli';
import * as init from '../src/init';
import {nop, readJsonp as readJson} from '../src/util';

import {withFixtures} from './fixtures';

const OPTIONS: Options = {
gtsRootDir: path.resolve(__dirname, '../..'),
targetRootDir: './',
dryRun: false,
yes: false,
no: false,
logger: {log: nop, error: nop, dir: nop}
};
const OPTIONS_YES = Object.assign({}, OPTIONS, {yes: true});
const OPTIONS_NO = Object.assign({}, OPTIONS, {no: true});
const OPTIONS_DRY_RUN = Object.assign({}, OPTIONS, {dryRun: true});

function hasExpectedScripts(packageJson: init.PackageJson): boolean {
return !!packageJson.scripts && [
'check', 'clean', 'compile', 'fix', 'prepare', 'pretest', 'posttest'
].every(s => !!packageJson.scripts![s]);
}

function hasExpectedDependencies(packageJson: init.PackageJson): boolean {
return !!packageJson.devDependencies &&
['gts', 'typescript'].every(d => !!packageJson.devDependencies![d]);
}

test('addScripts should add a scripts section if none exists', async t => {
const pkg: init.PackageJson = {};
const result = await init.addScripts(pkg, OPTIONS);
t.is(result, true); // made edits.
t.truthy(pkg.scripts);
t.truthy(hasExpectedScripts(pkg));
});

test('addScripts should not edit existing scripts on no', async t => {
const SCRIPTS = {
check: `fake check`,
clean: 'fake clean',
compile: `fake tsc -p .`,
fix: `fake fix`,
prepare: `fake run compile`,
pretest: `fake run compile`,
posttest: `fake run check`
};
const pkg: init.PackageJson = {scripts: Object.assign({}, SCRIPTS)};

const result = await init.addScripts(pkg, OPTIONS_NO);
t.is(result, false); // no edits.
t.deepEqual(pkg.scripts, SCRIPTS);
});

test('addScripts should edit existing scripts on yes', async t => {
const SCRIPTS = {
check: `fake check`,
clean: 'fake clean',
compile: `fake tsc -p .`,
fix: `fake fix`,
prepare: `fake run compile`,
pretest: `fake run compile`,
posttest: `fake run check`
};
const pkg: init.PackageJson = {scripts: Object.assign({}, SCRIPTS)};
const result = await init.addScripts(pkg, OPTIONS_YES);
t.is(result, true); // made edits.
t.notDeepEqual(pkg.scripts, SCRIPTS);
});

test('addDependencies should add a deps section if none exists', async t => {
const pkg: init.PackageJson = {};
const result = await init.addDependencies(pkg, OPTIONS);
t.is(result, true); // made edits.
t.truthy(pkg.devDependencies);
});

test('addDependencies should not edit existing deps on no', async t => {
const DEPS = {gts: 'something', typescript: 'or the other'};
const pkg: init.PackageJson = {devDependencies: Object.assign({}, DEPS)};
const OPTIONS_NO = Object.assign({}, OPTIONS, {no: true});
const result = await init.addDependencies(pkg, OPTIONS_NO);
t.is(result, false); // no edits.
t.deepEqual(pkg.devDependencies, DEPS);
});

test('addDependencies should edit existing deps on yes', async t => {
const DEPS = {gts: 'something', typescript: 'or the other'};
const pkg: init.PackageJson = {devDependencies: Object.assign({}, DEPS)};

const result = await init.addDependencies(pkg, OPTIONS_YES);
t.is(result, true); // made edits.
t.notDeepEqual(pkg.devDependencies, DEPS);
});

// TODO: test generateConfigFile

// init
test.serial('init should read local package.json', t => {
const originalContents = {some: 'property'};
return withFixtures(
{'package.json': JSON.stringify(originalContents)}, async () => {
// TODO: this test causes `npm install` to run in the fixture directory.
// This may make it sensistive to the network, npm resiliency. Find a
// way to mock npm.
const result = await init.init(OPTIONS_YES);
t.truthy(result);
const contents = await readJson('./package.json');

t.not(contents, originalContents, 'the file should have been modified');
t.is(
contents.some, originalContents.some,
'unrelated property should have preserved');
});
});

test.serial('init should handle missing package.json', t => {
return withFixtures({}, async () => {
// TODO: this test causes `npm install` to run in the fixture directory.
// This may make it sensistive to the network, npm resiliency. Find a way to
// mock npm.
const result = await init.init(OPTIONS_YES);
t.truthy(result);
const contents = await readJson('./package.json');
t.truthy(hasExpectedScripts(contents));
t.truthy(hasExpectedDependencies(contents));
});
});


// TODO: need more tests.

0 comments on commit b2b5bbd

Please sign in to comment.