Compare commits

...

12 Commits

Author SHA1 Message Date
9f898b6579 1.0.14 2018-08-13 23:58:51 +02:00
b1725b636b fix(improve test handling): now failing correctly and with better log output 2018-08-13 23:58:50 +02:00
df3f1ea9d6 1.0.13 2018-08-08 22:51:21 +02:00
d749476d0c fix(update dependencies): update 2018-08-08 22:51:20 +02:00
4456cd68d0 1.0.12 2018-08-05 23:20:32 +02:00
8f61b5648f fix(log): improve log output 2018-08-05 23:20:32 +02:00
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
12 changed files with 328 additions and 192 deletions

3
contribute.md Normal file
View File

@ -0,0 +1,3 @@
# How to contribute
Start with `tstest.classes.tstest.ts` to understand whats happening

101
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "@pushrocks/tstest", "name": "@gitzone/tstest",
"version": "1.0.8", "version": "1.0.14",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -18,7 +18,6 @@
"version": "2.0.21", "version": "2.0.21",
"resolved": "https://registry.npmjs.org/@gitzone/tsbuild/-/tsbuild-2.0.21.tgz", "resolved": "https://registry.npmjs.org/@gitzone/tsbuild/-/tsbuild-2.0.21.tgz",
"integrity": "sha512-MAKfqnhf+42twSzXziRoBCu+sW61+2Rvc5qXxpEb594Fpnsj28cZ1VIEckSmiAkoBSiCnoU+2/qea2ycwWMBTg==", "integrity": "sha512-MAKfqnhf+42twSzXziRoBCu+sW61+2Rvc5qXxpEb594Fpnsj28cZ1VIEckSmiAkoBSiCnoU+2/qea2ycwWMBTg==",
"dev": true,
"requires": { "requires": {
"@pushrocks/smartfile": "^6.0.3", "@pushrocks/smartfile": "^6.0.3",
"@pushrocks/smartlog": "^2.0.1", "@pushrocks/smartlog": "^2.0.1",
@ -28,13 +27,21 @@
} }
}, },
"@gitzone/tsrun": { "@gitzone/tsrun": {
"version": "1.1.9", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/@gitzone/tsrun/-/tsrun-1.1.9.tgz", "resolved": "https://registry.npmjs.org/@gitzone/tsrun/-/tsrun-1.1.11.tgz",
"integrity": "sha512-MbCLj4hSK5nY6cMqT0OxY0BrXffmiC1Rjbzan8CmEpB8OttaAJT+zsJErJWhI+pk4s75Te73PyhHYaJAXUoJhw==", "integrity": "sha512-LkWEmEDyG1px40sDWSgC3STw54VbVAGq828eZsfhYkKlpJa+HzLP0LG5Q31mwjSUFWlCf4AU4MFOD9xbUXTahA==",
"requires": { "requires": {
"@pushrocks/smartfile": "^6.0.3", "@gitzone/tsbuild": "^2.0.21",
"@pushrocks/smartfile": "^6.0.6",
"ts-node": "^7.0.0", "ts-node": "^7.0.0",
"typescript": "^2.9.1" "typescript": "^3.0.1"
},
"dependencies": {
"typescript": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz",
"integrity": "sha512-zQIMOmC+372pC/CCVLqnQ0zSBiY7HHodU7mpQdjiZddek4GMj31I3dUJ7gAs9o65X7mnRma6OokOkc6f9jjfBg=="
}
} }
}, },
"@pushrocks/consolecolor": { "@pushrocks/consolecolor": {
@ -55,18 +62,18 @@
} }
}, },
"@pushrocks/smartfile": { "@pushrocks/smartfile": {
"version": "6.0.3", "version": "6.0.6",
"resolved": "https://registry.npmjs.org/@pushrocks/smartfile/-/smartfile-6.0.3.tgz", "resolved": "https://registry.npmjs.org/@pushrocks/smartfile/-/smartfile-6.0.6.tgz",
"integrity": "sha512-oYnLQzY/R6kVNerbWY4WwnPvdxXldrzMPWcB9j0aAdSDSqGwBEO1/ZFTQuNzN5MmPopoYmJrc06ZmI6dm4OJmw==", "integrity": "sha512-vA1+yS6n0kuBZ+Bl30rxOCYvgIj0mo9g303cUpOZR0I781iQVWHcBKRC05FaGDxJD1HuYdvbSK+7vlrzZjVcMw==",
"requires": { "requires": {
"@pushrocks/smartpath": "^4.0.1",
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^2.0.5",
"@pushrocks/smartrequest": "^1.0.15", "@pushrocks/smartrequest": "^1.1.12",
"@types/fs-extra": "^5.0.3", "@types/fs-extra": "^5.0.4",
"@types/vinyl": "^2.0.2", "@types/vinyl": "^2.0.2",
"fs-extra": "^6.0.1", "fs-extra": "^7.0.0",
"glob": "^7.1.2", "glob": "^7.1.2",
"js-yaml": "^3.10.0", "js-yaml": "^3.10.0",
"smartpath": "^3.2.8",
"vinyl-file": "^3.0.0" "vinyl-file": "^3.0.0"
} }
}, },
@ -86,8 +93,7 @@
"@pushrocks/smartpath": { "@pushrocks/smartpath": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/@pushrocks/smartpath/-/smartpath-4.0.1.tgz", "resolved": "https://registry.npmjs.org/@pushrocks/smartpath/-/smartpath-4.0.1.tgz",
"integrity": "sha512-MaI0+uLQPCr2V3WGnbdgb0pWa9xkWyrP4qYcbsHIjeismGLbn9s3jmP/HIXU8LkgzRgaVb+BJxmZJHOwl32DyA==", "integrity": "sha512-MaI0+uLQPCr2V3WGnbdgb0pWa9xkWyrP4qYcbsHIjeismGLbn9s3jmP/HIXU8LkgzRgaVb+BJxmZJHOwl32DyA=="
"dev": true
}, },
"@pushrocks/smartpromise": { "@pushrocks/smartpromise": {
"version": "2.0.5", "version": "2.0.5",
@ -105,9 +111,9 @@
} }
}, },
"@pushrocks/smartshell": { "@pushrocks/smartshell": {
"version": "2.0.5", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/@pushrocks/smartshell/-/smartshell-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@pushrocks/smartshell/-/smartshell-2.0.6.tgz",
"integrity": "sha512-bMmh46jfJxQ7F46bdujmBR8BqPeEFxBqdXab7885v0kaXASIf9+1BMPKfXiPsDrrR8z/2j2cG/Wgh/0+DDD9hQ==", "integrity": "sha512-D48KB3DDqLfMjOXGEutqJi+v3Z4RcWacu5BJXxUwrecvd6oetbKobfmNGxeHSQPmNGb7U3ISfKwV6c5T5EZkJg==",
"requires": { "requires": {
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^2.0.5",
"@types/which": "^1.3.1", "@types/which": "^1.3.1",
@ -151,6 +157,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",
@ -168,9 +179,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "10.5.5", "version": "10.5.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.7.tgz",
"integrity": "sha512-6Qnb1gXbp3g1JX9QVJj3A6ORzc9XCyhokxUKaoonHgNXcQhmk8adhotxfkeK8El9TnFeUuH72yI6jQ5nDJKS6w==" "integrity": "sha512-VkKcfuitP+Nc/TaTFH0B8qNmn+6NbI6crLkQonbedViVz7O2w8QV/GERPlkJ4bg42VGHiEWa31CoTOPs1q6z1w=="
}, },
"@types/vinyl": { "@types/vinyl": {
"version": "2.0.2", "version": "2.0.2",
@ -397,11 +408,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",
@ -427,9 +451,9 @@
} }
}, },
"fs-extra": { "fs-extra": {
"version": "6.0.1", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.0.tgz",
"integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", "integrity": "sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ==",
"requires": { "requires": {
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0", "jsonfile": "^4.0.0",
@ -480,14 +504,6 @@
"function-bind": "^1.1.1" "function-bind": "^1.1.1"
} }
}, },
"home": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/home/-/home-1.0.1.tgz",
"integrity": "sha1-lqQjzrSbmDeP9e886uBZpVf53TU=",
"requires": {
"os-homedir": "^1.0.1"
}
},
"inflight": { "inflight": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@ -656,11 +672,6 @@
"wrappy": "1" "wrappy": "1"
} }
}, },
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -731,15 +742,6 @@
"chai-string": "^1.4.0" "chai-string": "^1.4.0"
} }
}, },
"smartpath": {
"version": "3.2.8",
"resolved": "https://registry.npmjs.org/smartpath/-/smartpath-3.2.8.tgz",
"integrity": "sha1-SDS9OouuIpW6rK26I8h6UBlS+UA=",
"requires": {
"home": "^1.0.1",
"typings-global": "^1.0.14"
}
},
"smartq": { "smartq": {
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/smartq/-/smartq-1.1.8.tgz", "resolved": "https://registry.npmjs.org/smartq/-/smartq-1.1.8.tgz",
@ -830,7 +832,8 @@
"typings-global": { "typings-global": {
"version": "1.0.28", "version": "1.0.28",
"resolved": "https://registry.npmjs.org/typings-global/-/typings-global-1.0.28.tgz", "resolved": "https://registry.npmjs.org/typings-global/-/typings-global-1.0.28.tgz",
"integrity": "sha512-6VOwJWEY2971HOMHu/7sURzUXiD4/LiMJPsMAOqkHHAtS3MVpLFE5gzTiHilsH9KY5VE1mBQirWIgWFsDuo90A==" "integrity": "sha512-6VOwJWEY2971HOMHu/7sURzUXiD4/LiMJPsMAOqkHHAtS3MVpLFE5gzTiHilsH9KY5VE1mBQirWIgWFsDuo90A==",
"dev": true
}, },
"universalify": { "universalify": {
"version": "0.1.2", "version": "0.1.2",

View File

@ -1,6 +1,6 @@
{ {
"name": "@gitzone/tstest", "name": "@gitzone/tstest",
"version": "1.0.8", "version": "1.0.14",
"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",
@ -23,11 +23,13 @@
"@pushrocks/tapbundle": "^3.0.1" "@pushrocks/tapbundle": "^3.0.1"
}, },
"dependencies": { "dependencies": {
"@gitzone/tsrun": "^1.1.9", "@gitzone/tsrun": "^1.1.11",
"@pushrocks/consolecolor": "^2.0.1", "@pushrocks/consolecolor": "^2.0.1",
"@pushrocks/smartfile": "^6.0.3", "@pushrocks/smartfile": "^6.0.6",
"@pushrocks/smartlog": "^2.0.1", "@pushrocks/smartlog": "^2.0.1",
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^2.0.5",
"@pushrocks/smartshell": "^2.0.5" "@pushrocks/smartshell": "^2.0.6",
"@types/figures": "^2.0.0",
"figures": "^2.0.0"
} }
} }

View File

@ -0,0 +1,46 @@
// ============
// combines different tap test files to an overall result
// ============
import * as plugins from './tstest.plugins';
import { coloredString as cs } from '@pushrocks/consolecolor';
import { TapParser } from './tstest.classes.tap.parser';
import * as logPrefixes from './tstest.logprefixes';
export class TapCombinator {
tapParserStore: TapParser[] = [];
addTapParser(tapParserArg: TapParser) {
this.tapParserStore.push(tapParserArg);
}
evaluate() {
console.log(`${logPrefixes.TsTestPrefix} RESULTS FOR ${this.tapParserStore.length} TESTFILE(S):`);
let failGlobal = false; // determine wether tstest should fail
for (const tapParser of this.tapParserStore) {
if (tapParser.getErrorTests().length === 0) {
let overviewString =
logPrefixes.TsTestPrefix +
cs(` ${tapParser.fileName} ${plugins.figures.tick}`, 'green') +
` ${plugins.figures.pointer} ` +
tapParser.getTestOverviewAsString();
console.log(overviewString);
} else {
let overviewString =
logPrefixes.TsTestPrefix +
cs(` ${tapParser.fileName} ${plugins.figures.cross}`, 'red') +
` ${plugins.figures.pointer} ` +
tapParser.getTestOverviewAsString();
console.log(overviewString);
failGlobal = true;
}
}
console.log(cs(plugins.figures.hamburger.repeat(48), 'cyan'));
if (!failGlobal) {
console.log(cs('FINAL RESULT: SUCCESS!', 'green'));
} else {
console.log(cs('FINAL RESULT: FAIL!', 'red'));
process.exit(1);
}
}
}

View File

@ -0,0 +1,199 @@
import { ChildProcess } from 'child_process';
import { coloredString as cs } from '@pushrocks/consolecolor';
// ============
// combines different tap test files to an overall result
// ============
import * as plugins from './tstest.plugins';
import { TapTestResult } from './tstest.classes.tap.testresult';
import * as logPrefixes from './tstest.logprefixes';
export class TapParser {
testStore: TapTestResult[] = [];
expectedTestsRegex = /([0-9]*)\.\.([0-9]*)$/;
expectedTests: number;
receivedTests: number;
testStatusRegex = /(ok|not\sok)\s([0-9]+)\s-\s(.*)\s#\stime=(.*)ms$/;
activeTapTestResult: TapTestResult;
/**
* the constructor for TapParser
*/
constructor(public fileName: string) {}
private _getNewTapTestResult() {
this.activeTapTestResult = new TapTestResult(this.testStore.length + 1);
}
private _processLog(logChunk: Buffer | string) {
if (Buffer.isBuffer(logChunk)) {
logChunk = logChunk.toString();
}
const logLineArray = logChunk.split('\n');
if (logLineArray[logLineArray.length - 1] === '') {
logLineArray.pop();
}
// lets parse the log information
for (const logLine of logLineArray) {
let logLineIsTapProtocol = false;
if (!this.expectedTests && this.expectedTestsRegex.test(logLine)) {
logLineIsTapProtocol = true;
const regexResult = this.expectedTestsRegex.exec(logLine);
this.expectedTests = parseInt(regexResult[2]);
console.log(
`${logPrefixes.TapPrefix} ${cs(
`Expecting ${this.expectedTests} tests!`,
'blue'
)}`
);
// initiating first TapResult
this._getNewTapTestResult();
} else if (this.testStatusRegex.test(logLine)) {
logLineIsTapProtocol = true;
const regexResult = this.testStatusRegex.exec(logLine);
const testId = parseInt(regexResult[2]);
const testOk = (() => {
if (regexResult[1] === 'ok') {
return true;
}
return false;
})();
const testSubject = regexResult[3];
const testDuration = parseInt(regexResult[4]);
// test for protocol error
if (testId !== this.activeTapTestResult.id) {
console.log(
`${
logPrefixes.TapErrorPrefix
} Something is strange! Test Ids are not equal!`
);
}
this.activeTapTestResult.setTestResult(testOk);
if (testOk) {
console.log(
logPrefixes.TapPrefix,
`${cs(`T${testId} ${plugins.figures.tick}`, 'green')} ${plugins.figures.arrowRight} ` +
cs(testSubject, 'blue') +
` | ${cs(`${testDuration} ms`, 'orange')}`
);
} else {
console.log(
logPrefixes.TapPrefix,
`${cs(`T${testId} ${plugins.figures.cross}`, 'red')} ${plugins.figures.arrowRight} ` +
cs(testSubject, 'blue') +
` | ${cs(`${testDuration} ms`, 'orange')}`
);
}
}
if (!logLineIsTapProtocol) {
if (this.activeTapTestResult) {
this.activeTapTestResult.addLogLine(logLine);
}
console.log(logLine);
}
if (this.activeTapTestResult && this.activeTapTestResult.testSettled) {
this.testStore.push(this.activeTapTestResult);
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;
});
}
/**
* returns a test overview as string
*/
getTestOverviewAsString() {
let overviewString = ''
for(let test of this.testStore) {
if(overviewString !== '') {
overviewString += ' | ';
}
if (test.testOk) {
overviewString += cs(`T${test.id} ${plugins.figures.tick}`, 'green');
} else {
overviewString += cs(`T${test.id} ${plugins.figures.cross}`, 'red');
}
}
return overviewString;
}
/**
* handles a tap process
* @param childProcessArg
*/
async handleTapProcess(childProcessArg: ChildProcess) {
const done = plugins.smartpromise.defer();
childProcessArg.stdout.on('data', data => {
this._processLog(data);
});
childProcessArg.stderr.on('data', data => {
this._processLog(data);
});
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();
});
await done.promise;
}
}

