This commit is contained in:
Dan Schulte 2018-11-27 13:36:56 -08:00
Родитель 9419f81db5
Коммит 1f68aa8b54
7 изменённых файлов: 103 добавлений и 171 удалений

Просмотреть файл

@ -1,65 +0,0 @@
const { major } = require("semver");
const { spawn, exec } = require("child_process");
const { join } = require("path");
const kill = require("tree-kill");
const webpackDevServer = spawn(join(__dirname, "../node_modules/.bin/ts-node"), ["-T", join(__dirname, "../testserver")], { shell: true })
function cleanupDevServer() {
webpackDevServer.stderr.destroy();
webpackDevServer.stdout.destroy();
console.log(`kill ${webpackDevServer.pid}`);
kill(webpackDevServer.pid);
};
let mochaRunning = false
const webpackDevServerHandler = (data) => {
if (!mochaRunning) {
mochaRunning = true
const mochaChromePromise = new Promise((resolve, reject) => {
if (major(process.version) < 8) {
// Skip browser tests in pre-node 8
resolve();
} else {
const mochaChromeExecutable = join(__dirname, "../node_modules/.bin/mocha-chrome");
exec(`${mochaChromeExecutable} http://localhost:3001 --timeout 60000`, (err, stdout, stderr) => {
console.log(stdout);
console.error(stderr);
if (err) {
reject(err);
} else {
resolve();
}
});
}
});
const mochaPromise = new Promise((resolve, reject) => {
const mochaExecutable = join(__dirname, "../node_modules/.bin/_mocha");
const mocha = exec(mochaExecutable, (err, stdout, stderr) => {
console.log(stdout);
console.error(stderr);
if (err) {
reject(err);
} else {
resolve();
}
});
});
Promise.all([mochaPromise, mochaChromePromise]).then(res => {
cleanupDevServer();
process.exit(0);
}).catch((err) => {
cleanupDevServer();
process.exit(1);
});
}
}
webpackDevServer.stderr.on('data', data => {
console.error("webpack dev server error:", data.toString());
});
webpackDevServer.stdout.on('data', webpackDevServerHandler);
webpackDevServer.on('exit', webpackDevServerHandler);

Просмотреть файл

