Compare commits

...

16 Commits

Author SHA1 Message Date
5e1b378ac6 1.0.11 2018-08-05 22:58:53 +02:00
a0ed5c7a16 fix(test result): now failing and succeeding correctly 2018-08-05 22:58:52 +02:00
7a20c0a27f 1.0.10 2018-08-04 23:16:22 +02:00
12414d7b5d fix(core): update 2018-08-04 23:16:21 +02:00
addf9e51e9 1.0.9 2018-08-04 19:41:01 +02:00
24a6b7480b fix(console): shorten log output 2018-08-04 19:41:00 +02:00
953a4e4b72 1.0.8 2018-08-04 19:23:17 +02:00
e7192800ea fix(improve log output): update 2018-08-04 19:23:17 +02:00
1516f843aa 1.0.7 2018-08-04 17:19:24 +02:00
f29558d6d1 fix(package): fix packagename 2018-08-04 17:19:24 +02:00
b6dc2df384 1.0.6 2018-08-04 17:13:01 +02:00
ec3999300d fix(peerDependency): now correctly finds bin of tsrun peer Dependency 2018-08-04 17:13:01 +02:00
b0dddd48a2 1.0.5 2018-08-04 16:04:12 +02:00
65dda322c5 fix(ci): switch to https for cloning ci dependencies 2018-08-04 16:04:11 +02:00
8db6e5e6f1 1.0.4 2018-08-04 15:55:49 +02:00
d1e60ad4ab fix(ci): remove globally required tools 2018-08-04 15:55:48 +02:00
10 changed files with 188 additions and 69 deletions

View File

@ -1,9 +1,6 @@
{ {
"npmci": { "npmci": {
"npmGlobalTools": [ "npmGlobalTools": [],
"@gitzone/npmts",
"ts-node"
],
"npmAccessLevel": "public" "npmAccessLevel": "public"
} }
} }

28
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "@pushrocks/tstest", "name": "@gitzone/tstest",
"version": "1.0.3", "version": "1.0.11",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -105,9 +105,9 @@
} }
}, },
"@pushrocks/smartshell": { "@pushrocks/smartshell": {
"version": "2.0.4", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@pushrocks/smartshell/-/smartshell-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@pushrocks/smartshell/-/smartshell-2.0.5.tgz",
"integrity": "sha512-yGVfp0i474nBUL44ufx5AQchFs5gAYBHiVAupDcG5H0f0KmnR2RKK1EIqKmdfmK7CIqLf8IAvv9FlhetmSrUhw==", "integrity": "sha512-bMmh46jfJxQ7F46bdujmBR8BqPeEFxBqdXab7885v0kaXASIf9+1BMPKfXiPsDrrR8z/2j2cG/Wgh/0+DDD9hQ==",
"requires": { "requires": {
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^2.0.5",
"@types/which": "^1.3.1", "@types/which": "^1.3.1",
@ -151,6 +151,11 @@
"@types/chai": "*" "@types/chai": "*"
} }
}, },
"@types/figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/figures/-/figures-2.0.0.tgz",
"integrity": "sha512-mcRgJ+ncKuNI+Dwac7omO18B8C8u+YBS+AU/oyLhEyjAnT3cUUThhHgZpbiIvu5ZqSvdD30BXtrqg9nxc3OKMg=="
},
"@types/form-data": { "@types/form-data": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
@ -397,11 +402,24 @@
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"dev": true "dev": true
}, },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"esprima": { "esprima": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
}, },
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
"requires": {
"escape-string-regexp": "^1.0.5"
}
},
"first-chunk-stream": { "first-chunk-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz",

View File

@ -1,6 +1,6 @@
{ {
"name": "@pushrocks/tstest", "name": "@gitzone/tstest",
"version": "1.0.3", "version": "1.0.11",
"private": false, "private": false,
"description": "a test utility to run tests that match test/**/*.ts", "description": "a test utility to run tests that match test/**/*.ts",
"main": "dist/index.js", "main": "dist/index.js",
@ -12,7 +12,7 @@
}, },
"scripts": { "scripts": {
"test": "(npm run prepareTest && npm run tstest && npm run cleanUp)", "test": "(npm run prepareTest && npm run tstest && npm run cleanUp)",
"prepareTest": "git clone git@gitlab.com:sandboxzone/sandbox-npmts.git .nogit/sandbox-npmts && cd .nogit/sandbox-npmts && npm install", "prepareTest": "git clone https://gitlab.com/sandboxzone/sandbox-npmts.git .nogit/sandbox-npmts && cd .nogit/sandbox-npmts && npm install",
"tstest": "cd .nogit/sandbox-npmts && node ../../cli.ts.js test/", "tstest": "cd .nogit/sandbox-npmts && node ../../cli.ts.js test/",
"cleanUp": "rm -rf .nogit/sandbox-npmts", "cleanUp": "rm -rf .nogit/sandbox-npmts",
"format": "(gitzone format)", "format": "(gitzone format)",
@ -28,6 +28,8 @@
"@pushrocks/smartfile": "^6.0.3", "@pushrocks/smartfile": "^6.0.3",
"@pushrocks/smartlog": "^2.0.1", "@pushrocks/smartlog": "^2.0.1",
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^2.0.5",
"@pushrocks/smartshell": "^2.0.4" "@pushrocks/smartshell": "^2.0.5",
"@types/figures": "^2.0.0",
"figures": "^2.0.0"
} }
} }