View File

@ -3,9 +3,9 @@ import * as paths from './tstest.paths';
import { Smartfile } from '@pushrocks/smartfile'; import { Smartfile } from '@pushrocks/smartfile';
// tap related stuff // tap related stuff
import { TapCombinator } from './tstest.tap.combinator'; import { TapCombinator } from './tstest.classes.tap.combinator';
import { TapParser } from './tstest.tap.parser'; import { TapParser } from './tstest.classes.tap.parser';
import { TapTestResult } from './tstest.tap.testresult'; import { TapTestResult } from './tstest.classes.tap.testresult';
export class TestDirectory { export class TestDirectory {
/** /**

View File

@ -1,10 +1,12 @@
import * as plugins from './tstest.plugins'; import * as plugins from './tstest.plugins';
import * as paths from './tstest.paths'; import * as paths from './tstest.paths';
import * as logPrefixes from './tstest.logprefixes';
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.classes.tap.combinator';
import { TapParser } from './tstest.tap.parser'; import { TapParser } from './tstest.classes.tap.parser';
export class TsTest { export class TsTest {
testDir: TestDirectory; testDir: TestDirectory;
@ -15,11 +17,13 @@ export class TsTest {
async run() { async run() {
const fileNamesToRun: string[] = await this.testDir.getTestFilePathArray(); const fileNamesToRun: string[] = await this.testDir.getTestFilePathArray();
console.log(`Found ${fileNamesToRun.length} Testfile(s):`); console.log(cs(plugins.figures.hamburger.repeat(80), 'cyan'));
console.log('');
console.log(`${logPrefixes.TsTestPrefix} FOUND ${fileNamesToRun.length} TESTFILE(S):`);
for (const fileName of fileNamesToRun) { for (const fileName of fileNamesToRun) {
console.log(cs(fileName, 'orange')); console.log(`${logPrefixes.TsTestPrefix} ${cs(fileName, 'orange')}`);
} }
console.log('-'.repeat(16)); console.log('-'.repeat(48));
console.log(''); // force new line console.log(''); // force new line
const smartshellInstance = new plugins.smartshell.Smartshell({ const smartshellInstance = new plugins.smartshell.Smartshell({
executor: 'bash', executor: 'bash',
@ -30,7 +34,7 @@ export class TsTest {
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(cs(`=`.repeat(16), 'cyan')); console.log(cs(`=`.repeat(16), 'cyan'));
const tapParser = new TapParser(); const tapParser = new TapParser(fileName);
const execResultStreaming = await smartshellInstance.execStreamingSilent(`tsrun ${fileName}`); const execResultStreaming = await smartshellInstance.execStreamingSilent(`tsrun ${fileName}`);
await tapParser.handleTapProcess(execResultStreaming.childProcess); await tapParser.handleTapProcess(execResultStreaming.childProcess);
console.log(cs(`^`.repeat(16), 'cyan')); console.log(cs(`^`.repeat(16), 'cyan'));

View File

@ -1,3 +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(`:::TAP:::`, 'green', 'black'); export const TapPrefix = cs(`::TAP::`, 'pink', 'black');
export const TapErrorPrefix = cs(` !!!TAP PROTOCOL ERROR!!! `, 'red', 'black');
export const TsTestPrefix = cs(`**TSTEST**`, 'pink', 'black');

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

@ -1,20 +0,0 @@
// ============
// combines different tap test files to an overall result
// ============
import * as plugins from './tstest.plugins';
import { coloredString as cs } from '@pushrocks/consolecolor';
import { TapParser } from './tstest.tap.parser';
export class TapCombinator {
tapParserStore: TapParser[] = [];
addTapParser(tapParserArg: TapParser) {
this.tapParserStore.push(tapParserArg);
}
evaluate() {
console.log(`Ran ${this.tapParserStore.length} Testfiles!`);
for (const tapParser of this.tapParserStore) {
}
}
}

View File

@ -1,108 +0,0 @@
import { ChildProcess } from 'child_process';
import { coloredString as cs } from '@pushrocks/consolecolor';
// ============
// combines different tap test files to an overall result
// ============
import * as plugins from './tstest.plugins';
import { TapTestResult } from './tstest.tap.testresult';
import * as logPrefixes from './tstest.logprefixes';
export class TapParser {
resultStore: TapTestResult[] = [];
expectedTestsRegex = /([0-9]*)\.\.([0-9]*)/;
expectedTests: number;
testStatusRegex = /(ok|not\sok)\s([0-9]+)\s-\s(.*)\s#\stime=(.*)ms$/;
activeTapTestResult: TapTestResult;
private _getNewTapTestResult() {
this.activeTapTestResult = new TapTestResult(this.resultStore.length + 1);
}
private _processLog(logChunk: Buffer | string) {
if (Buffer.isBuffer(logChunk)) {
logChunk = logChunk.toString();
}
const logLineArray = logChunk.split('\n');
if (logLineArray[logLineArray.length - 1] === '') {
logLineArray.pop();
}
// lets parse the log information
for (const logLine of logLineArray) {
let logLineIsTapProtocol = false;
if (!this.expectedTests && this.expectedTestsRegex.test(logLine)) {
logLineIsTapProtocol = true;
const regexResult = this.expectedTestsRegex.exec(logLine);
this.expectedTests = parseInt(regexResult[2]);
console.log(`:::TAP::: Expecting ${this.expectedTests} tests!`);
// initiating first TapResult
this._getNewTapTestResult();
} else if (this.testStatusRegex.test(logLine)) {
logLineIsTapProtocol = true;
const regexResult = this.testStatusRegex.exec(logLine);
const testId = parseInt(regexResult[2]);
const testOk = (() => {
if (regexResult[1] === 'ok') {
return true;
}
return false;
})();
const testSubject = regexResult[3];
const testDuration = parseInt(regexResult[4]);
// test for protocol error
if (testId !== this.activeTapTestResult.id) {
console.log(`:::TAP PROTOCOL ERROR::: Something is strange! Test Ids are not equal!`);
}
this.activeTapTestResult.setTestResult(testOk);
if (testOk) {
console.log(
logPrefixes.TapPrefix,
` ${cs(`Test ${testId} -> Success!`, 'green')} | ` +
cs(testSubject, 'blue') +
` | ${cs(`${testDuration} milliseconds`, 'orange')}`
);
} else {
console.log(
logPrefixes.TapPrefix,
` ${cs(`Test ${testId} -> Error!`, 'red')} | ` +
cs(testSubject, 'blue') +
` | ${cs(`${testDuration} milliseconds`, 'orange')}`
);
}
}
if (!logLineIsTapProtocol) {
if (this.activeTapTestResult) {
this.activeTapTestResult.addLogLine(logLine);
}
console.log(logLine);
}
if (this.activeTapTestResult && this.activeTapTestResult.testSettled) {
this.resultStore.push(this.activeTapTestResult);
this._getNewTapTestResult();
}
}
}
async handleTapProcess(childProcessArg: ChildProcess) {
const done = plugins.smartpromise.defer();
childProcessArg.stdout.on('data', data => {
this._processLog(data);
});
childProcessArg.stderr.on('data', data => {
this._processLog(data);
});
childProcessArg.on('exit', () => {
done.resolve();
});
await done.promise;
}
}