@ -1,8 +1,6 @@
import { major } from "semver";
import { spawn, exec, ExecException, ChildProcess, spawnSync, execSync } from "child_process";
import { spawn, ChildProcess, spawnSync, SpawnSyncReturns } from "child_process";
import { join } from "path";
import kill from "tree-kill";
import { execute } from "./dependencies";
const repositoryRootFolderPath: string = join(__dirname, "..");
const nodeModulesBinFolderPath: string = join(repositoryRootFolderPath, "node_modules/.bin/");
@ -11,79 +9,99 @@ const testServerFolderPath: string = join(repositoryRootFolderPath, "testserver"
const mochaExecutable = join(nodeModulesBinFolderPath, "_mocha");
const mochaChromeFilePath: string = join(nodeModulesBinFolderPath, "mocha-chrome");
interface ServerProcess extends ChildProcess {
serverPid?: number;
}
/**
* Execute the provided command on the shell synchronously.
* @param {string} command The command to execute.
* @param {string} workingDirectory The working directory to execute the command in.
* @returns {void}
*/
function execute(command: string, workingDirectory: string): number {
log(workingDirectory, `Running "${command}"...`);
return spawnSync(command, { cwd: workingDirectory, stdio: [0, 1, 2] }).status;
function executeSync(command: string, workingDirectory: string): SpawnSyncReturns<string> {
console.log(`Running "${command}"...`);
const result: SpawnSyncReturns<string> = spawnSync(command, { cwd: workingDirectory, stdio: [0, 1, 2], encoding: "utf8", shell: true });
if (result.error) {
throw result.error;
}
return result;
}
function startTestServer(): Promise<ServerProcess> {
return new Promise((resolve, reject) => {
console.log(`Starting "${tsNodeFilePath} ${testServerFolderPath}"...`);
const testServer: ServerProcess = spawn(tsNodeFilePath, [testServerFolderPath], { cwd: repositoryRootFolderPath, shell: true });
let testServerRunning = false;
testServer.stdout.on("data", (chunk: any) => {
const chunkString: string = chunk.toString("utf8");
const matchResult: RegExpMatchArray | null = chunkString.match(/ms-rest-js testserver \((.*)\) listening on port (.*).../);
if (matchResult) {
testServer.serverPid = parseInt(matchResult[1]);
}
if (testServer.serverPid == undefined) {
reject(new Error("Test server didn't output its process id in its start message."));
} else if (!testServerRunning) {
testServerRunning = true;
resolve(testServer);
}
});
testServer.stderr.on("data", (data: any) => {
console.error(`Test server error: "${data}"`);
reject();
});
testServer.on("exit", (code: number, signal: string) => {
console.log(`Test server exit code: ${code}, signal: ${signal}`);
if (!testServerRunning) {
testServerRunning = true;
resolve(testServer);
}
});
});
}
function stopProcess(processId: number | undefined): void {
if (processId != undefined) {
console.log(`Stopping process ${processId}...`);
process.kill(processId);
}
}
function stopTestServer(testServer: ServerProcess): void {
stopProcess(testServer.pid);
stopProcess(testServer.serverPid);
}
function runNodeJsUnitTests(): number {
return spawnSync(mochaExecutable)
console.log(`Running Node.js Unit Tests...`);
return executeSync(mochaExecutable, repositoryRootFolderPath).status;
}
const webpackDevServer: ChildProcess = spawn(tsNodeFilePath, ["-T", testServerFolderPath], { shell: true });
function cleanupDevServer(): void {
webpackDevServer.stderr.destroy();
webpackDevServer.stdout.destroy();
console.log(`kill ${webpackDevServer.pid}`);
kill(webpackDevServer.pid);
console.log(`Killed dev server.`);
function runBrowserUnitTests(): number {
console.log(`Running Browser Unit Tests...`);
const portNumber: string | number = process.env.PORT || 3001;
return executeSync(`${mochaChromeFilePath} http://localhost:${portNumber} --timeout 60000`, repositoryRootFolderPath).status;
}
let mochaRunning = false;
const webpackDevServerHandler = () => {
if (!mochaRunning) {
mochaRunning = true;
const mochaChromePromise = new Promise((resolve, reject) => {
if (major(process.version) < 8) {
// Skip browser tests in pre-node 8
resolve();
} else {
exec(`${mochaChromeFilePath} http://localhost:${process.env.PORT || 3001} --timeout 60000`, (err, stdout, stderr) => {
console.log(`Browser output: "${stdout}"`);
console.error(`Browser error: "${stderr}"`);
if (err) {
reject(err);
} else {
resolve();
}
});
}
});
const mochaPromise = new Promise((resolve, reject) => {
exec(mochaExecutable, (err: ExecException | null, stdout: string, stderr: string) => {
console.log(stdout);
console.log(`Node.js error: "${stderr}"`);
if (err) {
reject(err);
} else {
resolve();
let exitCode = 0;
startTestServer()
.then((testServer: ChildProcess) => {
try {
exitCode = runNodeJsUnitTests();
if (exitCode === 0) {
if (major(process.version) >= 8) {
exitCode = runBrowserUnitTests();
}
});
});
Promise.all([mochaPromise, mochaChromePromise]).then(() => {
console.log(`Overall done.`);
cleanupDevServer();
process.exit(0);
}).catch((err) => {
console.log(`Error: ${JSON.stringify(err)}`);
cleanupDevServer();
process.exit(1);
});
}
};
webpackDevServer.stderr.on("data", data => {
console.error("webpack dev server error:", data.toString());
});
webpackDevServer.stdout.on("data", webpackDevServerHandler);
webpackDevServer.on("exit", webpackDevServerHandler);
}
} finally {
stopTestServer(testServer);
}
})
.catch((error: Error) => {
console.log(`Error: ${error}`);
})
.finally(() => {
process.exit(exitCode);
});

12
.vscode/launch.json поставляемый
Просмотреть файл

@ -15,6 +15,16 @@
"--colors"
],
"internalConsoleOptions": "openOnSessionStart"
}
},
{
"type": "node",
"request": "launch",
"name": "Unit Tests",
"args": ["${workspaceFolder}/.scripts/unit.ts"],
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
"sourceMaps": true,
"cwd": "${workspaceFolder}",
"protocol": "inspector"
}
]
}

