diff --git a/Gulpfile.js b/Gulpfile.js index 3ce488caed..f3f1d7ae7a 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -12,10 +12,9 @@ const merge2 = require("merge2"); const mkdirp = require("mkdirp"); const { src, dest, task, parallel, series, watch } = require("gulp"); const { append, transform } = require("gulp-insert"); -const { browserify } = require("./scripts/build/browserify"); const { prependFile } = require("./scripts/build/prepend"); const { exec, readJson, needsUpdate, getDiffTool, getDirSize, flatten, rm } = require("./scripts/build/utils"); -const { runConsoleTests, cleanTestDirs, writeTestConfigFile, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests"); +const { runConsoleTests, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests"); const { buildProject, cleanProject, watchProject } = require("./scripts/build/projects"); const cmdLineOptions = require("./scripts/build/options"); @@ -454,44 +453,6 @@ task("runtests-parallel").flags = { " --built": "Compile using the built version of the compiler.", }; -const buildWebTestServer = () => buildProject("tests/webTestServer.tsconfig.json"); -const cleanWebTestServer = () => cleanProject("tests/webTestServer.tsconfig.json"); -cleanTasks.push(cleanWebTestServer); - -const browserifyTests = () => src(["built/local/run.js"], { base: "built/local" }) - .pipe(newer("built/local/bundle.js")) - .pipe(sourcemaps.init({ loadMaps: true })) - .pipe(browserify()) - .pipe(rename("bundle.js")) - .pipe(sourcemaps.write(".", /**@type {*}*/({ includeContent: false, destPath: "built/local" }))) - .pipe(dest("built/local")); - -const runtestsBrowser = async () => { - await cleanTestDirs(); - const { tests, runners, light } = cmdLineOptions; - const testConfigFile = "test.config"; - await del([testConfigFile]); - if (tests || runners || light) { - writeTestConfigFile(tests, runners, light); - } - const args = ["tests/webTestServer.js"]; - if (cmdLineOptions.browser) { - args.push(cmdLineOptions.browser); - } - if (tests) { - args.push(JSON.stringify(tests)); - } - await exec(process.execPath, args); -}; - -task("runtests-browser", series(preBuild, parallel(buildTests, buildServices, buildLssl, buildWebTestServer), browserifyTests, runtestsBrowser)); -task("runtests-browser").description = "Runs the tests using the built run.js file like 'gulp runtests'."; -task("runtests-browser").flags = { - "-t --tests=": "pattern for tests to run", - "-b --browser=": "Either 'IE' or 'chrome'", - " --built": "Compile using the built version of the compiler.", -}; - task("diff", () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true })); task("diff").description = "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable"; @@ -525,16 +486,6 @@ cleanTasks.push(cleanWebHost); task("clean-webhost", cleanWebHost); task("clean-webhost").description = "Cleans the outputs of the tsc web host"; -// TODO(rbuckton): Determine if 'perftsc' is still in use. -const buildPerfTsc = () => buildProject("tests/perftsc.tsconfig.json"); -task("perftsc", series(lkgPreBuild, buildPerfTsc)); -task("perftsc").description = "Builds augmented version of the compiler for perf tests"; - -const cleanPerfTsc = () => cleanProject("tests/perftsc.tsconfig.json"); -cleanTasks.push(cleanPerfTsc); -task("clean-perftsc", cleanPerfTsc); -task("clean-perftsc").description = "Cleans the outputs of the perftsc project"; - const buildLoggedIO = async () => { mkdirp.sync("built/local/temp"); await exec(process.execPath, ["lib/tsc", "--types", "--target", "es5", "--lib", "es5", "--outdir", "built/local/temp", "src/harness/loggedIO.ts"]); diff --git a/scripts/browserify-optional.js b/scripts/browserify-optional.js deleted file mode 100644 index 43997c7803..0000000000 --- a/scripts/browserify-optional.js +++ /dev/null @@ -1,24 +0,0 @@ -// simple script to optionally elide source-map-support (or other optional modules) when running browserify. - -var stream = require("stream"), - Transform = stream.Transform, - resolve = require("browser-resolve"); - -var requirePattern = /require\s*\(\s*['"](source-map-support)['"]\s*\)/; -module.exports = function (file) { - return new Transform({ - transform: function (data, encoding, cb) { - var text = encoding === "buffer" ? data.toString("utf8") : data; - this.push(new Buffer(text.replace(requirePattern, function (originalText, moduleName) { - try { - resolve.sync(moduleName, { filename: file }); - return originalText; - } - catch (e) { - return "(function () { throw new Error(\"module '" + moduleName + "' not found.\"); })()"; - } - }), "utf8")); - cb(); - } - }); -}; \ No newline at end of file diff --git a/scripts/build/browserify.js b/scripts/build/browserify.js deleted file mode 100644 index ba8ccd1582..0000000000 --- a/scripts/build/browserify.js +++ /dev/null @@ -1,33 +0,0 @@ -// @ts-check -const browserify = require("browserify"); -const Vinyl = require("vinyl"); -const { Transform } = require("stream"); -const { streamFromFile } = require("./utils"); -const { replaceContents } = require("./sourcemaps"); - -/** - * @param {import("browserify").Options} [opts] - */ -function browserifyFile(opts) { - return new Transform({ - objectMode: true, - /** - * @param {string | Buffer | Vinyl} input - */ - transform(input, _, cb) { - if (typeof input === "string" || Buffer.isBuffer(input)) return cb(new Error("Only Vinyl files are supported.")); - try { - browserify(Object.assign({}, opts, { debug: !!input.sourceMap, basedir: input.base })) - .add(streamFromFile(input), { file: input.path, basedir: input.base }) - .bundle((err, contents) => { - if (err) return cb(err); - cb(null, replaceContents(input, contents)); - }); - } - catch (e) { - cb(e); - } - } - }); -} -exports.browserify = browserifyFile; \ No newline at end of file diff --git a/scripts/build/sourcemaps.js b/scripts/build/sourcemaps.js index 2c85b897b0..24c13b941c 100644 --- a/scripts/build/sourcemaps.js +++ b/scripts/build/sourcemaps.js @@ -1,102 +1,4 @@ // @ts-check -/// - -const path = require("path"); -const convertMap = require("convert-source-map"); -const applySourceMap = require("vinyl-sourcemaps-apply"); -const through2 = require("through2"); - -/** - * @param {import("vinyl")} input - * @param {string | Buffer} contents - * @param {string | RawSourceMap} [sourceMap] - */ -function replaceContents(input, contents, sourceMap) { - const output = input.clone(); - output.contents = typeof contents === "string" ? Buffer.from(contents, "utf8") : contents; - if (input.sourceMap) { - output.sourceMap = typeof input.sourceMap === "string" ? /**@type {RawSourceMap}*/(JSON.parse(input.sourceMap)) : input.sourceMap; - if (typeof sourceMap === "string") { - sourceMap = /** @type {RawSourceMap} */(JSON.parse(sourceMap)); - } - else if (sourceMap === undefined) { - const stringContents = typeof contents === "string" ? contents : contents.toString("utf8"); - const newSourceMapConverter = convertMap.fromSource(stringContents); - if (newSourceMapConverter) { - sourceMap = /** @type {RawSourceMap} */(newSourceMapConverter.toObject()); - output.contents = new Buffer(convertMap.removeMapFileComments(stringContents), "utf8"); - } - } - if (sourceMap) { - const cwd = input.cwd || process.cwd(); - const base = input.base || cwd; - const sourceRoot = output.sourceMap.sourceRoot; - makeAbsoluteSourceMap(cwd, base, output.sourceMap); - makeAbsoluteSourceMap(cwd, base, /** @type {RawSourceMap} */(sourceMap)); - applySourceMap(output, sourceMap); - makeRelativeSourceMap(cwd, base, sourceRoot, output.sourceMap); - } - else { - output.sourceMap = undefined; - } - } - return output; -} -exports.replaceContents = replaceContents; - -function removeSourceMaps() { - return through2.obj((/**@type {import("vinyl")}*/file, _, cb) => { - if (file.isBuffer()) { - file.contents = Buffer.from(convertMap.removeMapFileComments(file.contents.toString("utf8")), "utf8"); - if (file.sourceMap) { - file.sourceMap = undefined; - } - } - cb(null, file); - }); -} -exports.removeSourceMaps = removeSourceMaps; - -/** - * @param {string | undefined} cwd - * @param {string | undefined} base - * @param {RawSourceMap} sourceMap - * - * @typedef {object} RawSourceMap - * @property {string} version - * @property {string} file - * @property {string} [sourceRoot] - * @property {string[]} sources - * @property {string[]} [sourcesContent] - * @property {string} mappings - * @property {string[]} [names] - */ -function makeAbsoluteSourceMap(cwd = process.cwd(), base = "", sourceMap) { - const sourceRoot = sourceMap.sourceRoot || ""; - const resolvedBase = path.resolve(cwd, base); - const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot); - sourceMap.file = path.resolve(resolvedBase, sourceMap.file).replace(/\\/g, "/"); - sourceMap.sources = sourceMap.sources.map(source => path.resolve(resolvedSourceRoot, source).replace(/\\/g, "/")); - sourceMap.sourceRoot = ""; -} -exports.makeAbsoluteSourceMap = makeAbsoluteSourceMap; - -/** - * @param {string | undefined} cwd - * @param {string | undefined} base - * @param {string} sourceRoot - * @param {RawSourceMap} sourceMap - */ -function makeRelativeSourceMap(cwd = process.cwd(), base = "", sourceRoot, sourceMap) { - makeAbsoluteSourceMap(cwd, base, sourceMap); - const resolvedBase = path.resolve(cwd, base); - const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot); - sourceMap.file = path.relative(resolvedBase, sourceMap.file).replace(/\\/g, "/"); - sourceMap.sources = sourceMap.sources.map(source => path.relative(resolvedSourceRoot, source).replace(/\\/g, "/")); - sourceMap.sourceRoot = sourceRoot; -} -exports.makeRelativeSourceMap = makeRelativeSourceMap; - /** * @param {string} message * @returns {never} diff --git a/scripts/createBenchmark.ts b/scripts/createBenchmark.ts deleted file mode 100644 index 254c0d99af..0000000000 --- a/scripts/createBenchmark.ts +++ /dev/null @@ -1,124 +0,0 @@ -/// -/// - -import * as fs from "fs"; -import * as path from "path"; -import * as typescript from "typescript"; -declare var ts: typeof typescript; - -var tsSourceDir = "../src"; -var tsBuildDir = "../built/local"; -var testOutputDir = "../built/benchmark"; -var sourceFiles = [ - "compiler/types.ts", - "compiler/core.ts", - "compiler/sys.ts", - "compiler/diagnosticInformationMap.generated.ts", - "compiler/scanner.ts", - "compiler/binder.ts", - "compiler/utilities.ts", - "compiler/parser.ts", - "compiler/checker.ts", - "compiler/declarationEmitter.ts", - "compiler/emitter.ts", - "compiler/program.ts", - "compiler/commandLineParser.ts", - "compiler/tsc.ts"]; - -// .ts sources for the compiler, used as a test input -var rawCompilerSources = ""; -sourceFiles.forEach(f=> { - rawCompilerSources += "\r\n" + fs.readFileSync(path.join(tsSourceDir, f)).toString(); -}); -var compilerSources = `var compilerSources = ${JSON.stringify(rawCompilerSources) };`; - -// .js code for the compiler, what we are actually testing -var rawCompilerJavaScript = fs.readFileSync(path.join(tsBuildDir, "tsc.js")).toString(); -rawCompilerJavaScript = rawCompilerJavaScript.replace("ts.executeCommandLine(ts.sys.args);", ""); - -// lib.d.ts sources -var rawLibSources = fs.readFileSync(path.join(tsBuildDir, "lib.d.ts")).toString(); -var libSources = `var libSources = ${JSON.stringify(rawLibSources) };`; - -// write test output -if (!fs.existsSync(testOutputDir)) { - fs.mkdirSync(testOutputDir); -} - -// 1. compiler ts sources, used to test -fs.writeFileSync( - path.join(testOutputDir, "compilerSources.js"), - `${ compilerSources } \r\n ${ libSources }`); - -// 2. the compiler js sources + a call the compiler -fs.writeFileSync( - path.join(testOutputDir, "benchmarktsc.js"), - `${ rawCompilerJavaScript }\r\n${ compile.toString() }\r\ncompile(compilerSources, libSources);`); - -// 3. test html file to drive the test -fs.writeFileSync( - path.join(testOutputDir, "benchmarktsc.html"), - ` - - - - Typescript 1.1 Compiler - - - -
Status: Running
-
End-to-End Time: N/A
- - - - - -`); - -function compile(compilerSources, librarySources) { - var program = ts.createProgram( - ["lib.d.ts", "compiler.ts"], - { - noResolve: true, - out: "compiler.js", - removeComments: true, - target: ts.ScriptTarget.ES3 - }, { - getDefaultLibFileName: () => "lib.d.ts", - getSourceFile: (filename, languageVersion) => { - var source: string; - if (filename === "lib.d.ts") source = librarySources; - else if (filename === "compiler.ts") source = compilerSources; - else console.error("Unexpected read file request: " + filename); - - return ts.createSourceFile(filename, source, languageVersion); - }, - writeFile: (filename, data, writeByteOrderMark) => { - if (filename !== "compiler.js") - console.error("Unexpected write file request: " + filename); - // console.log(data); - }, - getCurrentDirectory: () => "", - getCanonicalFileName: (filename) => filename, - useCaseSensitiveFileNames: () => false, - getNewLine: () => "\r\n" - }); - - var emitOutput = program.emit(); - - var errors = program.getSyntacticDiagnostics() - .concat(program.getSemanticDiagnostics()) - .concat(program.getGlobalDiagnostics()) - .concat(emitOutput.diagnostics); - - if (errors.length) { - console.error("Unexpected errors."); - errors.forEach(e=> console.log(`${e.code}: ${e.messageText}`)) - } -} diff --git a/scripts/ior.ts b/scripts/ior.ts deleted file mode 100644 index 374747d843..0000000000 --- a/scripts/ior.ts +++ /dev/null @@ -1,125 +0,0 @@ -/// - -import fs = require('fs'); -import path = require('path'); - -interface IOLog { - filesRead: { - path: string; - result: { contents: string; }; - }[]; - arguments: string[]; -} - -module Commands { - export function dir(obj: IOLog) { - obj.filesRead.filter(f => f.result !== undefined).forEach(f => { - console.log(f.path); - }); - } - dir['description'] = ': displays a list of files'; - - export function find(obj: IOLog, str: string) { - obj.filesRead.filter(f => f.result !== undefined).forEach(f => { - var lines = f.result.contents.split('\n'); - var printedHeader = false; - lines.forEach(line => { - if (line.indexOf(str) >= 0) { - if (!printedHeader) { - console.log(' === ' + f.path + ' ==='); - printedHeader = true; - } - console.log(line); - } - }); - }); - } - find['description'] = ' string: finds text in files'; - - export function grab(obj: IOLog, filename: string) { - obj.filesRead.filter(f => f.result !== undefined).forEach(f => { - if (path.basename(f.path) === filename) { - fs.writeFile(filename, f.result.contents); - } - }); - } - grab['description'] = ' filename.ts: writes out the specified file to disk'; - - export function extract(obj: IOLog, outputFolder: string) { - var directorySeparator = "/"; - function directoryExists(path: string): boolean { - return fs.existsSync(path) && fs.statSync(path).isDirectory(); - } - function getDirectoryPath(path: string) { - return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(directorySeparator))); - } - function getRootLength(path: string): number { - if (path.charAt(0) === directorySeparator) { - if (path.charAt(1) !== directorySeparator) return 1; - var p1 = path.indexOf(directorySeparator, 2); - if (p1 < 0) return 2; - var p2 = path.indexOf(directorySeparator, p1 + 1); - if (p2 < 0) return p1 + 1; - return p2 + 1; - } - if (path.charAt(1) === ":") { - if (path.charAt(2) === directorySeparator) return 3; - } - return 0; - } - function ensureDirectoriesExist(directoryPath: string) { - if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { - var parentDirectory = getDirectoryPath(directoryPath); - ensureDirectoriesExist(parentDirectory); - console.log("creating directory: " + directoryPath); - fs.mkdirSync(directoryPath); - } - } - function normalizeSlashes(path: string): string { - return path.replace(/\\/g, "/"); - } - function transalatePath(outputFolder:string, path: string): string { - return normalizeSlashes(outputFolder + directorySeparator + path.replace(":", "")); - } - function fileExists(path: string): boolean { - return fs.existsSync(path); - } - obj.filesRead.forEach(f => { - var filename = transalatePath(outputFolder, f.path); - ensureDirectoriesExist(getDirectoryPath(filename)); - console.log("writing filename: " + filename); - fs.writeFileSync(filename, f.result.contents); - }); - - console.log("Command: tsc "); - obj.arguments.forEach(a => { - if (getRootLength(a) > 0) { - console.log(transalatePath(outputFolder, a)); - } - else { - console.log(a); - } - console.log(" "); - }); - } - extract['description'] = ' outputFolder: extract all input files to '; -} - -var args = process.argv.slice(2); -if (args.length < 2) { - console.log('Usage: node ior.js path_to_file.json [command]'); - console.log('List of commands: '); - Object.keys(Commands).forEach(k => console.log(' ' + k + Commands[k]['description'])); -} else { - var cmd: Function = Commands[args[1]]; - if (cmd === undefined) { - console.log('Unknown command ' + args[1]); - } else { - fs.readFile(args[0], 'utf-8', (err, data) => { - if (err) throw err; - var json = JSON.parse(data); - cmd.apply(undefined, [json].concat(args.slice(2))); - }); - } -} - diff --git a/scripts/parallel-lint.js b/scripts/parallel-lint.js deleted file mode 100644 index 2ac84667d6..0000000000 --- a/scripts/parallel-lint.js +++ /dev/null @@ -1,50 +0,0 @@ -var tslint = require("tslint"); -var fs = require("fs"); -var path = require("path"); - -function getLinterOptions() { - return { - formatter: "prose", - formattersDirectory: undefined, - rulesDirectory: "built/local/tslint" - }; -} -function getLinterConfiguration() { - return tslint.Configuration.loadConfigurationFromPath(path.join(__dirname, "../tslint.json")); -} - -function lintFileContents(options, configuration, path, contents) { - var ll = new tslint.Linter(options); - ll.lint(path, contents, configuration); - return ll.getResult(); -} - -function lintFileAsync(options, configuration, path, cb) { - fs.readFile(path, "utf8", function (err, contents) { - if (err) { - return cb(err); - } - var result = lintFileContents(options, configuration, path, contents); - cb(undefined, result); - }); -} - -process.on("message", function (data) { - switch (data.kind) { - case "file": - var target = data.name; - var lintOptions = getLinterOptions(); - var lintConfiguration = getLinterConfiguration(); - lintFileAsync(lintOptions, lintConfiguration, target, function (err, result) { - if (err) { - process.send({ kind: "error", error: err.toString() }); - return; - } - process.send({ kind: "result", failures: result.failureCount, output: result.output }); - }); - break; - case "close": - process.exit(0); - break; - } -}); \ No newline at end of file diff --git a/scripts/types/ambient.d.ts b/scripts/types/ambient.d.ts index 52ddca6d7c..ecfe29f9db 100644 --- a/scripts/types/ambient.d.ts +++ b/scripts/types/ambient.d.ts @@ -1,13 +1,5 @@ import { TaskFunction } from "gulp"; -declare module "gulp-clone" { - function Clone(): NodeJS.ReadWriteStream; - namespace Clone { - export function sink() : NodeJS.ReadWriteStream & {tap: () => NodeJS.ReadWriteStream}; - } - export = Clone; -} - declare module "gulp-insert" { export function append(text: string | Buffer): NodeJS.ReadWriteStream; export function prepend(text: string | Buffer): NodeJS.ReadWriteStream; diff --git a/scripts/types/mocha/LICENSE b/scripts/types/mocha/LICENSE deleted file mode 100644 index 21071075c2..0000000000 --- a/scripts/types/mocha/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE diff --git a/scripts/types/mocha/index.d.ts b/scripts/types/mocha/index.d.ts deleted file mode 100644 index 1ada77c0a4..0000000000 --- a/scripts/types/mocha/index.d.ts +++ /dev/null @@ -1,2856 +0,0 @@ -// Type definitions for mocha 5.2 -// Project: http://mochajs.org/ -// Definitions by: Kazi Manzur Rashid -// otiai10 -// jt000 -// Vadim Macagon -// Andrew Bradley -// Dmitrii Sorin -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.1 - -export = Mocha; -export as namespace Mocha; - -/** - * Mocha API - * - * @see https://mochajs.org/api/mocha - */ -declare class Mocha { - private _growl; - private _reporter; - private _ui; - - constructor(options?: Mocha.MochaOptions); - - suite: Mocha.Suite; - files: string[]; - options: Mocha.MochaInstanceOptions; - - /** - * Enable or disable bailing on the first failure. - * - * @see https://mochajs.org/api/mocha#bail - */ - bail(bail?: boolean): this; - - /** - * Add test `file`. - * - * @see https://mochajs.org/api/mocha#addFile - */ - addFile(file: string): this; - - /** - * Set reporter to one of the built-in reporters. - * - * @see https://mochajs.org/api/mocha#reporter - */ - reporter(reporter: Mocha.Reporter, reporterOptions?: any): this; - - /** - * Set reporter to the provided constructor, one of the built-in reporters, or loads a reporter - * from a module path. Defaults to `"spec"`. - * - * @see https://mochajs.org/api/mocha#reporter - */ - reporter(reporter?: string | Mocha.ReporterConstructor, reporterOptions?: any): this; - - /** - * Set test UI to one of the built-in test interfaces. - * - * @see https://mochajs.org/api/mocha#ui - */ - ui(name: Mocha.Interface): this; - - /** - * Set test UI to one of the built-in test interfaces or loads a test interface from a module - * path. Defaults to `"bdd"`. - * - * @see https://mochajs.org/api/mocha#ui - */ - ui(name?: string): this; - - /** - * Escape string and add it to grep as a RegExp. - * - * @see https://mochajs.org/api/mocha#fgrep - */ - fgrep(str: string): this; - - /** - * Add regexp to grep, if `re` is a string it is escaped. - * - * @see https://mochajs.org/api/mocha#grep - */ - grep(re: string | RegExp): this; - - /** - * Invert `.grep()` matches. - * - * @see https://mochajs.org/api/mocha#invert - */ - invert(): this; - - /** - * Ignore global leaks. - * - * @see https://mochajs.org/api/mocha#ignoreLeaks - */ - ignoreLeaks(ignore: boolean): this; - - /** - * Enable global leak checking. - * - * @see https://mochajs.org/api/mocha#checkLeaks - */ - checkLeaks(): this; - - /** - * Display long stack-trace on failing - * - * @see https://mochajs.org/api/mocha#fullTrace - */ - fullTrace(): this; - - /** - * Enable growl support. - * - * @see https://mochajs.org/api/mocha#growl - */ - growl(): this; - - /** - * Ignore `globals` array or string. - * - * @see https://mochajs.org/api/mocha#globals - */ - globals(globals: string | ReadonlyArray): this; - - /** - * Emit color output. - * - * @see https://mochajs.org/api/mocha#useColors - */ - useColors(colors: boolean): this; - - /** - * Use inline diffs rather than +/-. - * - * @see https://mochajs.org/api/mocha#useInlineDiffs - */ - useInlineDiffs(inlineDiffs: boolean): this; - - /** - * Do not show diffs at all. - * - * @see https://mochajs.org/api/mocha#hideDiff - */ - hideDiff(hideDiff: boolean): this; - - /** - * Set the timeout in milliseconds. - * - * @see https://mochajs.org/api/mocha#timeout - */ - timeout(timeout: string | number): this; - - /** - * Set the number of times to retry failed tests. - * - * @see https://mochajs.org/api/mocha#retries - */ - retries(n: number): this; - - /** - * Set slowness threshold in milliseconds. - * - * @see https://mochajs.org/api/mocha#slow - */ - slow(slow: string | number): this; - - /** - * Enable timeouts. - * - * @see https://mochajs.org/api/mocha#enableTimeouts - */ - enableTimeouts(enabled?: boolean): this; - - /** - * Makes all tests async (accepting a callback) - * - * @see https://mochajs.org/api/mocha#asyncOnly. - */ - asyncOnly(): this; - - /** - * Disable syntax highlighting (in browser). - * - * @see https://mochajs.org/api/mocha#noHighlighting - */ - noHighlighting(): this; - - /** - * Enable uncaught errors to propagate (in browser). - * - * @see https://mochajs.org/api/mocha#allowUncaught - */ - allowUncaught(): boolean; - - /** - * Delay root suite execution. - * - * @see https://mochajs.org/api/mocha#delay - */ - delay(): boolean; - - /** - * Tests marked only fail the suite - * - * @see https://mochajs.org/api/mocha#forbidOnly - */ - forbidOnly(): boolean; - - /** - * Pending tests and tests marked skip fail the suite - * - * @see https://mochajs.org/api/mocha#forbidPending - */ - forbidPending(): boolean; - - /** - * Run tests and invoke `fn()` when complete. - * - * Note that `run` relies on Node's `require` to execute - * the test interface functions and will be subject to the - * cache - if the files are already in the `require` cache, - * they will effectively be skipped. Therefore, to run tests - * multiple times or to run tests in files that are already - * in the `require` cache, make sure to clear them from the - * cache first in whichever manner best suits your needs. - * - * @see https://mochajs.org/api/mocha#run - */ - run(fn?: (failures: number) => void): Mocha.Runner; - - /** - * Load registered files. - * - * @see https://mochajs.org/api/mocha#loadFiles - */ - protected loadFiles(fn?: () => void): void; -} - -declare namespace Mocha { - namespace utils { - /** - * Compute a slug from the given `str`. - * - * @see https://mochajs.org/api/module-utils.html#.slug - */ - function slug(str: string): string; - - /** - * Strip the function definition from `str`, and re-indent for pre whitespace. - * - * @see https://mochajs.org/api/module-utils.html#.clean - */ - function clean(str: string): string; - - /** - * Highlight the given string of `js`. - */ - function highlight(js: string): string; - - /** - * Takes some variable and asks `Object.prototype.toString()` what it thinks it is. - */ - function type(value: any): string; - - /** - * Stringify `value`. Different behavior depending on type of value: - * - * - If `value` is undefined or null, return `'[undefined]'` or `'[null]'`, respectively. - * - If `value` is not an object, function or array, return result of `value.toString()` wrapped in double-quotes. - * - If `value` is an *empty* object, function, or array, returns `'{}'`, `'[Function]'`, or `'[]'` respectively. - * - If `value` has properties, call canonicalize} on it, then return result of `JSON.stringify()` - * - * @see https://mochajs.org/api/module-utils.html#.stringify - */ - function stringify(value: any): string; - - /** - * Return a new Thing that has the keys in sorted order. Recursive. - * - * If the Thing... - * - has already been seen, return string `'[Circular]'` - * - is `undefined`, return string `'[undefined]'` - * - is `null`, return value `null` - * - is some other primitive, return the value - * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method - * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again. - * - is an empty `Array`, `Object`, or `Function`, returns `'[]'`, `'{}'`, or `'[Function]'` respectively. - * - * @see https://mochajs.org/api/module-utils.html#.canonicalize - */ - function canonicalize(value: any, stack: any[], typeHint: string): any; - - /** - * Lookup file names at the given `path`. - * - * @see https://mochajs.org/api/Mocha.utils.html#.exports.lookupFiles - */ - function lookupFiles(filepath: string, extensions?: string[], recursive?: boolean): string[]; - - /** - * Generate an undefined error with a message warning the user. - * - * @see https://mochajs.org/api/module-utils.html#.undefinedError - */ - function undefinedError(): Error; - - /** - * Generate an undefined error if `err` is not defined. - * - * @see https://mochajs.org/api/module-utils.html#.getError - */ - function getError(err: Error | undefined): Error; - - /** - * When invoking this function you get a filter function that get the Error.stack as an - * input, and return a prettify output. (i.e: strip Mocha and internal node functions from - * stack trace). - * - * @see https://mochajs.org/api/module-utils.html#.stackTraceFilter - */ - function stackTraceFilter(): (stack: string) => string; - } - - namespace interfaces { - function bdd(suite: Suite): void; - function tdd(suite: Suite): void; - function qunit(suite: Suite): void; - function exports(suite: Suite): void; - } - - // #region Test interface augmentations - - interface HookFunction { - /** - * [bdd, qunit, tdd] Describe a "hook" to execute the given callback `fn`. The name of the - * function is used as the name of the hook. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: Func): void; - - /** - * [bdd, qunit, tdd] Describe a "hook" to execute the given callback `fn`. The name of the - * function is used as the name of the hook. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: AsyncFunc): void; - - /** - * [bdd, qunit, tdd] Describe a "hook" to execute the given `title` and callback `fn`. - * - * - _Only available when invoked via the mocha CLI._ - */ - (name: string, fn?: Func): void; - - /** - * [bdd, qunit, tdd] Describe a "hook" to execute the given `title` and callback `fn`. - * - * - _Only available when invoked via the mocha CLI._ - */ - (name: string, fn?: AsyncFunc): void; - } - - interface SuiteFunction { - /** - * [bdd, tdd] Describe a "suite" with the given `title` and callback `fn` containing - * nested suites. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn: (this: Suite) => void): Suite; - - /** - * [qunit] Describe a "suite" with the given `title`. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string): Suite; - - /** - * [bdd, tdd, qunit] Indicates this suite should be executed exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - only: ExclusiveSuiteFunction; - - /** - * [bdd, tdd] Indicates this suite should not be executed. - * - * - _Only available when invoked via the mocha CLI._ - */ - skip: PendingSuiteFunction; - } - - interface ExclusiveSuiteFunction { - /** - * [bdd, tdd] Describe a "suite" with the given `title` and callback `fn` containing - * nested suites. Indicates this suite should be executed exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn: (this: Suite) => void): Suite; - - /** - * [qunit] Describe a "suite" with the given `title`. Indicates this suite should be executed - * exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string): Suite; - } - - /** - * [bdd, tdd] Describe a "suite" with the given `title` and callback `fn` containing - * nested suites. Indicates this suite should not be executed. - * - * - _Only available when invoked via the mocha CLI._ - * - * @returns [bdd] `Suite` - * @returns [tdd] `void` - */ - type PendingSuiteFunction = (title: string, fn: (this: Suite) => void) => Suite | void; - - interface TestFunction { - /** - * Describe a specification or test-case with the given callback `fn` acting as a thunk. - * The name of the function is used as the name of the test. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: Func): Test; - - /** - * Describe a specification or test-case with the given callback `fn` acting as a thunk. - * The name of the function is used as the name of the test. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: AsyncFunc): Test; - - /** - * Describe a specification or test-case with the given `title` and callback `fn` acting - * as a thunk. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn?: Func): Test; - - /** - * Describe a specification or test-case with the given `title` and callback `fn` acting - * as a thunk. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn?: AsyncFunc): Test; - - /** - * Indicates this test should be executed exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - only: ExclusiveTestFunction; - - /** - * Indicates this test should not be executed. - * - * - _Only available when invoked via the mocha CLI._ - */ - skip: PendingTestFunction; - - /** - * Number of attempts to retry. - * - * - _Only available when invoked via the mocha CLI._ - */ - retries(n: number): void; - } - - interface ExclusiveTestFunction { - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` - * acting as a thunk. The name of the function is used as the name of the test. Indicates - * this test should be executed exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: Func): Test; - - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` - * acting as a thunk. The name of the function is used as the name of the test. Indicates - * this test should be executed exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: AsyncFunc): Test; - - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and - * callback `fn` acting as a thunk. Indicates this test should be executed exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn?: Func): Test; - - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and - * callback `fn` acting as a thunk. Indicates this test should be executed exclusively. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn?: AsyncFunc): Test; - } - - interface PendingTestFunction { - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` - * acting as a thunk. The name of the function is used as the name of the test. Indicates - * this test should not be executed. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: Func): Test; - - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` - * acting as a thunk. The name of the function is used as the name of the test. Indicates - * this test should not be executed. - * - * - _Only available when invoked via the mocha CLI._ - */ - (fn: AsyncFunc): Test; - - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and - * callback `fn` acting as a thunk. Indicates this test should not be executed. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn?: Func): Test; - - /** - * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and - * callback `fn` acting as a thunk. Indicates this test should not be executed. - * - * - _Only available when invoked via the mocha CLI._ - */ - (title: string, fn?: AsyncFunc): Test; - } - - /** - * Execute after each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#afterEach - */ - let afterEach: HookFunction; - - /** - * Execute after running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#after - */ - let after: HookFunction; - - /** - * Execute before each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#beforeEach - */ - let beforeEach: HookFunction; - - /** - * Execute before running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#before - */ - let before: HookFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - let describe: SuiteFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - let it: TestFunction; - - /** - * Describes a pending test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - let xit: PendingTestFunction; - - /** - * Execute before each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#beforeEach - */ - let setup: HookFunction; - - /** - * Execute before running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#before - */ - let suiteSetup: HookFunction; - - /** - * Execute after running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#after - */ - let suiteTeardown: HookFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - let suite: SuiteFunction; - - /** - * Execute after each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#afterEach - */ - let teardown: HookFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - let test: TestFunction; - - /** - * Triggers root suite execution. - * - * - _Only available if flag --delay is passed into Mocha._ - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#runWithSuite - */ - function run(): void; - - // #endregion Test interface augmentations - - namespace reporters { - /** - * Initialize a new `Base` reporter. - * - * All other reporters generally inherit from this reporter, providing stats such as test duration, - * number of tests passed / failed, etc. - * - * @see https://mochajs.org/api/Mocha.reporters.Base.html - */ - class Base { - constructor(runner: Runner, options?: MochaOptions); - /** @deprecated Use the overload that accepts `Mocha.Runner` instead. */ - constructor(runner: IRunner, options?: MochaOptions); - - /** - * Test run statistics - */ - stats: Stats; - - /** - * Test failures - */ - failures: Test[]; - - /** - * The configured runner - */ - runner: Runner; - - /** - * Output common epilogue used by many of the bundled reporters. - * - * @see https://mochajs.org/api/Mocha.reporters.Base.html#.Base#epilogue - */ - epilogue(): void; - - done?(failures: number, fn?: (failures: number) => void): void; - } - - namespace Base { - /** - * Enables coloring by default - * - * @see https://mochajs.org/api/module-base#.useColors - */ - let useColors: boolean; - - /** - * Inline diffs instead of +/- - * - * @see https://mochajs.org/api/module-base#.inlineDiffs - */ - let inlineDiffs: boolean; - - /** - * Default color map - * - * @see https://mochajs.org/api/module-base#.colors - */ - const colors: ColorMap; - - /** - * Default color map - * - * @see https://mochajs.org/api/module-base#.colors - */ - interface ColorMap { - // added by Base - pass: number; - fail: number; - "bright pass": number; - "bright fail": number; - "bright yellow": number; - pending: number; - suite: number; - "error title": number; - "error message": number; - "error stack": number; - checkmark: number; - fast: number; - medium: number; - slow: number; - green: number; - light: number; - "diff gutter": number; - "diff added": number; - "diff removed": number; - - // added by Progress - progress: number; - - // added by Landing - plane: number; - "plane crash": number; - runway: number; - - [key: string]: number; - } - - /** - * Default symbol map - * - * @see https://mochajs.org/api/module-base#.symbols - */ - const symbols: SymbolMap; - - /** - * Default symbol map - * - * @see https://mochajs.org/api/module-base#.symbols - */ - interface SymbolMap { - ok: string; - err: string; - dot: string; - comma: string; - bang: string; - [key: string]: string; - } - - /** - * Color `str` with the given `type` (from `colors`) - * - * @see https://mochajs.org/api/module-base#.color - */ - function color(type: string, str: string): string; - - /** - * Expose terminal window size - * - * @see https://mochajs.org/api/module-base#.window - */ - const window: { - width: number; - }; - - /** - * ANSI TTY control sequences common among reporters. - * - * @see https://mochajs.org/api/module-base#.cursor - */ - namespace cursor { - /** - * Hides the cursor - */ - function hide(): void; - - /** - * Shows the cursor - */ - function show(): void; - - /** - * Deletes the current line - */ - function deleteLine(): void; - - /** - * Moves to the beginning of the line - */ - function beginningOfLine(): void; - - /** - * Clears the line and moves to the beginning of the line. - */ - function CR(): void; - } - - /** - * Returns a diff between two strings with colored ANSI output. - * - * @see https://mochajs.org/api/module-base#.generateDiff - */ - function generateDiff(actual: string, expected: string): string; - - /** - * Output the given `failures` as a list. - * - * @see https://mochajs.org/api/Mocha.reporters.Base.html#.exports.list1 - */ - function list(failures: Test[]): void; - } - - /** - * Initialize a new `Dot` matrix test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.Dot.html - */ - class Dot extends Base { - } - - /** - * Initialize a new `Doc` reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.Doc.html - */ - class Doc extends Base { - } - - /** - * Initialize a new `TAP` test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.TAP.html - */ - class TAP extends Base { - } - - /** - * Initialize a new `JSON` reporter - * - * @see https://mochajs.org/api/Mocha.reporters.JSON.html - */ - class JSON extends Base { - } - - /** - * Initialize a new `HTML` reporter. - * - * - _This reporter cannot be used on the console._ - * - * @see https://mochajs.org/api/Mocha.reporters.HTML.html - */ - class HTML extends Base { - /** - * Provide suite URL. - * - * @see https://mochajs.org/api/Mocha.reporters.HTML.html#suiteURL - */ - suiteURL(suite: Suite): string; - - /** - * Provide test URL. - * - * @see https://mochajs.org/api/Mocha.reporters.HTML.html#testURL - */ - testURL(test: Test): string; - - /** - * Adds code toggle functionality for the provided test's list element. - * - * @see https://mochajs.org/api/Mocha.reporters.HTML.html#addCodeToggle - */ - addCodeToggle(el: HTMLLIElement, contents: string): void; - } - - /** - * Initialize a new `List` test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.List.html - */ - class List extends Base { - } - - /** - * Initialize a new `Min` minimal test reporter (best used with --watch). - * - * @see https://mochajs.org/api/Mocha.reporters.Min.html - */ - class Min extends Base { - } - - /** - * Initialize a new `Spec` test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.Spec.html - */ - class Spec extends Base { - } - - /** - * Initialize a new `NyanCat` test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.Nyan.html - */ - class Nyan extends Base { - private colorIndex; - private numberOfLines; - private rainbowColors; - private scoreboardWidth; - private tick; - private trajectories; - private trajectoryWidthMax; - private draw; - private drawScoreboard; - private appendRainbow; - private drawRainbow; - private drawNyanCat; - private face; - private cursorUp; - private cursorDown; - private generateColors; - private rainbowify; - } - - /** - * Initialize a new `XUnit` test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.XUnit.html - */ - class XUnit extends Base { - constructor(runner: Runner, options?: XUnit.MochaOptions); - /** @deprecated Use the overload that accepts `Mocha.Runner` instead. */ - constructor(runner: IRunner, options?: XUnit.MochaOptions); - - /** - * Override done to close the stream (if it's a file). - * - * @see https://mochajs.org/api/Mocha.reporters.XUnit.html#done - */ - done(failures: number, fn: (failures: number) => void): void; - - /** - * Write out the given line. - * - * @see https://mochajs.org/api/Mocha.reporters.XUnit.html#write - */ - write(line: string): void; - - /** - * Output tag for the given `test.` - * - * @see https://mochajs.org/api/Mocha.reporters.XUnit.html#test - */ - test(test: Test): void; - } - - namespace XUnit { - interface MochaOptions extends Mocha.MochaOptions { - reporterOptions?: ReporterOptions; - } - - interface ReporterOptions { - output?: string; - suiteName?: string; - } - } - - /** - * Initialize a new `Markdown` test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.Markdown.html - */ - class Markdown extends Base { - } - - /** - * Initialize a new `Progress` bar test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.Progress.html - */ - class Progress extends Base { - constructor(runner: Runner, options?: Progress.MochaOptions); - /** @deprecated Use the overload that accepts `Mocha.Runner` instead. */ - constructor(runner: IRunner, options?: Progress.MochaOptions); - } - - namespace Progress { - interface MochaOptions extends Mocha.MochaOptions { - reporterOptions?: ReporterOptions; - } - - interface ReporterOptions { - open?: string; - complete?: string; - incomplete?: string; - close?: string; - verbose?: boolean; - } - } - - /** - * Initialize a new `Landing` reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.Landing.html - */ - class Landing extends Base { - } - - /** - * Initialize a new `JSONStream` test reporter. - * - * @see https://mochajs.org/api/Mocha.reporters.JSONStream.html - */ - class JSONStream extends Base { - } - - // value-only aliases - const base: typeof Base; - const dot: typeof Dot; - const doc: typeof Doc; - const tap: typeof TAP; - const json: typeof JSON; - const html: typeof HTML; - const list: typeof List; - const spec: typeof Spec; - const nyan: typeof Nyan; - const xunit: typeof XUnit; - const markdown: typeof Markdown; - const progress: typeof Progress; - const landing: typeof Landing; - // NOTE: not possible to type this correctly: - // const "json-stream": typeof JSONStream; - } - - /** - * Initialize a new `Runnable` with the given `title` and callback `fn`. - * - * @see https://mochajs.org/api/Runnable.html - */ - class Runnable { - private _slow; - private _enableTimeouts; - private _retries; - private _currentRetry; - private _timeout; - private _timeoutError; - - constructor(title: string, fn?: Func | AsyncFunc); - - title: string; - fn: Func | AsyncFunc | undefined; - body: string; - async: boolean; - sync: boolean; - timedOut: boolean; - pending: boolean; - duration?: number; - parent?: Suite; - state?: "failed" | "passed"; - timer?: any; - ctx?: Context; - callback?: Done; - allowUncaught?: boolean; - file?: string; - - /** - * Get test timeout. - * - * @see https://mochajs.org/api/Runnable.html#timeout - */ - timeout(): number; - - /** - * Set test timeout. - * - * @see https://mochajs.org/api/Runnable.html#timeout - */ - timeout(ms: string | number): this; - - /** - * Get test slowness threshold. - * - * @see https://mochajs.org/api/Runnable.html#slow - */ - slow(): number; - - /** - * Set test slowness threshold. - * - * @see https://mochajs.org/api/Runnable.html#slow - */ - slow(ms: string | number): this; - - /** - * Get whether timeouts are enabled. - * - * @see https://mochajs.org/api/Runnable.html#enableTimeouts - */ - enableTimeouts(): boolean; - - /** - * Set whether timeouts are enabled. - * - * @see https://mochajs.org/api/Runnable.html#enableTimeouts - */ - enableTimeouts(enabled: boolean): this; - - /** - * Halt and mark as pending. - */ - skip(): never; - - /** - * Check if this runnable or its parent suite is marked as pending. - * - * @see https://mochajs.org/api/Runnable.html#isPending - */ - isPending(): boolean; - - /** - * Return `true` if this Runnable has failed. - */ - isFailed(): boolean; - - /** - * Return `true` if this Runnable has passed. - */ - isPassed(): boolean; - - /** - * Set or get number of retries. - * - * @see https://mochajs.org/api/Runnable.html#retries - */ - retries(): number; - - /** - * Set or get number of retries. - * - * @see https://mochajs.org/api/Runnable.html#retries - */ - retries(n: number): void; - - /** - * Set or get current retry - * - * @see https://mochajs.org/api/Runnable.html#currentRetry - */ - protected currentRetry(): number; - - /** - * Set or get current retry - * - * @see https://mochajs.org/api/Runnable.html#currentRetry - */ - protected currentRetry(n: number): void; - - /** - * Return the full title generated by recursively concatenating the parent's full title. - */ - fullTitle(): string; - - /** - * Return the title path generated by concatenating the parent's title path with the title. - */ - titlePath(): string[]; - - /** - * Clear the timeout. - * - * @see https://mochajs.org/api/Runnable.html#clearTimeout - */ - clearTimeout(): void; - - /** - * Inspect the runnable void of private properties. - * - * @see https://mochajs.org/api/Runnable.html#inspect - */ - inspect(): string; - - /** - * Reset the timeout. - * - * @see https://mochajs.org/api/Runnable.html#resetTimeout - */ - resetTimeout(): void; - - /** - * Get a list of whitelisted globals for this test run. - * - * @see https://mochajs.org/api/Runnable.html#globals - */ - globals(): string[]; - - /** - * Set a list of whitelisted globals for this test run. - * - * @see https://mochajs.org/api/Runnable.html#globals - */ - globals(globals: ReadonlyArray): void; - - /** - * Run the test and invoke `fn(err)`. - * - * @see https://mochajs.org/api/Runnable.html#run - */ - run(fn: Done): void; - } - - // #region Runnable "error" event - interface Runnable extends NodeJS.EventEmitter { - on(event: "error", listener: (error: any) => void): this; - once(event: "error", listener: (error: any) => void): this; - addListener(event: "error", listener: (error: any) => void): this; - removeListener(event: "error", listener: (error: any) => void): this; - prependListener(event: "error", listener: (error: any) => void): this; - prependOnceListener(event: "error", listener: (error: any) => void): this; - emit(name: "error", error: any): boolean; - } - // #endregion Runnable "error" event - // #region Runnable untyped events - interface Runnable extends NodeJS.EventEmitter { - on(event: string, listener: (...args: any[]) => void): this; - once(event: string, listener: (...args: any[]) => void): this; - addListener(event: string, listener: (...args: any[]) => void): this; - removeListener(event: string, listener: (...args: any[]) => void): this; - prependListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: string, listener: (...args: any[]) => void): this; - emit(name: string, ...args: any[]): boolean; - } - // #endregion Runnable untyped events - - /** - * Test context - * - * @see https://mochajs.org/api/module-Context.html#~Context - */ - class Context { - private _runnable; - - test?: Runnable; - currentTest?: Test; - - /** - * Get the context `Runnable`. - */ - runnable(): Runnable; - - /** - * Set the context `Runnable`. - */ - runnable(runnable: Runnable): this; - /** @deprecated Use the overload that accepts `Mocha.Runnable` instead. */ - runnable(runnable: IRunnable): this; - - /** - * Get test timeout. - */ - timeout(): number; - - /** - * Set test timeout. - */ - timeout(ms: string | number): this; - - /** - * Get whether timeouts are enabled. - */ - enableTimeouts(): boolean; - - /** - * Set whether timeouts are enabled. - */ - enableTimeouts(enabled: boolean): this; - - /** - * Get test slowness threshold. - */ - slow(): number; - - /** - * Set test slowness threshold. - */ - slow(ms: string | number): this; - - /** - * Mark a test as skipped. - */ - skip(): never; - - /** - * Get the number of allowed retries on failed tests. - */ - retries(): number; - - /** - * Set the number of allowed retries on failed tests. - */ - retries(n: number): this; - - [key: string]: any; - } - - /** - * Initialize a `Runner` for the given `suite`. - * - * @see https://mochajs.org/api/Mocha.Runner.html - */ - class Runner { - private _globals; - private _abort; - private _delay; - private _defaultGrep; - private next; - private hookErr; - private prevGlobalsLength; - private nextSuite; - - constructor(suite: Suite, delay: boolean); - - /** @deprecated Use the overload that accepts `Mocha.Suite` instead. */ - constructor(suite: ISuite, delay: boolean); - - suite: Suite; - started: boolean; - total: number; - failures: number; - asyncOnly?: boolean; - allowUncaught?: boolean; - fullStackTrace?: boolean; - forbidOnly?: boolean; - forbidPending?: boolean; - ignoreLeaks?: boolean; - test?: Test; - currentRunnable?: Runnable; - stats?: Stats; // added by reporters - - /** - * Run tests with full titles matching `re`. Updates runner.total - * with number of tests matched. - * - * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#grep - */ - grep(re: RegExp, invert: boolean): this; - - /** - * Returns the number of tests matching the grep search for the - * given suite. - * - * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#grepTotal - */ - grepTotal(suite: Suite): number; - - /** @deprecated Use the overload that accepts `Mocha.Suite` instead. */ - grepTotal(suite: ISuite): number; - - /** - * Gets the allowed globals. - * - * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#globals - */ - globals(): string[]; - - /** - * Allow the given `arr` of globals. - * - * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#globals - */ - globals(arr: ReadonlyArray): this; - - /** - * Run the root suite and invoke `fn(failures)` on completion. - * - * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#run - */ - run(fn?: (failures: number) => void): this; - - /** - * Cleanly abort execution. - * - * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#abort - */ - abort(): this; - - /** - * Handle uncaught exceptions. - * - * @see https://mochajs.org/api/Mocha.Runner.html#uncaught - */ - uncaught(err: any): void; - - /** - * Wrapper for setImmediate, process.nextTick, or browser polyfill. - */ - protected static immediately(callback: Function): void; - - /** - * Return a list of global properties. - * - * @see https://mochajs.org/api/Mocha.Runner.html#globalProps - */ - protected globalProps(): string[]; - - /** - * Check for global variable leaks. - * - * @see https://mochajs.org/api/Mocha.Runner.html#checkGlobals - */ - protected checkGlobals(test: Test): void; - - /** - * Fail the given `test`. - * - * @see https://mochajs.org/api/Mocha.Runner.html#fail - */ - protected fail(test: Test, err: any): void; - - /** - * Fail the given `hook` with `err`. - * - * Hook failures work in the following pattern: - * - If bail, then exit - * - Failed `before` hook skips all tests in a suite and subsuites, - * but jumps to corresponding `after` hook - * - Failed `before each` hook skips remaining tests in a - * suite and jumps to corresponding `after each` hook, - * which is run only once - * - Failed `after` hook does not alter - * execution order - * - Failed `after each` hook skips remaining tests in a - * suite and subsuites, but executes other `after each` - * hooks - * - * @see https://mochajs.org/api/Mocha.Runner.html#failHook - */ - protected failHook(hook: Hook, err: any): void; - - /** - * Run hook `name` callbacks and then invoke `fn()`. - * - * @see https://mochajs.org/api/Mocha.Runner.html#hook - */ - protected hook(name: string, fn: () => void): void; - - /** - * Run hook `name` for the given array of `suites` - * in order, and callback `fn(err, errSuite)`. - * - * @see https://mochajs.org/api/Mocha.Runner.html#hooks - */ - protected hooks(name: string, suites: Suite[], fn: (err?: any, errSuite?: Suite) => void): void; - - /** - * Run hooks from the top level down. - * - * @see https://mochajs.org/api/Mocha.Runner.html#hookUp - */ - protected hookUp(name: string, fn: (err?: any, errSuite?: Suite) => void): void; - - /** - * Run hooks from the bottom up. - * - * @see https://mochajs.org/api/Mocha.Runner.html#hookDown - */ - protected hookDown(name: string, fn: (err?: any, errSuite?: Suite) => void): void; - - /** - * Return an array of parent Suites from closest to furthest. - * - * @see https://mochajs.org/api/Mocha.Runner.html#parents - */ - protected parents(): Suite[]; - - /** - * Run the current test and callback `fn(err)`. - * - * @see https://mochajs.org/api/Mocha.Runner.html#runTest - */ - protected runTest(fn: Done): any; - - /** - * Run tests in the given `suite` and invoke the callback `fn()` when complete. - * - * @see https://mochajs.org/api/Mocha.Runner.html#runTests - */ - protected runTests(suite: Suite, fn: (errSuite?: Suite) => void): void; - - /** - * Run the given `suite` and invoke the callback `fn()` when complete. - * - * @see https://mochajs.org/api/Mocha.Runner.html#runSuite - */ - protected runSuite(suite: Suite, fn: (errSuite?: Suite) => void): void; - } - - // #region Runner "waiting" event - interface Runner { - on(event: "waiting", listener: (rootSuite: Suite) => void): this; - once(event: "waiting", listener: (rootSuite: Suite) => void): this; - addListener(event: "waiting", listener: (rootSuite: Suite) => void): this; - removeListener(event: "waiting", listener: (rootSuite: Suite) => void): this; - prependListener(event: "waiting", listener: (rootSuite: Suite) => void): this; - prependOnceListener(event: "waiting", listener: (rootSuite: Suite) => void): this; - emit(name: "waiting", rootSuite: Suite): boolean; - } - // #endregion Runner "waiting" event - // #region Runner "start" event - interface Runner extends NodeJS.EventEmitter { - on(event: "start", listener: () => void): this; - once(event: "start", listener: () => void): this; - addListener(event: "start", listener: () => void): this; - removeListener(event: "start", listener: () => void): this; - prependListener(event: "start", listener: () => void): this; - prependOnceListener(event: "start", listener: () => void): this; - emit(name: "start"): boolean; - } - // #endregion Runner "start" event - // #region Runner "end" event - interface Runner extends NodeJS.EventEmitter { - on(event: "end", listener: () => void): this; - once(event: "end", listener: () => void): this; - addListener(event: "end", listener: () => void): this; - removeListener(event: "end", listener: () => void): this; - prependListener(event: "end", listener: () => void): this; - prependOnceListener(event: "end", listener: () => void): this; - emit(name: "end"): boolean; - } - // #endregion Runner "end" event - // #region Runner "suite" event - interface Runner extends NodeJS.EventEmitter { - on(event: "suite", listener: (suite: Suite) => void): this; - once(event: "suite", listener: (suite: Suite) => void): this; - addListener(event: "suite", listener: (suite: Suite) => void): this; - removeListener(event: "suite", listener: (suite: Suite) => void): this; - prependListener(event: "suite", listener: (suite: Suite) => void): this; - prependOnceListener(event: "suite", listener: (suite: Suite) => void): this; - emit(name: "suite", suite: Suite): boolean; - } - // #endregion Runner "suite" event - // #region Runner "suite end" event - interface Runner extends NodeJS.EventEmitter { - on(event: "suite end", listener: (suite: Suite) => void): this; - once(event: "suite end", listener: (suite: Suite) => void): this; - addListener(event: "suite end", listener: (suite: Suite) => void): this; - removeListener(event: "suite end", listener: (suite: Suite) => void): this; - prependListener(event: "suite end", listener: (suite: Suite) => void): this; - prependOnceListener(event: "suite end", listener: (suite: Suite) => void): this; - emit(name: "suite end", suite: Suite): boolean; - } - // #endregion Runner "suite end" event - // #region Runner "test" event - interface Runner extends NodeJS.EventEmitter { - on(event: "test", listener: (test: Test) => void): this; - once(event: "test", listener: (test: Test) => void): this; - addListener(event: "test", listener: (test: Test) => void): this; - removeListener(event: "test", listener: (test: Test) => void): this; - prependListener(event: "test", listener: (test: Test) => void): this; - prependOnceListener(event: "test", listener: (test: Test) => void): this; - emit(name: "test", test: Test): boolean; - } - // #endregion Runner "test" event - // #region Runner "test end" event - interface Runner extends NodeJS.EventEmitter { - on(event: "test end", listener: (test: Test) => void): this; - once(event: "test end", listener: (test: Test) => void): this; - addListener(event: "test end", listener: (test: Test) => void): this; - removeListener(event: "test end", listener: (test: Test) => void): this; - prependListener(event: "test end", listener: (test: Test) => void): this; - prependOnceListener(event: "test end", listener: (test: Test) => void): this; - emit(name: "test end", test: Test): boolean; - } - // #endregion Runner "test end" event - // #region Runner "hook" event - interface Runner extends NodeJS.EventEmitter { - on(event: "hook", listener: (hook: Hook) => void): this; - once(event: "hook", listener: (hook: Hook) => void): this; - addListener(event: "hook", listener: (hook: Hook) => void): this; - removeListener(event: "hook", listener: (hook: Hook) => void): this; - prependListener(event: "hook", listener: (hook: Hook) => void): this; - prependOnceListener(event: "hook", listener: (hook: Hook) => void): this; - emit(name: "hook", hook: Hook): boolean; - } - // #endregion Runner "hook" event - // #region Runner "hook end" event - interface Runner extends NodeJS.EventEmitter { - on(event: "hook end", listener: (hook: Hook) => void): this; - once(event: "hook end", listener: (hook: Hook) => void): this; - addListener(event: "hook end", listener: (hook: Hook) => void): this; - removeListener(event: "hook end", listener: (hook: Hook) => void): this; - prependListener(event: "hook end", listener: (hook: Hook) => void): this; - prependOnceListener(event: "hook end", listener: (hook: Hook) => void): this; - emit(name: "hook end", hook: Hook): boolean; - } - // #endregion Runner "hook end" event - // #region Runner "pass" event - interface Runner extends NodeJS.EventEmitter { - on(event: "pass", listener: (test: Test) => void): this; - once(event: "pass", listener: (test: Test) => void): this; - addListener(event: "pass", listener: (test: Test) => void): this; - removeListener(event: "pass", listener: (test: Test) => void): this; - prependListener(event: "pass", listener: (test: Test) => void): this; - prependOnceListener(event: "pass", listener: (test: Test) => void): this; - emit(name: "pass", test: Test): boolean; - } - // #endregion Runner "pass" event - // #region Runner "fail" event - interface Runner extends NodeJS.EventEmitter { - on(event: "fail", listener: (test: Test, err: any) => void): this; - once(event: "fail", listener: (test: Test, err: any) => void): this; - addListener(event: "fail", listener: (test: Test, err: any) => void): this; - removeListener(event: "fail", listener: (test: Test, err: any) => void): this; - prependListener(event: "fail", listener: (test: Test, err: any) => void): this; - prependOnceListener(event: "fail", listener: (test: Test, err: any) => void): this; - emit(name: "fail", test: Test, err: any): boolean; - } - // #endregion Runner "fail" event - // #region Runner "pending" event - interface Runner extends NodeJS.EventEmitter { - on(event: "pending", listener: (test: Test) => void): this; - once(event: "pending", listener: (test: Test) => void): this; - addListener(event: "pending", listener: (test: Test) => void): this; - removeListener(event: "pending", listener: (test: Test) => void): this; - prependListener(event: "pending", listener: (test: Test) => void): this; - prependOnceListener(event: "pending", listener: (test: Test) => void): this; - emit(name: "pending", test: Test): boolean; - } - // #endregion Runner "pending" event - // #region Runner untyped events - interface Runner extends NodeJS.EventEmitter { - on(event: string, listener: (...args: any[]) => void): this; - once(event: string, listener: (...args: any[]) => void): this; - addListener(event: string, listener: (...args: any[]) => void): this; - removeListener(event: string, listener: (...args: any[]) => void): this; - prependListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: string, listener: (...args: any[]) => void): this; - emit(name: string, ...args: any[]): boolean; - } - // #endregion Runner untyped events - - /** - * Initialize a new `Suite` with the given `title` and `ctx`. - * - * @see https://mochajs.org/api/Mocha.Suite.html - */ - class Suite { - private _beforeEach; - private _beforeAll; - private _afterEach; - private _afterAll; - private _timeout; - private _enableTimeouts; - private _slow; - private _bail; - private _retries; - private _onlyTests; - private _onlySuites; - - constructor(title: string, parentContext?: Context); - /** @deprecated Use the overload that accepts `Mocha.Context` instead. */ - constructor(title: string, parentContext?: IContext); - - ctx: Context; - suites: Suite[]; - tests: Test[]; - pending: boolean; - file?: string; - root: boolean; - delayed: boolean; - parent: Suite | undefined; - title: string; - - /** - * Create a new `Suite` with the given `title` and parent `Suite`. When a suite - * with the same title is already present, that suite is returned to provide - * nicer reporter and more flexible meta-testing. - * - * @see https://mochajs.org/api/mocha#.exports.create - */ - static create(parent: Suite, title: string): Suite; - /** @deprecated Use the overload that accepts `Mocha.Suite` instead. */ - static create(parent: ISuite, title: string): Suite; - - /** - * Return a clone of this `Suite`. - * - * @see https://mochajs.org/api/Mocha.Suite.html#clone - */ - clone(): Suite; - - /** - * Get timeout `ms`. - * - * @see https://mochajs.org/api/Mocha.Suite.html#timeout - */ - timeout(): number; - - /** - * Set timeout `ms` or short-hand such as "2s". - * - * @see https://mochajs.org/api/Mocha.Suite.html#timeout - */ - timeout(ms: string | number): this; - - /** - * Get number of times to retry a failed test. - * - * @see https://mochajs.org/api/Mocha.Suite.html#retries - */ - retries(): number; - - /** - * Set number of times to retry a failed test. - * - * @see https://mochajs.org/api/Mocha.Suite.html#retries - */ - retries(n: string | number): this; - - /** - * Get whether timeouts are enabled. - * - * @see https://mochajs.org/api/Mocha.Suite.html#enableTimeouts - */ - enableTimeouts(): boolean; - - /** - * Set whether timeouts are `enabled`. - * - * @see https://mochajs.org/api/Mocha.Suite.html#enableTimeouts - */ - enableTimeouts(enabled: boolean): this; - - /** - * Get slow `ms`. - * - * @see https://mochajs.org/api/Mocha.Suite.html#slow - */ - slow(): number; - - /** - * Set slow `ms` or short-hand such as "2s". - * - * @see https://mochajs.org/api/Mocha.Suite.html#slow - */ - slow(ms: string | number): this; - - /** - * Get whether to bail after first error. - * - * @see https://mochajs.org/api/Mocha.Suite.html#bail - */ - bail(): boolean; - - /** - * Set whether to bail after first error. - * - * @see https://mochajs.org/api/Mocha.Suite.html#bail - */ - bail(bail: boolean): this; - - /** - * Check if this suite or its parent suite is marked as pending. - * - * @see https://mochajs.org/api/Mocha.Suite.html#isPending - */ - isPending(): boolean; - - /** - * Run `fn(test[, done])` before running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll - */ - beforeAll(fn?: Func): this; - - /** - * Run `fn(test[, done])` before running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll - */ - beforeAll(fn?: AsyncFunc): this; - - /** - * Run `fn(test[, done])` before running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll - */ - beforeAll(title: string, fn?: Func): this; - - /** - * Run `fn(test[, done])` before running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll - */ - beforeAll(title: string, fn?: AsyncFunc): this; - - /** - * Run `fn(test[, done])` after running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterAll - */ - afterAll(fn?: Func): this; - - /** - * Run `fn(test[, done])` after running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterAll - */ - afterAll(fn?: AsyncFunc): this; - - /** - * Run `fn(test[, done])` after running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterAll - */ - afterAll(title: string, fn?: Func): this; - - /** - * Run `fn(test[, done])` after running tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterAll - */ - afterAll(title: string, fn?: AsyncFunc): this; - - /** - * Run `fn(test[, done])` before each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach - */ - beforeEach(fn?: Func): this; - - /** - * Run `fn(test[, done])` before each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach - */ - beforeEach(fn?: AsyncFunc): this; - - /** - * Run `fn(test[, done])` before each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach - */ - beforeEach(title: string, fn?: Func): this; - - /** - * Run `fn(test[, done])` before each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach - */ - beforeEach(title: string, fn?: AsyncFunc): this; - - /** - * Run `fn(test[, done])` after each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterEach - */ - afterEach(fn?: Func): this; - - /** - * Run `fn(test[, done])` after each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterEach - */ - afterEach(fn?: AsyncFunc): this; - - /** - * Run `fn(test[, done])` after each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterEach - */ - afterEach(title: string, fn?: Func): this; - - /** - * Run `fn(test[, done])` after each test case. - * - * @see https://mochajs.org/api/Mocha.Suite.html#afterEach - */ - afterEach(title: string, fn?: AsyncFunc): this; - - /** - * Add a test `suite`. - * - * @see https://mochajs.org/api/Mocha.Suite.html#addSuite - */ - addSuite(suite: Suite): this; - /** @deprecated Use the overload that accepts `Mocha.ISuite` instead. */ - addSuite(suite: ISuite): this; - - /** - * Add a `test` to this suite. - * - * @see https://mochajs.org/api/Mocha.Suite.html#addTest - */ - addTest(test: Test): this; - /** @deprecated Use the overload that accepts `Mocha.ITest` instead. */ - addTest(test: ITest): this; - - /** - * Return the full title generated by recursively concatenating the parent's - * full title. - * - * @see https://mochajs.org/api/Mocha.Suite.html#.Suite#fullTitle - */ - fullTitle(): string; - - /** - * Return the title path generated by recursively concatenating the parent's - * title path. - * - * @see https://mochajs.org/api/Mocha.Suite.html#.Suite#titlePath - */ - titlePath(): string[]; - - /** - * Return the total number of tests. - * - * @see https://mochajs.org/api/Mocha.Suite.html#.Suite#total - */ - total(): number; - - /** - * Iterates through each suite recursively to find all tests. Applies a - * function in the format `fn(test)`. - * - * @see https://mochajs.org/api/Mocha.Suite.html#eachTest - */ - eachTest(fn: (test: Test) => void): this; - - /** - * This will run the root suite if we happen to be running in delayed mode. - * - * @see https://mochajs.org/api/Mocha.Suite.html#run - */ - run(): void; - - /** - * Generic hook-creator. - */ - protected _createHook(title: string, fn?: Func | AsyncFunc): Hook; - } - - // #region Suite "beforeAll" event - interface Suite extends NodeJS.EventEmitter { - on(event: "beforeAll", listener: (hook: Hook) => void): this; - once(event: "beforeAll", listener: (hook: Hook) => void): this; - addListener(event: "beforeAll", listener: (hook: Hook) => void): this; - removeListener(event: "beforeAll", listener: (hook: Hook) => void): this; - prependListener(event: "beforeAll", listener: (hook: Hook) => void): this; - prependOnceListener(event: "beforeAll", listener: (hook: Hook) => void): this; - emit(name: "beforeAll", hook: Hook): boolean; - } - // #endregion Suite "beforeAll" event - // #region Suite "afterAll" event - interface Suite extends NodeJS.EventEmitter { - on(event: "afterAll", listener: (hook: Hook) => void): this; - once(event: "afterAll", listener: (hook: Hook) => void): this; - addListener(event: "afterAll", listener: (hook: Hook) => void): this; - removeListener(event: "afterAll", listener: (hook: Hook) => void): this; - prependListener(event: "afterAll", listener: (hook: Hook) => void): this; - prependOnceListener(event: "afterAll", listener: (hook: Hook) => void): this; - emit(name: "afterAll", hook: Hook): boolean; - } - // #endregion Suite "afterAll" event - // #region Suite "beforeEach" event - interface Suite extends NodeJS.EventEmitter { - on(event: "beforeEach", listener: (hook: Hook) => void): this; - once(event: "beforeEach", listener: (hook: Hook) => void): this; - addListener(event: "beforeEach", listener: (hook: Hook) => void): this; - removeListener(event: "beforeEach", listener: (hook: Hook) => void): this; - prependListener(event: "beforeEach", listener: (hook: Hook) => void): this; - prependOnceListener(event: "beforeEach", listener: (hook: Hook) => void): this; - emit(name: "beforeEach", hook: Hook): boolean; - } - // #endregion Suite "beforeEach" event - // #region Suite "afterEach" event - interface Suite extends NodeJS.EventEmitter { - on(event: "afterEach", listener: (hook: Hook) => void): this; - once(event: "afterEach", listener: (hook: Hook) => void): this; - addListener(event: "afterEach", listener: (hook: Hook) => void): this; - removeListener(event: "afterEach", listener: (hook: Hook) => void): this; - prependListener(event: "afterEach", listener: (hook: Hook) => void): this; - prependOnceListener(event: "afterEach", listener: (hook: Hook) => void): this; - emit(name: "afterEach", hook: Hook): boolean; - } - // #endregion Suite "afterEach" event - // #region Suite "suite" event - interface Suite extends NodeJS.EventEmitter { - on(event: "suite", listener: (suite: Suite) => void): this; - once(event: "suite", listener: (suite: Suite) => void): this; - addListener(event: "suite", listener: (suite: Suite) => void): this; - removeListener(event: "suite", listener: (suite: Suite) => void): this; - prependListener(event: "suite", listener: (suite: Suite) => void): this; - prependOnceListener(event: "suite", listener: (suite: Suite) => void): this; - emit(name: "suite", suite: Suite): boolean; - } - // #endregion Suite "suite" event - // #region Suite "test" event - interface Suite { - on(event: "test", listener: (test: Test) => void): this; - once(event: "test", listener: (test: Test) => void): this; - addListener(event: "test", listener: (test: Test) => void): this; - removeListener(event: "test", listener: (test: Test) => void): this; - prependListener(event: "test", listener: (test: Test) => void): this; - prependOnceListener(event: "test", listener: (test: Test) => void): this; - emit(name: "test", test: Test): boolean; - } - // #endregion Suite "test" event - // #region Suite "run" event - interface Suite extends NodeJS.EventEmitter { - on(event: "run", listener: () => void): this; - once(event: "run", listener: () => void): this; - addListener(event: "run", listener: () => void): this; - removeListener(event: "run", listener: () => void): this; - prependListener(event: "run", listener: () => void): this; - prependOnceListener(event: "run", listener: () => void): this; - emit(name: "run"): boolean; - } - // #endregion Suite "run" event - // #region Suite "pre-require" event - interface Suite extends NodeJS.EventEmitter { - on(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - once(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - addListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - removeListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - prependListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - prependOnceListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - emit(name: "pre-require", context: MochaGlobals, file: string, mocha: Mocha): boolean; - } - // #endregion Suite "pre-require" event - // #region Suite "require" event - interface Suite extends NodeJS.EventEmitter { - on(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; - once(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; - addListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; - removeListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; - prependListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; - prependOnceListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; - emit(name: "require", module: any, file: string, mocha: Mocha): boolean; - } - // #endregion Suite "require" event - // #region Suite "post-require" event - interface Suite extends NodeJS.EventEmitter { - on(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - once(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - addListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - removeListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - prependListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - prependOnceListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; - emit(name: "post-require", context: MochaGlobals, file: string, mocha: Mocha): boolean; - } - // #endregion Suite "post-require" event - // #region Suite untyped events - interface Suite extends NodeJS.EventEmitter { - on(event: string, listener: (...args: any[]) => void): this; - once(event: string, listener: (...args: any[]) => void): this; - addListener(event: string, listener: (...args: any[]) => void): this; - removeListener(event: string, listener: (...args: any[]) => void): this; - prependListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: string, listener: (...args: any[]) => void): this; - emit(name: string, ...args: any[]): boolean; - } - // #endregion Runner untyped events - - /** - * Initialize a new `Hook` with the given `title` and callback `fn` - * - * @see https://mochajs.org/api/Hook.html - */ - class Hook extends Runnable { - private _error; - - type: "hook"; - originalTitle?: string; // added by Runner - - /** - * Get the test `err`. - * - * @see https://mochajs.org/api/Hook.html#error - */ - error(): any; - - /** - * Set the test `err`. - * - * @see https://mochajs.org/api/Hook.html#error - */ - error(err: any): void; - } - - /** - * Initialize a new `Test` with the given `title` and callback `fn`. - * - * @see https://mochajs.org/api/Test.html - */ - class Test extends Runnable { - type: "test"; - speed?: "slow" | "medium" | "fast"; // added by reporters - err?: Error; // added by reporters - clone(): Test; - } - - /** - * Test statistics - */ - interface Stats { - suites: number; - tests: number; - passes: number; - pending: number; - failures: number; - start?: Date; - end?: Date; - duration?: number; - } - - type TestInterface = (suite: Suite) => void; - - interface ReporterConstructor { - new (runner: Runner, options: { reporterOptions?: any; }): reporters.Base; - } - - type Done = (err?: any) => void; - - /** - * Callback function used for tests and hooks. - */ - type Func = (this: Context, done: Done) => void; - - /** - * Async callback function used for tests and hooks. - */ - type AsyncFunc = (this: Context) => PromiseLike; - - /** - * Options to pass to Mocha. - */ - interface MochaOptions { - /** Test interfaces ("bdd", "tdd", "exports", etc.). */ - ui?: Interface; - - /** - * Reporter constructor, built-in reporter name, or reporter module path. Defaults to - * `"spec"`. - */ - reporter?: string | ReporterConstructor; - - /** Options to pass to the reporter. */ - reporterOptions?: any; - - /** Array of accepted globals. */ - globals?: string[]; - - /** timeout in milliseconds. */ - timeout?: number; - - enableTimeouts?: boolean; - - /** number of times to retry failed tests. */ - retries?: number; - - /** bail on the first test failure. */ - bail?: boolean; - - /** milliseconds to wait before considering a test slow. */ - slow?: number; - - /** ignore global leaks. */ - ignoreLeaks?: boolean; - - /** display the full stack trace on failure. */ - fullStackTrace?: boolean; - - /** string or regexp to filter tests with. */ - grep?: string | RegExp; - - /** Enable growl support. */ - growl?: boolean; - - /** Emit color output. */ - useColors?: boolean; - - /** Use inline diffs rather than +/-. */ - inlineDiffs?: boolean; - - /** Do not show diffs at all. */ - hideDiff?: boolean; - - asyncOnly?: boolean; - delay?: boolean; - forbidOnly?: boolean; - forbidPending?: boolean; - noHighlighting?: boolean; - allowUncaught?: boolean; - } - - interface MochaInstanceOptions extends MochaOptions { - files?: string[]; - } - - /** - * Variables added to the global scope by Mocha when run in the CLI. - */ - interface MochaGlobals { - /** - * Execute before running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#before - */ - before: HookFunction; - - /** - * Execute after running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#after - */ - after: HookFunction; - - /** - * Execute before each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#beforeEach - */ - beforeEach: HookFunction; - - /** - * Execute after each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#afterEach - */ - afterEach: HookFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - describe: SuiteFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - context: SuiteFunction; - - /** - * Pending suite. - * - * - _Only available when invoked via the mocha CLI._ - */ - xdescribe: PendingSuiteFunction; - - /** - * Pending suite. - * - * - _Only available when invoked via the mocha CLI._ - */ - xcontext: PendingSuiteFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - it: TestFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - specify: TestFunction; - - /** - * Describes a pending test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - xit: PendingTestFunction; - - /** - * Describes a pending test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - xspecify: PendingTestFunction; - - /** - * Execute before running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#before - */ - suiteSetup: HookFunction; - - /** - * Execute after running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#after - */ - suiteTeardown: HookFunction; - - /** - * Execute before each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#beforeEach - */ - setup: HookFunction; - - /** - * Execute after each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#afterEach - */ - teardown: HookFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - suite: SuiteFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - test: TestFunction; - - run: typeof run; - } - - /** - * Third-party declarations that want to add new entries to the `Reporter` union can - * contribute names here. - */ - interface ReporterContributions { - Base: never; - base: never; - Dot: never; - dot: never; - TAP: never; - tap: never; - JSON: never; - json: never; - HTML: never; - html: never; - List: never; - list: never; - Min: never; - min: never; - Spec: never; - spec: never; - Nyan: never; - nyan: never; - XUnit: never; - xunit: never; - Markdown: never; - markdown: never; - Progress: never; - progress: never; - Landing: never; - landing: never; - JSONStream: never; - "json-stream": never; - } - - type Reporter = keyof ReporterContributions; - - /** - * Third-party declarations that want to add new entries to the `Interface` union can - * contribute names here. - */ - interface InterfaceContributions { - bdd: never; - tdd: never; - qunit: never; - exports: never; - } - - type Interface = keyof InterfaceContributions; - - // #region Deprecations - - /** @deprecated use `Mocha.Context` instead. */ - interface IContext { - test?: IRunnable; - runnable(): IRunnable | undefined; - /** @deprecated `.runnable()` returns `this` in `Mocha.Context`. */ - runnable(runnable: IRunnable): IContext; - timeout(): number; - /** @deprecated `.timeout()` returns `this` in `Mocha.Context`. */ - timeout(timeout: number): IContext; - /** @deprecated `.enableTimeouts()` has additional overloads in `Mocha.Context`. */ - /** @deprecated `.enableTimeouts()` returns `this` in `Mocha.Context`. */ - enableTimeouts(enableTimeouts: boolean): IContext; - /** @deprecated `.slow()` has additional overloads in `Mocha.Context`. */ - /** @deprecated `.slow()` returns `this` in `Mocha.Context`. */ - slow(slow: number): IContext; - /** @deprecated `.skip()` returns `never` in `Mocha.Context`. */ - skip(): IContext; - retries(): number; - /** @deprecated `.retries()` returns `this` in `Mocha.Context`. */ - retries(retries: number): IContext; - } - - /** @deprecated use `Mocha.Suite` instead. */ - interface ISuiteCallbackContext { - /** @deprecated `.timeout()` has additional overloads in `Mocha.Suite`. */ - timeout(ms: number | string): this; - /** @deprecated `.retries()` has additional overloads in `Mocha.Suite`. */ - retries(n: number): this; - /** @deprecated `.slow()` has additional overloads in `Mocha.Suite`. */ - slow(ms: number): this; - } - - /** @deprecated use `Mocha.Context` instead. */ - interface IHookCallbackContext { - /** @deprecated `.skip()` returns `never` in `Mocha.Context`. */ - skip(): this; - /** @deprecated `.timeout()` has additional overloads in `Mocha.Context`. */ - timeout(ms: number | string): this; - [index: string]: any; - } - - /** @deprecated use `Mocha.Context` instead. */ - interface ITestCallbackContext { - /** @deprecated `.skip()` returns `never` in `Mocha.Context`. */ - skip(): this; - /** @deprecated `.timeout()` has additional overloads in `Mocha.Context`. */ - timeout(ms: number | string): this; - /** @deprecated `.retries()` has additional overloads in `Mocha.Context`. */ - retries(n: number): this; - /** @deprecated `.slow()` has additional overloads in `Mocha.Context`. */ - slow(ms: number): this; - [index: string]: any; - } - - /** Partial interface for Mocha's `Runnable` class. */ - /** @deprecated use `Mocha.Runnable` instead. */ - interface IRunnable extends NodeJS.EventEmitter { - title: string; - /** @deprecated `.fn` has type `Func | AsyncFunc` in `Mocha.Runnable`. */ - fn: Function | undefined; - async: boolean; - sync: boolean; - timedOut: boolean; - /** @deprecated `.timeout()` has additional overloads in `Mocha.Runnable`. */ - timeout(n: number | string): this; - duration?: number; - } - - /** Partial interface for Mocha's `Suite` class. */ - /** @deprecated use `Mocha.Suite` instead. */ - interface ISuite { - /** @deprecated `.ctx` has type `Mocha.Context` in `Mocha.Suite`. */ - ctx: IContext; - /** @deprecated `.parent` has type `Mocha.Suite | undefined` in `Mocha.Suite`. */ - parent: ISuite | undefined; - root: boolean; - title: string; - /** @deprecated `.suites` has type `Mocha.Suite[]` in `Mocha.Suite`. */ - suites: ISuite[]; - /** @deprecated `.tests` has type `Mocha.Test[]` in `Mocha.Suite`. */ - tests: ITest[]; - - bail(): boolean; - /** @deprecated `.bail()` returns `this` in `Mocha.Suite`. */ - bail(bail: boolean): ISuite; - fullTitle(): string; - retries(): number; - /** @deprecated `.retries()` returns `this` in `Mocha.Suite`. */ - retries(retries: number): ISuite; - slow(): number; - /** @deprecated `.slow()` returns `this` in `Mocha.Suite`. */ - slow(slow: number): ISuite; - timeout(): number; - /** @deprecated `.timeout()` returns `this` in `Mocha.Suite`. */ - timeout(timeout: number): ISuite; - } - - /** Partial interface for Mocha's `Test` class. */ - /** @deprecated use `Mocha.Test` instead. */ - interface ITest extends IRunnable { - body?: string; - file?: string; - /** @deprecated `.parent` has type `Mocha.Suite | undefined` in `Mocha.Test`. */ - parent?: ISuite; - pending: boolean; - state?: 'failed' | 'passed'; - type: 'test'; - fullTitle(): string; - } - - /** @deprecated use `Mocha.Hook` instead. */ - interface IHook extends IRunnable { - /** @deprecated `.ctx` has type `Mocha.Context` in `Mocha.Runnable`. */ - ctx?: IContext; - /** @deprecated `.parent` has type `Mocha.Suite` in `Mocha.Runnable`. */ - parent?: ISuite; - type: 'hook'; - /** @deprecated `.error()` has additional overloads in `Mocha.Hook`. */ - error(err: Error): void; - } - - /** @deprecated use `Mocha.Context` instead. */ - interface IBeforeAndAfterContext extends IHookCallbackContext { - /** @deprecated `.currentTest` has type `Mocha.Test` in `Mocha.Context`. */ - currentTest?: ITest; - } - - /** @deprecated use `Mocha.Stats` instead. */ - type IStats = Stats; - - /** Partial interface for Mocha's `Runner` class. */ - /** @deprecated use `Mocha.Runner` instead. */ - interface IRunner extends NodeJS.EventEmitter { - asyncOnly?: boolean; - stats?: IStats; - started: boolean; - /** @deprecated `.suite` has type `Mocha.Suite` in `Mocha.Runner`. */ - suite: ISuite; - total: number; - failures: number; - forbidOnly?: boolean; - forbidPending?: boolean; - fullStackTrace?: boolean; - ignoreLeaks?: boolean; - grep(re: RegExp, invert: boolean): this; - /** @deprecated Parameter `suite` has type `Mocha.Suite` in `Mocha.Runner`. */ - grepTotal(suite: ISuite): number; - /** @deprecated `.globals()` has different overloads in `Mocha.Runner`. */ - globals(arr: ReadonlyArray): this | string[]; - abort(): this; - run(fn?: (failures: number) => void): this; - } - - /** @deprecated use `Mocha.SuiteFunction` instead. */ - interface IContextDefinition { - /** @deprecated use `Mocha.SuiteFunction` instead. */ - (description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; - /** @deprecated use `Mocha.SuiteFunction` instead. */ - only(description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; - /** @deprecated use `Mocha.SuiteFunction` instead. */ - skip(description: string, callback: (this: ISuiteCallbackContext) => void): void; - } - - /** @deprecated use `Mocha.TestFunction` instead. */ - interface ITestDefinition { - /** @deprecated use `Mocha.TestFunction` instead. */ - /** @deprecated `Mocha.TestFunction` does not allow mixing `done` with a return type of `PromiseLike`. */ - (expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): ITest; - /** @deprecated use `Mocha.TestFunction` instead. */ - /** @deprecated `Mocha.TestFunction#only` does not allow mixing `done` with a return type of `PromiseLike`. */ - only(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): ITest; - /** @deprecated use `Mocha.TestFunction` instead. */ - /** @deprecated `Mocha.TestFunction#skip` does not allow mixing `done` with a return type of `PromiseLike`. */ - skip(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): void; - } - - // #endregion -} - -declare global { - // #region Test interface augmentations - - /** - * Triggers root suite execution. - * - * - _Only available if flag --delay is passed into Mocha._ - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#runWithSuite - */ - function run(): void; - - /** - * Execute before running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#before - */ - var before: Mocha.HookFunction; - - /** - * Execute before running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#before - */ - var suiteSetup: Mocha.HookFunction; - - /** - * Execute after running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#after - */ - var after: Mocha.HookFunction; - - /** - * Execute after running tests. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#after - */ - var suiteTeardown: Mocha.HookFunction; - - /** - * Execute before each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#beforeEach - */ - var beforeEach: Mocha.HookFunction; - - /** - * Execute before each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#beforeEach - */ - var setup: Mocha.HookFunction; - - /** - * Execute after each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#afterEach - */ - var afterEach: Mocha.HookFunction; - - /** - * Execute after each test case. - * - * - _Only available when invoked via the mocha CLI._ - * - * @see https://mochajs.org/api/global.html#afterEach - */ - var teardown: Mocha.HookFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - var describe: Mocha.SuiteFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - var context: Mocha.SuiteFunction; - - /** - * Describe a "suite" containing nested suites and tests. - * - * - _Only available when invoked via the mocha CLI._ - */ - var suite: Mocha.SuiteFunction; - - /** - * Pending suite. - * - * - _Only available when invoked via the mocha CLI._ - */ - var xdescribe: Mocha.PendingSuiteFunction; - - /** - * Pending suite. - * - * - _Only available when invoked via the mocha CLI._ - */ - var xcontext: Mocha.PendingSuiteFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - var it: Mocha.TestFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - var specify: Mocha.TestFunction; - - /** - * Describes a test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - var test: Mocha.TestFunction; - - /** - * Describes a pending test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - var xit: Mocha.PendingTestFunction; - - /** - * Describes a pending test case. - * - * - _Only available when invoked via the mocha CLI._ - */ - var xspecify: Mocha.PendingTestFunction; - - // #endregion Test interface augmentations - - // #region Reporter augmentations - - // Forward declaration for `HTMLLIElement` from lib.dom.d.ts. - // Required by Mocha.reporters.HTML. - // NOTE: Mocha *must not* have a direct dependency on DOM types. - // tslint:disable-next-line no-empty-interface - interface HTMLLIElement { } - - // Augments the DOM `Window` object when lib.dom.d.ts is loaded. - // tslint:disable-next-line no-empty-interface - interface Window extends Mocha.MochaGlobals { } - - namespace NodeJS { - // Forward declaration for `NodeJS.EventEmitter` from node.d.ts. - // Required by Mocha.Runnable, Mocha.Runner, and Mocha.Suite. - // NOTE: Mocha *must not* have a direct dependency on @types/node. - // tslint:disable-next-line no-empty-interface - interface EventEmitter { } - - // Augments NodeJS's `global` object when node.d.ts is loaded - // tslint:disable-next-line no-empty-interface - interface Global extends Mocha.MochaGlobals { } - } - - // #endregion Reporter augmentations - - // #region Browser augmentations - - /** - * Mocha global. - * - * - _Only supported in the browser._ - */ - const mocha: BrowserMocha; - - interface BrowserMocha extends Mocha { - /** - * Function to allow assertion libraries to throw errors directly into mocha. - * This is useful when running tests in a browser because window.onerror will - * only receive the 'message' attribute of the Error. - * - * - _Only supported in the browser._ - */ - throwError(err: any): never; - - /** - * Setup mocha with the given settings options. - * - * - _Only supported in the browser._ - */ - setup(opts?: Mocha.Interface | MochaSetupOptions): this; - } - - /** - * Options to pass to `mocha.setup` in the browser. - */ - interface MochaSetupOptions extends Mocha.MochaOptions { - // TODO: This does not seem to be supported according to the source. Should it be removed? - require?: string[]; - fullTrace?: boolean; - } - - // #endregion Browser augmentations - - // #region Deprecations - - /** @deprecated use `Mocha.DoneCallback` instead. */ - type MochaDone = Mocha.Done; - - /** @deprecated use `Mocha.ReporterConstructor` instead. */ - type ReporterConstructor = Mocha.ReporterConstructor; - - // #endregion Deprecations -} diff --git a/scripts/types/mocha/lib/interfaces/common.d.ts b/scripts/types/mocha/lib/interfaces/common.d.ts deleted file mode 100644 index 1deb9712e6..0000000000 --- a/scripts/types/mocha/lib/interfaces/common.d.ts +++ /dev/null @@ -1,109 +0,0 @@ -import Mocha = require("../../"); - -export = common; - -declare function common(suites: Mocha.Suite[], context: Mocha.MochaGlobals, mocha: Mocha): common.CommonFunctions; - -declare namespace common { - export interface CommonFunctions { - /** - * This is only present if flag --delay is passed into Mocha. It triggers - * root suite execution. - */ - runWithSuite(suite: Mocha.Suite): () => void; - - /** - * Execute before running tests. - */ - before(fn?: Mocha.Func | Mocha.AsyncFunc): void; - - /** - * Execute before running tests. - */ - before(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; - - /** - * Execute after running tests. - */ - after(fn?: Mocha.Func | Mocha.AsyncFunc): void; - - /** - * Execute after running tests. - */ - after(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; - - /** - * Execute before each test case. - */ - beforeEach(fn?: Mocha.Func | Mocha.AsyncFunc): void; - - /** - * Execute before each test case. - */ - beforeEach(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; - - /** - * Execute after each test case. - */ - afterEach(fn?: Mocha.Func | Mocha.AsyncFunc): void; - - /** - * Execute after each test case. - */ - afterEach(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; - - suite: SuiteFunctions; - test: TestFunctions; - } - - export interface CreateOptions { - /** Title of suite */ - title: string; - - /** Suite function */ - fn?: (this: Mocha.Suite) => void; - - /** Is suite pending? */ - pending?: boolean; - - /** Filepath where this Suite resides */ - file?: string; - - /** Is suite exclusive? */ - isOnly?: boolean; - } - - export interface SuiteFunctions { - /** - * Create an exclusive Suite; convenience function - */ - only(opts: CreateOptions): Mocha.Suite; - - /** - * Create a Suite, but skip it; convenience function - */ - skip(opts: CreateOptions): Mocha.Suite; - - /** - * Creates a suite. - */ - create(opts: CreateOptions): Mocha.Suite; - } - - export interface TestFunctions { - /** - * Exclusive test-case. - */ - only(mocha: Mocha, test: Mocha.Test): Mocha.Test; - - /** - * Pending test case. - */ - skip(title: string): void; - - /** - * Number of retry attempts - */ - retries(n: number): void; - } -} diff --git a/scripts/types/mocha/lib/ms.d.ts b/scripts/types/mocha/lib/ms.d.ts deleted file mode 100644 index 890da5b8c5..0000000000 --- a/scripts/types/mocha/lib/ms.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -export = milliseconds; - -/** - * Parse the given `str` and return milliseconds. - * - * @see {@link https://mochajs.org/api/module-milliseconds.html} - * @see {@link https://mochajs.org/api/module-milliseconds.html#~parse} - */ -declare function milliseconds(val: string): number; - -/** - * Format for `ms`. - * - * @see {@link https://mochajs.org/api/module-milliseconds.html} - * @see {@link https://mochajs.org/api/module-milliseconds.html#~format} - */ -declare function milliseconds(val: number): string; diff --git a/scripts/types/mocha/package.json b/scripts/types/mocha/package.json deleted file mode 100644 index e45485e803..0000000000 --- a/scripts/types/mocha/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "@types/mocha", - "private": true, - "version": "5.2.1" -} diff --git a/src/harness/harness.ts b/src/harness/harness.ts index a78a04c3ec..f03103d023 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -47,23 +47,6 @@ interface XMLHttpRequest { /* tslint:enable:no-var-keyword prefer-const */ namespace Utils { - // Setup some globals based on the current environment - export const enum ExecutionEnvironment { - Node, - Browser, - } - - export function getExecutionEnvironment() { - if (typeof window !== "undefined") { - return ExecutionEnvironment.Browser; - } - else { - return ExecutionEnvironment.Node; - } - } - - export let currentExecutionEnvironment = getExecutionEnvironment(); - export function encodeString(s: string): string { return ts.sys.bufferFrom!(s).toString("utf8"); } @@ -74,23 +57,12 @@ namespace Utils { } export function evalFile(fileContents: string, fileName: string, nodeContext?: any) { - const environment = getExecutionEnvironment(); - switch (environment) { - case ExecutionEnvironment.Browser: - // tslint:disable-next-line:no-eval - eval(fileContents); - break; - case ExecutionEnvironment.Node: - const vm = require("vm"); - if (nodeContext) { - vm.runInNewContext(fileContents, nodeContext, fileName); - } - else { - vm.runInThisContext(fileContents, fileName); - } - break; - default: - throw new Error("Unknown context"); + const vm = require("vm"); + if (nodeContext) { + vm.runInNewContext(fileContents, nodeContext, fileName); + } + else { + vm.runInThisContext(fileContents, fileName); } } @@ -624,344 +596,11 @@ namespace Harness { }; } - interface URL { - hash: string; - host: string; - hostname: string; - href: string; - password: string; - pathname: string; - port: string; - protocol: string; - search: string; - username: string; - toString(): string; - } - - declare var URL: { - prototype: URL; - new(url: string, base?: string | URL): URL; - }; - - function createBrowserIO(): IO { - const serverRoot = new URL("http://localhost:8888/"); - - class HttpHeaders extends collections.SortedMap { - constructor(template?: Record) { - super(ts.compareStringsCaseInsensitive); - if (template) { - for (const key in template) { - if (ts.hasProperty(template, key)) { - this.set(key, template[key]); - } - } - } - } - - public static combine(left: HttpHeaders | undefined, right: HttpHeaders | undefined): HttpHeaders | undefined { - if (!left && !right) return undefined; - const headers = new HttpHeaders(); - if (left) left.forEach((value, key) => { headers.set(key, value); }); - if (right) right.forEach((value, key) => { headers.set(key, value); }); - return headers; - } - - public has(key: string) { - return super.has(key.toLowerCase()); - } - - public get(key: string) { - return super.get(key.toLowerCase()); - } - - public set(key: string, value: string | string[]) { - return super.set(key.toLowerCase(), value); - } - - public delete(key: string) { - return super.delete(key.toLowerCase()); - } - - public writeRequestHeaders(xhr: XMLHttpRequest) { - this.forEach((values, key) => { - if (key === "access-control-allow-origin" || key === "content-length") return; - const value = Array.isArray(values) ? values.join(",") : values; - if (key === "content-type") { - xhr.overrideMimeType(value); - return; - } - xhr.setRequestHeader(key, value); - }); - } - - public static readResponseHeaders(xhr: XMLHttpRequest): HttpHeaders { - const allHeaders = xhr.getAllResponseHeaders(); - const headers = new HttpHeaders(); - for (const header of allHeaders.split(/\r\n/g)) { - const colonIndex = header.indexOf(":"); - if (colonIndex >= 0) { - const key = header.slice(0, colonIndex).trim(); - const value = header.slice(colonIndex + 1).trim(); - const values = value.split(","); - headers.set(key, values.length > 1 ? values : value); - } - } - return headers; - } - } - - class HttpContent { - public headers: HttpHeaders; - public content: string; - - constructor(headers: HttpHeaders | Record, content: string) { - this.headers = headers instanceof HttpHeaders ? headers : new HttpHeaders(headers); - this.content = content; - } - - public static fromMediaType(mediaType: string, content: string) { - return new HttpContent({ "Content-Type": mediaType }, content); - } - - public static text(content: string) { - return HttpContent.fromMediaType("text/plain", content); - } - - public static json(content: object) { - return HttpContent.fromMediaType("application/json", JSON.stringify(content)); - } - - public static readResponseContent(xhr: XMLHttpRequest) { - if (typeof xhr.responseText === "string") { - return new HttpContent({ - "Content-Type": xhr.getResponseHeader("Content-Type") || undefined!, // TODO: GH#18217 - "Content-Length": xhr.getResponseHeader("Content-Length") || undefined!, // TODO: GH#18217 - }, xhr.responseText); - } - return undefined; - } - - public writeRequestHeaders(xhr: XMLHttpRequest) { - this.headers.writeRequestHeaders(xhr); - } - } - - class HttpRequestMessage { - public method: string; - public url: URL; - public headers: HttpHeaders; - public content?: HttpContent; - - constructor(method: string, url: string | URL, headers?: HttpHeaders | Record, content?: HttpContent) { - this.method = method; - this.url = typeof url === "string" ? new URL(url) : url; - this.headers = headers instanceof HttpHeaders ? headers : new HttpHeaders(headers); - this.content = content; - } - - public static options(url: string | URL) { - return new HttpRequestMessage("OPTIONS", url); - } - - public static head(url: string | URL) { - return new HttpRequestMessage("HEAD", url); - } - - public static get(url: string | URL) { - return new HttpRequestMessage("GET", url); - } - - public static delete(url: string | URL) { - return new HttpRequestMessage("DELETE", url); - } - - public static put(url: string | URL, content: HttpContent) { - return new HttpRequestMessage("PUT", url, /*headers*/ undefined, content); - } - - public static post(url: string | URL, content: HttpContent) { - return new HttpRequestMessage("POST", url, /*headers*/ undefined, content); - } - - public writeRequestHeaders(xhr: XMLHttpRequest) { - this.headers.writeRequestHeaders(xhr); - if (this.content) { - this.content.writeRequestHeaders(xhr); - } - } - } - - class HttpResponseMessage { - public statusCode: number; - public statusMessage: string; - public headers: HttpHeaders; - public content?: HttpContent; - - constructor(statusCode: number, statusMessage: string, headers?: HttpHeaders | Record, content?: HttpContent) { - this.statusCode = statusCode; - this.statusMessage = statusMessage; - this.headers = headers instanceof HttpHeaders ? headers : new HttpHeaders(headers); - this.content = content; - } - - public static notFound(): HttpResponseMessage { - return new HttpResponseMessage(404, "Not Found"); - } - - public static hasSuccessStatusCode(response: HttpResponseMessage) { - return response.statusCode === 304 || (response.statusCode >= 200 && response.statusCode < 300); - } - - public static readResponseMessage(xhr: XMLHttpRequest) { - return new HttpResponseMessage( - xhr.status, - xhr.statusText, - HttpHeaders.readResponseHeaders(xhr), - HttpContent.readResponseContent(xhr)); - } - } - - function send(request: HttpRequestMessage): HttpResponseMessage { - const xhr = new XMLHttpRequest(); - try { - xhr.open(request.method, request.url.toString(), /*async*/ false); - request.writeRequestHeaders(xhr); - xhr.setRequestHeader("Access-Control-Allow-Origin", "*"); - xhr.send(request.content && request.content.content); - while (xhr.readyState !== 4); // block until ready - return HttpResponseMessage.readResponseMessage(xhr); - } - catch (e) { - return HttpResponseMessage.notFound(); - } - } - - let caseSensitivity: "CI" | "CS" | undefined; - - function useCaseSensitiveFileNames() { - if (!caseSensitivity) { - const response = send(HttpRequestMessage.options(new URL("*", serverRoot))); - const xCaseSensitivity = response.headers.get("X-Case-Sensitivity"); - caseSensitivity = xCaseSensitivity === "CS" ? "CS" : "CI"; - } - return caseSensitivity === "CS"; - } - - function resolvePath(path: string) { - const response = send(HttpRequestMessage.post(new URL("/api/resolve", serverRoot), HttpContent.text(path))); - return HttpResponseMessage.hasSuccessStatusCode(response) && response.content ? response.content.content : undefined; - } - - function getFileSize(path: string): number { - const response = send(HttpRequestMessage.head(new URL(path, serverRoot))); - return HttpResponseMessage.hasSuccessStatusCode(response) ? +response.headers.get("Content-Length")!.toString() : 0; - } - - function readFile(path: string): string | undefined { - const response = send(HttpRequestMessage.get(new URL(path, serverRoot))); - return HttpResponseMessage.hasSuccessStatusCode(response) && response.content ? response.content.content : undefined; - } - - function writeFile(path: string, contents: string) { - send(HttpRequestMessage.put(new URL(path, serverRoot), HttpContent.text(contents))); - } - - function fileExists(path: string): boolean { - const response = send(HttpRequestMessage.head(new URL(path, serverRoot))); - return HttpResponseMessage.hasSuccessStatusCode(response); - } - - function directoryExists(path: string): boolean { - const response = send(HttpRequestMessage.post(new URL("/api/directoryExists", serverRoot), HttpContent.text(path))); - return hasJsonContent(response) && JSON.parse(response.content.content) as boolean; - } - - function deleteFile(path: string) { - send(HttpRequestMessage.delete(new URL(path, serverRoot))); - } - - function directoryName(path: string) { - const url = new URL(path, serverRoot); - return ts.getDirectoryPath(ts.normalizeSlashes(url.pathname || "/")); - } - - function enumerateTestFiles(runner: RunnerBase): (string | FileBasedTest)[] { - const response = send(HttpRequestMessage.post(new URL("/api/enumerateTestFiles", serverRoot), HttpContent.text(runner.kind()))); - return hasJsonContent(response) ? JSON.parse(response.content.content) : []; - } - - function listFiles(dirname: string, spec?: RegExp, options?: { recursive?: boolean }): string[] { - if (spec || (options && !options.recursive)) { - let results = IO.listFiles(dirname); - if (spec) { - results = results.filter(file => spec.test(file)); - } - if (options && !options.recursive) { - results = results.filter(file => ts.getDirectoryPath(ts.normalizeSlashes(file)) === dirname); - } - return results; - } - - const response = send(HttpRequestMessage.post(new URL("/api/listFiles", serverRoot), HttpContent.text(dirname))); - return hasJsonContent(response) ? JSON.parse(response.content.content) : []; - } - - function readDirectory(path: string, extension?: string[], exclude?: string[], include?: string[], depth?: number) { - return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), "", depth, getAccessibleFileSystemEntries); - } - - function getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries { - const response = send(HttpRequestMessage.post(new URL("/api/getAccessibleFileSystemEntries", serverRoot), HttpContent.text(dirname))); - return hasJsonContent(response) ? JSON.parse(response.content.content) : { files: [], directories: [] }; - } - - function hasJsonContent(response: HttpResponseMessage): response is HttpResponseMessage & { content: HttpContent } { - return HttpResponseMessage.hasSuccessStatusCode(response) - && !!response.content - && /^application\/json(;.*)$/.test("" + response.content.headers.get("Content-Type")); - } - - return { - newLine: () => harnessNewLine, - getCurrentDirectory: () => "", - useCaseSensitiveFileNames, - resolvePath, - getFileSize, - readFile, - writeFile, - directoryName: Utils.memoize(directoryName, path => path), - getDirectories: () => [], - createDirectory: () => {}, // tslint:disable-line no-empty - fileExists, - directoryExists, - deleteFile, - listFiles: Utils.memoize(listFiles, (path, spec, options) => `${path}|${spec}|${options ? options.recursive === true : true}`), - enumerateTestFiles: Utils.memoize(enumerateTestFiles, runner => runner.kind()), - log: s => console.log(s), - args: () => [], - getExecutingFilePath: () => "", - exit: () => {}, // tslint:disable-line no-empty - readDirectory, - getAccessibleFileSystemEntries, - getWorkspaceRoot: () => "/" - }; - } - export function mockHash(s: string): string { return `hash-${s}`; } - const environment = Utils.getExecutionEnvironment(); - switch (environment) { - case Utils.ExecutionEnvironment.Node: - IO = createNodeIO(); - break; - case Utils.ExecutionEnvironment.Browser: - IO = createBrowserIO(); - break; - default: - throw new Error(`Unknown value '${environment}' for ExecutionEnvironment.`); - } + IO = createNodeIO(); } if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable!("NODE_ENV"))) { @@ -970,10 +609,8 @@ if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.ge namespace Harness { export const libFolder = "built/local/"; - const tcServicesFileName = ts.combinePaths(libFolder, Utils.getExecutionEnvironment() === Utils.ExecutionEnvironment.Browser ? "typescriptServicesInBrowserTest.js" : "typescriptServices.js"); - export const tcServicesFile = IO.readFile(tcServicesFileName) + (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser - ? IO.newLine() + `//# sourceURL=${IO.resolvePath(tcServicesFileName)}` - : ""); + const tcServicesFileName = ts.combinePaths(libFolder, "typescriptServices.js"); + export const tcServicesFile = IO.readFile(tcServicesFileName) + IO.newLine() + `//# sourceURL=${IO.resolvePath(tcServicesFileName)}`; export type SourceMapEmitterCallback = ( emittedFile: string, diff --git a/src/testRunner/parallel/host.ts b/src/testRunner/parallel/host.ts index 597013ed0d..3e531561e5 100644 --- a/src/testRunner/parallel/host.ts +++ b/src/testRunner/parallel/host.ts @@ -538,25 +538,23 @@ namespace Harness.Parallel.Host { let xunitReporter: import("mocha").reporters.XUnit | undefined; let failedTestReporter: import("../../../scripts/failed-tests") | undefined; - if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser) { - if (process.env.CI === "true") { - xunitReporter = new Mocha.reporters.XUnit(replayRunner, { - reporterOptions: { - suiteName: "Tests", - output: "./TEST-results.xml" - } - }); - patchStats(xunitReporter.stats); - xunitReporter.write(`\n`); - } - else { - failedTestReporter = new FailedTestReporter(replayRunner, { - reporterOptions: { - file: path.resolve(".failed-tests"), - keepFailed - } - }); - } + if (process.env.CI === "true") { + xunitReporter = new Mocha.reporters.XUnit(replayRunner, { + reporterOptions: { + suiteName: "Tests", + output: "./TEST-results.xml" + } + }); + patchStats(xunitReporter.stats); + xunitReporter.write(`\n`); + } + else { + failedTestReporter = new FailedTestReporter(replayRunner, { + reporterOptions: { + file: path.resolve(".failed-tests"), + keepFailed + } + }); } const savedUseColors = Base.useColors; diff --git a/src/testRunner/runner.ts b/src/testRunner/runner.ts index e528678ab8..be46d93529 100644 --- a/src/testRunner/runner.ts +++ b/src/testRunner/runner.ts @@ -182,10 +182,7 @@ function handleTestConfig() { runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance)); runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions)); - // TODO: project tests don"t work in the browser yet - if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser) { - runners.push(new project.ProjectRunner()); - } + runners.push(new project.ProjectRunner()); // language services runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Native)); @@ -195,7 +192,7 @@ function handleTestConfig() { // runners.push(new GeneratedFourslashRunner()); // CRON-only tests - if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser && process.env.TRAVIS_EVENT_TYPE === "cron") { + if (process.env.TRAVIS_EVENT_TYPE === "cron") { runners.push(new UserCodeRunner()); } } @@ -229,13 +226,11 @@ function beginTests() { let isWorker: boolean; function startTestEnvironment() { isWorker = handleTestConfig(); - if (Utils.getExecutionEnvironment() !== Utils.ExecutionEnvironment.Browser) { - if (isWorker) { - return Harness.Parallel.Worker.start(); - } - else if (taskConfigsFolder && workerCount && workerCount > 1) { - return Harness.Parallel.Host.start(); - } + if (isWorker) { + return Harness.Parallel.Worker.start(); + } + else if (taskConfigsFolder && workerCount && workerCount > 1) { + return Harness.Parallel.Host.start(); } beginTests(); } diff --git a/tests/perfsys.ts b/tests/perfsys.ts deleted file mode 100644 index abe09c88a0..0000000000 --- a/tests/perfsys.ts +++ /dev/null @@ -1,104 +0,0 @@ -/// -/// - -namespace perftest { - interface IOLog { - resolvePath: ts.Map; - fileNames: string[]; - } - - export interface IO { - getOut(): string; - } - - export const readFile = ts.sys.readFile; - const writeFile = ts.sys.writeFile; - export const write = ts.sys.write; - const resolvePath = ts.sys.resolvePath; - export const getExecutingFilePath = ts.sys.getExecutingFilePath; - export const getCurrentDirectory = ts.sys.getCurrentDirectory; - // const exit = ts.sys.exit; - - const args = ts.sys.args; - - // augment sys so first ts.executeCommandLine call will be finish silently - ts.sys.write = (s: string) => { }; - ts.sys.exit = (code: number) => { }; - ts.sys.args = []; - - export function restoreSys() { - ts.sys.args = args; - ts.sys.write = write; - } - - export function hasLogIOFlag() { - return args.length > 2 && args[0] === "--logio"; - } - - export function getArgsWithoutLogIOFlag() { - return args.slice(2); - } - - export function getArgsWithoutIOLogFile() { - return args.slice(1); - } - - const resolvePathLog: ts.Map = {}; - - export function interceptIO() { - ts.sys.resolvePath = (s) => { - const result = resolvePath(s); - resolvePathLog[s] = result; - return result; - }; - } - - export function writeIOLog(fileNames: string[]) { - const path = args[1]; - const log: IOLog = { - fileNames: fileNames, - resolvePath: resolvePathLog - }; - - writeFile(path, JSON.stringify(log)); - } - - export function prepare(): IO { - const log = JSON.parse(readFile(args[0])); - - const files: ts.Map = {}; - log.fileNames.forEach(f => { files[f] = readFile(f); }); - - ts.sys.createDirectory = (s: string) => { }; - ts.sys.directoryExists = (s: string) => true; - ts.sys.fileExists = (s: string) => true; - - const currentDirectory = ts.sys.getCurrentDirectory(); - ts.sys.getCurrentDirectory = () => currentDirectory; - - const executingFilePath = ts.sys.getExecutingFilePath(); - ts.sys.getExecutingFilePath = () => executingFilePath; - - ts.sys.readFile = (s: string) => { - return files[s]; - }; - - ts.sys.resolvePath = (s: string) => { - const path = log.resolvePath[s]; - if (!path) { - throw new Error("Unexpected path '" + s + "'"); - } - return path; - }; - - ts.sys.writeFile = (path: string, data: string) => { }; - - let out = ""; - - ts.sys.write = (s: string) => { out += s; }; - - return { - getOut: () => out, - }; - } -} diff --git a/tests/perftsc.ts b/tests/perftsc.ts deleted file mode 100644 index 0753023853..0000000000 --- a/tests/perftsc.ts +++ /dev/null @@ -1,30 +0,0 @@ -/// -/// - -// resolve all files used in this compilation -if (perftest.hasLogIOFlag()) { - perftest.interceptIO(); - - const compilerHost: ts.CompilerHost = { - getSourceFile: (s, v) => { - const content = perftest.readFile(s); - return content !== undefined ? ts.createSourceFile(s, content, v) : undefined; - }, - getDefaultLibFileName: () => ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(perftest.getExecutingFilePath())), "lib.d.ts"), - writeFile: (f: string, content: string) => { throw new Error("Unexpected operation: writeFile"); }, - getCurrentDirectory: () => perftest.getCurrentDirectory(), - getCanonicalFileName: (f: string) => ts.sys.useCaseSensitiveFileNames ? f : f.toLowerCase(), - useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, - getNewLine: () => ts.sys.newLine - }; - - const commandLine = ts.parseCommandLine(perftest.getArgsWithoutLogIOFlag()); - const program = ts.createProgram(commandLine.fileNames, commandLine.options, compilerHost); - const fileNames = program.getSourceFiles().map(f => f.fileName); - perftest.writeIOLog(fileNames); -} -else { - const io = perftest.prepare(); - ts.executeCommandLine(perftest.getArgsWithoutIOLogFile()); - perftest.write(io.getOut()); -} diff --git a/tests/perftsc.tsconfig.json b/tests/perftsc.tsconfig.json deleted file mode 100644 index dafd33f9de..0000000000 --- a/tests/perftsc.tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "target": "es2015", - "module": "commonjs", - "declaration": false, - "removeComments": true, - "noResolve": false, - "stripInternal": false, - "sourceMap": true, - "outFile": "../built/local/perftsc.js" - }, - "files": [ - "perftsc.ts" - ] -} \ No newline at end of file diff --git a/tests/test.bat b/tests/test.bat deleted file mode 100644 index 4517d99f3c..0000000000 --- a/tests/test.bat +++ /dev/null @@ -1,13 +0,0 @@ -@echo off -setlocal -set LF=^ - - -for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a" - -setlocal enableDelayedExpansion -echo "START" -echo "asdf!CR!asdf" -echo "AASDF!LF!ASDF" -echo "END" -findstr /S /R /M /C:"[^!CR!]!LF!" * diff --git a/tests/webTestResults.html b/tests/webTestResults.html deleted file mode 100644 index 487abfc117..0000000000 --- a/tests/webTestResults.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - Mocha Tests - - - - - -
- -
-
- - - - - - - - - \ No newline at end of file diff --git a/tests/webTestServer.ts b/tests/webTestServer.ts deleted file mode 100644 index c33196a99c..0000000000 --- a/tests/webTestServer.ts +++ /dev/null @@ -1,1014 +0,0 @@ -/// -// tslint:disable:no-null-keyword - -import minimist = require("minimist"); -import http = require("http"); -import fs = require("fs"); -import path = require("path"); -import url = require("url"); -import URL = url.URL; -import child_process = require("child_process"); -import os = require("os"); -import crypto = require("crypto"); -import { Readable, Writable } from "stream"; -import { isBuffer, isString, isObject } from "util"; -import { install, getErrorSource } from "source-map-support"; - -install(); - -const port = 8888; // harness.ts and webTestResults.html depend on this exact port number. -const baseUrl = new URL(`http://localhost:${port}/`); -const rootDir = path.dirname(__dirname); -const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); - -const defaultBrowser = os.platform() === "win32" ? "edge" : "chrome"; -let browser: "edge" | "chrome" | "none" = defaultBrowser; -let grep: string | undefined; -let verbose = false; - -interface FileBasedTest { - file: string; - configurations?: FileBasedTestConfiguration[]; -} - -interface FileBasedTestConfiguration { - [setting: string]: string; -} - -function isFileSystemCaseSensitive(): boolean { - // win32\win64 are case insensitive platforms - const platform = os.platform(); - if (platform === "win32" || platform === "win64") { - return false; - } - // If this file exists under a different case, we must be case-insensitve. - return !fs.existsSync(swapCase(__filename)); -} - -function swapCase(s: string): string { - return s.replace(/\w/g, (ch) => { - const up = ch.toUpperCase(); - return ch === up ? ch.toLowerCase() : up; - }); -} - -function hasLeadingSeparator(pathname: string) { - const ch = pathname.charAt(0); - return ch === "/" || ch === "\\"; -} - -function ensureLeadingSeparator(pathname: string) { - return hasLeadingSeparator(pathname) ? pathname : "/" + pathname; -} - -function trimLeadingSeparator(pathname: string) { - return hasLeadingSeparator(pathname) ? pathname.slice(1) : pathname; -} - -function normalizeSlashes(path: string) { - return path.replace(/\\+/g, "/"); -} - -function hasTrailingSeparator(pathname: string) { - const ch = pathname.charAt(pathname.length - 1); - return ch === "/" || ch === "\\"; -} - -function toServerPath(url: url.URL | string) { - if (typeof url === "string") url = new URL(url, baseUrl); - const pathname = decodeURIComponent(url.pathname); - return path.join(rootDir, pathname); -} - -function toClientPath(pathname: string) { - pathname = normalizeSlashes(pathname); - pathname = trimLeadingSeparator(pathname); - - const serverPath = path.resolve(rootDir, pathname); - if (serverPath.slice(0, rootDir.length) !== rootDir) { - return undefined; - } - - let clientPath = serverPath.slice(rootDir.length); - clientPath = ensureLeadingSeparator(clientPath); - clientPath = normalizeSlashes(clientPath); - return clientPath; -} - -function flatMap(array: T[], selector: (value: T) => U | U[]) { - let result: U[] = []; - for (const item of array) { - const mapped = selector(item); - if (Array.isArray(mapped)) { - result = result.concat(mapped); - } - else { - result.push(mapped); - } - } - return result; -} - -declare module "http" { - interface IncomingHttpHeaders { - "if-match"?: string; - "if-none-match"?: string; - "if-modified-since"?: string; - "if-unmodified-since"?: string; - "accept-charset"?: string; - "accept-encoding"?: string; - "range"?: string; - } -} - -function getQuality(value: T) { - return value.quality === undefined ? 1 : value.quality; -} - -function bestMatch(value: T, patterns: TPattern[], isMatch: (value: T, pattern: TPattern) => boolean) { - let match: TPattern | undefined; - for (const pattern of patterns) { - if (!isMatch(value, pattern)) continue; - if (match === undefined || getQuality(pattern) > getQuality(match)) { - match = pattern; - } - } - return match; -} - -const mediaTypeParser = /^([^\/]+)\/([^\/;]+)(?:;(.*))?$/; - -interface MediaType { - type: string; - subtype: string; - parameters: Record; - charset?: string; - quality?: number; -} - -function parseMediaType(mediaType: string): MediaType { - const match = mediaTypeParser.exec(mediaType); - if (!match) throw new Error("Invalid media type"); - const type = match[1].trim(); - const subtype = match[2].trim(); - if (type === "*" && subtype !== "*") throw new Error("Invalid media type"); - const parameters: Record = {}; - let charset: string | undefined; - let quality: number | undefined; - if (match[3]) { - for (const parameter of match[3].split(";")) { - const pair = parameter.split("="); - const name = pair[0].trim(); - const value = pair[1].trim(); - parameters[name] = value; - if (name === "charset") charset = value; - if (name === "q") quality = +value; - } - } - return { type, subtype, parameters, charset, quality }; -} - -function parseMediaTypes(value: string) { - const mediaTypes: MediaType[] = []; - for (const mediaRange of value.split(",")) { - mediaTypes.push(parseMediaType(mediaRange)); - } - return mediaTypes; -} - -function matchesMediaType(mediaType: MediaType, mediaTypePattern: MediaType) { - if (mediaTypePattern.type === "*") return true; - if (mediaTypePattern.type === mediaType.type) { - if (mediaTypePattern.subtype === "*") return true; - if (mediaTypePattern.subtype === mediaType.subtype) return true; - } - return false; -} - -interface StringWithQuality { - value: string; - quality?: number; -} - -const stringWithQualityParser = /^([^;]+)(;\s*q\s*=\s*([^\s]+)\s*)?$/; - -function parseStringWithQuality(value: string) { - const match = stringWithQualityParser.exec(value); - if (!match) throw new Error("Invalid header value"); - return { value: match[1].trim(), quality: match[2] ? +match[2] : undefined }; -} - -function parseStringsWithQuality(value: string) { - const charsets: StringWithQuality[] = []; - for (const charset of value.split(",")) { - charsets.push(parseStringWithQuality(charset)); - } - return charsets; -} - -function matchesCharSet(charset: string, charsetPattern: StringWithQuality) { - return charsetPattern.value === "*" || charsetPattern.value === charset; -} - -function computeETag(stats: fs.Stats) { - return JSON.stringify(crypto - .createHash("sha1") - .update(JSON.stringify({ - dev: stats.dev, - ino: stats.ino, - mtime: stats.mtimeMs, - size: stats.size - })) - .digest("base64")); -} - -function tryParseETags(value: string | undefined): "*" | string[] | undefined { - if (!value) return undefined; - if (value === "*") return value; - const etags: string[] = []; - for (const etag of value.split(",")) { - etags.push(etag.trim()); - } - return etags; -} - -function matchesETag(etag: string | undefined, condition: "*" | string[] | undefined) { - if (!condition) return true; - if (!etag) return false; - return condition === "*" || condition.indexOf(etag) >= 0; -} - -function tryParseDate(value: string | undefined) { - return value ? new Date(value) : undefined; -} - -interface ByteRange { - start: number; - end: number; -} - -const byteRangeParser = /^\s*(\d+)\s*-\s*(\d+)\s*$/; - -function tryParseByteRange(value: string, contentLength: number): ByteRange | undefined { - const match = byteRangeParser.exec(value); - const firstBytePos = match && match[1] ? +match[1] : undefined; - const lastBytePos = match && match[2] ? +match[2] : undefined; - if (firstBytePos !== undefined && lastBytePos !== undefined) { - if (lastBytePos < firstBytePos) return undefined; - return { start: firstBytePos, end: lastBytePos + 1 }; - } - if (firstBytePos !== undefined) return { start: firstBytePos, end: contentLength }; - if (lastBytePos !== undefined) return { start: contentLength - lastBytePos, end: contentLength }; - return undefined; -} - -function tryParseByteRanges(value: string, contentLength: number): ByteRange[] | undefined { - if (!value.startsWith("bytes=")) return; - const ranges: ByteRange[] = []; - for (const range of value.slice(6).split(",")) { - const byteRange = tryParseByteRange(range, contentLength); - if (byteRange === undefined) return undefined; - if (byteRange.start >= contentLength) continue; - ranges.push(byteRange); - } - return ranges; -} - -function once void>(callback: T): T; -function once(callback: (...args: any[]) => void) { - let called = false; - return (...args: any[]) => { - if (called) return; - called = true; - callback(...args); - }; -} - -function mkdirp(dirname: string, callback: (err: NodeJS.ErrnoException | null) => void) { - fs.mkdir(dirname, err => { - if (err && err.code === "EEXIST") err = null; - if (err && err.code === "ENOENT") { - const parentdir = path.dirname(dirname); - if (!parentdir || parentdir === dirname) return callback(err); - return mkdirp(parentdir, err => { - if (err) return callback(err); - return fs.mkdir(dirname, callback); - }); - } - return callback(err); - }); -} - -function getAccessibleFileSystemEntries(pathname: string) { - try { - const entries = fs.readdirSync(pathname).sort(); - const files: string[] = []; - const directories: string[] = []; - for (const entry of entries) { - // This is necessary because on some file system node fails to exclude - // "." and "..". See https://github.com/nodejs/node/issues/4002 - if (entry === "." || entry === "..") { - continue; - } - const name = path.join(pathname, entry); - - let stat: fs.Stats; - try { - stat = fs.statSync(name); - } - catch (e) { - continue; - } - - if (stat.isFile()) { - files.push(entry); - } - else if (stat.isDirectory()) { - directories.push(entry); - } - } - return { files, directories }; - } - catch (e) { - return { files: [], directories: [] }; - } -} - -function guessMediaType(pathname: string) { - switch (path.extname(pathname).toLowerCase()) { - case ".html": return "text/html; charset=utf-8"; - case ".css": return "text/css; charset=utf-8"; - case ".js": return "application/javascript; charset=utf-8"; - case ".mjs": return "application/javascript; charset=utf-8"; - case ".jsx": return "text/jsx; charset=utf-8"; - case ".ts": return "text/plain; charset=utf-8"; - case ".tsx": return "text/plain; charset=utf-8"; - case ".json": return "text/plain; charset=utf-8"; - case ".map": return "application/json; charset=utf-8"; - default: return "application/octet-stream"; - } -} - -function readContent(req: http.ServerRequest, callback: (err: NodeJS.ErrnoException | null, content: string | null) => void) { - const chunks: Buffer[] = []; - const done = once((err: NodeJS.ErrnoException | null) => { - if (err) return callback(err, /*content*/ null); - let content: string | null = null; - try { - content = Buffer.concat(chunks).toString("utf8"); - } - catch (e) { - err = e; - } - return callback(err, content); - }); - req.on("data", chunk => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8"))); - req.on("error", err => done(err)); - req.on("end", () => done(/*err*/ null)); -} - -function saveToFile(file: string, readable: Readable, callback: (err: NodeJS.ErrnoException | null) => void) { - callback = once(callback); - const writable = fs.createWriteStream(file, { autoClose: true }); - writable.on("error", err => callback(err)); - readable.on("end", () => callback(/*err*/ null)); - readable.pipe(writable, { end: true }); -} - -function sendContent(res: http.ServerResponse, statusCode: number, content: string | Buffer, contentType: string): void; -function sendContent(res: http.ServerResponse, statusCode: number, content: Readable, contentType: string, contentLength: number): void; -function sendContent(res: http.ServerResponse, statusCode: number, content: string | Buffer | Readable, contentType: string, contentLength?: number) { - res.statusCode = statusCode; - res.setHeader("Content-Type", contentType); - if (isString(content)) { - res.setHeader("Content-Length", Buffer.byteLength(content, "utf8")); - res.end(content, "utf8"); - } - else if (isBuffer(content)) { - res.setHeader("Content-Length", content.byteLength); - res.end(content); - } - else { - if (contentLength !== undefined) res.setHeader("Content-Length", contentLength); - content.on("error", e => sendInternalServerError(res, e)); - content.pipe(res, { end: true }); - } -} - -function sendJson(res: http.ServerResponse, statusCode: number, value: any) { - try { - sendContent(res, statusCode, JSON.stringify(value), "application/json; charset=utf-8"); - } - catch (e) { - sendInternalServerError(res, e); - } -} - -function sendCreated(res: http.ServerResponse, location?: string, etag?: string) { - res.statusCode = 201; - if (location) res.setHeader("Location", location); - if (etag) res.setHeader("ETag", etag); - res.end(); -} - -function sendNoContent(res: http.ServerResponse) { - res.statusCode = 204; - res.end(); -} - -function sendFound(res: http.ServerResponse, location: string) { - res.statusCode = 302; - res.setHeader("Location", location); - res.end(); -} - -function sendNotModified(res: http.ServerResponse) { - res.statusCode = 304; - res.end(); -} - -function sendBadRequest(res: http.ServerResponse) { - res.statusCode = 400; - res.end(); -} - -function sendNotFound(res: http.ServerResponse) { - res.statusCode = 404; - res.end(); -} - -function sendMethodNotAllowed(res: http.ServerResponse, allowedMethods: string[]) { - res.statusCode = 405; - res.setHeader("Allow", allowedMethods); - res.end(); -} - -function sendNotAcceptable(res: http.ServerResponse) { - res.statusCode = 406; - res.end(); -} - -function sendPreconditionFailed(res: http.ServerResponse) { - res.statusCode = 412; - res.end(); -} - -function sendUnsupportedMediaType(res: http.ServerResponse) { - res.statusCode = 415; - res.end(); -} - -function sendRangeNotSatisfiable(res: http.ServerResponse) { - res.statusCode = 416; - res.end(); -} - -function sendInternalServerError(res: http.ServerResponse, error: Error) { - console.error(error); - return sendContent(res, /*statusCode*/ 500, error.stack, "text/plain; charset=utf8"); -} - -function sendNotImplemented(res: http.ServerResponse) { - res.statusCode = 501; - res.end(); -} - -function shouldIgnoreCache(url: URL) { - switch (url.pathname) { - case "/built/local/bundle.js": - case "/built/local/bundle.js.map": - return true; - default: - return false; - } -} - -function isAcceptable(req: http.ServerRequest, contentType: string) { - const mediaType = parseMediaType(contentType); - return isAcceptableMediaType(req, mediaType) - && isAcceptableCharSet(req, mediaType) - && isAcceptableEncoding(req); -} - -function isAcceptableMediaType(req: http.ServerRequest, mediaType: MediaType) { - if (!req.headers.accept) return true; - const acceptedMediaType = bestMatch(mediaType, parseMediaTypes(req.headers.accept), matchesMediaType); - return acceptedMediaType ? getQuality(acceptedMediaType) > 0 : false; -} - -function isAcceptableCharSet(req: http.ServerRequest, mediaType: MediaType) { - if (!req.headers["accept-charset"]) return true; - const acceptedCharSet = bestMatch(mediaType.charset || "utf-8", parseStringsWithQuality(req.headers["accept-charset"]), matchesCharSet); - return acceptedCharSet ? getQuality(acceptedCharSet) > 0 : false; -} - -function isAcceptableEncoding(req: http.ServerRequest) { - if (!req.headers["accept-encoding"]) return true; - const acceptedEncoding = bestMatch(/*value*/ undefined, parseStringsWithQuality(req.headers["accept-encoding"]), (_, pattern) => pattern.value === "*" || pattern.value === "identity"); - return acceptedEncoding ? getQuality(acceptedEncoding) > 0 : true; -} - -function shouldSendNotModified(req: http.ServerRequest, stats: fs.Stats, etag: string) { - const ifNoneMatch = tryParseETags(req.headers["if-none-match"]); - if (ifNoneMatch) return matchesETag(etag, ifNoneMatch); - - const ifModifiedSince = tryParseDate(req.headers["if-modified-since"]); - if (ifModifiedSince) return stats.mtime.getTime() <= ifModifiedSince.getTime(); - - return false; -} - -function shouldSendPreconditionFailed(req: http.ServerRequest, stats: fs.Stats, etag: string) { - const ifMatch = tryParseETags(req.headers["if-match"]); - if (ifMatch && !matchesETag(etag, ifMatch)) return true; - - const ifUnmodifiedSince = tryParseDate(req.headers["if-unmodified-since"]); - if (ifUnmodifiedSince && stats.mtime.getTime() > ifUnmodifiedSince.getTime()) return true; - - return false; -} - -function handleGetRequest(req: http.ServerRequest, res: http.ServerResponse) { - const url = new URL(req.url, baseUrl); - if (url.pathname === "/") { - url.pathname = "/tests/webTestResults.html"; - return sendFound(res, url.toString()); - } - - const file = toServerPath(url); - fs.stat(file, (err, stats) => { - try { - if (err) { - if (err.code === "ENOENT") return sendNotFound(res); - return sendInternalServerError(res, err); - } - if (stats && stats.isFile()) { - const contentType = guessMediaType(file); - if (!isAcceptable(req, contentType)) return sendNotAcceptable(res); - - const etag = computeETag(stats); - if (shouldSendNotModified(req, stats, etag)) return sendNotModified(res); - if (shouldSendPreconditionFailed(req, stats, etag)) return sendPreconditionFailed(res); - - if (shouldIgnoreCache(url)) res.setHeader("Cache-Control", "no-store"); - res.setHeader("Last-Modified", stats.mtime.toUTCString()); - res.setHeader("ETag", etag); - res.setHeader("Content-Type", contentType); - res.setHeader("Accept-Ranges", "bytes"); - - const ranges = req.headers.range && tryParseByteRanges(req.headers.range, stats.size); - if (ranges && ranges.length === 0) return sendRangeNotSatisfiable(res); - - let start: number | undefined; - let end: number | undefined; - if (ranges && ranges.length === 1) { - start = ranges[0].start; - end = ranges[0].end; - if (start >= stats.size || end > stats.size) return sendRangeNotSatisfiable(res); - res.statusCode = 206; - res.setHeader("Content-Length", end - start); - res.setHeader("Content-Range", `bytes ${start}-${end - 1}/${stats.size}`); - } - else { - res.statusCode = 200; - res.setHeader("Content-Length", stats.size); - } - if (req.method === "HEAD") return res.end(); - const readable = fs.createReadStream(file, { start, end, autoClose: true }); - readable.on("error", err => sendInternalServerError(res, err)); - readable.pipe(res, { end: true }); - } - else { - if (req.headers["if-match"] === "*") return sendPreconditionFailed(res); - return sendNotFound(res); - } - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function handlePutRequest(req: http.ServerRequest, res: http.ServerResponse) { - if (req.headers["content-encoding"]) return sendUnsupportedMediaType(res); - if (req.headers["content-range"]) return sendNotImplemented(res); - const file = toServerPath(req.url); - fs.stat(file, (err, stats) => { - try { - if (err && err.code !== "ENOENT") return sendInternalServerError(res, err); - if (stats && !stats.isFile()) return sendMethodNotAllowed(res, []); - return mkdirp(path.dirname(file), err => { - if (err) return sendInternalServerError(res, err); - try { - const writable = fs.createWriteStream(file, { autoClose: true }); - writable.on("error", err => sendInternalServerError(res, err)); - writable.on("finish", () => { - if (stats) return sendNoContent(res); - fs.stat(file, (err, stats) => { - if (err) return sendInternalServerError(res, err); - return sendCreated(res, toClientPath(file), computeETag(stats)); - }); - }); - req.pipe(writable, { end: true }); - return; - } - catch (e) { - return sendInternalServerError(res, e); - } - }); - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function handleDeleteRequest(req: http.ServerRequest, res: http.ServerResponse) { - const file = toServerPath(req.url); - fs.stat(file, (err, stats) => { - try { - if (err && err.code !== "ENOENT") return sendInternalServerError(res, err); - if (!stats) return sendNotFound(res); - if (stats.isFile()) return fs.unlink(file, handleResult); - if (stats.isDirectory()) return fs.rmdir(file, handleResult); - return sendNotFound(res); - function handleResult(err: NodeJS.ErrnoException) { - if (err && err.code !== "ENOENT") return sendInternalServerError(res, err); - if (err) return sendNotFound(res); - return sendNoContent(res); - } - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function handleOptionsRequest(req: http.ServerRequest, res: http.ServerResponse) { - res.setHeader("X-Case-Sensitivity", useCaseSensitiveFileNames ? "CS" : "CI"); - return sendNoContent(res); -} - -function handleApiResolve(req: http.ServerRequest, res: http.ServerResponse) { - readContent(req, (err, content) => { - try { - if (err) return sendInternalServerError(res, err); - if (!content) return sendBadRequest(res); - const serverPath = toServerPath(content); - const clientPath = toClientPath(serverPath); - if (clientPath === undefined) return sendBadRequest(res); - return sendContent(res, /*statusCode*/ 200, clientPath, /*contentType*/ "text/plain;charset=utf-8"); - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function handleApiEnumerateTestFiles(req: http.ServerRequest, res: http.ServerResponse) { - readContent(req, (err, content) => { - try { - if (err) return sendInternalServerError(res, err); - if (!content) return sendBadRequest(res); - const tests: (string | FileBasedTest)[] = enumerateTestFiles(content); - return sendJson(res, /*statusCode*/ 200, tests); - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function enumerateTestFiles(runner: string) { - switch (runner) { - case "conformance": - case "compiler": - return listFiles(`tests/cases/${runner}`, /*serverDirname*/ undefined, /\.tsx?$/, { recursive: true }).map(parseCompilerTestConfigurations); - case "fourslash": - return listFiles(`tests/cases/fourslash`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); - case "fourslash-shims": - return listFiles(`tests/cases/fourslash/shims`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); - case "fourslash-shims-pp": - return listFiles(`tests/cases/fourslash/shims-pp`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); - case "fourslash-server": - return listFiles(`tests/cases/fourslash/server`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); - default: - throw new Error(`Runner '${runner}' not supported in browser tests.`); - } -} - -// Regex for parsing options in the format "@Alpha: Value of any sort" -const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines - -function extractCompilerSettings(content: string): Record { - const opts: Record = {}; - - let match: RegExpExecArray; - while ((match = optionRegex.exec(content)) !== null) { - opts[match[1]] = match[2].trim(); - } - - return opts; -} - -function splitVaryBySettingValue(text: string): string[] | undefined { - if (!text) return undefined; - const entries = text.split(/,/).map(s => s.trim().toLowerCase()).filter(s => s.length > 0); - return entries && entries.length > 1 ? entries : undefined; -} - -function computeFileBasedTestConfigurationVariations(configurations: FileBasedTestConfiguration[], variationState: FileBasedTestConfiguration, varyByEntries: [string, string[]][], offset: number) { - if (offset >= varyByEntries.length) { - // make a copy of the current variation state - configurations.push({ ...variationState }); - return; - } - - const [varyBy, entries] = varyByEntries[offset]; - for (const entry of entries) { - // set or overwrite the variation - variationState[varyBy] = entry; - computeFileBasedTestConfigurationVariations(configurations, variationState, varyByEntries, offset + 1); - } -} - -function getFileBasedTestConfigurations(settings: Record, varyBy: string[]): FileBasedTestConfiguration[] | undefined { - let varyByEntries: [string, string[]][] | undefined; - for (const varyByKey of varyBy) { - if (Object.prototype.hasOwnProperty.call(settings, varyByKey)) { - const entries = splitVaryBySettingValue(settings[varyByKey]); - if (entries) { - if (!varyByEntries) varyByEntries = []; - varyByEntries.push([varyByKey, entries]); - } - } - } - - if (!varyByEntries) return undefined; - - const configurations: FileBasedTestConfiguration[] = []; - computeFileBasedTestConfigurationVariations(configurations, {}, varyByEntries, 0); - return configurations; -} - -function parseCompilerTestConfigurations(file: string): FileBasedTest { - const content = fs.readFileSync(path.join(rootDir, file), "utf8"); - const settings = extractCompilerSettings(content); - const configurations = getFileBasedTestConfigurations(settings, ["module", "target"]); - return { file, configurations }; -} - -function handleApiListFiles(req: http.ServerRequest, res: http.ServerResponse) { - readContent(req, (err, content) => { - try { - if (err) return sendInternalServerError(res, err); - if (!content) return sendBadRequest(res); - const serverPath = toServerPath(content); - const files = listFiles(content, serverPath, /*spec*/ undefined, { recursive: true }); - return sendJson(res, /*statusCode*/ 200, files); - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function listFiles(clientDirname: string, serverDirname: string = path.resolve(rootDir, clientDirname), spec?: RegExp, options: { recursive?: boolean } = {}): string[] { - const files: string[] = []; - visit(serverDirname, clientDirname, files); - return files; - - function visit(dirname: string, relative: string, results: string[]) { - const { files, directories } = getAccessibleFileSystemEntries(dirname); - for (const file of files) { - if (!spec || file.match(spec)) { - results.push(path.join(relative, file)); - } - } - for (const directory of directories) { - if (options.recursive) { - visit(path.join(dirname, directory), path.join(relative, directory), results); - } - } - } -} - -function handleApiDirectoryExists(req: http.ServerRequest, res: http.ServerResponse) { - readContent(req, (err, content) => { - try { - if (err) return sendInternalServerError(res, err); - if (!content) return sendBadRequest(res); - const serverPath = toServerPath(content); - fs.stat(serverPath, (err, stats) => { - try { - if (err && err.code !== "ENOENT") return sendInternalServerError(res, err); - return sendJson(res, /*statusCode*/ 200, !!stats && stats.isDirectory()); - } - catch (e) { - return sendInternalServerError(res, e); - } - }); - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function handleApiGetAccessibleFileSystemEntries(req: http.ServerRequest, res: http.ServerResponse) { - readContent(req, (err, content) => { - try { - if (err) return sendInternalServerError(res, err); - if (!content) return sendBadRequest(res); - const serverPath = toServerPath(content); - return sendJson(res, /*statusCode*/ 200, getAccessibleFileSystemEntries(serverPath)); - } - catch (e) { - return sendInternalServerError(res, e); - } - }); -} - -function handlePostRequest(req: http.ServerRequest, res: http.ServerResponse) { - // API responses should not be cached - res.setHeader("Cache-Control", "no-cache"); - switch (new URL(req.url, baseUrl).pathname) { - case "/api/resolve": return handleApiResolve(req, res); - case "/api/listFiles": return handleApiListFiles(req, res); - case "/api/enumerateTestFiles": return handleApiEnumerateTestFiles(req, res); - case "/api/directoryExists": return handleApiDirectoryExists(req, res); - case "/api/getAccessibleFileSystemEntries": return handleApiGetAccessibleFileSystemEntries(req, res); - default: return sendMethodNotAllowed(res, ["HEAD", "GET", "PUT", "DELETE", "OPTIONS"]); - } -} - -function handleRequest(req: http.ServerRequest, res: http.ServerResponse) { - try { - switch (req.method) { - case "HEAD": - case "GET": return handleGetRequest(req, res); - case "PUT": return handlePutRequest(req, res); - case "POST": return handlePostRequest(req, res); - case "DELETE": return handleDeleteRequest(req, res); - case "OPTIONS": return handleOptionsRequest(req, res); - default: return sendMethodNotAllowed(res, ["HEAD", "GET", "PUT", "POST", "DELETE"]); - } - } - catch (e) { - return sendInternalServerError(res, e); - } -} - -function startServer() { - console.log(`Static file server running at\n => http://localhost:${port}/\nCTRL + C to shutdown`); - return http.createServer(handleRequest).listen(port); -} - -const REG_COLUMN_PADDING = 4; - -function queryRegistryValue(keyPath: string, callback: (error: Error | null, value: string) => void) { - const args = ["query", keyPath]; - child_process.execFile("reg", ["query", keyPath, "/ve"], { encoding: "utf8" }, (error, stdout) => { - if (error) return callback(error, null); - - const valueLine = stdout.replace(/^\r\n.+?\r\n|\r\n\r\n$/g, ""); - if (!valueLine) { - return callback(new Error("Unable to retrieve value."), null); - } - - const valueNameColumnOffset = REG_COLUMN_PADDING; - if (valueLine.lastIndexOf("(Default)", valueNameColumnOffset) !== valueNameColumnOffset) { - return callback(new Error("Unable to retrieve value."), null); - } - - const dataTypeColumnOffset = valueNameColumnOffset + "(Default)".length + REG_COLUMN_PADDING; - if (valueLine.lastIndexOf("REG_SZ", dataTypeColumnOffset) !== dataTypeColumnOffset) { - return callback(new Error("Unable to retrieve value."), null); - } - - const valueColumnOffset = dataTypeColumnOffset + "REG_SZ".length + REG_COLUMN_PADDING; - const value = valueLine.slice(valueColumnOffset); - return callback(null, value); - }); -} - -interface Browser { - description: string; - command: string; -} - -function createBrowserFromPath(path: string): Browser { - return { description: path, command: path }; -} - -function getChromePath(callback: (error: Error | null, browser: Browser | string | null) => void) { - switch (os.platform()) { - case "win32": - return queryRegistryValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe", (error, value) => { - if (error) return callback(null, "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"); - return callback(null, createBrowserFromPath(value)); - }); - case "darwin": return callback(null, "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"); - case "linux": return callback(null, "/opt/google/chrome/chrome"); - default: return callback(new Error(`Chrome location is unknown for platform '${os.platform()}'`), null); - } -} - -function getEdgePath(callback: (error: Error | null, browser: Browser | null) => void) { - switch (os.platform()) { - case "win32": return callback(null, { description: "Microsoft Edge", command: "cmd /c start microsoft-edge:%1" }); - default: return callback(new Error(`Edge location is unknown for platform '${os.platform()}'`), null); - } -} - -function getBrowserPath(callback: (error: Error | null, browser: Browser | null) => void) { - switch (browser) { - case "chrome": return getChromePath(afterGetBrowserPath); - case "edge": return getEdgePath(afterGetBrowserPath); - default: return callback(new Error(`Browser location is unknown for '${browser}'`), null); - } - - function afterGetBrowserPath(error: Error | null, browser: Browser | string | null) { - if (error) return callback(error, null); - if (typeof browser === "object") return callback(null, browser); - return fs.stat(browser, (error, stats) => { - if (!error && stats.isFile()) { - return callback(null, createBrowserFromPath(browser)); - } - if (browser === "chrome") return callback(null, createBrowserFromPath("chrome")); - return callback(new Error(`Browser location is unknown for '${browser}'`), null); - }); - } -} - -function startClient(server: http.Server) { - let browserPath: string; - if (browser === "none") { - return; - } - - getBrowserPath((error, browser) => { - if (error) return console.error(error); - console.log(`Using browser: ${browser.description}`); - const queryString = grep ? `?grep=${grep}` : ""; - const args = [`http://localhost:${port}/tests/webTestResults.html${queryString}`]; - if (browser.command.indexOf("%") === -1) { - child_process.spawn(browser.command, args); - } - else { - const command = browser.command.replace(/%(\d+)/g, (_, offset) => args[+offset - 1]); - child_process.exec(command); - } - }); -} - -function printHelp() { - console.log("Runs an http server on port 8888, looking for tests folder in the current directory\n"); - console.log("Syntax: node webTestServer.js [browser] [tests] [--verbose]\n"); - console.log("Options:"); - console.log(" The browser to launch. One of 'edge', 'chrome', or 'none' (default 'edge' on Windows, otherwise `chrome`)."); - console.log(" A regular expression to pass to Mocha."); - console.log(" --verbose Enables verbose logging."); -} - -function parseCommandLine(args: string[]) { - const parsed = minimist(args, { boolean: ["help", "verbose"] }); - if (parsed.help) { - printHelp(); - return false; - } - - if (parsed.verbose) { - verbose = true; - } - - const [parsedBrowser = defaultBrowser, parsedGrep, ...unrecognized] = parsed._; - if (parsedBrowser !== "edge" && parsedBrowser !== "chrome" && parsedBrowser !== "none") { - console.log(`Unrecognized browser '${parsedBrowser}', expected 'edge', 'chrome', or 'none'.`); - return false; - } - - if (unrecognized.length > 0) { - console.log(`Unrecognized argument: ${unrecognized[0]}`); - return false; - } - - browser = parsedBrowser; - grep = parsedGrep; - return true; -} - -function log(msg: string) { - if (verbose) { - console.log(msg); - } -} - -function main() { - if (parseCommandLine(process.argv.slice(2))) { - startClient(startServer()); - } -} - -main(); -// tslint:enable:no-null-keyword \ No newline at end of file diff --git a/tests/webTestServer.tsconfig.json b/tests/webTestServer.tsconfig.json deleted file mode 100644 index ff9fbb54bb..0000000000 --- a/tests/webTestServer.tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "es2015", - "module": "commonjs", - "declaration": false, - "removeComments": true, - "noResolve": false, - "stripInternal": false, - "sourceMap": true - }, - "files": [ - "webTestServer.ts" - ] -} diff --git a/tests/webhost/favicon-32x32.png b/tests/webhost/favicon-32x32.png deleted file mode 100644 index efbce163f9..0000000000 Binary files a/tests/webhost/favicon-32x32.png and /dev/null differ diff --git a/tests/webhost/webhost.html b/tests/webhost/webhost.html deleted file mode 100644 index 8d67918732..0000000000 --- a/tests/webhost/webhost.html +++ /dev/null @@ -1,87 +0,0 @@ - - - WebTSC - - - - - - - -
- -
-
-

