mirror of
https://github.com/wassname/DefinitelyTyped.git
synced 2026-09-09 11:13:57 +08:00
split runner code over files
main file got cumbersome - extracted parts to own files - still one --out file - existing code into DT module cleaned some syntax and lint expanded arrow-functions to full form builds using 0.9.7
This commit is contained in:
+654
-590
File diff suppressed because it is too large
Load Diff
+93
-454
@@ -1,60 +1,33 @@
|
||||
/// <reference path='../../node/node.d.ts' />
|
||||
|
||||
/// <reference path='src/exec.ts' />
|
||||
/// <reference path='src/io.ts' />
|
||||
/// <reference path='src/host/exec.ts' />
|
||||
/// <reference path='src/host/io.ts' />
|
||||
|
||||
module DefinitelyTyped.TestManager {
|
||||
/// <reference path='src/file.ts' />
|
||||
/// <reference path='src/tsc.ts' />
|
||||
/// <reference path='src/timer.ts' />
|
||||
/// <reference path="src/util.ts" />
|
||||
|
||||
/// <reference path='src/printer.ts' />
|
||||
/// <reference path='src/reporter/reporter.ts' />
|
||||
|
||||
/// <reference path='src/suite/suite.ts' />
|
||||
/// <reference path='src/suite/syntax.ts' />
|
||||
/// <reference path='src/suite/testEval.ts' />
|
||||
/// <reference path='src/suite/tscParams.ts' />
|
||||
|
||||
module DT {
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
export var DEFAULT_TSC_VERSION = "0.9.1.1";
|
||||
|
||||
function endsWith(str:string, suffix:string) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
|
||||
export interface TscExecOptions {
|
||||
tscVersion?:string;
|
||||
useTscParams?:boolean;
|
||||
checkNoImplicitAny?:boolean;
|
||||
}
|
||||
|
||||
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 (!IO.fileExists(tsfile)) {
|
||||
throw new Error(tsfile + " not exists");
|
||||
}
|
||||
|
||||
var tscPath = './_infrastructure/tests/typescript/' + options.tscVersion + '/tsc.js';
|
||||
if (!IO.fileExists(tscPath)) {
|
||||
throw new Error(tscPath + ' is not exists');
|
||||
}
|
||||
var command = 'node ' + tscPath + ' --module commonjs ';
|
||||
if (options.useTscParams && IO.fileExists(tsfile + '.tscparams')) {
|
||||
command += '@' + tsfile + '.tscparams';
|
||||
} else if (options.checkNoImplicitAny) {
|
||||
command += '--noImplicitAny';
|
||||
}
|
||||
Exec.exec(command, [tsfile], (execResult) => {
|
||||
callback(execResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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)=> {
|
||||
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;
|
||||
@@ -68,380 +41,22 @@ module DefinitelyTyped.TestManager {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// 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 start() {
|
||||
this.time = 0;
|
||||
this.startTime = this.now();
|
||||
}
|
||||
|
||||
public now():number {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
public end() {
|
||||
this.time = (this.now() - this.startTime) / 1000;
|
||||
this.asString = Timer.prettyDate(this.startTime, this.now());
|
||||
}
|
||||
|
||||
public static prettyDate(date1:number, date2:number):string {
|
||||
var diff = ((date2 - date1) / 1000),
|
||||
day_diff = Math.floor(diff / 86400);
|
||||
|
||||
if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
|
||||
return;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// 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;
|
||||
|
||||
constructor(public baseDir:string, public filePathWithName:string) {
|
||||
var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/');
|
||||
this.dir = dirName.split('/')[0];
|
||||
this.file = path.basename(this.filePathWithName, '.ts');
|
||||
this.ext = path.extname(this.filePathWithName);
|
||||
}
|
||||
|
||||
// From '/complete/path/to/file' to 'specfolder/specfile.d.ts'
|
||||
public get formatName():string {
|
||||
var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/');
|
||||
return this.dir + ((dirName.split('/').length > 1) ? '/-/' : '/') + this.file + this.ext;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Test results
|
||||
/////////////////////////////////
|
||||
export class TestResult {
|
||||
hostedBy:ITestSuite;
|
||||
targetFile:File;
|
||||
options:TscExecOptions;
|
||||
hostedBy: ITestSuite;
|
||||
targetFile: File;
|
||||
options: TscExecOptions;
|
||||
|
||||
stdout:string;
|
||||
stderr:string;
|
||||
exitCode:number;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
exitCode: number;
|
||||
|
||||
public get success():boolean {
|
||||
public get success(): boolean {
|
||||
return this.exitCode === 0;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// The interface for test suite
|
||||
/////////////////////////////////
|
||||
export interface ITestSuite {
|
||||
testSuiteName:string;
|
||||
errorHeadline:string;
|
||||
filterTargetFiles(files:File[]):File[];
|
||||
|
||||
start(targetFiles:File[], testCallback:(result:TestResult, index:number)=>void, suiteCallback:(suite:ITestSuite)=>void):void;
|
||||
|
||||
testResults:TestResult[];
|
||||
okTests:TestResult[];
|
||||
ngTests:TestResult[];
|
||||
timer:Timer;
|
||||
|
||||
testReporter:ITestReporter;
|
||||
printErrorCount:boolean;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Test reporter interface
|
||||
// for example, . and x
|
||||
/////////////////////////////////
|
||||
export interface ITestReporter {
|
||||
printPositiveCharacter(index:number, testResult:TestResult):void;
|
||||
printNegativeCharacter(index:number, testResult:TestResult):void;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Default test reporter
|
||||
/////////////////////////////////
|
||||
class DefaultTestReporter implements ITestReporter {
|
||||
constructor(public print:Print) {
|
||||
}
|
||||
|
||||
public printPositiveCharacter(index:number, testResult:TestResult) {
|
||||
this.print.out('\33[36m\33[1m' + '.' + '\33[0m');
|
||||
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
|
||||
public printNegativeCharacter(index:number, testResult:TestResult) {
|
||||
this.print.out("x");
|
||||
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
|
||||
private printBreakIfNeeded(index:number) {
|
||||
if (index % this.print.WIDTH === 0) {
|
||||
this.print.printBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// All the common things that we pring are functions of this class
|
||||
/////////////////////////////////
|
||||
class Print {
|
||||
|
||||
WIDTH = 77;
|
||||
|
||||
constructor(public version:string, public typings:number, public tests:number, public tsFiles:number) {
|
||||
}
|
||||
|
||||
public out(s:any):Print {
|
||||
process.stdout.write(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
public repeat(s:string, times:number):string {
|
||||
return new Array(times + 1).join(s);
|
||||
}
|
||||
|
||||
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 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 printDiv() {
|
||||
this.out('-----------------------------------------------------------------------------\n');
|
||||
}
|
||||
|
||||
public printBoldDiv() {
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
|
||||
public printErrorsHeader() {
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[34m\33[1mErrors in files\33[0m \n');
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
|
||||
public printErrorsForFile(testResult:TestResult) {
|
||||
this.out('----------------- For file:' + testResult.targetFile.formatName);
|
||||
this.printBreak().out(testResult.stderr).printBreak();
|
||||
}
|
||||
|
||||
public printBreak():Print {
|
||||
this.out('\n');
|
||||
return this;
|
||||
}
|
||||
|
||||
public clearCurrentLine():Print {
|
||||
this.out("\r\33[K");
|
||||
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 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 printTypingsWithoutTestsMessage() {
|
||||
this.out(' \33[36m\33[1mTyping without tests\33[0m\n');
|
||||
}
|
||||
|
||||
public printTotalMessage() {
|
||||
this.out(' \33[36m\33[1mTotal\33[0m\n');
|
||||
}
|
||||
|
||||
public printElapsedTime(time:string, s:number) {
|
||||
this.out(' \33[36m\33[1mElapsed time :\33[0m ~' + time + ' (' + s + 's)\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 printTypingsWithoutTestName(file:string) {
|
||||
this.out(' - \33[33m\33[1m' + file + '\33[0m\n');
|
||||
}
|
||||
|
||||
public printTypingsWithoutTest(withoutTestTypings:string[]) {
|
||||
if (withoutTestTypings.length > 0) {
|
||||
this.printTypingsWithoutTestsMessage();
|
||||
|
||||
this.printDiv();
|
||||
withoutTestTypings.forEach(t=> {
|
||||
this.printTypingsWithoutTestName(t);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Base class for test suite
|
||||
/////////////////////////////////
|
||||
class TestSuiteBase implements ITestSuite {
|
||||
timer:Timer = new Timer();
|
||||
testResults:TestResult[] = [];
|
||||
testReporter:ITestReporter;
|
||||
printErrorCount = true;
|
||||
|
||||
constructor(public options:ITestRunnerOptions, public testSuiteName:string, public errorHeadline:string) {
|
||||
}
|
||||
|
||||
public filterTargetFiles(files:File[]):File[] {
|
||||
throw new Error("please implement this method");
|
||||
}
|
||||
|
||||
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 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 finish(suiteCallback:(suite:ITestSuite)=>void) {
|
||||
suiteCallback(this);
|
||||
}
|
||||
|
||||
public get okTests():TestResult[] {
|
||||
return this.testResults.filter(r=>r.success);
|
||||
}
|
||||
|
||||
public get ngTests():TestResult[] {
|
||||
return this.testResults.filter(r=>!r.success);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// .d.ts syntax inspection
|
||||
/////////////////////////////////
|
||||
class SyntaxChecking extends TestSuiteBase {
|
||||
|
||||
constructor(options:ITestRunnerOptions) {
|
||||
super(options, "Syntax checking", "Syntax error");
|
||||
}
|
||||
|
||||
public filterTargetFiles(files:File[]):File[] {
|
||||
return files.filter(file => endsWith(file.formatName.toUpperCase(), '.D.TS'));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Compile with *-tests.ts
|
||||
/////////////////////////////////
|
||||
class TestEval extends TestSuiteBase {
|
||||
|
||||
constructor(options) {
|
||||
super(options, "Typing tests", "Failed tests");
|
||||
}
|
||||
|
||||
public filterTargetFiles(files:File[]):File[] {
|
||||
return files.filter(file => endsWith(file.formatName.toUpperCase(), '-TESTS.TS'));
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Try compile without .tscparams
|
||||
// It may indicate that it is compatible with --noImplicitAny maybe...
|
||||
/////////////////////////////////
|
||||
class FindNotRequiredTscparams extends TestSuiteBase {
|
||||
testReporter:ITestReporter;
|
||||
printErrorCount = false;
|
||||
|
||||
constructor(options:ITestRunnerOptions, private print:Print) {
|
||||
super(options, "Find not required .tscparams files", "New arrival!");
|
||||
|
||||
this.testReporter = {
|
||||
printPositiveCharacter: (index:number, testResult:TestResult)=> {
|
||||
this.print
|
||||
.clearCurrentLine()
|
||||
.printTypingsWithoutTestName(testResult.targetFile.formatName);
|
||||
},
|
||||
printNegativeCharacter: (index:number, testResult:TestResult)=> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public filterTargetFiles(files:File[]):File[] {
|
||||
return files.filter(file=> IO.fileExists(file.filePathWithName + '.tscparams'));
|
||||
}
|
||||
|
||||
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 finish(suiteCallback:(suite:ITestSuite)=>void) {
|
||||
this.print.clearCurrentLine();
|
||||
suiteCallback(this);
|
||||
}
|
||||
|
||||
public get ngTests():TestResult[] {
|
||||
// Do not show ng test results
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export interface ITestRunnerOptions {
|
||||
tscVersion:string;
|
||||
findNotRequiredTscparams?:boolean;
|
||||
@@ -451,23 +66,31 @@ module DefinitelyTyped.TestManager {
|
||||
// The main class to kick things off
|
||||
/////////////////////////////////
|
||||
export class TestRunner {
|
||||
files:File[];
|
||||
timer:Timer;
|
||||
suites:ITestSuite[] = [];
|
||||
private print:Print;
|
||||
files: File[];
|
||||
timer: Timer;
|
||||
suites: ITestSuite[] = [];
|
||||
private print: Print;
|
||||
|
||||
constructor(dtPath:string, public options:ITestRunnerOptions = {tscVersion: DEFAULT_TSC_VERSION}) {
|
||||
constructor(dtPath: string, public options: ITestRunnerOptions = {tscVersion: DT.DEFAULT_TSC_VERSION}) {
|
||||
this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams;
|
||||
|
||||
var filesName = IO.dir(dtPath, /.\.ts/g, { recursive: true }).sort();
|
||||
// only includes .d.ts or -tests.ts or -test.ts or .ts
|
||||
filesName = filesName
|
||||
.filter(fileName => fileName.indexOf('../_infrastructure') < 0)
|
||||
.filter(fileName => !endsWith(fileName, ".tscparams"));
|
||||
this.files = filesName.map(fileName => new File(dtPath, fileName));
|
||||
this.files = filesName
|
||||
.filter((fileName) => {
|
||||
return fileName.indexOf('../_infrastructure') < 0;
|
||||
})
|
||||
.filter((fileName) => {
|
||||
return fileName.indexOf('../node_modules') < 0;
|
||||
})
|
||||
.filter((fileName) => {
|
||||
return !DT.endsWith(fileName, ".tscparams");
|
||||
}).map((fileName) => {
|
||||
return new File(dtPath, fileName);
|
||||
});
|
||||
}
|
||||
|
||||
public addSuite(suite:ITestSuite) {
|
||||
public addSuite(suite: ITestSuite) {
|
||||
this.suites.push(suite);
|
||||
}
|
||||
|
||||
@@ -504,7 +127,7 @@ module DefinitelyTyped.TestManager {
|
||||
(testResult, index) => {
|
||||
this.testCompleteCallback(testResult, index);
|
||||
},
|
||||
suite=> {
|
||||
(suite) => {
|
||||
this.suiteCompleteCallback(suite);
|
||||
count++;
|
||||
executor();
|
||||
@@ -517,7 +140,7 @@ module DefinitelyTyped.TestManager {
|
||||
executor();
|
||||
}
|
||||
|
||||
private testCompleteCallback(testResult:TestResult, index:number) {
|
||||
private testCompleteCallback(testResult: TestResult, index: number) {
|
||||
var reporter = testResult.hostedBy.testReporter;
|
||||
if (testResult.success) {
|
||||
reporter.printPositiveCharacter(index, testResult);
|
||||
@@ -526,7 +149,7 @@ module DefinitelyTyped.TestManager {
|
||||
}
|
||||
}
|
||||
|
||||
private suiteCompleteCallback(suite:ITestSuite) {
|
||||
private suiteCompleteCallback(suite: ITestSuite) {
|
||||
this.print.printBreak();
|
||||
|
||||
this.print.printDiv();
|
||||
@@ -536,16 +159,26 @@ module DefinitelyTyped.TestManager {
|
||||
}
|
||||
|
||||
private allTestCompleteCallback() {
|
||||
var testEval = this.suites.filter(suite=>suite instanceof TestEval)[0];
|
||||
var testEval = this.suites.filter(suite => suite instanceof TestEval)[0];
|
||||
if (testEval) {
|
||||
var existsTestTypings:string[] = testEval.testResults
|
||||
.map(testResult=>testResult.targetFile.dir)
|
||||
.reduce((a, b)=> a.indexOf(b) < 0 ? a.concat([b]) : a, []);
|
||||
var typings:string[] = this.files
|
||||
.map(file=>file.dir)
|
||||
.reduce((a, b)=> a.indexOf(b) < 0 ? a.concat([b]) : a, []);
|
||||
var withoutTestTypings:string[] = typings
|
||||
.filter(typing=>existsTestTypings.indexOf(typing) < 0);
|
||||
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);
|
||||
}
|
||||
@@ -556,8 +189,10 @@ module DefinitelyTyped.TestManager {
|
||||
this.print.printDiv();
|
||||
this.print.printElapsedTime(this.timer.asString, this.timer.time);
|
||||
this.suites
|
||||
.filter(suite=>suite.printErrorCount)
|
||||
.forEach(suite=> {
|
||||
.filter((suite: ITestSuite) => {
|
||||
return suite.printErrorCount;
|
||||
})
|
||||
.forEach((suite: ITestSuite) => {
|
||||
this.print.printSuiteErrorCount(suite.errorHeadline, suite.ngTests.length, suite.testResults.length);
|
||||
});
|
||||
if (testEval) {
|
||||
@@ -565,13 +200,17 @@ module DefinitelyTyped.TestManager {
|
||||
}
|
||||
|
||||
this.print.printDiv();
|
||||
if (this.suites.some(suite=>suite.ngTests.length !== 0)) {
|
||||
if (this.suites.some((suite) => {
|
||||
return suite.ngTests.length !== 0
|
||||
})) {
|
||||
this.print.printErrorsHeader();
|
||||
|
||||
this.suites
|
||||
.filter(suite=>suite.ngTests.length !== 0)
|
||||
.forEach(suite=> {
|
||||
suite.ngTests.forEach(testResult => {
|
||||
.filter((suite) => {
|
||||
return suite.ngTests.length !== 0;
|
||||
})
|
||||
.forEach((suite) => {
|
||||
suite.ngTests.forEach((testResult) => {
|
||||
this.print.printErrorsForFile(testResult);
|
||||
});
|
||||
this.print.printBoldDiv();
|
||||
@@ -581,18 +220,18 @@ module DefinitelyTyped.TestManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dtPath = __dirname + '/../..';
|
||||
var findNotRequiredTscparams = process.argv.some(arg=>arg == "--try-without-tscparams");
|
||||
var tscVersionIndex = process.argv.indexOf("--tsc-version");
|
||||
var tscVersion = DefinitelyTyped.TestManager.DEFAULT_TSC_VERSION;
|
||||
if (-1 < tscVersionIndex) {
|
||||
tscVersion = process.argv[tscVersionIndex + 1];
|
||||
}
|
||||
var dtPath = __dirname + '/../..';
|
||||
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];
|
||||
}
|
||||
|
||||
var runner = new DefinitelyTyped.TestManager.TestRunner(dtPath, {
|
||||
tscVersion: tscVersion,
|
||||
findNotRequiredTscparams: findNotRequiredTscparams
|
||||
});
|
||||
runner.run();
|
||||
var runner = new TestRunner(dtPath, {
|
||||
tscVersion: tscVersion,
|
||||
findNotRequiredTscparams: findNotRequiredTscparams
|
||||
});
|
||||
runner.run();
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
var ExecResult = (function () {
|
||||
function ExecResult() {
|
||||
this.stdout = "";
|
||||
this.stderr = "";
|
||||
}
|
||||
return ExecResult;
|
||||
})();
|
||||
|
||||
var WindowsScriptHostExec = (function () {
|
||||
function WindowsScriptHostExec() {
|
||||
}
|
||||
WindowsScriptHostExec.prototype.exec = function (filename, cmdLineArgs, handleResult) {
|
||||
var result = new ExecResult();
|
||||
var shell = new ActiveXObject('WScript.Shell');
|
||||
try {
|
||||
var process = shell.Exec(filename + ' ' + cmdLineArgs.join(' '));
|
||||
} catch (e) {
|
||||
result.stderr = e.message;
|
||||
result.exitCode = 1;
|
||||
handleResult(result);
|
||||
return;
|
||||
}
|
||||
|
||||
while (process.Status != 0) {
|
||||
}
|
||||
|
||||
result.exitCode = process.ExitCode;
|
||||
if (!process.StdOut.AtEndOfStream)
|
||||
result.stdout = process.StdOut.ReadAll();
|
||||
if (!process.StdErr.AtEndOfStream)
|
||||
result.stderr = process.StdErr.ReadAll();
|
||||
|
||||
handleResult(result);
|
||||
};
|
||||
return WindowsScriptHostExec;
|
||||
})();
|
||||
|
||||
var NodeExec = (function () {
|
||||
function NodeExec() {
|
||||
}
|
||||
NodeExec.prototype.exec = function (filename, cmdLineArgs, handleResult) {
|
||||
var nodeExec = require('child_process').exec;
|
||||
|
||||
var result = new ExecResult();
|
||||
result.exitCode = null;
|
||||
var cmdLine = filename + ' ' + cmdLineArgs.join(' ');
|
||||
|
||||
var process = nodeExec(cmdLine, function (error, stdout, stderr) {
|
||||
result.stdout = stdout;
|
||||
result.stderr = stderr;
|
||||
result.exitCode = error ? error.code : 0;
|
||||
handleResult(result);
|
||||
});
|
||||
};
|
||||
return NodeExec;
|
||||
})();
|
||||
|
||||
var Exec = (function () {
|
||||
var global = Function("return this;").call(null);
|
||||
if (typeof global.ActiveXObject !== "undefined") {
|
||||
return new WindowsScriptHostExec();
|
||||
} else {
|
||||
return new NodeExec();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,26 @@
|
||||
module DT {
|
||||
var path = require('path');
|
||||
|
||||
/////////////////////////////////
|
||||
// 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;
|
||||
|
||||
constructor(public baseDir: string, public filePathWithName: string) {
|
||||
var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/');
|
||||
this.dir = dirName.split('/')[0];
|
||||
this.file = path.basename(this.filePathWithName, '.ts');
|
||||
this.ext = path.extname(this.filePathWithName);
|
||||
}
|
||||
|
||||
// From '/complete/path/to/file' to 'specfolder/specfile.d.ts'
|
||||
public get formatName(): string {
|
||||
var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/');
|
||||
return this.dir + ((dirName.split('/').length > 1) ? '/-/' : '/') + this.file + this.ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,6 @@ interface IExec {
|
||||
exec: (filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void) => void;
|
||||
}
|
||||
|
||||
declare var require;
|
||||
|
||||
class ExecResult {
|
||||
public stdout = "";
|
||||
public stderr = "";
|
||||
@@ -27,31 +25,31 @@ class ExecResult {
|
||||
}
|
||||
|
||||
class WindowsScriptHostExec implements IExec {
|
||||
public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void) : void {
|
||||
public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void): void {
|
||||
var result = new ExecResult();
|
||||
var shell = new ActiveXObject('WScript.Shell');
|
||||
try {
|
||||
var process = shell.Exec(filename + ' ' + cmdLineArgs.join(' '));
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
result.stderr = e.message;
|
||||
result.exitCode = 1
|
||||
handleResult(result);
|
||||
return;
|
||||
}
|
||||
// Wait for it to finish running
|
||||
while (process.Status != 0) { /* todo: sleep? */ }
|
||||
while (process.Status != 0) { /* todo: sleep? */
|
||||
}
|
||||
|
||||
|
||||
result.exitCode = process.ExitCode;
|
||||
if(!process.StdOut.AtEndOfStream) result.stdout = process.StdOut.ReadAll();
|
||||
if(!process.StdErr.AtEndOfStream) result.stderr = process.StdErr.ReadAll();
|
||||
if (!process.StdOut.AtEndOfStream) result.stdout = process.StdOut.ReadAll();
|
||||
if (!process.StdErr.AtEndOfStream) result.stderr = process.StdErr.ReadAll();
|
||||
|
||||
handleResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
class NodeExec implements IExec {
|
||||
public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void) : void {
|
||||
public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void): void {
|
||||
var nodeExec = require('child_process').exec;
|
||||
|
||||
var result = new ExecResult();
|
||||
@@ -67,11 +65,11 @@ class NodeExec implements IExec {
|
||||
}
|
||||
}
|
||||
|
||||
var Exec: IExec = function() : IExec {
|
||||
var Exec: IExec = function (): IExec {
|
||||
var global = <any>Function("return this;").call(null);
|
||||
if(typeof global.ActiveXObject !== "undefined") {
|
||||
if (typeof global.ActiveXObject !== "undefined") {
|
||||
return new WindowsScriptHostExec();
|
||||
} else {
|
||||
return new NodeExec();
|
||||
}
|
||||
}();
|
||||
}();
|
||||
@@ -27,7 +27,8 @@ interface IIO {
|
||||
writeFile(path: string, contents: string): void;
|
||||
createFile(path: string, useUTF8?: boolean): ITextWriter;
|
||||
deleteFile(path: string): void;
|
||||
dir(path: string, re?: RegExp, options?: { recursive?: boolean; deep?: number; }): string[];
|
||||
dir(path: string, re?: RegExp, options?: { recursive?: boolean; deep?: number;
|
||||
}): string[];
|
||||
fileExists(path: string): boolean;
|
||||
directoryExists(path: string): boolean;
|
||||
createDirectory(path: string): void;
|
||||
@@ -39,7 +40,7 @@ interface IIO {
|
||||
arguments: string[];
|
||||
stderr: ITextWriter;
|
||||
stdout: ITextWriter;
|
||||
watchFile(filename: string, callback: (string) => void ): IFileWatcher;
|
||||
watchFile(filename: string, callback: (string) => void): IFileWatcher;
|
||||
run(source: string, filename: string): void;
|
||||
getExecutingFilePath(): string;
|
||||
quit(exitCode?: number);
|
||||
@@ -79,9 +80,12 @@ module IOUtils {
|
||||
// Declare dependencies needed for all supported hosts
|
||||
declare class Enumerator {
|
||||
public atEnd(): boolean;
|
||||
|
||||
public moveNext();
|
||||
|
||||
public item(): any;
|
||||
constructor (o: any);
|
||||
|
||||
constructor(o: any);
|
||||
}
|
||||
|
||||
// Missing in node definitions, but called in code below.
|
||||
@@ -91,7 +95,7 @@ interface NodeProcess {
|
||||
}
|
||||
}
|
||||
|
||||
var IO = (function() {
|
||||
var IO = (function () {
|
||||
|
||||
// Create an IO object for use inside WindowsScriptHost hosts
|
||||
// Depends on WSCript and FileSystemObject
|
||||
@@ -99,15 +103,15 @@ var IO = (function() {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var streamObjectPool = [];
|
||||
|
||||
function getStreamObject(): any {
|
||||
function getStreamObject(): any {
|
||||
if (streamObjectPool.length > 0) {
|
||||
return streamObjectPool.pop();
|
||||
} else {
|
||||
} else {
|
||||
return new ActiveXObject("ADODB.Stream");
|
||||
}
|
||||
}
|
||||
|
||||
function releaseStreamObject(obj: any) {
|
||||
function releaseStreamObject(obj: any) {
|
||||
streamObjectPool.push(obj);
|
||||
}
|
||||
|
||||
@@ -117,7 +121,7 @@ var IO = (function() {
|
||||
}
|
||||
|
||||
return {
|
||||
readFile: function(path) {
|
||||
readFile: function (path) {
|
||||
try {
|
||||
var streamObj = getStreamObject();
|
||||
streamObj.Open();
|
||||
@@ -130,7 +134,7 @@ var IO = (function() {
|
||||
|| (bomChar.charCodeAt(0) == 0xFF && bomChar.charCodeAt(1) == 0xFE)) {
|
||||
streamObj.Charset = 'unicode';
|
||||
} else if (bomChar.charCodeAt(0) == 0xEF && bomChar.charCodeAt(1) == 0xBB) {
|
||||
streamObj.Charset = 'utf-8';
|
||||
streamObj.Charset = 'utf-8';
|
||||
}
|
||||
|
||||
// Read the whole file
|
||||
@@ -144,25 +148,25 @@ var IO = (function() {
|
||||
}
|
||||
},
|
||||
|
||||
writeFile: function(path, contents) {
|
||||
writeFile: function (path, contents) {
|
||||
var file = this.createFile(path);
|
||||
file.Write(contents);
|
||||
file.Close();
|
||||
},
|
||||
|
||||
fileExists: function(path: string): boolean {
|
||||
fileExists: function (path: string): boolean {
|
||||
return fso.FileExists(path);
|
||||
},
|
||||
|
||||
resolvePath: function(path: string): string {
|
||||
resolvePath: function (path: string): string {
|
||||
return fso.GetAbsolutePathName(path);
|
||||
},
|
||||
|
||||
dirName: function(path: string): string {
|
||||
dirName: function (path: string): string {
|
||||
return fso.GetParentFolderName(path);
|
||||
},
|
||||
|
||||
findFile: function(rootPath: string, partialFilePath: string): IResolvedFile {
|
||||
findFile: function (rootPath: string, partialFilePath: string): IResolvedFile {
|
||||
var path = fso.GetAbsolutePathName(rootPath) + "/" + partialFilePath;
|
||||
|
||||
while (true) {
|
||||
@@ -188,7 +192,7 @@ var IO = (function() {
|
||||
}
|
||||
},
|
||||
|
||||
deleteFile: function(path: string): void {
|
||||
deleteFile: function (path: string): void {
|
||||
try {
|
||||
if (fso.FileExists(path)) {
|
||||
fso.DeleteFile(path, true); // true: delete read-only files
|
||||
@@ -204,9 +208,13 @@ var IO = (function() {
|
||||
streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi';
|
||||
streamObj.Open();
|
||||
return {
|
||||
Write: function (str) { streamObj.WriteText(str, 0); },
|
||||
WriteLine: function (str) { streamObj.WriteText(str, 1); },
|
||||
Close: function() {
|
||||
Write: function (str) {
|
||||
streamObj.WriteText(str, 0);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
streamObj.WriteText(str, 1);
|
||||
},
|
||||
Close: function () {
|
||||
try {
|
||||
streamObj.SaveToFile(path, 2);
|
||||
} catch (saveError) {
|
||||
@@ -225,11 +233,11 @@ var IO = (function() {
|
||||
}
|
||||
},
|
||||
|
||||
directoryExists: function(path) {
|
||||
directoryExists: function (path) {
|
||||
return <boolean>fso.FolderExists(path);
|
||||
},
|
||||
|
||||
createDirectory: function(path) {
|
||||
createDirectory: function (path) {
|
||||
try {
|
||||
if (!this.directoryExists(path)) {
|
||||
fso.CreateFolder(path);
|
||||
@@ -239,23 +247,24 @@ var IO = (function() {
|
||||
}
|
||||
},
|
||||
|
||||
dir: function(path, spec?, options?) {
|
||||
options = options || <{ recursive?: boolean; deep?: number; }>{};
|
||||
function filesInFolder(folder, root): string[]{
|
||||
dir: function (path, spec?, options?) {
|
||||
options = options || <{ recursive?: boolean; deep?: number;
|
||||
}>{};
|
||||
function filesInFolder(folder, root): string[] {
|
||||
var paths = [];
|
||||
var fc: Enumerator;
|
||||
|
||||
if (options.recursive) {
|
||||
fc = new Enumerator(folder.subfolders);
|
||||
|
||||
for (; !fc.atEnd() ; fc.moveNext()) {
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
paths = paths.concat(filesInFolder(fc.item(), root + "/" + fc.item().Name));
|
||||
}
|
||||
}
|
||||
|
||||
fc = new Enumerator(folder.files);
|
||||
|
||||
for (; !fc.atEnd() ; fc.moveNext()) {
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
if (!spec || fc.item().Name.match(spec)) {
|
||||
paths.push(root + "/" + fc.item().Name);
|
||||
}
|
||||
@@ -270,11 +279,11 @@ var IO = (function() {
|
||||
return filesInFolder(folder, path);
|
||||
},
|
||||
|
||||
print: function(str) {
|
||||
print: function (str) {
|
||||
WScript.StdOut.Write(str);
|
||||
},
|
||||
|
||||
printLine: function(str) {
|
||||
printLine: function (str) {
|
||||
WScript.Echo(str);
|
||||
},
|
||||
|
||||
@@ -282,7 +291,7 @@ var IO = (function() {
|
||||
stderr: WScript.StdErr,
|
||||
stdout: WScript.StdOut,
|
||||
watchFile: null,
|
||||
run: function(source, filename) {
|
||||
run: function (source, filename) {
|
||||
try {
|
||||
eval(source);
|
||||
} catch (e) {
|
||||
@@ -292,7 +301,7 @@ var IO = (function() {
|
||||
getExecutingFilePath: function () {
|
||||
return WScript.ScriptFullName;
|
||||
},
|
||||
quit: function (exitCode : number = 0) {
|
||||
quit: function (exitCode: number = 0) {
|
||||
try {
|
||||
WScript.Quit(exitCode);
|
||||
} catch (e) {
|
||||
@@ -311,7 +320,7 @@ var IO = (function() {
|
||||
var _module = require('module');
|
||||
|
||||
return {
|
||||
readFile: function(file) {
|
||||
readFile: function (file) {
|
||||
try {
|
||||
var buffer = _fs.readFileSync(file);
|
||||
switch (buffer[0]) {
|
||||
@@ -348,17 +357,17 @@ var IO = (function() {
|
||||
}
|
||||
},
|
||||
writeFile: <(path: string, contents: string) => void >_fs.writeFileSync,
|
||||
deleteFile: function(path) {
|
||||
deleteFile: function (path) {
|
||||
try {
|
||||
_fs.unlinkSync(path);
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e);
|
||||
}
|
||||
},
|
||||
fileExists: function(path): boolean {
|
||||
fileExists: function (path): boolean {
|
||||
return _fs.existsSync(path);
|
||||
},
|
||||
createFile: function(path, useUTF8?) {
|
||||
createFile: function (path, useUTF8?) {
|
||||
function mkdirRecursiveSync(path) {
|
||||
var stats = _fs.statSync(path);
|
||||
if (stats.isFile()) {
|
||||
@@ -367,7 +376,7 @@ var IO = (function() {
|
||||
return;
|
||||
} else {
|
||||
mkdirRecursiveSync(_path.dirname(path));
|
||||
_fs.mkdirSync(path, 0775);
|
||||
_fs.mkdirSync(path, parseInt('0775', 8));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,15 +388,23 @@ var IO = (function() {
|
||||
IOUtils.throwIOError("Couldn't write to file '" + path + "'.", e);
|
||||
}
|
||||
return {
|
||||
Write: function(str) { _fs.writeSync(fd, str); },
|
||||
WriteLine: function(str) { _fs.writeSync(fd, str + '\r\n'); },
|
||||
Close: function() { _fs.closeSync(fd); fd = null; }
|
||||
Write: function (str) {
|
||||
_fs.writeSync(fd, str);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
_fs.writeSync(fd, str + '\r\n');
|
||||
},
|
||||
Close: function () {
|
||||
_fs.closeSync(fd);
|
||||
fd = null;
|
||||
}
|
||||
};
|
||||
},
|
||||
dir: function dir(path, spec?, options?) {
|
||||
options = options || <{ recursive?: boolean; deep?: number; }>{};
|
||||
options = options || <{ recursive?: boolean; deep?: number;
|
||||
}>{};
|
||||
|
||||
function filesInFolder(folder: string, deep?: number): string[]{
|
||||
function filesInFolder(folder: string, deep?: number): string[] {
|
||||
var paths = [];
|
||||
|
||||
var files = _fs.readdirSync(folder);
|
||||
@@ -407,7 +424,7 @@ var IO = (function() {
|
||||
|
||||
return filesInFolder(path, 0);
|
||||
},
|
||||
createDirectory: function(path: string): void {
|
||||
createDirectory: function (path: string): void {
|
||||
try {
|
||||
if (!this.directoryExists(path)) {
|
||||
_fs.mkdirSync(path);
|
||||
@@ -417,16 +434,16 @@ var IO = (function() {
|
||||
}
|
||||
},
|
||||
|
||||
directoryExists: function(path: string): boolean {
|
||||
directoryExists: function (path: string): boolean {
|
||||
return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory();
|
||||
},
|
||||
resolvePath: function(path: string): string {
|
||||
resolvePath: function (path: string): string {
|
||||
return _path.resolve(path);
|
||||
},
|
||||
dirName: function(path: string): string {
|
||||
dirName: function (path: string): string {
|
||||
return _path.dirname(path);
|
||||
},
|
||||
findFile: function(rootPath: string, partialFilePath): IResolvedFile {
|
||||
findFile: function (rootPath: string, partialFilePath): IResolvedFile {
|
||||
var path = rootPath + "/" + partialFilePath;
|
||||
|
||||
while (true) {
|
||||
@@ -452,24 +469,38 @@ var IO = (function() {
|
||||
}
|
||||
}
|
||||
},
|
||||
print: function(str) { process.stdout.write(str) },
|
||||
printLine: function(str) { process.stdout.write(str + '\n') },
|
||||
print: function (str) {
|
||||
process.stdout.write(str)
|
||||
},
|
||||
printLine: function (str) {
|
||||
process.stdout.write(str + '\n')
|
||||
},
|
||||
arguments: process.argv.slice(2),
|
||||
stderr: {
|
||||
Write: function(str) { process.stderr.write(str); },
|
||||
WriteLine: function(str) { process.stderr.write(str + '\n'); },
|
||||
Close: function() { }
|
||||
Write: function (str) {
|
||||
process.stderr.write(str);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
process.stderr.write(str + '\n');
|
||||
},
|
||||
Close: function () {
|
||||
}
|
||||
},
|
||||
stdout: {
|
||||
Write: function(str) { process.stdout.write(str); },
|
||||
WriteLine: function(str) { process.stdout.write(str + '\n'); },
|
||||
Close: function() { }
|
||||
Write: function (str) {
|
||||
process.stdout.write(str);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
process.stdout.write(str + '\n');
|
||||
},
|
||||
Close: function () {
|
||||
}
|
||||
},
|
||||
watchFile: function(filename: string, callback: (string) => void ): IFileWatcher {
|
||||
watchFile: function (filename: string, callback: (string) => void): IFileWatcher {
|
||||
var firstRun = true;
|
||||
var processingChange = false;
|
||||
|
||||
var fileChanged: any = function(curr, prev) {
|
||||
var fileChanged: any = function (curr, prev) {
|
||||
if (!firstRun) {
|
||||
if (curr.mtime < prev.mtime) {
|
||||
return;
|
||||
@@ -479,7 +510,9 @@ var IO = (function() {
|
||||
if (!processingChange) {
|
||||
processingChange = true;
|
||||
callback(filename);
|
||||
setTimeout(function() { processingChange = false; }, 100);
|
||||
setTimeout(function () {
|
||||
processingChange = false;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
firstRun = false;
|
||||
@@ -489,16 +522,16 @@ var IO = (function() {
|
||||
fileChanged();
|
||||
return {
|
||||
filename: filename,
|
||||
close: function() {
|
||||
close: function () {
|
||||
_fs.unwatchFile(filename, fileChanged);
|
||||
}
|
||||
};
|
||||
},
|
||||
run: function(source, filename) {
|
||||
run: function (source, filename) {
|
||||
require.main.filename = filename;
|
||||
require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename)));
|
||||
require.main._compile(source, filename);
|
||||
},
|
||||
},
|
||||
getExecutingFilePath: function () {
|
||||
return process.mainModule.filename;
|
||||
},
|
||||
@@ -1,475 +0,0 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
var IOUtils;
|
||||
(function (IOUtils) {
|
||||
// Creates the directory including its parent if not already present
|
||||
function createDirectoryStructure(ioHost, dirName) {
|
||||
if (ioHost.directoryExists(dirName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var parentDirectory = ioHost.dirName(dirName);
|
||||
if (parentDirectory != "") {
|
||||
createDirectoryStructure(ioHost, parentDirectory);
|
||||
}
|
||||
ioHost.createDirectory(dirName);
|
||||
}
|
||||
|
||||
// Creates a file including its directory structure if not already present
|
||||
function createFileAndFolderStructure(ioHost, fileName, useUTF8) {
|
||||
var path = ioHost.resolvePath(fileName);
|
||||
var dirName = ioHost.dirName(path);
|
||||
createDirectoryStructure(ioHost, dirName);
|
||||
return ioHost.createFile(path, useUTF8);
|
||||
}
|
||||
IOUtils.createFileAndFolderStructure = createFileAndFolderStructure;
|
||||
|
||||
function throwIOError(message, error) {
|
||||
var errorMessage = message;
|
||||
if (error && error.message) {
|
||||
errorMessage += (" " + error.message);
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
IOUtils.throwIOError = throwIOError;
|
||||
})(IOUtils || (IOUtils = {}));
|
||||
|
||||
var IO = (function () {
|
||||
// Create an IO object for use inside WindowsScriptHost hosts
|
||||
// Depends on WSCript and FileSystemObject
|
||||
function getWindowsScriptHostIO() {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var streamObjectPool = [];
|
||||
|
||||
function getStreamObject() {
|
||||
if (streamObjectPool.length > 0) {
|
||||
return streamObjectPool.pop();
|
||||
} else {
|
||||
return new ActiveXObject("ADODB.Stream");
|
||||
}
|
||||
}
|
||||
|
||||
function releaseStreamObject(obj) {
|
||||
streamObjectPool.push(obj);
|
||||
}
|
||||
|
||||
var args = [];
|
||||
for (var i = 0; i < WScript.Arguments.length; i++) {
|
||||
args[i] = WScript.Arguments.Item(i);
|
||||
}
|
||||
|
||||
return {
|
||||
readFile: function (path) {
|
||||
try {
|
||||
var streamObj = getStreamObject();
|
||||
streamObj.Open();
|
||||
streamObj.Type = 2;
|
||||
streamObj.Charset = 'x-ansi';
|
||||
streamObj.LoadFromFile(path);
|
||||
var bomChar = streamObj.ReadText(2);
|
||||
streamObj.Position = 0;
|
||||
if ((bomChar.charCodeAt(0) == 0xFE && bomChar.charCodeAt(1) == 0xFF) || (bomChar.charCodeAt(0) == 0xFF && bomChar.charCodeAt(1) == 0xFE)) {
|
||||
streamObj.Charset = 'unicode';
|
||||
} else if (bomChar.charCodeAt(0) == 0xEF && bomChar.charCodeAt(1) == 0xBB) {
|
||||
streamObj.Charset = 'utf-8';
|
||||
}
|
||||
|
||||
// Read the whole file
|
||||
var str = streamObj.ReadText(-1);
|
||||
streamObj.Close();
|
||||
releaseStreamObject(streamObj);
|
||||
return str;
|
||||
} catch (err) {
|
||||
IOUtils.throwIOError("Error reading file \"" + path + "\".", err);
|
||||
}
|
||||
},
|
||||
writeFile: function (path, contents) {
|
||||
var file = this.createFile(path);
|
||||
file.Write(contents);
|
||||
file.Close();
|
||||
},
|
||||
fileExists: function (path) {
|
||||
return fso.FileExists(path);
|
||||
},
|
||||
resolvePath: function (path) {
|
||||
return fso.GetAbsolutePathName(path);
|
||||
},
|
||||
dirName: function (path) {
|
||||
return fso.GetParentFolderName(path);
|
||||
},
|
||||
findFile: function (rootPath, partialFilePath) {
|
||||
var path = fso.GetAbsolutePathName(rootPath) + "/" + partialFilePath;
|
||||
|
||||
while (true) {
|
||||
if (fso.FileExists(path)) {
|
||||
try {
|
||||
var content = this.readFile(path);
|
||||
return { content: content, path: path };
|
||||
} catch (err) {
|
||||
//Tools.CompilerDiagnostics.debugPrint("Could not find " + path + ", trying parent");
|
||||
}
|
||||
} else {
|
||||
rootPath = fso.GetParentFolderName(fso.GetAbsolutePathName(rootPath));
|
||||
|
||||
if (rootPath == "") {
|
||||
return null;
|
||||
} else {
|
||||
path = fso.BuildPath(rootPath, partialFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
deleteFile: function (path) {
|
||||
try {
|
||||
if (fso.FileExists(path)) {
|
||||
fso.DeleteFile(path, true);
|
||||
}
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e);
|
||||
}
|
||||
},
|
||||
createFile: function (path, useUTF8) {
|
||||
try {
|
||||
var streamObj = getStreamObject();
|
||||
streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi';
|
||||
streamObj.Open();
|
||||
return {
|
||||
Write: function (str) {
|
||||
streamObj.WriteText(str, 0);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
streamObj.WriteText(str, 1);
|
||||
},
|
||||
Close: function () {
|
||||
try {
|
||||
streamObj.SaveToFile(path, 2);
|
||||
} catch (saveError) {
|
||||
IOUtils.throwIOError("Couldn't write to file '" + path + "'.", saveError);
|
||||
} finally {
|
||||
if (streamObj.State != 0) {
|
||||
streamObj.Close();
|
||||
}
|
||||
releaseStreamObject(streamObj);
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (creationError) {
|
||||
IOUtils.throwIOError("Couldn't write to file '" + path + "'.", creationError);
|
||||
}
|
||||
},
|
||||
directoryExists: function (path) {
|
||||
return fso.FolderExists(path);
|
||||
},
|
||||
createDirectory: function (path) {
|
||||
try {
|
||||
if (!this.directoryExists(path)) {
|
||||
fso.CreateFolder(path);
|
||||
}
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e);
|
||||
}
|
||||
},
|
||||
dir: function (path, spec, options) {
|
||||
options = options || {};
|
||||
function filesInFolder(folder, root) {
|
||||
var paths = [];
|
||||
var fc;
|
||||
|
||||
if (options.recursive) {
|
||||
fc = new Enumerator(folder.subfolders);
|
||||
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
paths = paths.concat(filesInFolder(fc.item(), root + "/" + fc.item().Name));
|
||||
}
|
||||
}
|
||||
|
||||
fc = new Enumerator(folder.files);
|
||||
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
if (!spec || fc.item().Name.match(spec)) {
|
||||
paths.push(root + "/" + fc.item().Name);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
var folder = fso.GetFolder(path);
|
||||
var paths = [];
|
||||
|
||||
return filesInFolder(folder, path);
|
||||
},
|
||||
print: function (str) {
|
||||
WScript.StdOut.Write(str);
|
||||
},
|
||||
printLine: function (str) {
|
||||
WScript.Echo(str);
|
||||
},
|
||||
arguments: args,
|
||||
stderr: WScript.StdErr,
|
||||
stdout: WScript.StdOut,
|
||||
watchFile: null,
|
||||
run: function (source, filename) {
|
||||
try {
|
||||
eval(source);
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Error while executing file '" + filename + "'.", e);
|
||||
}
|
||||
},
|
||||
getExecutingFilePath: function () {
|
||||
return WScript.ScriptFullName;
|
||||
},
|
||||
quit: function (exitCode) {
|
||||
if (typeof exitCode === "undefined") { exitCode = 0; }
|
||||
try {
|
||||
WScript.Quit(exitCode);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
// Create an IO object for use inside Node.js hosts
|
||||
// Depends on 'fs' and 'path' modules
|
||||
function getNodeIO() {
|
||||
var _fs = require('fs');
|
||||
var _path = require('path');
|
||||
var _module = require('module');
|
||||
|
||||
return {
|
||||
readFile: function (file) {
|
||||
try {
|
||||
var buffer = _fs.readFileSync(file);
|
||||
switch (buffer[0]) {
|
||||
case 0xFE:
|
||||
if (buffer[1] == 0xFF) {
|
||||
// utf16-be. Reading the buffer as big endian is not supported, so convert it to
|
||||
// Little Endian first
|
||||
var i = 0;
|
||||
while ((i + 1) < buffer.length) {
|
||||
var temp = buffer[i];
|
||||
buffer[i] = buffer[i + 1];
|
||||
buffer[i + 1] = temp;
|
||||
i += 2;
|
||||
}
|
||||
return buffer.toString("ucs2", 2);
|
||||
}
|
||||
break;
|
||||
case 0xFF:
|
||||
if (buffer[1] == 0xFE) {
|
||||
// utf16-le
|
||||
return buffer.toString("ucs2", 2);
|
||||
}
|
||||
break;
|
||||
case 0xEF:
|
||||
if (buffer[1] == 0xBB) {
|
||||
// utf-8
|
||||
return buffer.toString("utf8", 3);
|
||||
}
|
||||
}
|
||||
|
||||
// Default behaviour
|
||||
return buffer.toString();
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Error reading file \"" + file + "\".", e);
|
||||
}
|
||||
},
|
||||
writeFile: _fs.writeFileSync,
|
||||
deleteFile: function (path) {
|
||||
try {
|
||||
_fs.unlinkSync(path);
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e);
|
||||
}
|
||||
},
|
||||
fileExists: function (path) {
|
||||
return _fs.existsSync(path);
|
||||
},
|
||||
createFile: function (path, useUTF8) {
|
||||
function mkdirRecursiveSync(path) {
|
||||
var stats = _fs.statSync(path);
|
||||
if (stats.isFile()) {
|
||||
IOUtils.throwIOError("\"" + path + "\" exists but isn't a directory.", null);
|
||||
} else if (stats.isDirectory()) {
|
||||
return;
|
||||
} else {
|
||||
mkdirRecursiveSync(_path.dirname(path));
|
||||
_fs.mkdirSync(path, 0775);
|
||||
}
|
||||
}
|
||||
|
||||
mkdirRecursiveSync(_path.dirname(path));
|
||||
|
||||
try {
|
||||
var fd = _fs.openSync(path, 'w');
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Couldn't write to file '" + path + "'.", e);
|
||||
}
|
||||
return {
|
||||
Write: function (str) {
|
||||
_fs.writeSync(fd, str);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
_fs.writeSync(fd, str + '\r\n');
|
||||
},
|
||||
Close: function () {
|
||||
_fs.closeSync(fd);
|
||||
fd = null;
|
||||
}
|
||||
};
|
||||
},
|
||||
dir: function dir(path, spec, options) {
|
||||
options = options || {};
|
||||
|
||||
function filesInFolder(folder, deep) {
|
||||
var paths = [];
|
||||
|
||||
var files = _fs.readdirSync(folder);
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var stat = _fs.statSync(folder + "/" + files[i]);
|
||||
if (options.recursive && stat.isDirectory()) {
|
||||
if (deep < (options.deep || 100)) {
|
||||
paths = paths.concat(filesInFolder(folder + "/" + files[i], 1));
|
||||
}
|
||||
} else if (stat.isFile() && (!spec || files[i].match(spec))) {
|
||||
paths.push(folder + "/" + files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
return filesInFolder(path, 0);
|
||||
},
|
||||
createDirectory: function (path) {
|
||||
try {
|
||||
if (!this.directoryExists(path)) {
|
||||
_fs.mkdirSync(path);
|
||||
}
|
||||
} catch (e) {
|
||||
IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e);
|
||||
}
|
||||
},
|
||||
directoryExists: function (path) {
|
||||
return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory();
|
||||
},
|
||||
resolvePath: function (path) {
|
||||
return _path.resolve(path);
|
||||
},
|
||||
dirName: function (path) {
|
||||
return _path.dirname(path);
|
||||
},
|
||||
findFile: function (rootPath, partialFilePath) {
|
||||
var path = rootPath + "/" + partialFilePath;
|
||||
|
||||
while (true) {
|
||||
if (_fs.existsSync(path)) {
|
||||
try {
|
||||
var content = this.readFile(path);
|
||||
return { content: content, path: path };
|
||||
} catch (err) {
|
||||
//Tools.CompilerDiagnostics.debugPrint(("Could not find " + path) + ", trying parent");
|
||||
}
|
||||
} else {
|
||||
var parentPath = _path.resolve(rootPath, "..");
|
||||
|
||||
if (rootPath === parentPath) {
|
||||
return null;
|
||||
} else {
|
||||
rootPath = parentPath;
|
||||
path = _path.resolve(rootPath, partialFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
print: function (str) {
|
||||
process.stdout.write(str);
|
||||
},
|
||||
printLine: function (str) {
|
||||
process.stdout.write(str + '\n');
|
||||
},
|
||||
arguments: process.argv.slice(2),
|
||||
stderr: {
|
||||
Write: function (str) {
|
||||
process.stderr.write(str);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
process.stderr.write(str + '\n');
|
||||
},
|
||||
Close: function () {
|
||||
}
|
||||
},
|
||||
stdout: {
|
||||
Write: function (str) {
|
||||
process.stdout.write(str);
|
||||
},
|
||||
WriteLine: function (str) {
|
||||
process.stdout.write(str + '\n');
|
||||
},
|
||||
Close: function () {
|
||||
}
|
||||
},
|
||||
watchFile: function (filename, callback) {
|
||||
var firstRun = true;
|
||||
var processingChange = false;
|
||||
|
||||
var fileChanged = function (curr, prev) {
|
||||
if (!firstRun) {
|
||||
if (curr.mtime < prev.mtime) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fs.unwatchFile(filename, fileChanged);
|
||||
if (!processingChange) {
|
||||
processingChange = true;
|
||||
callback(filename);
|
||||
setTimeout(function () {
|
||||
processingChange = false;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
firstRun = false;
|
||||
_fs.watchFile(filename, { persistent: true, interval: 500 }, fileChanged);
|
||||
};
|
||||
|
||||
fileChanged();
|
||||
return {
|
||||
filename: filename,
|
||||
close: function () {
|
||||
_fs.unwatchFile(filename, fileChanged);
|
||||
}
|
||||
};
|
||||
},
|
||||
run: function (source, filename) {
|
||||
require.main.filename = filename;
|
||||
require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename)));
|
||||
require.main._compile(source, filename);
|
||||
},
|
||||
getExecutingFilePath: function () {
|
||||
return process.mainModule.filename;
|
||||
},
|
||||
quit: process.exit
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
if (typeof ActiveXObject === "function")
|
||||
return getWindowsScriptHostIO();
|
||||
else if (typeof require === "function")
|
||||
return getNodeIO();
|
||||
else
|
||||
return null;
|
||||
})();
|
||||
@@ -0,0 +1,111 @@
|
||||
/// <reference path='../../../node/node.d.ts' />
|
||||
/// <reference path='../runner.ts' />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// All the common things that we pring are functions of this class
|
||||
/////////////////////////////////
|
||||
export class Print {
|
||||
|
||||
WIDTH = 77;
|
||||
|
||||
constructor(public version: string, public typings: number, public tests: number, public tsFiles: number) {
|
||||
}
|
||||
|
||||
public out(s: any): Print {
|
||||
process.stdout.write(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
public repeat(s: string, times: number): string {
|
||||
return new Array(times + 1).join(s);
|
||||
}
|
||||
|
||||
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 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 printDiv() {
|
||||
this.out('-----------------------------------------------------------------------------\n');
|
||||
}
|
||||
|
||||
public printBoldDiv() {
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
|
||||
public printErrorsHeader() {
|
||||
this.out('=============================================================================\n');
|
||||
this.out(' \33[34m\33[1mErrors in files\33[0m \n');
|
||||
this.out('=============================================================================\n');
|
||||
}
|
||||
|
||||
public printErrorsForFile(testResult: TestResult) {
|
||||
this.out('----------------- For file:' + testResult.targetFile.formatName);
|
||||
this.printBreak().out(testResult.stderr).printBreak();
|
||||
}
|
||||
|
||||
public printBreak(): Print {
|
||||
this.out('\n');
|
||||
return this;
|
||||
}
|
||||
|
||||
public clearCurrentLine(): Print {
|
||||
this.out("\r\33[K");
|
||||
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 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 printTypingsWithoutTestsMessage() {
|
||||
this.out(' \33[36m\33[1mTyping without tests\33[0m\n');
|
||||
}
|
||||
|
||||
public printTotalMessage() {
|
||||
this.out(' \33[36m\33[1mTotal\33[0m\n');
|
||||
}
|
||||
|
||||
public printElapsedTime(time: string, s: number) {
|
||||
this.out(' \33[36m\33[1mElapsed time :\33[0m ~' + time + ' (' + s + 's)\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 printTypingsWithoutTestName(file: string) {
|
||||
this.out(' - \33[33m\33[1m' + file + '\33[0m\n');
|
||||
}
|
||||
|
||||
public printTypingsWithoutTest(withoutTestTypings: string[]) {
|
||||
if (withoutTestTypings.length > 0) {
|
||||
this.printTypingsWithoutTestsMessage();
|
||||
|
||||
this.printDiv();
|
||||
withoutTestTypings.forEach((t) => {
|
||||
this.printTypingsWithoutTestName(t);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// Test reporter interface
|
||||
// for example, . and x
|
||||
/////////////////////////////////
|
||||
export interface ITestReporter {
|
||||
printPositiveCharacter(index: number, testResult: TestResult):void;
|
||||
printNegativeCharacter(index: number, testResult: TestResult):void;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Default test reporter
|
||||
/////////////////////////////////
|
||||
export class DefaultTestReporter implements ITestReporter {
|
||||
constructor(public print: Print) {
|
||||
}
|
||||
|
||||
public printPositiveCharacter(index: number, testResult: TestResult) {
|
||||
this.print.out('\33[36m\33[1m' + '.' + '\33[0m');
|
||||
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
|
||||
public printNegativeCharacter(index: number, testResult: TestResult) {
|
||||
this.print.out("x");
|
||||
|
||||
this.printBreakIfNeeded(index);
|
||||
}
|
||||
|
||||
private printBreakIfNeeded(index: number) {
|
||||
if (index % this.print.WIDTH === 0) {
|
||||
this.print.printBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/// <reference path="../../runner.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// The interface for test suite
|
||||
/////////////////////////////////
|
||||
export interface ITestSuite {
|
||||
testSuiteName:string;
|
||||
errorHeadline:string;
|
||||
filterTargetFiles(files: File[]):File[];
|
||||
|
||||
start(targetFiles: File[], testCallback: (result: TestResult, index: number) => void, suiteCallback: (suite: ITestSuite) => void):void;
|
||||
|
||||
testResults:TestResult[];
|
||||
okTests:TestResult[];
|
||||
ngTests:TestResult[];
|
||||
timer:Timer;
|
||||
|
||||
testReporter:ITestReporter;
|
||||
printErrorCount:boolean;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Base class for test suite
|
||||
/////////////////////////////////
|
||||
export class TestSuiteBase implements ITestSuite {
|
||||
timer: Timer = new Timer();
|
||||
testResults: TestResult[] = [];
|
||||
testReporter: ITestReporter;
|
||||
printErrorCount = true;
|
||||
|
||||
constructor(public options: ITestRunnerOptions, public testSuiteName: string, public errorHeadline: string) {
|
||||
}
|
||||
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
throw new Error("please implement this method");
|
||||
}
|
||||
|
||||
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 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 finish(suiteCallback: (suite: ITestSuite) => void) {
|
||||
suiteCallback(this);
|
||||
}
|
||||
|
||||
public get okTests(): TestResult[] {
|
||||
return this.testResults.filter((r) => {
|
||||
return r.success;
|
||||
});
|
||||
}
|
||||
|
||||
public get ngTests(): TestResult[] {
|
||||
return this.testResults.filter((r) => {
|
||||
return !r.success
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path="../../runner.ts" />
|
||||
/// <reference path="../util.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// .d.ts syntax inspection
|
||||
/////////////////////////////////
|
||||
export class SyntaxChecking extends TestSuiteBase {
|
||||
|
||||
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');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path="../../runner.ts" />
|
||||
/// <reference path="../util.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// Compile with *-tests.ts
|
||||
/////////////////////////////////
|
||||
export class TestEval extends TestSuiteBase {
|
||||
|
||||
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')
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/// <reference path="../../runner.ts" />
|
||||
/// <reference path="../file.ts" />
|
||||
|
||||
module DT {
|
||||
/////////////////////////////////
|
||||
// Try compile without .tscparams
|
||||
// It may indicate that it is compatible with --noImplicitAny maybe...
|
||||
/////////////////////////////////
|
||||
export class FindNotRequiredTscparams extends TestSuiteBase {
|
||||
testReporter: ITestReporter;
|
||||
printErrorCount = false;
|
||||
|
||||
constructor(options: ITestRunnerOptions, private print: Print) {
|
||||
super(options, "Find not required .tscparams files", "New arrival!");
|
||||
|
||||
this.testReporter = {
|
||||
printPositiveCharacter: (index: number, testResult: TestResult) => {
|
||||
this.print
|
||||
.clearCurrentLine()
|
||||
.printTypingsWithoutTestName(testResult.targetFile.formatName);
|
||||
},
|
||||
printNegativeCharacter: (index: number, testResult: TestResult) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public filterTargetFiles(files: File[]): File[] {
|
||||
return files.filter(file=> IO.fileExists(file.filePathWithName + '.tscparams'));
|
||||
}
|
||||
|
||||
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 finish(suiteCallback: (suite: ITestSuite)=>void) {
|
||||
this.print.clearCurrentLine();
|
||||
suiteCallback(this);
|
||||
}
|
||||
|
||||
public get ngTests(): TestResult[] {
|
||||
// Do not show ng test results
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/// <reference path='../../../node/node.d.ts' />
|
||||
/// <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;
|
||||
|
||||
public start() {
|
||||
this.time = 0;
|
||||
this.startTime = this.now();
|
||||
}
|
||||
|
||||
public now(): number {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
public end() {
|
||||
this.time = (this.now() - this.startTime) / 1000;
|
||||
this.asString = Timer.prettyDate(this.startTime, this.now());
|
||||
}
|
||||
|
||||
public static prettyDate(date1: number, date2: number): string {
|
||||
var diff = ((date2 - date1) / 1000),
|
||||
day_diff = Math.floor(diff / 86400);
|
||||
|
||||
if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
|
||||
return;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/// <reference path='../../../node/node.d.ts' />
|
||||
/// <reference path='../runner.ts' />
|
||||
|
||||
/// <reference path='host/exec.ts' />
|
||||
|
||||
module DT {
|
||||
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;
|
||||
}
|
||||
|
||||
if (!IO.fileExists(tsfile)) {
|
||||
throw new Error(tsfile + " not exists");
|
||||
}
|
||||
|
||||
var tscPath = './_infrastructure/tests/typescript/' + options.tscVersion + '/tsc.js';
|
||||
if (!IO.fileExists(tscPath)) {
|
||||
throw new Error(tscPath + ' is not exists');
|
||||
}
|
||||
var command = 'node ' + tscPath + ' --module commonjs ';
|
||||
if (options.useTscParams && IO.fileExists(tsfile + '.tscparams')) {
|
||||
command += '@' + tsfile + '.tscparams';
|
||||
} else if (options.checkNoImplicitAny) {
|
||||
command += '--noImplicitAny';
|
||||
}
|
||||
Exec.exec(command, [tsfile], (execResult) => {
|
||||
callback(execResult);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module DT {
|
||||
export function endsWith(str: string, suffix: string) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user