From 4c2b1c5390deab989b5ec9cadb84891de9c75b87 Mon Sep 17 00:00:00 2001 From: Kamil Pajdzik <41709775+kpajdzik@users.noreply.github.com> Date: Tue, 22 Jan 2019 11:46:55 -0800 Subject: [PATCH] Fix default HTTP client tests (#321) * Enable CORS * Add empty line * Add mock http proxy * Fix few tests * Remove axios workaround that was fixed in current release * Fix all tests except download/upload progress * Fix stream HTTP tests * Delete testserver * Remove reporting skipped tests as warning * Remove .only * Add nodeIt * Fix Constants.ts * Remove it.skip() --- .scripts/checkEverything.ts | 5 +- karma.conf.ts | 6 +- lib/axiosHttpClient.ts | 4 +- lib/util/constants.ts | 2 +- mocha.config.json | 2 +- package.json | 6 +- test/defaultHttpClientTests.ts | 356 +++++++++++++++++++-------------- test/mockHttp.ts | 132 ++++++++++++ testserver/index.ts | 63 ------ tsconfig.json | 2 +- webpack.testconfig.ts | 18 +- 11 files changed, 369 insertions(+), 227 deletions(-) create mode 100644 test/mockHttp.ts delete mode 100644 testserver/index.ts diff --git a/.scripts/checkEverything.ts b/.scripts/checkEverything.ts index 7786a0b10d30..e727d89bf32d 100644 --- a/.scripts/checkEverything.ts +++ b/.scripts/checkEverything.ts @@ -2,11 +2,8 @@ import { checkEverything } from "@ts-common/azure-js-dev-tools"; import { checkConstantsVersion } from "./checkConstantsVersion"; checkEverything({ - checkForSkipCallsOptions: { - skipIsWarning: true - }, additionalChecks: { name: "Constants.ts Version", check: checkConstantsVersion } -}); \ No newline at end of file +}); diff --git a/karma.conf.ts b/karma.conf.ts index 962bea65701b..cacd163776c0 100644 --- a/karma.conf.ts +++ b/karma.conf.ts @@ -49,9 +49,13 @@ module.exports = function (config: any) { concurrency: Infinity, customLaunchers: { + ChromeNoSecurity: { + base: "ChromeHeadless", + flags: ["--disable-web-security"] + }, ChromeDebugging: { base: "Chrome", - flags: [`http://localhost:${defaults.port}/debug.html`, "--auto-open-devtools-for-tabs"] + flags: [`http://localhost:${defaults.port}/debug.html`, "--auto-open-devtools-for-tabs", "--disable-web-security"] } }, }); diff --git a/lib/axiosHttpClient.ts b/lib/axiosHttpClient.ts index 9e76cf7802a4..aa71c1443774 100644 --- a/lib/axiosHttpClient.ts +++ b/lib/axiosHttpClient.ts @@ -12,9 +12,7 @@ import { RestError } from "./restError"; import { WebResource, HttpRequestBody } from "./webResource"; import { ProxySettings } from "./serviceClient"; -const axiosClient = axios.create(); -// Workaround for https://github.com/axios/axios/issues/1158 -axiosClient.interceptors.request.use(config => ({ ...config, method: config.method && config.method.toUpperCase() as any })); +export const axiosClient = axios.create(); /** * A HttpClient implementation that uses axios to send HTTP requests. diff --git a/lib/util/constants.ts b/lib/util/constants.ts index 72bf2d405144..2da02b23752f 100644 --- a/lib/util/constants.ts +++ b/lib/util/constants.ts @@ -8,7 +8,7 @@ export const Constants = { * @const * @type {string} */ - msRestVersion: "1.5.0", + msRestVersion: "1.5.1", /** * Specifies HTTP. diff --git a/mocha.config.json b/mocha.config.json index 9e5174866f14..f58eb1ee5d4f 100644 --- a/mocha.config.json +++ b/mocha.config.json @@ -1,3 +1,3 @@ { "reporterEnabled": "list, mocha-junit-reporter" -} \ No newline at end of file +} diff --git a/package.json b/package.json index b903e0a3d9a7..2b8bea26d476 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "email": "azsdkteam@microsoft.com", "url": "https://github.com/Azure/ms-rest-js" }, - "version": "1.5.0", + "version": "1.5.1", "description": "Isomorphic client Runtime for Typescript/node.js/browser javascript client libraries generated using AutoRest", "tags": [ "isomorphic", @@ -73,6 +73,7 @@ "@types/xhr-mock": "^2.0.0", "@types/xml2js": "^0.4.3", "abortcontroller-polyfill": "^1.1.9", + "axios-mock-adapter": "^1.16.0", "chai": "^4.2.0", "express": "^4.16.3", "glob": "^7.1.2", @@ -111,6 +112,7 @@ "webpack": "^4.27.1", "webpack-cli": "^3.1.2", "webpack-dev-middleware": "^3.1.2", + "xhr-mock": "^2.4.1", "yarn": "^1.6.0" }, "homepage": "https://github.com/Azure/ms-rest-js", @@ -132,7 +134,7 @@ "test": "run-p test:tslint test:unit test:karma", "test:tslint": "tslint -p . -c tslint.json --exclude \"./test/**/*.ts\"", "test:unit": "nyc mocha", - "test:karma": "npm run build:test-browser && node ./node_modules/karma/bin/karma start karma.conf.ts --single-run", + "test:karma": "npm run build:test-browser && node ./node_modules/karma/bin/karma start karma.conf.ts --browsers ChromeNoSecurity --single-run ", "test:karma:debug": "npm run build:test-browser && node ./node_modules/karma/bin/karma start karma.conf.ts --log-level debug --browsers ChromeDebugging --debug --auto-watch", "publish-preview": "mocha --no-colors && shx rm -rf dist/test && node ./.scripts/publish", "local": "ts-node ./.scripts/local.ts", diff --git a/test/defaultHttpClientTests.ts b/test/defaultHttpClientTests.ts index bde05ea229ec..afe42f71f719 100644 --- a/test/defaultHttpClientTests.ts +++ b/test/defaultHttpClientTests.ts @@ -1,14 +1,18 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. + import { assert, AssertionError } from "chai"; import "chai/register-should"; import { createReadStream } from "fs"; -import { join } from "path"; import { DefaultHttpClient } from "../lib/defaultHttpClient"; import { RestError } from "../lib/restError"; import { isNode } from "../lib/util/utils"; -import { WebResource, HttpRequestBody } from "../lib/webResource"; +import { WebResource, HttpRequestBody, TransferProgressEvent } from "../lib/webResource"; +import { getHttpMock } from "./mockHttp"; + +const nodeIt = isNode ? it : it.skip; +const httpMock = getHttpMock(); function getAbortController(): AbortController { let controller: AbortController; @@ -21,92 +25,38 @@ function getAbortController(): AbortController { return controller; } -const baseURL = "https://example.com"; +describe("defaultHttpClient", function () { + function sleep(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); + } -describe.skip("defaultHttpClient", function () { - it("should send HTTP requests", async function () { - const request = new WebResource("https://example.com/", "GET"); - request.headers.set("Access-Control-Allow-Origin", "https://example.com"); - const httpClient = new DefaultHttpClient(); + beforeEach(() => httpMock.setup()); + afterEach(() => httpMock.teardown()); - const response = await httpClient.sendRequest(request); - assert.deepEqual(response.request, request); - assert.strictEqual(response.status, 200); - assert(response.headers); - // content-length varies based on OS line endings - assert.strictEqual(response.headers.get("content-length"), response.bodyAsText!.length.toString()); - assert.strictEqual(response.headers.get("content-type")!.split(";")[0], "text/html"); - const responseBody: string | null | undefined = response.bodyAsText; - const expectedResponseBody = - ` - - - Example Domain - - - - - - + it("should return a response instead of throwing for awaited 404", async function () { + const resourceUrl = "/nonexistent/"; - -
-

Example Domain

-

This domain is established to be used for illustrative examples in documents. You may use this - domain in examples without prior coordination or asking for permission.

-

More information...

-
- - -`; - assert.strictEqual( - responseBody && responseBody.replace(/\s/g, ""), - expectedResponseBody.replace(/\s/g, "")); - }); + httpMock.get(resourceUrl, async () => { + return { status: 404 }; + }); - it("should return a response instead of throwing for awaited 404", async function () { - const resourceUrl = `${baseURL}/nonexistent`; const request = new WebResource(resourceUrl, "GET"); const httpClient = new DefaultHttpClient(); const response = await httpClient.sendRequest(request); - response.should.exist; + response.status.should.equal(404); }); it("should allow canceling requests", async function () { + const resourceUrl = `/fileupload`; + httpMock.post(resourceUrl, async () => { + await sleep(10000); + assert.fail(); + return { status: 201 }; + }); const controller = getAbortController(); const veryBigPayload = "very long string"; - const request = new WebResource(`${baseURL}/fileupload`, "POST", veryBigPayload, undefined, undefined, true, undefined, controller.signal); + const request = new WebResource(resourceUrl, "POST", veryBigPayload, undefined, undefined, true, undefined, controller.signal); const client = new DefaultHttpClient(); const promise = client.sendRequest(request); controller.abort(); @@ -118,32 +68,49 @@ describe.skip("defaultHttpClient", function () { } }); - it("should not overwrite a user-provided cookie (nodejs only)", async function () { + nodeIt("should not overwrite a user-provided cookie (nodejs only)", async function () { // Cookie is only allowed to be set by the browser based on an actual response Set-Cookie header - if (!isNode) { - this.skip(); - } + httpMock.get("http://my.fake.domain/set-cookie", { + status: 200, + headers: { + "Set-Cookie": "data=123456" + } + }); + + httpMock.get("http://my.fake.domain/cookie", async (_url, _method, _body, headers) => { + return { + status: 200, + headers: headers + }; + }); const client = new DefaultHttpClient(); - const request1 = new WebResource(`${baseURL}/set-cookie`); - await client.sendRequest(request1); + const request1 = new WebResource("http://my.fake.domain/set-cookie"); + const response1 = await client.sendRequest(request1); + response1.headers.get("Set-Cookie")!.should.equal("data=123456"); - const request2 = new WebResource(`${baseURL}/cookie`); + const request2 = new WebResource("http://my.fake.domain/cookie"); const response2 = await client.sendRequest(request2); response2.headers.get("Cookie")!.should.equal("data=123456"); - const request3 = new WebResource(`${baseURL}/cookie`, "GET", undefined, undefined, { Cookie: "data=abcdefg" }); + const request3 = new WebResource("http://my.fake.domain/cookie", "GET", undefined, undefined, { Cookie: "data=abcdefg" }); const response3 = await client.sendRequest(request3); response3.headers.get("Cookie")!.should.equal("data=abcdefg"); }); it("should allow canceling multiple requests with one token", async function () { + httpMock.post("/fileupload", async () => { + await sleep(1000); + assert.fail(); + return { status: 201 }; + }); + const controller = getAbortController(); - const buf = new Uint8Array(1024 * 1024 * 1); + const buf = "Very large string"; const requests = [ - new WebResource(`${baseURL}/fileupload`, "POST", buf, undefined, undefined, true, undefined, controller.signal), - new WebResource(`${baseURL}/fileupload`, "POST", buf, undefined, undefined, true, undefined, controller.signal) + new WebResource("/fileupload", "POST", buf, undefined, undefined, true, undefined, controller.signal), + new WebResource("/fileupload", "POST", buf, undefined, undefined, true, undefined, controller.signal) ]; const client = new DefaultHttpClient(); const promises = requests.map(r => client.sendRequest(r)); @@ -152,84 +119,86 @@ describe.skip("defaultHttpClient", function () { for (const promise of promises) { try { await promise; - assert.fail(""); + assert.fail(); } catch (err) { err.should.not.be.instanceof(AssertionError); } } }); - it("should report upload and download progress for simple bodies", async function () { - let uploadNotified = false; - let downloadNotified = false; + describe("should report upload and download progress", () => { + type Notified = { notified: boolean }; + const listener = (operationStatus: Notified, ev: TransferProgressEvent) => { + operationStatus.notified = true; + if (typeof ProgressEvent !== "undefined") { + ev.should.not.be.instanceof(ProgressEvent); + } + ev.loadedBytes.should.be.a("Number"); + }; - const body = isNode ? Buffer.alloc(1024 * 1024) : new Uint8Array(1024 * 1024); - const request = new WebResource(`${baseURL}/fileupload`, "POST", body, undefined, undefined, false, undefined, undefined, 0, - ev => { - uploadNotified = true; - if (typeof ProgressEvent !== "undefined") { - ev.should.not.be.instanceof(ProgressEvent); - } - ev.loadedBytes.should.be.a("Number"); - }, - ev => { - downloadNotified = true; - if (typeof ProgressEvent !== "undefined") { - ev.should.not.be.instanceof(ProgressEvent); - } - ev.loadedBytes.should.be.a("Number"); + it("for simple bodies", async function () { + httpMock.post("/fileupload", async (_url, _method, body) => { + return { status: 201, body: body, headers: { "Content-Length": "200" } }; }); - const client = new DefaultHttpClient(); - await client.sendRequest(request); - assert(uploadNotified); - assert(downloadNotified); - }); + const upload: Notified = { notified: false }; + const download: Notified = { notified: false }; - it("should report upload and download progress for blob or stream bodies", async function () { - let uploadNotified = false; - let downloadNotified = false; + const body = "Very large string to upload"; + const request = new WebResource("/fileupload", "POST", body, undefined, undefined, false, undefined, undefined, 0, + ev => listener(upload, ev), + ev => listener(download, ev)); - let body: HttpRequestBody; - if (isNode) { - body = () => createReadStream(join(__dirname, "..", "resources", "example-index.html")); - } else { - body = new Blob([new Uint8Array(1024 * 1024)]); - } - const request = new WebResource(`${baseURL}/fileupload`, "POST", body, undefined, undefined, true, undefined, undefined, 0, - ev => { - uploadNotified = true; - if (typeof ProgressEvent !== "undefined") { - ev.should.not.be.instanceof(ProgressEvent); - } - ev.loadedBytes.should.be.a("Number"); - }, - ev => { - downloadNotified = true; - if (typeof ProgressEvent !== "undefined") { - ev.should.not.be.instanceof(ProgressEvent); - } - ev.loadedBytes.should.be.a("Number"); - }); + const client = new DefaultHttpClient(); + const response = await client.sendRequest(request); + response.should.exist; + upload.notified.should.be.true; + download.notified.should.be.true; + }); - const client = new DefaultHttpClient(); - const response = await client.sendRequest(request); - const streamBody = response.readableStreamBody; - if (response.blobBody) { - await response.blobBody; - } else if (streamBody) { - streamBody.on("data", () => { }); - await new Promise((resolve, reject) => { - streamBody.on("end", resolve); - streamBody.on("error", reject); + it("for blob or stream bodies", async function () { + let payload: HttpRequestBody; + if (isNode) { + payload = () => createReadStream(__filename); + } else { + payload = new Blob([new Uint8Array(1024 * 1024)]); + } + + const size = isNode ? payload.toString().length : undefined; + + httpMock.post("/fileupload", async (_url, _method, _body) => { + return { status: 201, body: payload, headers: { "Content-Type": "text/javascript", "Content-length": size } }; }); - } - assert(uploadNotified); - assert(downloadNotified); + + const upload: Notified = { notified: false }; + const download: Notified = { notified: false }; + + const request = new WebResource("/fileupload", "POST", payload, undefined, undefined, true, undefined, undefined, 0, + ev => listener(upload, ev), + ev => listener(download, ev)); + + const client = new DefaultHttpClient(); + const response = await client.sendRequest(request); + if (response.blobBody) { + await response.blobBody; + } else if ((typeof response.readableStreamBody === "function")) { + const streamBody = (response.readableStreamBody as Function)(); + streamBody.on("data", () => { }); + await new Promise((resolve, reject) => { + streamBody.on("end", resolve); + streamBody.on("error", reject); + }); + } + + upload.notified.should.be.true; + download.notified.should.be.true; + }); }); it("should honor request timeouts", async function () { - const request = new WebResource(`${baseURL}/slow`, "GET", undefined, undefined, undefined, false, false, undefined, 100); + httpMock.timeout("GET", "/slow"); + + const request = new WebResource("/slow", "GET", undefined, undefined, undefined, false, false, undefined, 100); const client = new DefaultHttpClient(); try { await client.sendRequest(request); @@ -240,7 +209,9 @@ describe.skip("defaultHttpClient", function () { }); it("should give a graceful error for nonexistent hosts", async function () { - const request = new WebResource(`http://foo.notawebsite/`); + const requestUrl = "http://foo.notawebsite/"; + httpMock.passThrough(requestUrl); + const request = new WebResource(requestUrl); const client = new DefaultHttpClient(); try { await client.sendRequest(request); @@ -252,9 +223,94 @@ describe.skip("defaultHttpClient", function () { }); it("should interpret undefined as an empty body", async function () { - const request = new WebResource(`${baseURL}/expect-empty`, "PUT"); + const requestUrl = "/expect-empty"; + httpMock.put(requestUrl, async (_url, _method, body, _headers) => { + if (!body) { + return { + status: 200 + }; + } else { + return { + status: 400, + body: `Expected empty body but got "${JSON.stringify(body)}"` + }; + } + }); + + const request = new WebResource(requestUrl, "PUT"); const client = new DefaultHttpClient(); const response = await client.sendRequest(request); response.status.should.equal(200, response.bodyAsText!); }); + + it("should send HTTP requests", async function () { + httpMock.passThrough(); + const request = new WebResource("https://example.com", "GET"); + request.headers.set("Access-Control-Allow-Headers", "Content-Type"); + request.headers.set("Access-Control-Allow-Methods", "GET"); + request.headers.set("Access-Control-Allow-Origin", "https://example.com"); + const httpClient = new DefaultHttpClient(); + + const response = await httpClient.sendRequest(request); + assert.deepEqual(response.request, request); + assert.strictEqual(response.status, 200); + assert(response.headers); + assert.strictEqual(response.headers.get("content-type")!.split(";")[0], "text/html"); + const responseBody: string | null | undefined = response.bodyAsText; + const expectedResponseBody = + ` + + + Example Domain + + + + + + + + +
+

Example Domain

+

This domain is established to be used for illustrative examples in documents. You may use this + domain in examples without prior coordination or asking for permission.

+

More information...

+
+ + +`; + assert.strictEqual( + responseBody && responseBody.replace(/\s/g, ""), + expectedResponseBody.replace(/\s/g, "")); + }); }); diff --git a/test/mockHttp.ts b/test/mockHttp.ts new file mode 100644 index 000000000000..22da5cc98685 --- /dev/null +++ b/test/mockHttp.ts @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +import xhrMock, { proxy } from "xhr-mock"; +import MockAdapter from "axios-mock-adapter"; +import { isNode, HttpMethods } from "../lib/msRest"; +import { AxiosRequestConfig } from "axios"; + +export type UrlFilter = string | RegExp; + +export type MockResponseData = { + status?: number; + body?: any; + headers?: any; +}; + +export type MockResponseFunction = (url?: string, method?: string, body?: any, headers?: any) => Promise; + +export type MockResponse = MockResponseData | MockResponseFunction; + +interface HttpMockFacade { + setup(): void; + teardown(): void; + passThrough(url?: UrlFilter): void; + timeout(method: HttpMethods, url?: UrlFilter): void; + mockHttpMethod(method: HttpMethods, url: UrlFilter, response: MockResponse): void; + get(url: UrlFilter, response: MockResponse): void; + post(url: UrlFilter, response: MockResponse): void; + put(url: UrlFilter, response: MockResponse): void; +} + +export function getHttpMock(): HttpMockFacade { + return (isNode ? new NodeHttpMock() : new BrowserHttpMock()); +} + +class NodeHttpMock implements HttpMockFacade { + private _mockAdapter: MockAdapter; + + constructor() { + const axiosClient = require("../lib/axiosHttpClient").axiosClient; + this._mockAdapter = new MockAdapter(axiosClient); + } + + setup(): void { + } + + teardown(): void { + } + + mockHttpMethod(method: HttpMethods, url: UrlFilter, response: MockResponse): void { + const methodName = "on" + method.charAt(0) + method.slice(1).toLowerCase(); + const mockCall: { reply: (statusOrCallback: number | Function, data?: any, headers?: any) => MockAdapter } = (this._mockAdapter as any)[methodName](url); + + if (typeof response === "function") { + mockCall.reply(async (config: AxiosRequestConfig) => { + const result = await response(config.url, config.method, config.data, config.headers); + return [result.status, result.body, result.headers]; + }); + } else { + mockCall.reply(response.status || 200, response.body || {}, response.headers || {}); + } + } + + get(url: UrlFilter, response: MockResponse): void { + return this.mockHttpMethod("GET", url, response); + } + + post(url: UrlFilter, response: MockResponse): void { + return this.mockHttpMethod("POST", url, response); + } + + put(url: UrlFilter, response: MockResponse): void { + return this.mockHttpMethod("PUT", url, response); + } + + passThrough(url?: UrlFilter): void { + this._mockAdapter.onAny(url).passThrough(); + } + + timeout(_method: HttpMethods, url?: UrlFilter): void { + this._mockAdapter.onAny(url).timeout(); + } +} + +class BrowserHttpMock implements HttpMockFacade { + setup(): void { + xhrMock.setup(); + } + + teardown(): void { + xhrMock.teardown(); + } + + mockHttpMethod(method: HttpMethods, url: UrlFilter, response: MockResponse): void { + if (typeof response === "function") { + xhrMock.use(method, url, async (req, res) => { + const result = await response(req.url().toString(), req.method().toString(), req.body(), req.headers()); + return res.status(result.status || 200).body(result.body || {}).headers(result.headers || {}); + }); + } else { + xhrMock.use(method, url, { + status: response.status, + body: response.body + }); + } + } + + get(url: UrlFilter, response: MockResponse): void { + this.mockHttpMethod("GET", url, response); + } + + post(url: UrlFilter, response: MockResponse): void { + this.mockHttpMethod("POST", url, response); + } + + put(url: UrlFilter, response: MockResponse): void { + this.mockHttpMethod("PUT", url, response); + } + + passThrough(url?: UrlFilter): void { + if (url) { + console.warn("Browser mock doesn't support filtered passThrough calls."); + } + + xhrMock.use(proxy); + } + + timeout(method: HttpMethods, url: UrlFilter): void { + return this.mockHttpMethod(method, url, () => new Promise(() => { })); + } +} + diff --git a/testserver/index.ts b/testserver/index.ts deleted file mode 100644 index bb758075aa35..000000000000 --- a/testserver/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -import path = require("path"); -import webpackMiddleware = require("webpack-dev-middleware"); -import webpack = require("webpack"); -import express = require("express"); -import testconfig = require("../webpack.testconfig"); - -const port = parseInt(process.env.PORT!) || 3001; -const app = express(); - -if (process.argv.indexOf("--no-webpack") === -1) { - app.use(webpackMiddleware(webpack(testconfig), { - publicPath: "/" - })); -} - -app.use(express.static(path.join(__dirname, "../"))); -app.use(express.static(path.join(__dirname, "../test/resources/"))); - -app.post("/fileupload", function(req, res) { - req.pipe(res); -}); - -app.get("/set-cookie", function(_req, res) { - res.setHeader("Set-Cookie", "data=123456"); - res.end(); -}); - -app.get("/cookie", function(req, res) { - res.setHeader("Cookie", req.header("Cookie")!); - res.end(); -}); - -app.get("/slow", function(_req, res) { - setTimeout(() => { - res.status(200); - res.end(); - }, 2000); -}); - -app.put("/expect-empty", function (req, res) { - let bufs: Buffer[] = []; - req.on('data', (data: Buffer) => { - bufs.push(data); - }); - req.on('end', () => { - const buf = Buffer.concat(bufs); - if (buf.length === 0) { - res.status(200); - res.end(); - } else { - res.status(400); - res.end("Expected empty body but got " + buf.toString('utf-8')); - } - }); - req.on('error', err => { - res.status(500); - res.end(err); - }); -}); - -app.listen(port, function() { - console.log(`ms-rest-js testserver (${process.pid}) listening on port ${port}...`); -}); diff --git a/tsconfig.json b/tsconfig.json index 3904b5430601..418bf57b79b6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -35,4 +35,4 @@ "./samples/**/*.ts", "./test/**/*.ts" ] -} \ No newline at end of file +} diff --git a/webpack.testconfig.ts b/webpack.testconfig.ts index 711d7503058d..970ca05ca7b9 100644 --- a/webpack.testconfig.ts +++ b/webpack.testconfig.ts @@ -6,6 +6,22 @@ const config: webpack.Configuration = { entry: glob.sync(path.join(__dirname, "test/**/*.ts")), mode: "development", devtool: "source-map", + stats: { + colors: true, + hash: false, + version: false, + timings: false, + assets: false, + chunks: false, + modules: false, + reasons: false, + children: false, + source: false, + errors: true, + errorDetails: false, + warnings: false, + publicPath: false + }, output: { filename: "msRest.browser.test.js", path: path.resolve(__dirname, "test") @@ -31,7 +47,7 @@ const config: webpack.Configuration = { }, node: { fs: "empty", - net: false, + net: "empty", path: "empty", dns: false, tls: false,