Command line:

- -

Output:

- -
-
- -
-
-
- - \ No newline at end of file diff --git a/tests/webhost/webtsc.ts b/tests/webhost/webtsc.ts deleted file mode 100644 index 3c682df627..0000000000 --- a/tests/webhost/webtsc.ts +++ /dev/null @@ -1,104 +0,0 @@ -/// - -namespace TypeScript.WebTsc { - - declare var RealActiveXObject: { new (s: string): any }; - - function getWScriptSystem() { - const fso = new RealActiveXObject("Scripting.FileSystemObject"); - - const fileStream = new ActiveXObject("ADODB.Stream"); - fileStream.Type = 2 /*text*/; - - const args: string[] = []; - for (let i = 0; i < WScript.Arguments.length; i++) { - args[i] = WScript.Arguments.Item(i); - } - return { - args: args, - newLine: "\r\n", - write(s: string): void { - WScript.StdOut.Write(s); - }, - writeErr(s: string): void { - WScript.StdErr.Write(s); - }, - readFile(fileName: string, encoding?: string): string { - if (!fso.FileExists(fileName)) { - return undefined; - } - fileStream.Open(); - try { - if (encoding) { - fileStream.Charset = encoding; - fileStream.LoadFromFile(fileName); - } - else { - // Load file and read the first two bytes into a string with no interpretation - fileStream.Charset = "x-ansi"; - fileStream.LoadFromFile(fileName); - const bom = fileStream.ReadText(2) || ""; - // Position must be at 0 before encoding can be changed - fileStream.Position = 0; - // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8 - fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8"; - } - // ReadText method always strips byte order mark from resulting string - return fileStream.ReadText(); - } - catch (e) { - throw e; - } - finally { - fileStream.Close(); - } - }, - writeFile(fileName: string, data: string): boolean { - const f = fso.CreateTextFile(fileName, true); - f.Write(data); - f.Close(); - return true; - }, - resolvePath(path: string): string { - return fso.GetAbsolutePathName(path); - }, - fileExists(path: string): boolean { - return fso.FileExists(path); - }, - directoryExists(path: string) { - return fso.FolderExists(path); - }, - createDirectory(directoryName: string) { - if (!this.directoryExists(directoryName)) { - fso.CreateFolder(directoryName); - } - }, - getExecutingFilePath() { - return WScript.ScriptFullName; - }, - getCurrentDirectory() { - return ""; - }, - getMemoryUsage() { - return 0; - }, - exit(exitCode?: number): void { - WScript.Quit(exitCode); - }, - useCaseSensitiveFileNames: false - }; - } - - export function prepareCompiler(currentDir: string, stdOut: ITextWriter, stdErr: ITextWriter) { - const shell = new RealActiveXObject("WScript.Shell"); - shell.CurrentDirectory = currentDir; - WScript.ScriptFullName = currentDir + "\\tc.js"; - WScript.StdOut = stdOut; - WScript.StdErr = stdErr; - sys = getWScriptSystem(); - - return (commandLine: string) => { - ts.executeCommandLine(commandLine.split(" ")); - }; - } -} diff --git a/tests/webhost/webtsc.tsconfig.json b/tests/webhost/webtsc.tsconfig.json deleted file mode 100644 index a30b4ceef8..0000000000 --- a/tests/webhost/webtsc.tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "es2015", - "module": "commonjs", - "declaration": false, - "removeComments": true, - "noResolve": false, - "stripInternal": false, - "sourceMap": true - }, - "files": [ - "webtsc.ts" - ] -} \ No newline at end of file diff --git a/tests/webhost/wscript.js b/tests/webhost/wscript.js deleted file mode 100644 index 8cacfd4eb7..0000000000 --- a/tests/webhost/wscript.js +++ /dev/null @@ -1,22 +0,0 @@ -var RealActiveXObject = ActiveXObject - -var WScript; -(function (WScript) { - WScript.Arguments = []; - WScript.Echo = function (str) { }; - WScript.StdErr = { - Write: function() {} - } - WScript.StdOut = { - Write: function () { }, - WriteLine: function () { } - } - - WScript.Quit = function (exitCode) { } -})(WScript || (WScript = {})); - -var ActiveXObject = (function () { - function ActiveXObject(name) { - } - return ActiveXObject; -})();