Просмотреть файл

@ -86,7 +86,6 @@
"should": "^5.2.0",
"shx": "^0.2.2",
"sinon": "^7.1.1",
"tree-kill": "^1.2.1",
"ts-loader": "^4.2.0",
"ts-node": "^7.0.0",
"tslint": "^5.10.0",

Просмотреть файл

@ -1,30 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
import * as childProcess from "child_process";
import * as path from "path";
import kill from "tree-kill";
let serverProcess: childProcess.ChildProcess;
before(function(done) {
serverProcess = childProcess.spawn(path.join(__dirname, "../../node_modules/.bin/ts-node"), ["-T", "testserver", "--no-webpack"], { shell: true });
const dataListener = () => {
serverProcess.stdout.removeListener("data", dataListener);
serverProcess.stderr.removeListener("data", dataListener);
done();
};
serverProcess.stdout.on("data", dataListener);
serverProcess.stderr.on("data", dataListener);
serverProcess.on("error", err => {
console.error(err);
done(err);
});
});
after(function() {
serverProcess.stdout.destroy();
serverProcess.stderr.destroy();
console.log(`kill ${serverProcess.pid}`);
kill(serverProcess.pid);
});

Просмотреть файл

@ -7,8 +7,8 @@ import { RestError } from "../../lib/restError";
import { isNode } from "../../lib/util/utils";
import { WebResource, HttpRequestBody } from "../../lib/webResource";
import { baseURL } from "../testUtils";
import { createReadStream } from 'fs';
import { join } from 'path';
import { createReadStream } from "fs";
import { join } from "path";
function getAbortController(): AbortController {
let controller: AbortController;
@ -21,8 +21,8 @@ function getAbortController(): AbortController {
return controller;
}
describe("defaultHttpClient", () => {
it("should send HTTP requests", async () => {
describe("defaultHttpClient", function () {
it("should send HTTP requests", async function () {
const request = new WebResource(`${baseURL}/example-index.html`, "GET");
const httpClient = new DefaultHttpClient();
@ -91,7 +91,7 @@ describe("defaultHttpClient", () => {
expectedResponseBody.replace(/\r\n/g, "\n"));
});
it("should return a response instead of throwing for awaited 404", async () => {
it("should return a response instead of throwing for awaited 404", async function () {
const request = new WebResource(`${baseURL}/nonexistent`, "GET");
const httpClient = new DefaultHttpClient();
@ -181,7 +181,7 @@ describe("defaultHttpClient", () => {
assert(downloadNotified);
});
it("should report upload and download progress for blob or stream bodies", async function() {
it("should report upload and download progress for blob or stream bodies", async function () {
let uploadNotified = false;
let downloadNotified = false;
@ -213,7 +213,7 @@ describe("defaultHttpClient", () => {
if (response.blobBody) {
await response.blobBody;
} else if (streamBody) {
streamBody.on("data", () => {});
streamBody.on("data", () => { });
await new Promise((resolve, reject) => {
streamBody.on("end", resolve);
streamBody.on("error", reject);
@ -234,7 +234,7 @@ describe("defaultHttpClient", () => {
}
});
it("should give a graceful error for nonexistent hosts", async function() {
it("should give a graceful error for nonexistent hosts", async function () {
const request = new WebResource(`http://foo.notawebsite/`);
const client = new DefaultHttpClient();
try {

Просмотреть файл

@ -59,5 +59,5 @@ app.put("/expect-empty", function (req, res) {
});
app.listen(port, function() {
console.log(`ms-rest-js testserver listening on port ${port}...`);
console.log(`ms-rest-js testserver (${process.pid}) listening on port ${port}...`);
});