typescript-assistant
Version:
Combines and integrates professional Typescript tools into your project
109 lines (102 loc) • 3.48 kB
text/typescript
import { Task, TaskRunner } from '../taskrunner';
import { Logger } from '../logger';
import { Bus, EventType } from '../bus';
import { absolutePath } from '../util';
import { Git } from '../git';
export interface NYC {
start(triggers: EventType[]): void;
stop(): void;
run(): Promise<boolean>;
}
let delay = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));
export let createNyc = (dependencies: { taskRunner: TaskRunner, logger: Logger, bus: Bus, git: Git }): NYC => {
let { taskRunner, logger, bus, git } = dependencies;
let runningTask: Task | undefined;
let coolingDown: Promise<void> | undefined;
let startNyc = async (): Promise<boolean> => {
let hasFailingTest = false;
let myCoolingDown = delay(100);
coolingDown = myCoolingDown;
await (myCoolingDown);
if (coolingDown !== myCoolingDown) {
return false;
}
if (runningTask) {
logger.log('nyc', 'Aborting previous nyc run');
runningTask.kill();
runningTask = undefined;
} else {
bus.report({ tool: 'test', status: 'busy' });
bus.report({ tool: 'coverage', status: 'busy' });
}
let errorLine = '';
let lastLineWasNotOk = false;
let handleOutput = (line: string) => {
if (task === runningTask) {
if (lastLineWasNotOk) {
errorLine = line;
lastLineWasNotOk = false;
}
// For extra debug info:
// if (!/^ok \d+ (.*)/.exec(line)) { logger.log('nyc', ' [ ' + line); }
let notOk = /^not ok \d+ (.*)/.exec(line);
let contextIt = /^(} )?at Context\.\S+ \(([^)]+)\)/.exec(line);
if (notOk) {
lastLineWasNotOk = true;
logger.log('nyc', `FAILED: ${notOk[1]}`);
hasFailingTest = true;
} else if (contextIt) {
logger.log('nyc', `${absolutePath(contextIt[2])} ${errorLine}`);
errorLine = '';
}
}
return true;
};
let handleError = (line: string) => {
if (task === runningTask) {
if (!line.startsWith('ERROR: Coverage for')) {
logger.error('nyc', line);
}
}
return true;
};
let task = runningTask = taskRunner.runTask(
'./node_modules/.bin/nyc',
('--check-coverage -- ' +
'./node_modules/.bin/mocha --require ts-node/register/transpile-only --reporter tap test/**/*-tests.ts*').split(' '),
{
name: 'nyc',
logger,
handleOutput,
handleError
});
return runningTask.result.then(() => {
if (task === runningTask) {
runningTask = undefined;
logger.log('nyc', 'code coverage OK');
bus.report({ tool: 'test', status: 'ready', errors: 0 });
bus.report({ tool: 'coverage', status: 'ready', errors: 0 });
}
return true;
}).catch(async () => {
if (task === runningTask) {
runningTask = undefined;
logger.log('nyc', 'code coverage FAILED');
bus.report({ tool: 'test', status: 'ready', errors: hasFailingTest ? 1 : 0 });
bus.report({ tool: 'coverage', status: 'ready', errors: 1 });
}
let isOnBranch = await git.isOnBranch();
return isOnBranch && !hasFailingTest;
});
};
return {
run: () => startNyc().catch(() => false),
start: (triggers: EventType[]) => {
bus.registerAll(triggers, startNyc);
startNyc().catch(() => false);
},
stop: () => {
bus.unregister(startNyc);
}
};
};