Compare commits

...

26 Commits

Author SHA1 Message Date
5afe6e6981 1.0.18 2018-12-06 01:03:49 +01:00
5d071d0299 fix(core): update 2018-12-06 01:03:48 +01:00
180bfcb353 1.0.17 2018-12-06 00:56:36 +01:00
3161e6b4eb fix(core): update 2018-12-06 00:56:36 +01:00
6129388a20 1.0.16 2018-12-06 00:38:03 +01:00
8f0cfe1a06 fix(core): update 2018-12-06 00:38:03 +01:00
39926fb08b 1.0.15 2018-08-14 00:04:43 +02:00
36594b64f2 fix(dependencies): update 2018-08-14 00:04:42 +02:00
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
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
15 changed files with 910 additions and 360 deletions

View File

@ -26,6 +26,7 @@ mirror:
snyk:
stage: security
script:
- npmci npm prepare
- npmci command npm install -g snyk
- npmci command npm install --ignore-scripts
- npmci command snyk test
@ -36,21 +37,11 @@ snyk:
# ====================
# test stage
# ====================
testLEGACY:
stage: test
script:
- npmci node install legacy
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
allow_failure: true
testLTS:
stage: test
script:
- npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci npm test
@ -62,6 +53,7 @@ testLTS:
testSTABLE:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci npm test
@ -118,6 +110,7 @@ pages:
stage: metadata
script:
- npmci command npm install -g typedoc typescript
- npmci npm prepare
- npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
tags:
@ -130,13 +123,3 @@ pages:
paths:
- public
allow_failure: true
windowsCompatibility:
image: stefanscherer/node-windows:10-build-tools
stage: metadata
script:
- npm install & npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- windows
allow_failure: true

3
contribute.md Normal file
View File

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

782
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "@pushrocks/tstest",
"version": "1.0.5",
"name": "@gitzone/tstest",
"version": "1.0.18",
"private": false,
"description": "a test utility to run tests that match test/**/*.ts",
"main": "dist/index.js",
@ -19,15 +19,17 @@
"build": "(tsbuild)"
},
"devDependencies": {
"@gitzone/tsbuild": "^2.0.21",
"@pushrocks/tapbundle": "^3.0.1"
"@gitzone/tsbuild": "^2.1.3",
"@pushrocks/tapbundle": "^3.0.7"
},
"dependencies": {
"@gitzone/tsrun": "^1.1.9",
"@gitzone/tsrun": "^1.1.17",
"@pushrocks/consolecolor": "^2.0.1",
"@pushrocks/smartfile": "^6.0.3",
"@pushrocks/smartlog": "^2.0.1",
"@pushrocks/smartfile": "^6.0.11",
"@pushrocks/smartlog": "^2.0.9",
"@pushrocks/smartpromise": "^2.0.5",
"@pushrocks/smartshell": "^2.0.4"
"@pushrocks/smartshell": "^2.0.11",
"@types/figures": "^2.0.0",
"figures": "^2.0.0"
}
}

View File

@ -0,0 +1,48 @@
// ============
// 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,184 @@
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

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

View File

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

View File

@ -1,9 +1,12 @@
import * as plugins from "./tstest.plugins";
import * as plugins from './tstest.plugins';
import * as paths from './tstest.paths';
import * as logPrefixes from './tstest.logprefixes';
import { coloredString as cs } from '@pushrocks/consolecolor';
import { TestDirectory } from "./tstest.classes.testdirectory";
import { TapCombinator } from "./tstest.tap.combinator";
import { TapParser } from "./tstest.tap.parser";
import { TestDirectory } from './tstest.classes.testdirectory';
import { TapCombinator } from './tstest.classes.tap.combinator';
import { TapParser } from './tstest.classes.tap.parser';
export class TsTest {
testDir: TestDirectory;
@ -14,24 +17,37 @@ export class TsTest {
async run() {
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) {
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
const smartshellInstance = new plugins.smartshell.Smartshell({
executor: "bash",
executor: 'bash',
pathDirectories: [paths.binDirectory],
sourceFilePaths: []
});
const tapCombinator = new TapCombinator(); // lets create the TapCombinator
for (const fileName of fileNamesToRun) {
console.log(`${cs("=> ", "blue")} Running ${cs(fileName, "orange")}`);
console.log(`=`.repeat(16));
const tapParser = new TapParser();
console.log(`${cs('=> ', 'blue')} Running ${cs(fileName, 'orange')}`);
console.log(cs(`=`.repeat(16), 'cyan'));
const tapParser = new TapParser(fileName);
// tsrun options
let tsrunOptions = '';
if (process.argv.includes('--web')) {
tsrunOptions += ' --web';
}
const execResultStreaming = await smartshellInstance.execStreamingSilent(
`tsrun ${fileName}`
`tsrun ${fileName}${tsrunOptions}`
);
await tapParser.handleTapProcess(execResultStreaming.childProcess);
console.log(cs(`^`.repeat(16), 'cyan'));
console.log(''); // force new line
tapCombinator.addTapParser(tapParser);
}
tapCombinator.evaluate();

View File

@ -1,7 +1,7 @@
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

@ -2,3 +2,4 @@ import * as plugins from './tstest.plugins';
export const cwd = process.cwd();
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 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,21 +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,107 +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";
export class TapParser {
resultStore: TapTestResult[] = [];
expectedTestsRegex = /([0-9]*)\.\.([0-9]*)/;
expectedTests: number;
testStatusRegex = /(ok|not\sok)\s([0-9]+)\s-\s/;
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;
})();
// 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(
cs(
`:::TAP::: Success: Test ${testId} is ok!`,
'green',
'black'
));
} else {
console.log(
cs(
`:::TAP::: Error: Test ${testId} is NOT ok!`,
'green',
'black'
));
}
}
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;
}
}

View File

@ -1,3 +1,17 @@
{
"extends": "tslint-config-standard"
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}