From bd99c6c5c78d1594ce83e31fdbb3176f49f78821 Mon Sep 17 00:00:00 2001 From: Christoph Schlosser Date: Wed, 21 Feb 2018 00:11:34 +0100 Subject: Replace some JS stuff with TS and some cleaning up --- src/test/index.ts | 91 +++++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/test/index.ts b/src/test/index.ts index b3d719f..5dfa541 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -4,14 +4,15 @@ import * as fs from "fs"; import * as glob from "glob"; import * as paths from "path"; -// tslint:disable:no-var-requires -const istanbul = require("istanbul"); +import istanbul = require("istanbul"); +import remapIstanbul = require("remap-istanbul"); +// tslint:disable-next-line:no-var-requires +const tty = require("tty"); +// tslint:disable-next-line:no-var-requires const Mocha = require("mocha"); -const remapIstanbul = require("remap-istanbul"); // Linux: prevent a weird NPE when mocha on Linux requires the window size from the TTY // Since we are not running in a tty environment, we just implementt he method statically -const tty = require("tty"); if (!tty.getWindowSize) { tty.getWindowSize = (): number[] => { return [80, 75]; @@ -35,11 +36,10 @@ function _mkDirIfExists(dir: string): void { } function _readCoverOptions(testsRoot: string): ITestRunnerOptions { - // tslint:disable:prefer-const - let coverConfigPath = paths.join(testsRoot, "..", "..", "coverconfig.json"); + const coverConfigPath = paths.join(testsRoot, "..", "..", "coverconfig.json"); let coverConfig: ITestRunnerOptions; if (fs.existsSync(coverConfigPath)) { - let configContent = fs.readFileSync(coverConfigPath, "utf-8"); + const configContent = fs.readFileSync(coverConfigPath, "utf-8"); coverConfig = JSON.parse(configContent); } return coverConfig; @@ -50,10 +50,10 @@ function run(testsRoot, clb): any { require("source-map-support").install(); // Read configuration for the coverage file - let coverOptions: ITestRunnerOptions = _readCoverOptions(testsRoot); + const coverOptions: ITestRunnerOptions = _readCoverOptions(testsRoot); if (coverOptions && coverOptions.enabled) { // Setup coverage pre-test, including post-test hook to report - let coverageRunner = new CoverageRunner(coverOptions, testsRoot, clb); + const coverageRunner = new CoverageRunner(coverOptions, testsRoot, clb); coverageRunner.setupCoverage(); } @@ -110,21 +110,20 @@ class CoverageRunner { public setupCoverage(): void { // Set up Code Coverage, hooking require so that instrumented code is returned - let self = this; - self.instrumenter = new istanbul.Instrumenter({ coverageVariable: self.coverageVar }); - let sourceRoot = paths.join(self.testsRoot, self.options.relativeSourcePath); + this.instrumenter = new istanbul.Instrumenter({ coverageVariable: this.coverageVar }); + const sourceRoot = paths.join(this.testsRoot, this.options.relativeSourcePath); // Glob source files - let srcFiles = glob.sync("**/**.js", { + const srcFiles = glob.sync("**/**.js", { cwd: sourceRoot, - ignore: self.options.ignorePatterns, + ignore: this.options.ignorePatterns, }); // Create a match function - taken from the run-with-cover.js in istanbul. - let decache = require("decache"); - let fileMap = {}; + const decache = require("decache"); + const fileMap = {}; srcFiles.forEach( (file) => { - let fullPath = paths.join(sourceRoot, file); + const fullPath = paths.join(sourceRoot, file); fileMap[fullPath] = true; // On Windows, extension is loaded pre-test hooks and this mean we lose @@ -136,83 +135,83 @@ class CoverageRunner { decache(fullPath); }); - self.matchFn = (file): boolean => fileMap[file]; - self.matchFn.files = Object.keys(fileMap); + this.matchFn = (file): boolean => fileMap[file]; + this.matchFn.files = Object.keys(fileMap); // Hook up to the Require function so that when this is called, if any of our source files // are required, the instrumented version is pulled in instead. These instrumented versions // write to a global coverage variable with hit counts whenever they are accessed - self.transformer = self.instrumenter.instrumentSync.bind(self.instrumenter); - let hookOpts = { verbose: false, extensions: [".js"]}; - istanbul.hook.hookRequire(self.matchFn, self.transformer, hookOpts); + this.transformer = this.instrumenter.instrumentSync.bind(this.instrumenter); + const hookOpts = { verbose: false, extensions: [".js"]}; + istanbul.hook.hookRequire(this.matchFn, this.transformer, hookOpts); // initialize the global variable to stop mocha from complaining about leaks - global[self.coverageVar] = {}; + global[this.coverageVar] = {}; // Hook the process exit event to handle reporting // Only report coverage if the process is exiting successfully process.on("exit", (code) => { - self.reportCoverage(); + this.reportCoverage(); }); } - // tslint:disable:max-line-length /** - * Writes a coverage report. Note that as this is called in the process exit callback, all calls must be synchronous. + * Writes a coverage report. + * Note that as this is called in the process exit callback, all calls must be synchronous. * * @returns {void} * * @memberOf CoverageRunner */ public reportCoverage(): void { - let self = this; istanbul.hook.unhookRequire(); let cov: any; - if (typeof global[self.coverageVar] === "undefined" || Object.keys(global[self.coverageVar]).length === 0) { + if (typeof global[this.coverageVar] === "undefined" || Object.keys(global[this.coverageVar]).length === 0) { // tslint:disable:no-console console.error("No coverage information was collected, exit without writing coverage information"); return; } else { - cov = global[self.coverageVar]; + cov = global[this.coverageVar]; } // TODO consider putting this under a conditional flag // Files that are not touched by code ran by the test runner is manually instrumented, to // illustrate the missing coverage. - self.matchFn.files.forEach( (file) => { + this.matchFn.files.forEach( (file) => { if (!cov[file]) { - self.transformer(fs.readFileSync(file, "utf-8"), file); + this.transformer(fs.readFileSync(file, "utf-8"), file); - // When instrumenting the code, istanbul will give each FunctionDeclaration a value of 1 in coverState.s, - // presumably to compensate for function hoisting. We need to reset this, as the function was not hoisted, - // as it was never loaded. - Object.keys(self.instrumenter.coverState.s).forEach( (key) => { - self.instrumenter.coverState.s[key] = 0; + // When instrumenting the code, istanbul will give each FunctionDeclaration a value of 1 in + // coverState.s, presumably to compensate for function hoisting. We need to reset this, as the function + // was not hoisted, as it was never loaded. + Object.keys(this.instrumenter.coverState.s).forEach( (key) => { + this.instrumenter.coverState.s[key] = 0; }); - cov[file] = self.instrumenter.coverState; + cov[file] = this.instrumenter.coverState; } }); // TODO Allow config of reporting directory with - let reportingDir = paths.join(self.testsRoot, self.options.relativeCoverageDir); - let includePid = self.options.includePid; - let pidExt = includePid ? ("-" + process.pid) : ""; - let coverageFile = paths.resolve(reportingDir, "coverage" + pidExt + ".json"); + const reportingDir = paths.join(this.testsRoot, this.options.relativeCoverageDir); + const includePid = this.options.includePid; + const pidExt = includePid ? ("-" + process.pid) : ""; + const coverageFile = paths.resolve(reportingDir, "coverage" + pidExt + ".json"); - _mkDirIfExists(reportingDir); // yes, do this again since some test runners could clean the dir initially created + // yes, do this again since some test runners could clean the dir initially created + _mkDirIfExists(reportingDir); fs.writeFileSync(coverageFile, JSON.stringify(cov), "utf8"); - let remappedCollector = remapIstanbul.remap(cov, {warn: (warning) => { + const remappedCollector = remapIstanbul.remap(cov, {warn: (warning) => { // We expect some warnings as any JS file without a typescript mapping will cause this. // By default, we"ll skip printing these to the console as it clutters it up - if (self.options.verbose) { + if (this.options.verbose) { console.warn(warning); } }}); - let reporter = new istanbul.Reporter(undefined, reportingDir); - let reportTypes = (self.options.reports instanceof Array) ? self.options.reports : ["lcov"]; + const reporter = new istanbul.Reporter(undefined, reportingDir); + const reportTypes = (this.options.reports instanceof Array) ? this.options.reports : ["lcov"]; reporter.addAll(reportTypes); reporter.write(remappedCollector, true, () => { console.log(`reports written to ${reportingDir}`); -- cgit v1.2.3