mirror of
https://github.com/wassname/DefinitelyTyped.git
synced 2026-08-31 11:40:47 +08:00
first setup for incremental testing
combines reference parser and git changes still very dev mode
This commit is contained in:
+162
-69
@@ -47,6 +47,8 @@ var Exec = function () {
|
||||
/// <reference path="../_ref.d.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
/////////////////////////////////
|
||||
@@ -55,30 +57,17 @@ var DT;
|
||||
/////////////////////////////////
|
||||
var File = (function () {
|
||||
function File(baseDir, filePathWithName) {
|
||||
this.references = [];
|
||||
this.baseDir = baseDir;
|
||||
this.filePathWithName = filePathWithName;
|
||||
this.references = [];
|
||||
this.ext = path.extname(this.filePathWithName);
|
||||
this.file = path.basename(this.filePathWithName, this.ext);
|
||||
this.dir = path.dirname(this.filePathWithName);
|
||||
this.formatName = path.join(this.dir, this.file + this.ext);
|
||||
this.fullPath = path.join(this.baseDir, this.dir, this.file + this.ext);
|
||||
// lock it (shallow)
|
||||
// Object.freeze(this);
|
||||
}
|
||||
Object.defineProperty(File.prototype, "formatName", {
|
||||
// From '/complete/path/to/file' to 'specfolder/specfile.d.ts'
|
||||
get: function () {
|
||||
return path.join(this.dir, this.file + this.ext);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(File.prototype, "fullPath", {
|
||||
get: function () {
|
||||
return path.join(this.baseDir, this.dir, this.file + this.ext);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
File.prototype.toString = function () {
|
||||
return '[File ' + this.filePathWithName + ']';
|
||||
};
|
||||
@@ -91,6 +80,7 @@ var DT;
|
||||
/// <reference path="host/exec.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
var fs = require('fs');
|
||||
|
||||
var Tsc = (function () {
|
||||
@@ -132,6 +122,8 @@ var DT;
|
||||
/// <reference path="../runner.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
/////////////////////////////////
|
||||
// Timer.start starts a timer
|
||||
// Timer.end stops the timer and sets asString to the pretty print value
|
||||
@@ -171,6 +163,8 @@ var DT;
|
||||
/// <reference path="../_ref.d.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
var referenceTagExp = /<reference[ \t]*path=["']?([\w\.\/_-]*)["']?[ \t]*\/>/g;
|
||||
|
||||
function endsWith(str, suffix) {
|
||||
@@ -201,6 +195,8 @@ var DT;
|
||||
/// <reference path="util.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
@@ -219,6 +215,17 @@ var DT;
|
||||
});
|
||||
};
|
||||
|
||||
FileIndex.prototype.hasFile = function (target) {
|
||||
return target in this.fileMap;
|
||||
};
|
||||
|
||||
FileIndex.prototype.getFile = function (target) {
|
||||
if (target in this.fileMap) {
|
||||
return this.fileMap[target];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
FileIndex.prototype.loadReferences = function (files, callback) {
|
||||
var _this = this;
|
||||
var queue = files.slice(0);
|
||||
@@ -276,6 +283,8 @@ var DT;
|
||||
/// <reference path="../_ref.d.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Git = require('git-wrapper');
|
||||
@@ -283,7 +292,8 @@ var DT;
|
||||
var GitChanges = (function () {
|
||||
function GitChanges(baseDir) {
|
||||
this.baseDir = baseDir;
|
||||
this.options = [];
|
||||
this.options = {};
|
||||
this.paths = [];
|
||||
var dir = path.join(baseDir, '.git');
|
||||
if (!fs.existsSync(dir)) {
|
||||
throw new Error('cannot locate git-dir: ' + dir);
|
||||
@@ -291,19 +301,20 @@ var DT;
|
||||
this.options['git-dir'] = dir;
|
||||
}
|
||||
GitChanges.prototype.getChanges = function (callback) {
|
||||
var _this = this;
|
||||
//git diff --name-only HEAD~1
|
||||
var git = new Git(this.options);
|
||||
var opts = {};
|
||||
var args = ['--name-only HEAD~1'];
|
||||
git.exec('diff', opts, args, function (err, msg) {
|
||||
if (err) {
|
||||
callback(err, null);
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
var paths = msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
|
||||
_this.paths = msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
|
||||
|
||||
// console.log(paths);
|
||||
callback(null, paths);
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
return GitChanges;
|
||||
@@ -314,6 +325,8 @@ var DT;
|
||||
/// <reference path="../runner.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
/////////////////////////////////
|
||||
// All the common things that we pring are functions of this class
|
||||
/////////////////////////////////
|
||||
@@ -430,6 +443,8 @@ var DT;
|
||||
/// <reference path="../printer.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
@@ -463,6 +478,8 @@ var DT;
|
||||
/// <reference path="../../runner.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
@@ -549,6 +566,8 @@ var __extends = this.__extends || function (d, b) {
|
||||
};
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
/////////////////////////////////
|
||||
// .d.ts syntax inspection
|
||||
/////////////////////////////////
|
||||
@@ -570,6 +589,8 @@ var DT;
|
||||
/// <reference path="../util.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
/////////////////////////////////
|
||||
// Compile with *-tests.ts
|
||||
/////////////////////////////////
|
||||
@@ -591,6 +612,8 @@ var DT;
|
||||
/// <reference path="../file.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
/////////////////////////////////
|
||||
@@ -665,6 +688,8 @@ var DT;
|
||||
/// <reference path="src/suite/tscParams.ts" />
|
||||
var DT;
|
||||
(function (DT) {
|
||||
'use-strict';
|
||||
|
||||
require('source-map-support').install();
|
||||
|
||||
var fs = require('fs');
|
||||
@@ -673,17 +698,6 @@ var DT;
|
||||
|
||||
var tsExp = /\.ts$/;
|
||||
|
||||
// TOD0 remove this after dev!
|
||||
var testNames = [
|
||||
'async/',
|
||||
'jquery/jquery.d',
|
||||
'angularjs/angular.d',
|
||||
'pixi/'
|
||||
];
|
||||
|
||||
/* if (process.env.TRAVIS) {
|
||||
testNames = null;
|
||||
} */
|
||||
DT.DEFAULT_TSC_VERSION = "0.9.1.1";
|
||||
|
||||
var Test = (function () {
|
||||
@@ -731,6 +745,8 @@ var DT;
|
||||
/////////////////////////////////
|
||||
// The main class to kick things off
|
||||
/////////////////////////////////
|
||||
// TODO move to bluebird (Promises)
|
||||
// TODO move to lazy.js (functional)
|
||||
var TestRunner = (function () {
|
||||
function TestRunner(dtPath, options) {
|
||||
if (typeof options === "undefined") { options = { tscVersion: DT.DEFAULT_TSC_VERSION }; }
|
||||
@@ -741,8 +757,9 @@ var DT;
|
||||
this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams;
|
||||
|
||||
this.index = new DT.FileIndex(this.options);
|
||||
this.changes = new DT.GitChanges(this.dtPath);
|
||||
|
||||
// should be async
|
||||
// should be async (way faster)
|
||||
// only includes .d.ts or -tests.ts or -test.ts or .ts
|
||||
var filesName = glob.sync('**/*.ts', { cwd: dtPath });
|
||||
this.files = filesName.filter(function (fileName) {
|
||||
@@ -751,29 +768,50 @@ var DT;
|
||||
return new DT.File(dtPath, fileName);
|
||||
});
|
||||
}
|
||||
TestRunner.prototype.checkAcceptFile = function (fileName) {
|
||||
var ok = tsExp.test(fileName);
|
||||
ok = ok && fileName.indexOf('_infrastructure') < 0;
|
||||
ok = ok && fileName.indexOf('node_modules/') < 0;
|
||||
ok = ok && /^[a-z]/i.test(fileName);
|
||||
|
||||
//TODO remove this dev code
|
||||
ok = ok && (!testNames || testNames.some(function (pattern) {
|
||||
return fileName.indexOf(pattern) > -1;
|
||||
}));
|
||||
return ok;
|
||||
};
|
||||
|
||||
TestRunner.prototype.addSuite = function (suite) {
|
||||
this.suites.push(suite);
|
||||
};
|
||||
|
||||
TestRunner.prototype.run = function () {
|
||||
var _this = this;
|
||||
this.timer = new DT.Timer();
|
||||
this.timer.start();
|
||||
|
||||
// we need promises
|
||||
this.doGetChanges();
|
||||
};
|
||||
|
||||
TestRunner.prototype.checkAcceptFile = function (fileName) {
|
||||
var ok = tsExp.test(fileName);
|
||||
ok = ok && fileName.indexOf('_infrastructure') < 0;
|
||||
ok = ok && fileName.indexOf('node_modules/') < 0;
|
||||
ok = ok && /^[a-z]/i.test(fileName);
|
||||
return ok;
|
||||
};
|
||||
|
||||
TestRunner.prototype.doGetChanges = function () {
|
||||
var _this = this;
|
||||
this.changes.getChanges(function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console.log('');
|
||||
console.log('changes:');
|
||||
console.log('---');
|
||||
|
||||
_this.changes.paths.forEach(function (file) {
|
||||
console.log(file);
|
||||
});
|
||||
console.log('---');
|
||||
|
||||
// chain
|
||||
_this.doGetReferences();
|
||||
});
|
||||
};
|
||||
|
||||
TestRunner.prototype.doGetReferences = function () {
|
||||
var _this = this;
|
||||
this.index.parseFiles(this.files, function () {
|
||||
console.log('');
|
||||
console.log('files:');
|
||||
console.log('---');
|
||||
_this.files.forEach(function (file) {
|
||||
@@ -783,29 +821,80 @@ var DT;
|
||||
});
|
||||
});
|
||||
console.log('---');
|
||||
_this.getChanges();
|
||||
|
||||
// chain
|
||||
_this.doCollectTargets();
|
||||
});
|
||||
};
|
||||
|
||||
TestRunner.prototype.getChanges = function () {
|
||||
TestRunner.prototype.doCollectTargets = function () {
|
||||
// TODO clean this up when functional (do we need changeMap?)
|
||||
var _this = this;
|
||||
var changes = new DT.GitChanges(this.dtPath);
|
||||
changes.getChanges(function (err, changes) {
|
||||
if (err) {
|
||||
throw err;
|
||||
// bake map for lookup
|
||||
var changeMap = this.changes.paths.filter(function (full) {
|
||||
return _this.checkAcceptFile(full);
|
||||
}).map(function (local) {
|
||||
return path.resolve(_this.dtPath, local);
|
||||
}).reduce(function (memo, full) {
|
||||
var file = _this.index.getFile(full);
|
||||
if (!file) {
|
||||
// what does it mean? deleted?
|
||||
console.log('not in index: ' + full);
|
||||
return memo;
|
||||
}
|
||||
console.log('changes:');
|
||||
console.log('---');
|
||||
changes.forEach(function (file) {
|
||||
console.log(file);
|
||||
});
|
||||
console.log('---');
|
||||
memo[full] = file;
|
||||
return memo;
|
||||
}, Object.create(null));
|
||||
|
||||
_this.runTests();
|
||||
// collect referring files (and also log)
|
||||
var touched = Object.create(null);
|
||||
console.log('');
|
||||
console.log('relevant changes:');
|
||||
console.log('---');
|
||||
Object.keys(changeMap).sort().forEach(function (src) {
|
||||
touched[src] = changeMap[src];
|
||||
console.log(changeMap[src].formatName);
|
||||
});
|
||||
console.log('---');
|
||||
|
||||
// terrible loop (whatever)
|
||||
// just add stuff until there is nothing new added
|
||||
// TODO improve it
|
||||
var added;
|
||||
do {
|
||||
added = 0;
|
||||
this.files.forEach(function (file) {
|
||||
// lol getter
|
||||
if (file.fullPath in touched) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if one of our references is touched
|
||||
file.references.some(function (ref) {
|
||||
if (ref.fullPath in touched) {
|
||||
// add us
|
||||
touched[file.fullPath] = file;
|
||||
added++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
} while(added > 0);
|
||||
|
||||
console.log('');
|
||||
console.log('touched:');
|
||||
console.log('---');
|
||||
var files = Object.keys(touched).sort().map(function (src) {
|
||||
console.log(touched[src].formatName);
|
||||
return touched[src];
|
||||
});
|
||||
console.log('---');
|
||||
|
||||
this.runTests(files);
|
||||
};
|
||||
|
||||
TestRunner.prototype.runTests = function () {
|
||||
TestRunner.prototype.runTests = function (files) {
|
||||
var _this = this;
|
||||
var syntaxChecking = new DT.SyntaxChecking(this.options);
|
||||
var testEval = new DT.TestEval(this.options);
|
||||
@@ -814,9 +903,10 @@ var DT;
|
||||
this.addSuite(testEval);
|
||||
}
|
||||
|
||||
var typings = syntaxChecking.filterTargetFiles(this.files).length;
|
||||
var testFiles = testEval.filterTargetFiles(this.files).length;
|
||||
this.print = new DT.Print(this.options.tscVersion, typings, testFiles, this.files.length);
|
||||
var typings = syntaxChecking.filterTargetFiles(files).length;
|
||||
var testFiles = testEval.filterTargetFiles(files).length;
|
||||
|
||||
this.print = new DT.Print(this.options.tscVersion, typings, testFiles, files.length);
|
||||
this.print.printHeader();
|
||||
|
||||
if (this.options.findNotRequiredTscparams) {
|
||||
@@ -830,7 +920,7 @@ var DT;
|
||||
suite.testReporter = suite.testReporter || new DT.DefaultTestReporter(_this.print);
|
||||
|
||||
_this.print.printSuiteHeader(suite.testSuiteName);
|
||||
var targetFiles = suite.filterTargetFiles(_this.files);
|
||||
var targetFiles = suite.filterTargetFiles(files);
|
||||
suite.start(targetFiles, function (testResult, index) {
|
||||
_this.testCompleteCallback(testResult, index);
|
||||
}, function (suite) {
|
||||
@@ -840,7 +930,7 @@ var DT;
|
||||
});
|
||||
} else {
|
||||
_this.timer.end();
|
||||
_this.allTestCompleteCallback();
|
||||
_this.allTestCompleteCallback(files);
|
||||
}
|
||||
};
|
||||
executor();
|
||||
@@ -864,7 +954,7 @@ var DT;
|
||||
this.print.printFailedCount(suite.ngTests.length, suite.testResults.length);
|
||||
};
|
||||
|
||||
TestRunner.prototype.allTestCompleteCallback = function () {
|
||||
TestRunner.prototype.allTestCompleteCallback = function (files) {
|
||||
var _this = this;
|
||||
var testEval = this.suites.filter(function (suite) {
|
||||
return suite instanceof DT.TestEval;
|
||||
@@ -875,11 +965,13 @@ var DT;
|
||||
}).reduce(function (a, b) {
|
||||
return a.indexOf(b) < 0 ? a.concat([b]) : a;
|
||||
}, []);
|
||||
var typings = this.files.map(function (file) {
|
||||
|
||||
var typings = files.map(function (file) {
|
||||
return file.dir;
|
||||
}).reduce(function (a, b) {
|
||||
return a.indexOf(b) < 0 ? a.concat([b]) : a;
|
||||
}, []);
|
||||
|
||||
var withoutTestTypings = typings.filter(function (typing) {
|
||||
return existsTestTypings.indexOf(typing) < 0;
|
||||
});
|
||||
@@ -892,6 +984,7 @@ var DT;
|
||||
|
||||
this.print.printDiv();
|
||||
this.print.printElapsedTime(this.timer.asString, this.timer.time);
|
||||
|
||||
this.suites.filter(function (suite) {
|
||||
return suite.printErrorCount;
|
||||
}).forEach(function (suite) {
|
||||
|
||||
+308
-247
@@ -19,291 +19,352 @@
|
||||
/// <reference path="src/suite/tscParams.ts" />
|
||||
|
||||
module DT {
|
||||
require('source-map-support').install();
|
||||
'use-strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var glob = require('glob');
|
||||
require('source-map-support').install();
|
||||
|
||||
var tsExp = /\.ts$/;
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var glob = require('glob');
|
||||
|
||||
// TOD0 remove this after dev!
|
||||
var testNames = [
|
||||
'async/',
|
||||
'jquery/jquery.d',
|
||||
'angularjs/angular.d',
|
||||
'pixi/'
|
||||
];
|
||||
/* if (process.env.TRAVIS) {
|
||||
testNames = null;
|
||||
} */
|
||||
var tsExp = /\.ts$/;
|
||||
|
||||
export var DEFAULT_TSC_VERSION = "0.9.1.1";
|
||||
export var DEFAULT_TSC_VERSION = "0.9.1.1";
|
||||
|
||||
export class Test {
|
||||
constructor(public suite: ITestSuite, public tsfile: File, public options?: TscExecOptions) {
|
||||
}
|
||||
export class Test {
|
||||
constructor(public suite: ITestSuite, public tsfile: File, public options?: TscExecOptions) {
|
||||
}
|
||||
|
||||
public run(callback: (result: TestResult) => void) {
|
||||
Tsc.run(this.tsfile.filePathWithName, this.options, (execResult) => {
|
||||
var testResult = new TestResult();
|
||||
testResult.hostedBy = this.suite;
|
||||
testResult.targetFile = this.tsfile;
|
||||
testResult.options = this.options;
|
||||
public run(callback: (result: TestResult) => void) {
|
||||
Tsc.run(this.tsfile.filePathWithName, this.options, (execResult) => {
|
||||
var testResult = new TestResult();
|
||||
testResult.hostedBy = this.suite;
|
||||
testResult.targetFile = this.tsfile;
|
||||
testResult.options = this.options;
|
||||
|
||||
testResult.stdout = execResult.stdout;
|
||||
testResult.stderr = execResult.stderr;
|
||||
testResult.exitCode = execResult.exitCode;
|
||||
testResult.stdout = execResult.stdout;
|
||||
testResult.stderr = execResult.stderr;
|
||||
testResult.exitCode = execResult.exitCode;
|
||||
|
||||
callback(testResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
/////////////////////////////////
|
||||
// Test results
|
||||
/////////////////////////////////
|
||||
export class TestResult {
|
||||
hostedBy: ITestSuite;
|
||||
targetFile: File;
|
||||
options: TscExecOptions;
|
||||
callback(testResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
exitCode: number;
|
||||
/////////////////////////////////
|
||||
// Test results
|
||||
/////////////////////////////////
|
||||
export class TestResult {
|
||||
hostedBy: ITestSuite;
|
||||
targetFile: File;
|
||||
options: TscExecOptions;
|
||||
|
||||
public get success(): boolean {
|
||||
return this.exitCode === 0;
|
||||
}
|
||||
}
|
||||
export interface ITestRunnerOptions {
|
||||
tscVersion:string;
|
||||
findNotRequiredTscparams?:boolean;
|
||||
}
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
exitCode: number;
|
||||
|
||||
/////////////////////////////////
|
||||
// The main class to kick things off
|
||||
/////////////////////////////////
|
||||
export class TestRunner {
|
||||
files: File[];
|
||||
timer: Timer;
|
||||
suites: ITestSuite[] = [];
|
||||
private index: FileIndex;
|
||||
private print: Print;
|
||||
public get success(): boolean {
|
||||
return this.exitCode === 0;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(public dtPath: string, public options: ITestRunnerOptions = {tscVersion: DT.DEFAULT_TSC_VERSION}) {
|
||||
this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams;
|
||||
export interface ITestRunnerOptions {
|
||||
tscVersion:string;
|
||||
findNotRequiredTscparams?:boolean;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// The main class to kick things off
|
||||
/////////////////////////////////
|
||||
// TODO move to bluebird (Promises)
|
||||
// TODO move to lazy.js (functional)
|
||||
export class TestRunner {
|
||||
files: File[];
|
||||
timer: Timer;
|
||||
suites: ITestSuite[] = [];
|
||||
|
||||
this.index = new FileIndex(this.options);
|
||||
private index: FileIndex;
|
||||
private changes: GitChanges;
|
||||
private print: Print;
|
||||
|
||||
// should be async
|
||||
// only includes .d.ts or -tests.ts or -test.ts or .ts
|
||||
var filesName = glob.sync('**/*.ts', { cwd: dtPath });
|
||||
this.files = filesName
|
||||
.filter((fileName) => {
|
||||
return this.checkAcceptFile(fileName);
|
||||
})
|
||||
.sort()
|
||||
.map((fileName) => {
|
||||
return new File(dtPath, fileName);
|
||||
});
|
||||
}
|
||||
constructor(public dtPath: string, public options: ITestRunnerOptions = {tscVersion: DT.DEFAULT_TSC_VERSION}) {
|
||||
this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams;
|
||||
|
||||
public checkAcceptFile(fileName: string): boolean {
|
||||
var ok = tsExp.test(fileName);
|
||||
ok = ok && fileName.indexOf('_infrastructure') < 0;
|
||||
ok = ok && fileName.indexOf('node_modules/') < 0;
|
||||
ok = ok && /^[a-z]/i.test(fileName);
|
||||
this.index = new FileIndex(this.options);
|
||||
this.changes = new GitChanges(this.dtPath);
|
||||
|
||||
//TODO remove this dev code
|
||||
ok = ok && (!testNames || testNames.some((pattern) => {
|
||||
return fileName.indexOf(pattern) > -1;
|
||||
}));
|
||||
return ok;
|
||||
}
|
||||
// should be async (way faster)
|
||||
// only includes .d.ts or -tests.ts or -test.ts or .ts
|
||||
var filesName = glob.sync('**/*.ts', { cwd: dtPath });
|
||||
this.files = filesName.filter((fileName) => {
|
||||
return this.checkAcceptFile(fileName);
|
||||
}).sort().map((fileName) => {
|
||||
return new File(dtPath, fileName);
|
||||
});
|
||||
}
|
||||
|
||||
public addSuite(suite: ITestSuite):void {
|
||||
this.suites.push(suite);
|
||||
}
|
||||
public addSuite(suite: ITestSuite): void {
|
||||
this.suites.push(suite);
|
||||
}
|
||||
|
||||
public run():void {
|
||||
this.timer = new Timer();
|
||||
this.timer.start();
|
||||
public run(): void {
|
||||
this.timer = new Timer();
|
||||
this.timer.start();
|
||||
|
||||
this.index.parseFiles(this.files, () => {
|
||||
console.log('files:');
|
||||
console.log('---');
|
||||
this.files.forEach((file) => {
|
||||
console.log(file.filePathWithName);
|
||||
file.references.forEach((file) => {
|
||||
console.log(' - %s', file.filePathWithName);
|
||||
});
|
||||
});
|
||||
console.log('---');
|
||||
this.getChanges();
|
||||
});
|
||||
}
|
||||
// we need promises
|
||||
this.doGetChanges();
|
||||
}
|
||||
|
||||
public getChanges():void {
|
||||
var changes = new GitChanges(this.dtPath);
|
||||
changes.getChanges((err, changes: string[]) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console.log('changes:');
|
||||
console.log('---');
|
||||
changes.forEach((file) => {
|
||||
console.log(file);
|
||||
});
|
||||
console.log('---');
|
||||
private checkAcceptFile(fileName: string): boolean {
|
||||
var ok = tsExp.test(fileName);
|
||||
ok = ok && fileName.indexOf('_infrastructure') < 0;
|
||||
ok = ok && fileName.indexOf('node_modules/') < 0;
|
||||
ok = ok && /^[a-z]/i.test(fileName);
|
||||
return ok;
|
||||
}
|
||||
|
||||
this.runTests();
|
||||
});
|
||||
}
|
||||
private doGetChanges(): void {
|
||||
this.changes.getChanges((err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
console.log('');
|
||||
console.log('changes:');
|
||||
console.log('---');
|
||||
|
||||
public runTests():void {
|
||||
this.changes.paths.forEach((file) => {
|
||||
console.log(file);
|
||||
});
|
||||
console.log('---');
|
||||
|
||||
var syntaxChecking = new SyntaxChecking(this.options);
|
||||
var testEval = new TestEval(this.options);
|
||||
if (!this.options.findNotRequiredTscparams) {
|
||||
this.addSuite(syntaxChecking);
|
||||
this.addSuite(testEval);
|
||||
}
|
||||
// chain
|
||||
this.doGetReferences();
|
||||
});
|
||||
}
|
||||
|
||||
var typings = syntaxChecking.filterTargetFiles(this.files).length;
|
||||
var testFiles = testEval.filterTargetFiles(this.files).length;
|
||||
this.print = new Print(this.options.tscVersion, typings, testFiles, this.files.length);
|
||||
this.print.printHeader();
|
||||
private doGetReferences(): void {
|
||||
this.index.parseFiles(this.files, () => {
|
||||
console.log('');
|
||||
console.log('files:');
|
||||
console.log('---');
|
||||
this.files.forEach((file) => {
|
||||
console.log(file.filePathWithName);
|
||||
file.references.forEach((file) => {
|
||||
console.log(' - %s', file.filePathWithName);
|
||||
});
|
||||
});
|
||||
console.log('---');
|
||||
|
||||
if (this.options.findNotRequiredTscparams) {
|
||||
this.addSuite(new FindNotRequiredTscparams(this.options, this.print));
|
||||
}
|
||||
// chain
|
||||
this.doCollectTargets();
|
||||
});
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
var executor = () => {
|
||||
var suite = this.suites[count];
|
||||
if (suite) {
|
||||
suite.testReporter = suite.testReporter || new DefaultTestReporter(this.print);
|
||||
private doCollectTargets(): void {
|
||||
|
||||
this.print.printSuiteHeader(suite.testSuiteName);
|
||||
var targetFiles = suite.filterTargetFiles(this.files);
|
||||
suite.start(
|
||||
targetFiles,
|
||||
(testResult, index) => {
|
||||
this.testCompleteCallback(testResult, index);
|
||||
},
|
||||
(suite) => {
|
||||
this.suiteCompleteCallback(suite);
|
||||
count++;
|
||||
executor();
|
||||
});
|
||||
} else {
|
||||
this.timer.end();
|
||||
this.allTestCompleteCallback();
|
||||
}
|
||||
};
|
||||
executor();
|
||||
}
|
||||
// TODO clean this up when functional (do we need changeMap?)
|
||||
|
||||
private testCompleteCallback(testResult: TestResult, index: number) {
|
||||
var reporter = testResult.hostedBy.testReporter;
|
||||
if (testResult.success) {
|
||||
reporter.printPositiveCharacter(index, testResult);
|
||||
} else {
|
||||
reporter.printNegativeCharacter(index, testResult);
|
||||
}
|
||||
}
|
||||
// bake map for lookup
|
||||
var changeMap = this.changes.paths.filter((full) => {
|
||||
return this.checkAcceptFile(full);
|
||||
}).map((local) => {
|
||||
return path.resolve(this.dtPath, local);
|
||||
}).reduce((memo, full) => {
|
||||
var file = this.index.getFile(full);
|
||||
if (!file) {
|
||||
// what does it mean? deleted?
|
||||
console.log('not in index: ' + full);
|
||||
return memo;
|
||||
}
|
||||
memo[full] = file;
|
||||
return memo;
|
||||
}, Object.create(null));
|
||||
|
||||
private suiteCompleteCallback(suite: ITestSuite) {
|
||||
this.print.printBreak();
|
||||
// collect referring files (and also log)
|
||||
var touched = Object.create(null);
|
||||
console.log('');
|
||||
console.log('relevant changes:');
|
||||
console.log('---');
|
||||
Object.keys(changeMap).sort().forEach((src) => {
|
||||
touched[src] = changeMap[src];
|
||||
console.log(changeMap[src].formatName);
|
||||
});
|
||||
console.log('---');
|
||||
|
||||
this.print.printDiv();
|
||||
this.print.printElapsedTime(suite.timer.asString, suite.timer.time);
|
||||
this.print.printSuccessCount(suite.okTests.length, suite.testResults.length);
|
||||
this.print.printFailedCount(suite.ngTests.length, suite.testResults.length);
|
||||
}
|
||||
// terrible loop (whatever)
|
||||
// just add stuff until there is nothing new added
|
||||
// TODO improve it
|
||||
var added:number;
|
||||
do {
|
||||
added = 0;
|
||||
this.files.forEach((file) => {
|
||||
// lol getter
|
||||
if (file.fullPath in touched) {
|
||||
return;
|
||||
}
|
||||
// check if one of our references is touched
|
||||
file.references.some((ref) => {
|
||||
if (ref.fullPath in touched) {
|
||||
// add us
|
||||
touched[file.fullPath] = file;
|
||||
added++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
while(added > 0);
|
||||
|
||||
private allTestCompleteCallback() {
|
||||
var testEval = this.suites.filter(suite => suite instanceof TestEval)[0];
|
||||
if (testEval) {
|
||||
var existsTestTypings: string[] = testEval.testResults
|
||||
.map((testResult) => {
|
||||
return testResult.targetFile.dir;
|
||||
})
|
||||
.reduce((a: string[], b: string) => {
|
||||
return a.indexOf(b) < 0 ? a.concat([b]) : a;
|
||||
}, []);
|
||||
var typings: string[] = this.files
|
||||
.map((file) => {
|
||||
return file.dir;
|
||||
})
|
||||
.reduce((a: string[], b: string) => {
|
||||
return a.indexOf(b) < 0 ? a.concat([b]) : a;
|
||||
}, []);
|
||||
var withoutTestTypings: string[] = typings
|
||||
.filter((typing) => {
|
||||
return existsTestTypings.indexOf(typing) < 0;
|
||||
});
|
||||
this.print.printDiv();
|
||||
this.print.printTypingsWithoutTest(withoutTestTypings);
|
||||
}
|
||||
console.log('');
|
||||
console.log('touched:');
|
||||
console.log('---');
|
||||
var files: File[] = Object.keys(touched).sort().map((src) => {
|
||||
console.log(touched[src].formatName);
|
||||
return touched[src];
|
||||
});
|
||||
console.log('---');
|
||||
|
||||
this.print.printDiv();
|
||||
this.print.printTotalMessage();
|
||||
this.runTests(files);
|
||||
}
|
||||
|
||||
this.print.printDiv();
|
||||
this.print.printElapsedTime(this.timer.asString, this.timer.time);
|
||||
this.suites
|
||||
.filter((suite: ITestSuite) => {
|
||||
return suite.printErrorCount;
|
||||
})
|
||||
.forEach((suite: ITestSuite) => {
|
||||
this.print.printSuiteErrorCount(suite.errorHeadline, suite.ngTests.length, suite.testResults.length);
|
||||
});
|
||||
if (testEval) {
|
||||
this.print.printSuiteErrorCount("Without tests", withoutTestTypings.length, typings.length, '\33[33m\33[1m');
|
||||
}
|
||||
private runTests(files: File[]): void {
|
||||
|
||||
this.print.printDiv();
|
||||
if (this.suites.some((suite) => {
|
||||
return suite.ngTests.length !== 0
|
||||
})) {
|
||||
this.print.printErrorsHeader();
|
||||
var syntaxChecking = new SyntaxChecking(this.options);
|
||||
var testEval = new TestEval(this.options);
|
||||
if (!this.options.findNotRequiredTscparams) {
|
||||
this.addSuite(syntaxChecking);
|
||||
this.addSuite(testEval);
|
||||
}
|
||||
|
||||
this.suites
|
||||
.filter((suite) => {
|
||||
return suite.ngTests.length !== 0;
|
||||
})
|
||||
.forEach((suite) => {
|
||||
suite.ngTests.forEach((testResult) => {
|
||||
this.print.printErrorsForFile(testResult);
|
||||
});
|
||||
this.print.printBoldDiv();
|
||||
});
|
||||
var typings = syntaxChecking.filterTargetFiles(files).length;
|
||||
var testFiles = testEval.filterTargetFiles(files).length;
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.print = new Print(this.options.tscVersion, typings, testFiles, files.length);
|
||||
this.print.printHeader();
|
||||
|
||||
var dtPath = path.resolve(path.dirname((module).filename), '..', '..');
|
||||
var findNotRequiredTscparams = process.argv.some(arg => arg == "--try-without-tscparams");
|
||||
var tscVersionIndex = process.argv.indexOf("--tsc-version");
|
||||
var tscVersion = DEFAULT_TSC_VERSION;
|
||||
if (-1 < tscVersionIndex) {
|
||||
tscVersion = process.argv[tscVersionIndex + 1];
|
||||
}
|
||||
if (this.options.findNotRequiredTscparams) {
|
||||
this.addSuite(new FindNotRequiredTscparams(this.options, this.print));
|
||||
}
|
||||
|
||||
console.log('--');
|
||||
console.log(' dtPath %s', dtPath);
|
||||
console.log(' tscVersion %s', tscVersion);
|
||||
console.log(' findNotRequiredTscparams %s', findNotRequiredTscparams);
|
||||
console.log('--');
|
||||
console.log('');
|
||||
var count = 0;
|
||||
var executor = () => {
|
||||
var suite = this.suites[count];
|
||||
if (suite) {
|
||||
suite.testReporter = suite.testReporter || new DefaultTestReporter(this.print);
|
||||
|
||||
var runner = new TestRunner(dtPath, {
|
||||
tscVersion: tscVersion,
|
||||
findNotRequiredTscparams: findNotRequiredTscparams
|
||||
});
|
||||
runner.run();
|
||||
this.print.printSuiteHeader(suite.testSuiteName);
|
||||
var targetFiles = suite.filterTargetFiles(files);
|
||||
suite.start(targetFiles, (testResult, index) => {
|
||||
this.testCompleteCallback(testResult, index);
|
||||
}, (suite) => {
|
||||
this.suiteCompleteCallback(suite);
|
||||
count++;
|
||||
executor();
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.timer.end();
|
||||
this.allTestCompleteCallback(files);
|
||||
}
|
||||
};
|
||||
executor();
|
||||
}
|
||||
|
||||
private testCompleteCallback(testResult: TestResult, index: number) {
|
||||
var reporter = testResult.hostedBy.testReporter;
|
||||
if (testResult.success) {
|
||||
reporter.printPositiveCharacter(index, testResult);
|
||||
}
|
||||
else {
|
||||
reporter.printNegativeCharacter(index, testResult);
|
||||
}
|
||||
}
|
||||
|
||||
private suiteCompleteCallback(suite: ITestSuite) {
|
||||
this.print.printBreak();
|
||||
|
||||
this.print.printDiv();
|
||||
this.print.printElapsedTime(suite.timer.asString, suite.timer.time);
|
||||
this.print.printSuccessCount(suite.okTests.length, suite.testResults.length);
|
||||
this.print.printFailedCount(suite.ngTests.length, suite.testResults.length);
|
||||
}
|
||||
|
||||
private allTestCompleteCallback(files: File[]) {
|
||||
var testEval = this.suites.filter(suite => suite instanceof TestEval)[0];
|
||||
if (testEval) {
|
||||
var existsTestTypings: string[] = testEval.testResults.map((testResult) => {
|
||||
return testResult.targetFile.dir;
|
||||
}).reduce((a: string[], b: string) => {
|
||||
return a.indexOf(b) < 0 ? a.concat([b]) : a;
|
||||
}, []);
|
||||
|
||||
var typings: string[] = files.map((file) => {
|
||||
return file.dir;
|
||||
}).reduce((a: string[], b: string) => {
|
||||
return a.indexOf(b) < 0 ? a.concat([b]) : a;
|
||||
}, []);
|
||||
|
||||
var withoutTestTypings: string[] = typings.filter((typing) => {
|
||||
return existsTestTypings.indexOf(typing) < 0;
|
||||
});
|
||||
this.print.printDiv();
|
||||
this.print.printTypingsWithoutTest(withoutTestTypings);
|
||||
}
|
||||
|
||||
this.print.printDiv();
|
||||
this.print.printTotalMessage();
|
||||
|
||||
this.print.printDiv();
|
||||
this.print.printElapsedTime(this.timer.asString, this.timer.time);
|
||||
|
||||
this.suites.filter((suite: ITestSuite) => {
|
||||
return suite.printErrorCount;
|
||||
}).forEach((suite: ITestSuite) => {
|
||||
this.print.printSuiteErrorCount(suite.errorHeadline, suite.ngTests.length, suite.testResults.length);
|
||||
});
|
||||
if (testEval) {
|
||||
this.print.printSuiteErrorCount("Without tests", withoutTestTypings.length, typings.length, '\33[33m\33[1m');
|
||||
}
|
||||
|
||||
this.print.printDiv();
|
||||
if (this.suites.some((suite) => {
|
||||
return suite.ngTests.length !== 0
|
||||
})) {
|
||||
this.print.printErrorsHeader();
|
||||
|
||||
this.suites.filter((suite) => {
|
||||
return suite.ngTests.length !== 0;
|
||||
}).forEach((suite) => {
|
||||
suite.ngTests.forEach((testResult) => {
|
||||
this.print.printErrorsForFile(testResult);
|
||||
});
|
||||
this.print.printBoldDiv();
|
||||
});
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dtPath = path.resolve(path.dirname((module).filename), '..', '..');
|
||||
var findNotRequiredTscparams = process.argv.some(arg => arg == "--try-without-tscparams");
|
||||
var tscVersionIndex = process.argv.indexOf("--tsc-version");
|
||||
var tscVersion = DEFAULT_TSC_VERSION;
|
||||
if (-1 < tscVersionIndex) {
|
||||
tscVersion = process.argv[tscVersionIndex + 1];
|
||||
}
|
||||
|
||||
console.log('--');
|
||||
console.log(' dtPath %s', dtPath);
|
||||
console.log(' tscVersion %s', tscVersion);
|
||||
console.log(' findNotRequiredTscparams %s', findNotRequiredTscparams);
|
||||
console.log('--');
|
||||
console.log('');
|
||||
|
||||
var runner = new TestRunner(dtPath, {
|
||||
tscVersion: tscVersion,
|
||||
findNotRequiredTscparams: findNotRequiredTscparams
|
||||
});
|
||||
runner.run();
|
||||
}
|
||||
|
||||
@@ -1,37 +1,39 @@
|
||||
/// <reference path="../_ref.d.ts" />
|
||||
|
||||
module DT {
|
||||
'use-strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Git = require('git-wrapper');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Git = require('git-wrapper');
|
||||
|
||||
export class GitChanges {
|
||||
export class GitChanges {
|
||||
|
||||
options = [];
|
||||
options = {};
|
||||
paths: string[] = [];
|
||||
|
||||
constructor(public baseDir: string) {
|
||||
var dir = path.join(baseDir, '.git');
|
||||
if (!fs.existsSync(dir)) {
|
||||
throw new Error('cannot locate git-dir: ' + dir);
|
||||
}
|
||||
this.options['git-dir'] = dir;
|
||||
}
|
||||
constructor(public baseDir: string) {
|
||||
var dir = path.join(baseDir, '.git');
|
||||
if (!fs.existsSync(dir)) {
|
||||
throw new Error('cannot locate git-dir: ' + dir);
|
||||
}
|
||||
this.options['git-dir'] = dir;
|
||||
}
|
||||
|
||||
getChanges(callback: (err, paths: string[]) => void): void {
|
||||
//git diff --name-only HEAD~1
|
||||
var git = new Git(this.options);
|
||||
var opts = {};
|
||||
var args = ['--name-only HEAD~1'];
|
||||
git.exec('diff', opts, args, (err, msg: string) => {
|
||||
if (err) {
|
||||
callback(err, null);
|
||||
return;
|
||||
}
|
||||
var paths = msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
|
||||
// console.log(paths);
|
||||
callback(null, paths);
|
||||
});
|
||||
}
|
||||
}
|
||||
getChanges(callback: (err) => void): void {
|
||||
//git diff --name-only HEAD~1
|
||||
var git = new Git(this.options);
|
||||
var opts = {};
|
||||
var args = ['--name-only HEAD~1'];
|
||||
git.exec('diff', opts, args, (err, msg: string) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
this.paths = msg.replace(/^\s+/, '').replace(/\s+$/, '').split(/\r?\n/g);
|
||||
// console.log(paths);
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,39 @@
|
||||
/// <reference path="../_ref.d.ts" />
|
||||
|
||||
module DT {
|
||||
var path = require('path');
|
||||
'use-strict';
|
||||
|
||||
/////////////////////////////////
|
||||
// Given a document root + ts file pattern this class returns:
|
||||
// all the TS files OR just tests OR just definition files
|
||||
/////////////////////////////////
|
||||
export class File {
|
||||
dir: string;
|
||||
file: string;
|
||||
ext: string;
|
||||
references: File[] = [];
|
||||
var path = require('path');
|
||||
|
||||
constructor(public baseDir: string, public filePathWithName: string) {
|
||||
this.ext = path.extname(this.filePathWithName);
|
||||
this.file = path.basename(this.filePathWithName, this.ext);
|
||||
this.dir = path.dirname(this.filePathWithName);
|
||||
}
|
||||
/////////////////////////////////
|
||||
// Given a document root + ts file pattern this class returns:
|
||||
// all the TS files OR just tests OR just definition files
|
||||
/////////////////////////////////
|
||||
export class File {
|
||||
baseDir: string;
|
||||
filePathWithName: string;
|
||||
dir: string;
|
||||
file: string;
|
||||
ext: string;
|
||||
formatName: string;
|
||||
fullPath: string;
|
||||
references: File[] = [];
|
||||
|
||||
// From '/complete/path/to/file' to 'specfolder/specfile.d.ts'
|
||||
public get formatName(): string {
|
||||
return path.join(this.dir, this.file + this.ext);
|
||||
}
|
||||
constructor(baseDir: string, filePathWithName: string) {
|
||||
this.baseDir = baseDir;
|
||||
this.filePathWithName = filePathWithName;
|
||||
this.ext = path.extname(this.filePathWithName);
|
||||
this.file = path.basename(this.filePathWithName, this.ext);
|
||||
this.dir = path.dirname(this.filePathWithName);
|
||||
this.formatName = path.join(this.dir, this.file + this.ext);
|
||||
this.fullPath = path.join(this.baseDir, this.dir, this.file + this.ext);
|
||||
|
||||
public get fullPath(): string {
|
||||
return path.join(this.baseDir, this.dir, this.file + this.ext);
|
||||
}
|
||||
// lock it (shallow)
|
||||
// Object.freeze(this);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return '[File ' + this.filePathWithName + ']';
|
||||
}
|
||||
}
|
||||
toString() {
|
||||
return '[File ' + this.filePathWithName + ']';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,32 +15,32 @@
|
||||
|
||||
// Allows for executing a program with command-line arguments and reading the result
|
||||
interface IExec {
|
||||
exec: (filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void) => void;
|
||||
exec: (filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void) => void;
|
||||
}
|
||||
|
||||
class ExecResult {
|
||||
public stdout = "";
|
||||
public stderr = "";
|
||||
public exitCode: number;
|
||||
public stdout = "";
|
||||
public stderr = "";
|
||||
public exitCode: number;
|
||||
}
|
||||
|
||||
class NodeExec implements IExec {
|
||||
public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void): void {
|
||||
var nodeExec = require('child_process').exec;
|
||||
public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void): void {
|
||||
var nodeExec = require('child_process').exec;
|
||||
|
||||
var result = new ExecResult();
|
||||
result.exitCode = null;
|
||||
var cmdLine = filename + ' ' + cmdLineArgs.join(' ');
|
||||
var result = new ExecResult();
|
||||
result.exitCode = null;
|
||||
var cmdLine = filename + ' ' + cmdLineArgs.join(' ');
|
||||
|
||||
var process = nodeExec(cmdLine, {maxBuffer: 1 * 1024 * 1024}, function (error, stdout, stderr) {
|
||||
result.stdout = stdout;
|
||||
result.stderr = stderr;
|
||||
result.exitCode = error ? error.code : 0;
|
||||
handleResult(result);
|
||||
});
|
||||
}
|
||||
var process = nodeExec(cmdLine, {maxBuffer: 1 * 1024 * 1024}, function (error, stdout, stderr) {
|
||||
result.stdout = stdout;
|
||||
result.stderr = stderr;
|
||||
result.exitCode = error ? error.code : 0;
|
||||
handleResult(result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var Exec: IExec = function (): IExec {
|
||||
return new NodeExec();
|
||||
return new NodeExec();
|
||||
}();
|
||||
|
||||
@@ -3,77 +3,91 @@
|
||||
/// <reference path="util.ts" />
|
||||
|
||||
module DT {
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
'use-strict';
|
||||
|
||||
export class FileIndex {
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
fileMap: {[path:string]:File};
|
||||
export class FileIndex {
|
||||
|
||||
constructor(public options: ITestRunnerOptions) {
|
||||
fileMap: {[path:string]:File
|
||||
};
|
||||
|
||||
}
|
||||
constructor(public options: ITestRunnerOptions) {
|
||||
|
||||
parseFiles(files: File[], callback: () => void): void {
|
||||
this.fileMap = Object.create(null);
|
||||
files.forEach((file) => {
|
||||
this.fileMap[file.fullPath] = file;
|
||||
});
|
||||
this.loadReferences(files, () => {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private loadReferences(files: File[], callback: () => void): void {
|
||||
var queue = files.slice(0);
|
||||
var active = [];
|
||||
var max = 50;
|
||||
var next = () => {
|
||||
if (queue.length === 0 && active.length === 0) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
// queue paralel
|
||||
while (queue.length > 0 && active.length < max) {
|
||||
var file = queue.pop();
|
||||
active.push(file);
|
||||
this.parseFile(file, (file) => {
|
||||
active.splice(active.indexOf(file), 1);
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
process.nextTick(next);
|
||||
}
|
||||
parseFiles(files: File[], callback: () => void): void {
|
||||
this.fileMap = Object.create(null);
|
||||
files.forEach((file) => {
|
||||
this.fileMap[file.fullPath] = file;
|
||||
});
|
||||
this.loadReferences(files, () => {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
private parseFile(file: File, callback: (file: File) => void): void {
|
||||
fs.readFile(file.filePathWithName, {
|
||||
encoding: 'utf8',
|
||||
flag: 'r'
|
||||
}, (err, content) => {
|
||||
if (err) {
|
||||
// just blow up?
|
||||
throw err;
|
||||
}
|
||||
// console.log('----');
|
||||
// console.log(file.filePathWithName);
|
||||
hasFile(target: string): boolean {
|
||||
return target in this.fileMap;
|
||||
}
|
||||
|
||||
file.references = extractReferenceTags(content).map((ref: string) => {
|
||||
return path.resolve(path.dirname(file.fullPath), ref);
|
||||
}).reduce((memo: File[], ref: string) => {
|
||||
if (ref in this.fileMap) {
|
||||
memo.push(this.fileMap[ref]);
|
||||
}
|
||||
else {
|
||||
console.log('not mapped? -> ' + ref);
|
||||
}
|
||||
return memo;
|
||||
}, []);
|
||||
getFile(target: string): File {
|
||||
if (target in this.fileMap) {
|
||||
return this.fileMap[target];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// console.log(file.references);
|
||||
private loadReferences(files: File[], callback: () => void): void {
|
||||
var queue = files.slice(0);
|
||||
var active = [];
|
||||
var max = 50;
|
||||
var next = () => {
|
||||
if (queue.length === 0 && active.length === 0) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
// queue paralel
|
||||
while (queue.length > 0 && active.length < max) {
|
||||
var file = queue.pop();
|
||||
active.push(file);
|
||||
this.parseFile(file, (file) => {
|
||||
active.splice(active.indexOf(file), 1);
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
process.nextTick(next);
|
||||
}
|
||||
|
||||
callback(file);
|
||||
});
|
||||
}
|
||||
}
|
||||
private parseFile(file: File, callback: (file: File) => void): void {
|
||||
fs.readFile(file.filePathWithName, {
|
||||
encoding: 'utf8',
|
||||
flag: 'r'
|
||||
}, (err, content) => {
|
||||
if (err) {
|
||||
// just blow up?
|
||||
throw err;
|
||||
}
|
||||
// console.log('----');
|
||||
// console.log(file.filePathWithName);
|
||||
|
||||
file.references = extractReferenceTags(content).map((ref: string) => {
|
||||
return path.resolve(path.dirname(file.fullPath), ref);
|
||||
}).reduce((memo: File[], ref: string) => {
|
||||
if (ref in this.fileMap) {
|
||||
memo.push(this.fileMap[ref]);
|
||||
}
|
||||
else {
|
||||
console.log('not mapped? -> ' + ref);
|
||||
}
|
||||
return memo;
|
||||
}, []);
|
||||
|
||||
// console.log(file.references);
|
||||
|
||||
callback(file);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,110 +2,112 @@
|
||||
/// <reference path="../runner.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// All the common things that we pring are functions of this class
|
||||
/////////////////////////////////
|
||||
export class Print {
|
||||
'use-strict';
|
||||
|
||||
WIDTH = 77;
|
||||
/////////////////////////////////
|
||||
// All the common things that we pring are functions of this class
|
||||
/////////////////////////////////
|
||||
export class Print {
|
||||
|
||||
constructor(public version: string, public typings: number, public tests: number, public tsFiles: number) {
|
||||
}
|
||||
WIDTH = 77;
|
||||
|
||||
public out(s: any): Print {
|
||||
process.stdout.write(s);
|
||||
return this;
|
||||
}
|
||||
constructor(public version: string, public typings: number, public tests: number, public tsFiles: number) {
|
||||
}
|
||||
|
||||
public repeat(s: string, times: number): string {
|
||||
return new Array(times + 1).join(s);
|
||||
}
|
||||
public out(s: any): Print {
|
||||
process.stdout.write(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
public printHeader() {
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[36m\33[1mDefinitelyTyped test runner 0.4.0\33[0m\n');
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[36m\33[1mTypescript version:\33[0m ' + this.version + '\n');
|
||||
this.out(' \33[36m\33[1mTypings :\33[0m ' + this.typings + '\n');
|
||||
this.out(' \33[36m\33[1mTests :\33[0m ' + this.tests + '\n');
|
||||
this.out(' \33[36m\33[1mTypeScript files :\33[0m ' + this.tsFiles + '\n');
|
||||
}
|
||||
public repeat(s: string, times: number): string {
|
||||
return new Array(times + 1).join(s);
|
||||
}
|
||||
|
||||
public printSuiteHeader(title: string) {
|
||||
var left = Math.floor((this.WIDTH - title.length ) / 2) - 1;
|
||||
var right = Math.ceil((this.WIDTH - title.length ) / 2) - 1;
|
||||
this.out(this.repeat("=", left)).out(" \33[34m\33[1m");
|
||||
this.out(title);
|
||||
this.out("\33[0m ").out(this.repeat("=", right)).printBreak();
|
||||
}
|
||||
public printHeader() {
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[36m\33[1mDefinitelyTyped test runner 0.4.0\33[0m\n');
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[36m\33[1mTypescript version:\33[0m ' + this.version + '\n');
|
||||
this.out(' \33[36m\33[1mTypings :\33[0m ' + this.typings + '\n');
|
||||
this.out(' \33[36m\33[1mTests :\33[0m ' + this.tests + '\n');
|
||||
this.out(' \33[36m\33[1mTypeScript files :\33[0m ' + this.tsFiles + '\n');
|
||||
}
|
||||
|
||||
public printDiv() {
|
||||
this.out('-----------------------------------------------------------------------------\n');
|
||||
}
|
||||
public printSuiteHeader(title: string) {
|
||||
var left = Math.floor((this.WIDTH - title.length ) / 2) - 1;
|
||||
var right = Math.ceil((this.WIDTH - title.length ) / 2) - 1;
|
||||
this.out(this.repeat("=", left)).out(" \33[34m\33[1m");
|
||||
this.out(title);
|
||||
this.out("\33[0m ").out(this.repeat("=", right)).printBreak();
|
||||
}
|
||||
|
||||
public printBoldDiv() {
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
public printDiv() {
|
||||
this.out('-----------------------------------------------------------------------------\n');
|
||||
}
|
||||
|
||||
public printErrorsHeader() {
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[34m\33[1mErrors in files\33[0m \n');
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
public printBoldDiv() {
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
|
||||
public printErrorsForFile(testResult: TestResult) {
|
||||
this.out('----------------- For file:' + testResult.targetFile.formatName);
|
||||
this.printBreak().out(testResult.stderr).printBreak();
|
||||
}
|
||||
public printErrorsHeader() {
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[34m\33[1mErrors in files\33[0m \n');
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
|
||||
public printBreak(): Print {
|
||||
this.out('\n');
|
||||
return this;
|
||||
}
|
||||
public printErrorsForFile(testResult: TestResult) {
|
||||
this.out('----------------- For file:' + testResult.targetFile.formatName);
|
||||
this.printBreak().out(testResult.stderr).printBreak();
|
||||
}
|
||||
|
||||
public clearCurrentLine(): Print {
|
||||
this.out("\r\33[K");
|
||||
return this;
|
||||
}
|
||||
public printBreak(): Print {
|
||||
this.out('\n');
|
||||
return this;
|
||||
}
|
||||
|
||||
public printSuccessCount(current: number, total: number) {
|
||||
this.out(' \33[36m\33[1mSuccessful :\33[0m \33[32m\33[1m' + ((current / total) * 100).toFixed(2) + '% (' + current + '/' + total + ')\33[0m\n');
|
||||
}
|
||||
public clearCurrentLine(): Print {
|
||||
this.out("\r\33[K");
|
||||
return this;
|
||||
}
|
||||
|
||||
public printFailedCount(current: number, total: number) {
|
||||
this.out(' \33[36m\33[1mFailure :\33[0m \33[31m\33[1m' + ((current / total) * 100).toFixed(2) + '% (' + current + '/' + total + ')\33[0m\n');
|
||||
}
|
||||
public printSuccessCount(current: number, total: number) {
|
||||
this.out(' \33[36m\33[1mSuccessful :\33[0m \33[32m\33[1m' + ((current / total) * 100).toFixed(2) + '% (' + current + '/' + total + ')\33[0m\n');
|
||||
}
|
||||
|
||||
public printTypingsWithoutTestsMessage() {
|
||||
this.out(' \33[36m\33[1mTyping without tests\33[0m\n');
|
||||
}
|
||||
public printFailedCount(current: number, total: number) {
|
||||
this.out(' \33[36m\33[1mFailure :\33[0m \33[31m\33[1m' + ((current / total) * 100).toFixed(2) + '% (' + current + '/' + total + ')\33[0m\n');
|
||||
}
|
||||
|
||||
public printTotalMessage() {
|
||||
this.out(' \33[36m\33[1mTotal\33[0m\n');
|
||||
}
|
||||
public printTypingsWithoutTestsMessage() {
|
||||
this.out(' \33[36m\33[1mTyping without tests\33[0m\n');
|
||||
}
|
||||
|
||||
public printElapsedTime(time: string, s: number) {
|
||||
this.out(' \33[36m\33[1mElapsed time :\33[0m ~' + time + ' (' + s + 's)\n');
|
||||
}
|
||||
public printTotalMessage() {
|
||||
this.out(' \33[36m\33[1mTotal\33[0m\n');
|
||||
}
|
||||
|
||||
public printSuiteErrorCount(errorHeadline: string, current: number, total: number, valuesColor = '\33[31m\33[1m') {
|
||||
this.out(' \33[36m\33[1m').out(errorHeadline).out(this.repeat(' ', 16 - errorHeadline.length));
|
||||
this.out(':\33[0m ' + valuesColor + ((current / total) * 100).toFixed(2) + '% (' + current + '/' + total + ')\33[0m\n');
|
||||
}
|
||||
public printElapsedTime(time: string, s: number) {
|
||||
this.out(' \33[36m\33[1mElapsed time :\33[0m ~' + time + ' (' + s + 's)\n');
|
||||
}
|
||||
|
||||
public printTypingsWithoutTestName(file: string) {
|
||||
this.out(' - \33[33m\33[1m' + file + '\33[0m\n');
|
||||
}
|
||||
public printSuiteErrorCount(errorHeadline: string, current: number, total: number, valuesColor = '\33[31m\33[1m') {
|
||||
this.out(' \33[36m\33[1m').out(errorHeadline).out(this.repeat(' ', 16 - errorHeadline.length));
|
||||
this.out(':\33[0m ' + valuesColor + ((current / total) * 100).toFixed(2) + '% (' + current + '/' + total + ')\33[0m\n');
|
||||
}
|
||||
|
||||
public printTypingsWithoutTest(withoutTestTypings: string[]) {
|
||||
if (withoutTestTypings.length > 0) {
|
||||
this.printTypingsWithoutTestsMessage();
|
||||
public printTypingsWithoutTestName(file: string) {
|
||||
this.out(' - \33[33m\33[1m' + file + '\33[0m\n');
|
||||
}
|
||||
|
||||
this.printDiv();
|
||||
withoutTestTypings.forEach((t) => {
|
||||
this.printTypingsWithoutTestName(t);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
public printTypingsWithoutTest(withoutTestTypings: string[]) {
|
||||
if (withoutTestTypings.length > 0) {
|
||||
this.printTypingsWithoutTestsMessage();
|
||||
|
||||
this.printDiv();
|
||||
withoutTestTypings.forEach((t) => {
|
||||
this.printTypingsWithoutTestName(t);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,38 +2,40 @@
|
||||
/// <reference path="../printer.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// Test reporter interface
|
||||
// for example, . and x
|
||||
/////////////////////////////////
|
||||
export interface ITestReporter {
|
||||
printPositiveCharacter(index: number, testResult: TestResult):void;
|
||||
printNegativeCharacter(index: number, testResult: TestResult):void;
|
||||
}
|
||||
'use-strict';
|
||||
|
||||
/////////////////////////////////
|
||||
// Default test reporter
|
||||
/////////////////////////////////
|
||||
export class DefaultTestReporter implements ITestReporter {
|
||||
constructor(public print: Print) {
|
||||
}
|
||||
/////////////////////////////////
|
||||
// Test reporter interface
|
||||
// for example, . and x
|
||||
/////////////////////////////////
|
||||
export interface ITestReporter {
|
||||
printPositiveCharacter(index: number, testResult: TestResult):void;
|
||||
printNegativeCharacter(index: number, testResult: TestResult):void;
|
||||
}
|
||||
|
||||
public printPositiveCharacter(index: number, testResult: TestResult) {
|
||||
this.print.out('\33[36m\33[1m' + '.' + '\33[0m');
|
||||
/////////////////////////////////
|
||||
// Default test reporter
|
||||
/////////////////////////////////
|
||||
export class DefaultTestReporter implements ITestReporter {
|
||||
constructor(public print: Print) {
|
||||
}
|
||||
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
public printPositiveCharacter(index: number, testResult: TestResult) {
|
||||
this.print.out('\33[36m\33[1m' + '.' + '\33[0m');
|
||||
|
||||
public printNegativeCharacter(index: number, testResult: TestResult) {
|
||||
this.print.out("x");
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
public printNegativeCharacter(index: number, testResult: TestResult) {
|
||||
this.print.out("x");
|
||||
|
||||
private printBreakIfNeeded(index: number) {
|
||||
if (index % this.print.WIDTH === 0) {
|
||||
this.print.printBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
|
||||
private printBreakIfNeeded(index: number) {
|
||||
if (index % this.print.WIDTH === 0) {
|
||||
this.print.printBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,83 +1,86 @@
|
||||
/// <reference path="../../runner.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// The interface for test suite
|
||||
/////////////////////////////////
|
||||
export interface ITestSuite {
|
||||
testSuiteName:string;
|
||||
errorHeadline:string;
|
||||
filterTargetFiles(files: File[]):File[];
|
||||
'use-strict';
|
||||
|
||||
start(targetFiles: File[], testCallback: (result: TestResult, index: number) => void, suiteCallback: (suite: ITestSuite) => void):void;
|
||||
/////////////////////////////////
|
||||
// The interface for test suite
|
||||
/////////////////////////////////
|
||||
export interface ITestSuite {
|
||||
testSuiteName:string;
|
||||
errorHeadline:string;
|
||||
filterTargetFiles(files: File[]):File[];
|
||||
|
||||
testResults:TestResult[];
|
||||
okTests:TestResult[];
|
||||
ngTests:TestResult[];
|
||||
timer:Timer;
|
||||
start(targetFiles: File[], testCallback: (result: TestResult, index: number) => void, suiteCallback: (suite: ITestSuite) => void):void;
|
||||
|
||||
testReporter:ITestReporter;
|
||||
printErrorCount:boolean;
|
||||
}
|
||||
testResults:TestResult[];
|
||||
okTests:TestResult[];
|
||||
ngTests:TestResult[];
|
||||
timer:Timer;
|
||||
|
||||
/////////////////////////////////
|
||||
// Base class for test suite
|
||||
/////////////////////////////////
|
||||
export class TestSuiteBase implements ITestSuite {
|
||||
timer: Timer = new Timer();
|
||||
testResults: TestResult[] = [];
|
||||
testReporter: ITestReporter;
|
||||
printErrorCount = true;
|
||||
testReporter:ITestReporter;
|
||||
printErrorCount:boolean;
|
||||
}
|
||||
|
||||
constructor(public options: ITestRunnerOptions, public testSuiteName: string, public errorHeadline: string) {
|
||||
}
|
||||
/////////////////////////////////
|
||||
// Base class for test suite
|
||||
/////////////////////////////////
|
||||
export class TestSuiteBase implements ITestSuite {
|
||||
timer: Timer = new Timer();
|
||||
testResults: TestResult[] = [];
|
||||
testReporter: ITestReporter;
|
||||
printErrorCount = true;
|
||||
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
throw new Error("please implement this method");
|
||||
}
|
||||
constructor(public options: ITestRunnerOptions, public testSuiteName: string, public errorHeadline: string) {
|
||||
}
|
||||
|
||||
public start(targetFiles: File[], testCallback: (result: TestResult, index: number) => void, suiteCallback: (suite: ITestSuite) => void): void {
|
||||
targetFiles = this.filterTargetFiles(targetFiles);
|
||||
this.timer.start();
|
||||
var count = 0;
|
||||
// exec test is async process. serialize.
|
||||
var executor = () => {
|
||||
var targetFile = targetFiles[count];
|
||||
if (targetFile) {
|
||||
this.runTest(targetFile, (result) => {
|
||||
testCallback(result, count + 1);
|
||||
count++;
|
||||
executor();
|
||||
});
|
||||
} else {
|
||||
this.timer.end();
|
||||
this.finish(suiteCallback);
|
||||
}
|
||||
};
|
||||
executor();
|
||||
}
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
throw new Error("please implement this method");
|
||||
}
|
||||
|
||||
public runTest(targetFile: File, callback: (result: TestResult) => void): void {
|
||||
new Test(this, targetFile, {tscVersion: this.options.tscVersion}).run((result) => {
|
||||
this.testResults.push(result);
|
||||
callback(result);
|
||||
});
|
||||
}
|
||||
public start(targetFiles: File[], testCallback: (result: TestResult, index: number) => void, suiteCallback: (suite: ITestSuite) => void): void {
|
||||
targetFiles = this.filterTargetFiles(targetFiles);
|
||||
this.timer.start();
|
||||
var count = 0;
|
||||
// exec test is async process. serialize.
|
||||
var executor = () => {
|
||||
var targetFile = targetFiles[count];
|
||||
if (targetFile) {
|
||||
this.runTest(targetFile, (result) => {
|
||||
testCallback(result, count + 1);
|
||||
count++;
|
||||
executor();
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.timer.end();
|
||||
this.finish(suiteCallback);
|
||||
}
|
||||
};
|
||||
executor();
|
||||
}
|
||||
|
||||
public finish(suiteCallback: (suite: ITestSuite) => void) {
|
||||
suiteCallback(this);
|
||||
}
|
||||
public runTest(targetFile: File, callback: (result: TestResult) => void): void {
|
||||
new Test(this, targetFile, {tscVersion: this.options.tscVersion}).run((result) => {
|
||||
this.testResults.push(result);
|
||||
callback(result);
|
||||
});
|
||||
}
|
||||
|
||||
public get okTests(): TestResult[] {
|
||||
return this.testResults.filter((r) => {
|
||||
return r.success;
|
||||
});
|
||||
}
|
||||
public finish(suiteCallback: (suite: ITestSuite) => void) {
|
||||
suiteCallback(this);
|
||||
}
|
||||
|
||||
public get ngTests(): TestResult[] {
|
||||
return this.testResults.filter((r) => {
|
||||
return !r.success
|
||||
});
|
||||
}
|
||||
}
|
||||
public get okTests(): TestResult[] {
|
||||
return this.testResults.filter((r) => {
|
||||
return r.success;
|
||||
});
|
||||
}
|
||||
|
||||
public get ngTests(): TestResult[] {
|
||||
return this.testResults.filter((r) => {
|
||||
return !r.success
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,21 @@
|
||||
/// <reference path="../util.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// .d.ts syntax inspection
|
||||
/////////////////////////////////
|
||||
export class SyntaxChecking extends TestSuiteBase {
|
||||
'use-strict';
|
||||
|
||||
constructor(options: ITestRunnerOptions) {
|
||||
super(options, "Syntax checking", "Syntax error");
|
||||
}
|
||||
/////////////////////////////////
|
||||
// .d.ts syntax inspection
|
||||
/////////////////////////////////
|
||||
export class SyntaxChecking extends TestSuiteBase {
|
||||
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
return files.filter((file) => {
|
||||
return DT.endsWith(file.formatName.toUpperCase(), '.D.TS');
|
||||
});
|
||||
}
|
||||
}
|
||||
constructor(options: ITestRunnerOptions) {
|
||||
super(options, "Syntax checking", "Syntax error");
|
||||
}
|
||||
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
return files.filter((file) => {
|
||||
return DT.endsWith(file.formatName.toUpperCase(), '.D.TS');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,21 @@
|
||||
/// <reference path="../util.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// Compile with *-tests.ts
|
||||
/////////////////////////////////
|
||||
export class TestEval extends TestSuiteBase {
|
||||
'use-strict';
|
||||
/////////////////////////////////
|
||||
// Compile with *-tests.ts
|
||||
/////////////////////////////////
|
||||
export class TestEval extends TestSuiteBase {
|
||||
|
||||
constructor(options) {
|
||||
super(options, "Typing tests", "Failed tests");
|
||||
}
|
||||
constructor(options) {
|
||||
super(options, "Typing tests", "Failed tests");
|
||||
}
|
||||
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
return files.filter((file) => {
|
||||
return DT.endsWith(file.formatName.toUpperCase(), '-TESTS.TS')
|
||||
});
|
||||
}
|
||||
}
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
return files.filter((file) => {
|
||||
return DT.endsWith(file.formatName.toUpperCase(), '-TESTS.TS')
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,56 +2,58 @@
|
||||
/// <reference path="../file.ts" />
|
||||
|
||||
module DT {
|
||||
var fs = require('fs');
|
||||
'use-strict';
|
||||
|
||||
/////////////////////////////////
|
||||
// Try compile without .tscparams
|
||||
// It may indicate that it is compatible with --noImplicitAny maybe...
|
||||
/////////////////////////////////
|
||||
export class FindNotRequiredTscparams extends TestSuiteBase {
|
||||
testReporter: ITestReporter;
|
||||
printErrorCount = false;
|
||||
var fs = require('fs');
|
||||
|
||||
constructor(options: ITestRunnerOptions, private print: Print) {
|
||||
super(options, "Find not required .tscparams files", "New arrival!");
|
||||
/////////////////////////////////
|
||||
// Try compile without .tscparams
|
||||
// It may indicate that it is compatible with --noImplicitAny maybe...
|
||||
/////////////////////////////////
|
||||
export class FindNotRequiredTscparams extends TestSuiteBase {
|
||||
testReporter: ITestReporter;
|
||||
printErrorCount = false;
|
||||
|
||||
this.testReporter = {
|
||||
printPositiveCharacter: (index: number, testResult: TestResult) => {
|
||||
this.print
|
||||
.clearCurrentLine()
|
||||
.printTypingsWithoutTestName(testResult.targetFile.formatName);
|
||||
},
|
||||
printNegativeCharacter: (index: number, testResult: TestResult) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
constructor(options: ITestRunnerOptions, private print: Print) {
|
||||
super(options, "Find not required .tscparams files", "New arrival!");
|
||||
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
return files.filter((file) => {
|
||||
return fs.existsSync(file.filePathWithName + '.tscparams');
|
||||
});
|
||||
}
|
||||
this.testReporter = {
|
||||
printPositiveCharacter: (index: number, testResult: TestResult) => {
|
||||
this.print
|
||||
.clearCurrentLine()
|
||||
.printTypingsWithoutTestName(testResult.targetFile.formatName);
|
||||
},
|
||||
printNegativeCharacter: (index: number, testResult: TestResult) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public runTest(targetFile: File, callback: (result: TestResult) => void): void {
|
||||
this.print.clearCurrentLine().out(targetFile.formatName);
|
||||
new Test(this, targetFile, {
|
||||
tscVersion: this.options.tscVersion,
|
||||
useTscParams: false,
|
||||
checkNoImplicitAny: true
|
||||
}).run(result=> {
|
||||
this.testResults.push(result);
|
||||
callback(result);
|
||||
});
|
||||
}
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
return files.filter((file) => {
|
||||
return fs.existsSync(file.filePathWithName + '.tscparams');
|
||||
});
|
||||
}
|
||||
|
||||
public finish(suiteCallback: (suite: ITestSuite)=>void) {
|
||||
this.print.clearCurrentLine();
|
||||
suiteCallback(this);
|
||||
}
|
||||
public runTest(targetFile: File, callback: (result: TestResult) => void): void {
|
||||
this.print.clearCurrentLine().out(targetFile.formatName);
|
||||
new Test(this, targetFile, {
|
||||
tscVersion: this.options.tscVersion,
|
||||
useTscParams: false,
|
||||
checkNoImplicitAny: true
|
||||
}).run(result=> {
|
||||
this.testResults.push(result);
|
||||
callback(result);
|
||||
});
|
||||
}
|
||||
|
||||
public get ngTests(): TestResult[] {
|
||||
// Do not show ng test results
|
||||
return [];
|
||||
}
|
||||
}
|
||||
public finish(suiteCallback: (suite: ITestSuite)=>void) {
|
||||
this.print.clearCurrentLine();
|
||||
suiteCallback(this);
|
||||
}
|
||||
|
||||
public get ngTests(): TestResult[] {
|
||||
// Do not show ng test results
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,46 +2,48 @@
|
||||
/// <reference path="../runner.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// Timer.start starts a timer
|
||||
// Timer.end stops the timer and sets asString to the pretty print value
|
||||
/////////////////////////////////
|
||||
export class Timer {
|
||||
startTime: number;
|
||||
time = 0;
|
||||
asString: string;
|
||||
'use-strict';
|
||||
|
||||
public start() {
|
||||
this.time = 0;
|
||||
this.startTime = this.now();
|
||||
}
|
||||
/////////////////////////////////
|
||||
// Timer.start starts a timer
|
||||
// Timer.end stops the timer and sets asString to the pretty print value
|
||||
/////////////////////////////////
|
||||
export class Timer {
|
||||
startTime: number;
|
||||
time = 0;
|
||||
asString: string;
|
||||
|
||||
public now(): number {
|
||||
return Date.now();
|
||||
}
|
||||
public start() {
|
||||
this.time = 0;
|
||||
this.startTime = this.now();
|
||||
}
|
||||
|
||||
public end() {
|
||||
this.time = (this.now() - this.startTime) / 1000;
|
||||
this.asString = Timer.prettyDate(this.startTime, this.now());
|
||||
}
|
||||
public now(): number {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
public static prettyDate(date1: number, date2: number): string {
|
||||
var diff = ((date2 - date1) / 1000);
|
||||
var day_diff = Math.floor(diff / 86400);
|
||||
public end() {
|
||||
this.time = (this.now() - this.startTime) / 1000;
|
||||
this.asString = Timer.prettyDate(this.startTime, this.now());
|
||||
}
|
||||
|
||||
if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) {
|
||||
return null;
|
||||
}
|
||||
public static prettyDate(date1: number, date2: number): string {
|
||||
var diff = ((date2 - date1) / 1000);
|
||||
var day_diff = Math.floor(diff / 86400);
|
||||
|
||||
return (<string><any> (day_diff == 0 && (
|
||||
diff < 60 && (diff + " seconds") ||
|
||||
diff < 120 && "1 minute" ||
|
||||
diff < 3600 && Math.floor(diff / 60) + " minutes" ||
|
||||
diff < 7200 && "1 hour" ||
|
||||
diff < 86400 && Math.floor(diff / 3600) + " hours") ||
|
||||
day_diff == 1 && "Yesterday" ||
|
||||
day_diff < 7 && day_diff + " days" ||
|
||||
day_diff < 31 && Math.ceil(day_diff / 7) + " weeks"));
|
||||
}
|
||||
}
|
||||
if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (<string><any> (day_diff == 0 && (
|
||||
diff < 60 && (diff + " seconds") ||
|
||||
diff < 120 && "1 minute" ||
|
||||
diff < 3600 && Math.floor(diff / 60) + " minutes" ||
|
||||
diff < 7200 && "1 hour" ||
|
||||
diff < 86400 && Math.floor(diff / 3600) + " hours") ||
|
||||
day_diff == 1 && "Yesterday" ||
|
||||
day_diff < 7 && day_diff + " days" ||
|
||||
day_diff < 31 && Math.ceil(day_diff / 7) + " weeks"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,42 +3,44 @@
|
||||
/// <reference path="host/exec.ts" />
|
||||
|
||||
module DT {
|
||||
var fs = require('fs');
|
||||
'use-strict';
|
||||
var fs = require('fs');
|
||||
|
||||
export interface TscExecOptions {
|
||||
tscVersion?:string;
|
||||
useTscParams?:boolean;
|
||||
checkNoImplicitAny?:boolean;
|
||||
}
|
||||
export interface TscExecOptions {
|
||||
tscVersion?:string;
|
||||
useTscParams?:boolean;
|
||||
checkNoImplicitAny?:boolean;
|
||||
}
|
||||
|
||||
export class Tsc {
|
||||
public static run(tsfile: string, options: TscExecOptions, callback: (result: ExecResult) => void) {
|
||||
options = options || {};
|
||||
options.tscVersion = options.tscVersion || DEFAULT_TSC_VERSION;
|
||||
if (typeof options.checkNoImplicitAny === "undefined") {
|
||||
options.checkNoImplicitAny = true;
|
||||
}
|
||||
if (typeof options.useTscParams === "undefined") {
|
||||
options.useTscParams = true;
|
||||
}
|
||||
export class Tsc {
|
||||
public static run(tsfile: string, options: TscExecOptions, callback: (result: ExecResult) => void) {
|
||||
options = options || {};
|
||||
options.tscVersion = options.tscVersion || DEFAULT_TSC_VERSION;
|
||||
if (typeof options.checkNoImplicitAny === "undefined") {
|
||||
options.checkNoImplicitAny = true;
|
||||
}
|
||||
if (typeof options.useTscParams === "undefined") {
|
||||
options.useTscParams = true;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(tsfile)) {
|
||||
throw new Error(tsfile + " not exists");
|
||||
}
|
||||
if (!fs.existsSync(tsfile)) {
|
||||
throw new Error(tsfile + " not exists");
|
||||
}
|
||||
|
||||
var tscPath = './_infrastructure/tests/typescript/' + options.tscVersion + '/tsc.js';
|
||||
if (!fs.existsSync(tscPath)) {
|
||||
throw new Error(tscPath + ' is not exists');
|
||||
}
|
||||
var command = 'node ' + tscPath + ' --module commonjs ';
|
||||
if (options.useTscParams && fs.existsSync(tsfile + '.tscparams')) {
|
||||
command += '@' + tsfile + '.tscparams';
|
||||
} else if (options.checkNoImplicitAny) {
|
||||
command += '--noImplicitAny';
|
||||
}
|
||||
Exec.exec(command, [tsfile], (execResult) => {
|
||||
callback(execResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
var tscPath = './_infrastructure/tests/typescript/' + options.tscVersion + '/tsc.js';
|
||||
if (!fs.existsSync(tscPath)) {
|
||||
throw new Error(tscPath + ' is not exists');
|
||||
}
|
||||
var command = 'node ' + tscPath + ' --module commonjs ';
|
||||
if (options.useTscParams && fs.existsSync(tsfile + '.tscparams')) {
|
||||
command += '@' + tsfile + '.tscparams';
|
||||
}
|
||||
else if (options.checkNoImplicitAny) {
|
||||
command += '--noImplicitAny';
|
||||
}
|
||||
Exec.exec(command, [tsfile], (execResult) => {
|
||||
callback(execResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
/// <reference path="../_ref.d.ts" />
|
||||
|
||||
module DT {
|
||||
'use-strict';
|
||||
|
||||
var referenceTagExp = /<reference[ \t]*path=["']?([\w\.\/_-]*)["']?[ \t]*\/>/g;
|
||||
var referenceTagExp = /<reference[ \t]*path=["']?([\w\.\/_-]*)["']?[ \t]*\/>/g;
|
||||
|
||||
export function endsWith(str: string, suffix: string) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
export function endsWith(str: string, suffix: string) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
|
||||
export function extractReferenceTags(source: string): string[] {
|
||||
var ret: string[] = [];
|
||||
var match: RegExpExecArray;
|
||||
export function extractReferenceTags(source: string): string[] {
|
||||
var ret: string[] = [];
|
||||
var match: RegExpExecArray;
|
||||
|
||||
if (!referenceTagExp.global) {
|
||||
throw new Error('referenceTagExp RegExp must have global flag');
|
||||
}
|
||||
referenceTagExp.lastIndex = 0;
|
||||
if (!referenceTagExp.global) {
|
||||
throw new Error('referenceTagExp RegExp must have global flag');
|
||||
}
|
||||
referenceTagExp.lastIndex = 0;
|
||||
|
||||
while ((match = referenceTagExp.exec(source))) {
|
||||
if (match.length > 0 && match[1].length > 0) {
|
||||
ret.push(match[1]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
while ((match = referenceTagExp.exec(source))) {
|
||||
if (match.length > 0 && match[1].length > 0) {
|
||||
ret.push(match[1]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user