diff --git a/_infrastructure/tests/runner.js b/_infrastructure/tests/runner.js index ee80513a2..1a7c4fc98 100644 --- a/_infrastructure/tests/runner.js +++ b/_infrastructure/tests/runner.js @@ -47,6 +47,8 @@ var Exec = function () { /// 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; /// var DT; (function (DT) { + 'use-strict'; var fs = require('fs'); var Tsc = (function () { @@ -132,6 +122,8 @@ var DT; /// 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; /// var DT; (function (DT) { + 'use-strict'; + var referenceTagExp = //g; function endsWith(str, suffix) { @@ -201,6 +195,8 @@ var DT; /// 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; /// 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; /// var DT; (function (DT) { + 'use-strict'; + ///////////////////////////////// // All the common things that we pring are functions of this class ///////////////////////////////// @@ -430,6 +443,8 @@ var DT; /// var DT; (function (DT) { + 'use-strict'; + ///////////////////////////////// @@ -463,6 +478,8 @@ var DT; /// 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; /// var DT; (function (DT) { + 'use-strict'; + ///////////////////////////////// // Compile with *-tests.ts ///////////////////////////////// @@ -591,6 +612,8 @@ var DT; /// var DT; (function (DT) { + 'use-strict'; + var fs = require('fs'); ///////////////////////////////// @@ -665,6 +688,8 @@ var DT; /// 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) { diff --git a/_infrastructure/tests/runner.ts b/_infrastructure/tests/runner.ts index 555ec54ab..f2ca6a059 100644 --- a/_infrastructure/tests/runner.ts +++ b/_infrastructure/tests/runner.ts @@ -19,291 +19,352 @@ /// 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(); } diff --git a/_infrastructure/tests/src/changes.ts b/_infrastructure/tests/src/changes.ts index 5f28f24c5..3bc7334e0 100644 --- a/_infrastructure/tests/src/changes.ts +++ b/_infrastructure/tests/src/changes.ts @@ -1,37 +1,39 @@ /// 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); + }); + } + } } diff --git a/_infrastructure/tests/src/file.ts b/_infrastructure/tests/src/file.ts index bd7f62dc8..4bb81e985 100644 --- a/_infrastructure/tests/src/file.ts +++ b/_infrastructure/tests/src/file.ts @@ -1,35 +1,39 @@ /// 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 + ']'; + } + } } diff --git a/_infrastructure/tests/src/host/exec.ts b/_infrastructure/tests/src/host/exec.ts index 9ff896c3f..07a9d6662 100644 --- a/_infrastructure/tests/src/host/exec.ts +++ b/_infrastructure/tests/src/host/exec.ts @@ -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(); }(); diff --git a/_infrastructure/tests/src/index.ts b/_infrastructure/tests/src/index.ts index 4a40f35d4..7c9561af9 100644 --- a/_infrastructure/tests/src/index.ts +++ b/_infrastructure/tests/src/index.ts @@ -3,77 +3,91 @@ /// 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); + }); + } + } } diff --git a/_infrastructure/tests/src/printer.ts b/_infrastructure/tests/src/printer.ts index 53274587a..585ca5aa3 100644 --- a/_infrastructure/tests/src/printer.ts +++ b/_infrastructure/tests/src/printer.ts @@ -2,110 +2,112 @@ /// 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); + }); + } + } + } } diff --git a/_infrastructure/tests/src/reporter/reporter.ts b/_infrastructure/tests/src/reporter/reporter.ts index 5f01c43ab..edab8a6a0 100644 --- a/_infrastructure/tests/src/reporter/reporter.ts +++ b/_infrastructure/tests/src/reporter/reporter.ts @@ -2,38 +2,40 @@ /// 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(); + } + } + } } diff --git a/_infrastructure/tests/src/suite/suite.ts b/_infrastructure/tests/src/suite/suite.ts index 32013cce2..33d69af06 100644 --- a/_infrastructure/tests/src/suite/suite.ts +++ b/_infrastructure/tests/src/suite/suite.ts @@ -1,83 +1,86 @@ /// 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 + }); + } + } } diff --git a/_infrastructure/tests/src/suite/syntax.ts b/_infrastructure/tests/src/suite/syntax.ts index f36c26d99..ff4b3bdb4 100644 --- a/_infrastructure/tests/src/suite/syntax.ts +++ b/_infrastructure/tests/src/suite/syntax.ts @@ -2,19 +2,21 @@ /// 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'); + }); + } + } } diff --git a/_infrastructure/tests/src/suite/testEval.ts b/_infrastructure/tests/src/suite/testEval.ts index 860e17943..13a659887 100644 --- a/_infrastructure/tests/src/suite/testEval.ts +++ b/_infrastructure/tests/src/suite/testEval.ts @@ -2,20 +2,21 @@ /// 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') + }); + } + } } diff --git a/_infrastructure/tests/src/suite/tscParams.ts b/_infrastructure/tests/src/suite/tscParams.ts index 510e15ce7..e4bb4f4c1 100644 --- a/_infrastructure/tests/src/suite/tscParams.ts +++ b/_infrastructure/tests/src/suite/tscParams.ts @@ -2,56 +2,58 @@ /// 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 []; + } + } } diff --git a/_infrastructure/tests/src/timer.ts b/_infrastructure/tests/src/timer.ts index 446ea1b34..1bf965a82 100644 --- a/_infrastructure/tests/src/timer.ts +++ b/_infrastructure/tests/src/timer.ts @@ -2,46 +2,48 @@ /// 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 ( (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 ( (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")); + } + } } diff --git a/_infrastructure/tests/src/tsc.ts b/_infrastructure/tests/src/tsc.ts index 6bd3fb259..845b8557f 100644 --- a/_infrastructure/tests/src/tsc.ts +++ b/_infrastructure/tests/src/tsc.ts @@ -3,42 +3,44 @@ /// 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); + }); + } + } } diff --git a/_infrastructure/tests/src/util.ts b/_infrastructure/tests/src/util.ts index 3d63ce142..39115b1eb 100644 --- a/_infrastructure/tests/src/util.ts +++ b/_infrastructure/tests/src/util.ts @@ -1,27 +1,28 @@ /// module DT { + 'use-strict'; - var referenceTagExp = //g; + var referenceTagExp = //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; + } }