View File

@ -1,9 +1,10 @@
import * as plugins from "./tstest.plugins"; import * as plugins from './tstest.plugins';
import * as paths from './tstest.paths';
import { coloredString as cs } from '@pushrocks/consolecolor'; import { coloredString as cs } from '@pushrocks/consolecolor';
import { TestDirectory } from "./tstest.classes.testdirectory"; import { TestDirectory } from './tstest.classes.testdirectory';
import { TapCombinator } from "./tstest.tap.combinator"; import { TapCombinator } from './tstest.tap.combinator';
import { TapParser } from "./tstest.tap.parser"; import { TapParser } from './tstest.tap.parser';
export class TsTest { export class TsTest {
testDir: TestDirectory; testDir: TestDirectory;
@ -16,22 +17,24 @@ export class TsTest {
const fileNamesToRun: string[] = await this.testDir.getTestFilePathArray(); const fileNamesToRun: string[] = await this.testDir.getTestFilePathArray();
console.log(`Found ${fileNamesToRun.length} Testfile(s):`); console.log(`Found ${fileNamesToRun.length} Testfile(s):`);
for (const fileName of fileNamesToRun) { for (const fileName of fileNamesToRun) {
console.log(cs(fileName, "orange")); console.log(cs(fileName, 'orange'));
} }
console.log("-".repeat(16)); console.log('-'.repeat(16));
console.log(''); // force new line
const smartshellInstance = new plugins.smartshell.Smartshell({ const smartshellInstance = new plugins.smartshell.Smartshell({
executor: "bash", executor: 'bash',
pathDirectories: [paths.binDirectory],
sourceFilePaths: [] sourceFilePaths: []
}); });
const tapCombinator = new TapCombinator(); // lets create the TapCombinator const tapCombinator = new TapCombinator(); // lets create the TapCombinator
for (const fileName of fileNamesToRun) { for (const fileName of fileNamesToRun) {
console.log(`${cs("=> ", "blue")} Running ${cs(fileName, "orange")}`); console.log(`${cs('=> ', 'blue')} Running ${cs(fileName, 'orange')}`);
console.log(`=`.repeat(16)); console.log(cs(`=`.repeat(16), 'cyan'));
const tapParser = new TapParser(); const tapParser = new TapParser(fileName);
const execResultStreaming = await smartshellInstance.execStreamingSilent( const execResultStreaming = await smartshellInstance.execStreamingSilent(`tsrun ${fileName}`);
`tsrun ${fileName}`
);
await tapParser.handleTapProcess(execResultStreaming.childProcess); await tapParser.handleTapProcess(execResultStreaming.childProcess);
console.log(cs(`^`.repeat(16), 'cyan'));
console.log(''); // force new line
tapCombinator.addTapParser(tapParser); tapCombinator.addTapParser(tapParser);
} }
tapCombinator.evaluate(); tapCombinator.evaluate();

View File

@ -1,7 +1,7 @@
import * as plugins from './tstest.plugins'; import * as plugins from './tstest.plugins';
import { coloredString as cs } from '@pushrocks/consolecolor';
export const TapPrefix = plugins.consolecolor.coloredString( export const TapPrefix = cs(`:::TAP:::`, 'pink', 'black');
`:::TAP:::`, export const TapErrorPrefix = cs(`!!!TAP PROTOCOL ERROR!!!`, 'red', 'black');
'green',
'black' export const TsTestPrefix = cs(`>>>TSTEST<<<`, 'pink', 'black');
)

View File

@ -2,3 +2,4 @@ import * as plugins from './tstest.plugins';
export const cwd = process.cwd(); export const cwd = process.cwd();
export const testDir = plugins.path.join(cwd, './test/'); export const testDir = plugins.path.join(cwd, './test/');
export const binDirectory = plugins.path.join(cwd, 'node_modules/.bin');

View File

@ -8,4 +8,7 @@ import * as smartlog from '@pushrocks/smartlog';
import * as smartpromise from '@pushrocks/smartpromise'; import * as smartpromise from '@pushrocks/smartpromise';
import * as smartshell from '@pushrocks/smartshell'; import * as smartshell from '@pushrocks/smartshell';
export { consolecolor, path, smartfile, smartlog, smartpromise, smartshell }; // sindresorhus
import * as figures from 'figures';
export { consolecolor, figures, path, smartfile, smartlog, smartpromise, smartshell };

View File

@ -5,6 +5,7 @@ import * as plugins from './tstest.plugins';
import { coloredString as cs } from '@pushrocks/consolecolor'; import { coloredString as cs } from '@pushrocks/consolecolor';
import { TapParser } from './tstest.tap.parser'; import { TapParser } from './tstest.tap.parser';
import * as logPrefixes from './tstest.logprefixes';
export class TapCombinator { export class TapCombinator {
tapParserStore: TapParser[] = []; tapParserStore: TapParser[] = [];
@ -13,9 +14,35 @@ export class TapCombinator {
} }
evaluate() { evaluate() {
console.log(`Ran ${this.tapParserStore.length} Testfiles!`); console.log(`${logPrefixes.TsTestPrefix} Ran ${this.tapParserStore.length} Testfiles!`);
console.log(`${logPrefixes.TsTestPrefix} Here are the overall results:`);
let failGlobal = false; // determine wether tstest should fail
for (const tapParser of this.tapParserStore) { for (const tapParser of this.tapParserStore) {
if(tapParser.getErrorTests().length === 0) {
console.log(
logPrefixes.TsTestPrefix +
cs(` ${tapParser.fileName} ${plugins.figures.tick}`, 'green') +
' | ' +
cs(` all tests completed successfully!`, 'blue')
)
} else {
console.log(
logPrefixes.TsTestPrefix +
cs(` ${tapParser.fileName} ${plugins.figures.cross}`, 'red') +
' | ' +
cs(` Errors ocurred, please check for the logs!`, 'blue')
);
failGlobal = true;
}
}
console.log(cs('-'.repeat(16), 'cyan'));
console.log(cs('*'.repeat(16), 'cyan'));
console.log(cs('-'.repeat(16), 'cyan'));
if(!failGlobal) {
console.log(cs('Ending with code 0: TESTS ARE PASSING!', 'green'));
} else {
console.log(cs('Ending with code 1: TESTS ARE FAILING!', 'red'));
} }
} }
} }

View File

@ -1,33 +1,39 @@
import { ChildProcess } from "child_process"; import { ChildProcess } from 'child_process';
import { coloredString as cs } from '@pushrocks/consolecolor'; import { coloredString as cs } from '@pushrocks/consolecolor';
// ============ // ============
// combines different tap test files to an overall result // combines different tap test files to an overall result
// ============ // ============
import * as plugins from "./tstest.plugins"; import * as plugins from './tstest.plugins';
import { TapTestResult } from "./tstest.tap.testresult"; import { TapTestResult } from './tstest.tap.testresult';
import * as logPrefixes from './tstest.logprefixes';
export class TapParser { export class TapParser {
resultStore: TapTestResult[] = []; testStore: TapTestResult[] = [];
expectedTestsRegex = /([0-9]*)\.\.([0-9]*)/; expectedTestsRegex = /([0-9]*)\.\.([0-9]*)/;
expectedTests: number; expectedTests: number;
receivedTests: number;
testStatusRegex = /(ok|not\sok)\s([0-9]+)\s-\s/; testStatusRegex = /(ok|not\sok)\s([0-9]+)\s-\s(.*)\s#\stime=(.*)ms$/;
activeTapTestResult: TapTestResult; activeTapTestResult: TapTestResult;
private _getNewTapTestResult () { /**
this.activeTapTestResult = new TapTestResult( * the constructor for TapParser
this.resultStore.length + 1 */
); constructor(public fileName: string) {}
private _getNewTapTestResult() {
this.activeTapTestResult = new TapTestResult(this.testStore.length + 1);
} }
private _processLog(logChunk: Buffer | string) { private _processLog(logChunk: Buffer | string) {
if (Buffer.isBuffer(logChunk)) { if (Buffer.isBuffer(logChunk)) {
logChunk = logChunk.toString(); logChunk = logChunk.toString();
} }
const logLineArray = logChunk.split("\n"); const logLineArray = logChunk.split('\n');
if (logLineArray[logLineArray.length - 1] === "") { if (logLineArray[logLineArray.length - 1] === '') {
logLineArray.pop(); logLineArray.pop();
} }
@ -38,42 +44,53 @@ export class TapParser {
logLineIsTapProtocol = true; logLineIsTapProtocol = true;
const regexResult = this.expectedTestsRegex.exec(logLine); const regexResult = this.expectedTestsRegex.exec(logLine);
this.expectedTests = parseInt(regexResult[2]); this.expectedTests = parseInt(regexResult[2]);
console.log(`:::TAP::: Expecting ${this.expectedTests} tests!`); console.log(
`${logPrefixes.TapPrefix} ${cs(
`Expecting ${this.expectedTests} tests!`,
'blue'
)}`
);
// initiating first TapResult // initiating first TapResult
this._getNewTapTestResult(); this._getNewTapTestResult();
} else if (this.testStatusRegex.test(logLine)) { } else if (this.testStatusRegex.test(logLine)) {
logLineIsTapProtocol = true; logLineIsTapProtocol = true;
const regexResult = this.testStatusRegex.exec(logLine); const regexResult = this.testStatusRegex.exec(logLine);
const testId = parseInt(regexResult[2]); const testId = parseInt(regexResult[2]);
const testOk = (() => { const testOk = (() => {
if (regexResult[1] === "ok") { if (regexResult[1] === 'ok') {
return true; return true;
} }
return false; return false;
})(); })();
const testSubject = regexResult[3];
const testDuration = parseInt(regexResult[4]);
// test for protocol error // test for protocol error
if(testId !== this.activeTapTestResult.id) { if (testId !== this.activeTapTestResult.id) {
console.log(`:::TAP PROTOCOL ERROR::: Something is strange! Test Ids are not equal!`) console.log(
`${
logPrefixes.TapErrorPrefix
} Something is strange! Test Ids are not equal!`
);
} }
this.activeTapTestResult.setTestResult(testOk); this.activeTapTestResult.setTestResult(testOk);
if(testOk) { if (testOk) {
console.log( console.log(
cs( logPrefixes.TapPrefix,
`:::TAP::: Success: Test ${testId} is ok!`, `${cs(`T${testId} ${plugins.figures.tick}`, 'green')} | ` +
'green', cs(testSubject, 'blue') +
'black' ` | ${cs(`${testDuration} ms`, 'orange')}`
)); );
} else { } else {
console.log( console.log(
cs( logPrefixes.TapPrefix,
`:::TAP::: Error: Test ${testId} is NOT ok!`, `${cs(`T${testId} ${plugins.figures.cross}`, 'red')} | ` +
'green', cs(testSubject, 'blue') +
'black' ` | ${cs(`${testDuration} ms`, 'orange')}`
)); );
} }
} }
@ -84,22 +101,75 @@ export class TapParser {
console.log(logLine); console.log(logLine);
} }
if(this.activeTapTestResult && this.activeTapTestResult.testSettled) { if (this.activeTapTestResult && this.activeTapTestResult.testSettled) {
this.resultStore.push(this.activeTapTestResult); this.testStore.push(this.activeTapTestResult);
this._getNewTapTestResult(); this._getNewTapTestResult();
} }
} }
} }
/**
* returns all tests that are not completed
*/
getUncompletedTests() {
// TODO:
}
/**
* returns all tests that threw an error
*/
getErrorTests() {
return this.testStore.filter(tapTestArg => {
return !tapTestArg.testOk;
});
}
async handleTapProcess(childProcessArg: ChildProcess) { async handleTapProcess(childProcessArg: ChildProcess) {
const done = plugins.smartpromise.defer(); const done = plugins.smartpromise.defer();
childProcessArg.stdout.on("data", data => { childProcessArg.stdout.on('data', data => {
this._processLog(data); this._processLog(data);
}); });
childProcessArg.stderr.on("data", data => { childProcessArg.stderr.on('data', data => {
this._processLog(data); this._processLog(data);
}); });
childProcessArg.on("exit", () => { childProcessArg.on('exit', () => {
this.receivedTests = this.testStore.length;
// check wether all tests ran
if (this.expectedTests === this.receivedTests) {
console.log(
`${logPrefixes.TapPrefix} ${cs(
`${this.receivedTests} out of ${
this.expectedTests
} Tests completed!`,
'green'
)}`
);
} else {
console.log(
`${logPrefixes.TapErrorPrefix} ${cs(
`Only ${this.receivedTests} out of ${
this.expectedTests
} completed!`,
'red'
)}`
);
}
if (this.getErrorTests().length === 0) {
console.log(
`${logPrefixes.TapPrefix} ${cs(
`All tests are successfull!!!`,
'green'
)}`
);
} else {
console.log(
`${logPrefixes.TapPrefix} ${cs(
`${this.getErrorTests().length} tests threw an error!!!`,
'red'
)}`
);
}
done.resolve(); done.resolve();
}); });
await done.promise; await done.promise;

View File

@ -7,9 +7,7 @@ export class TapTestResult {
testLogBuffer = Buffer.from(''); testLogBuffer = Buffer.from('');
testOk: boolean = false; testOk: boolean = false;
testSettled: boolean = false; testSettled: boolean = false;
constructor(public id: number) { constructor(public id: number) {}
}
/** /**
* adds a logLine to the log buffer of the test * adds a logLine to the log buffer of the test