From 45ed1cd219a9385313ad4164b616228ff7e06a0c Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Tue, 12 Feb 2019 00:53:34 -0800 Subject: [PATCH 1/7] feat: webpack it --- .gitignore | 1 + browser-test/browser-test.sh | 30 ++++++++++++ browser-test/test.browser.ts | 26 ++++++++++ browser-test/webserver.ts | 36 ++++++++++++++ karma.conf.js | 95 ++++++++++++++++++++++++++++++++++++ package.json | 22 ++++++++- src/gaxios.ts | 6 ++- src/isbrowser.ts | 19 ++++++++ tsconfig.json | 2 + webpack-tests.config.js | 48 ++++++++++++++++++ webpack.config.js | 54 ++++++++++++++++++++ 11 files changed, 335 insertions(+), 4 deletions(-) create mode 100644 browser-test/browser-test.sh create mode 100644 browser-test/test.browser.ts create mode 100644 browser-test/webserver.ts create mode 100644 karma.conf.js create mode 100644 src/isbrowser.ts create mode 100644 webpack-tests.config.js create mode 100644 webpack.config.js diff --git a/.gitignore b/.gitignore index a8b5acbc..3f1a779f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ coverage package-lock.json yarn.lock .vscode +dist/ diff --git a/browser-test/browser-test.sh b/browser-test/browser-test.sh new file mode 100644 index 00000000..40036737 --- /dev/null +++ b/browser-test/browser-test.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# Copyright 2019, Google, LLC. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +node build/browser-test/webserver.js & +while : ; do + if curl http://localhost:3000/path > /dev/null 2>&1 ; then + break + fi + echo '[script] Still waiting for server to start...' + sleep 1 +done + +echo '[script] Server is running, starting Karma!' +npx karma start +result=$? +echo "[script] Karma has finished with code $result" +wait +exit $result diff --git a/browser-test/test.browser.ts b/browser-test/test.browser.ts new file mode 100644 index 00000000..e59439a0 --- /dev/null +++ b/browser-test/test.browser.ts @@ -0,0 +1,26 @@ +import * as assert from 'assert'; + +import {request} from '../src/index'; +const port = 3000; // should match the port defined in `webserver.ts` + +describe('💻 browser tests', async () => { + it('should just work from browser', async () => { + const result = await request({url: `http://localhost:${port}/path`}); + assert.strictEqual(result.status, 200); + assert.strictEqual(result.data, 'response'); + }); + + it('should pass querystring parameters from browser', async () => { + const result = await request({ + url: `http://localhost:${port}/querystring`, + params: {query: 'value'} + }); + assert.strictEqual(result.status, 200); + assert.strictEqual(result.data, 'value'); + }); + + after(async () => { + const result = await request({url: `http://localhost:${port}/enough`}); + // webserver will die now + }); +}); diff --git a/browser-test/webserver.ts b/browser-test/webserver.ts new file mode 100644 index 00000000..a71db900 --- /dev/null +++ b/browser-test/webserver.ts @@ -0,0 +1,36 @@ +import * as express from 'express'; +import * as http from 'http'; + +const port = 3000; + +function main() { + const app = express(); + let server: http.Server; + app.get('/path', (req: express.Request, res: express.Response) => { + if (req.header('origin')) { + res.set('Access-Control-Allow-Origin', req.header('origin')); + } + res.send('response'); + }); + app.get('/querystring', (req: express.Request, res: express.Response) => { + if (req.header('origin')) { + res.set('Access-Control-Allow-Origin', req.header('origin')); + } + const query = req.query.query; + res.send(query || ''); + }); + app.get('/enough', (req: express.Request, res: express.Response) => { + if (req.header('origin')) { + res.set('Access-Control-Allow-Origin', req.header('origin')); + } + res.send('have a great rest of your day'); + server.close(); + console.log(`[http server] I'm no longer listening on port ${port}!`); + process.exit(0); + }); + server = app.listen(port, () => { + console.log(`[http server] I'm listening on port ${port}!`); + }); +} + +main(); diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000..54ed5276 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,95 @@ +/** + * Copyright 2019 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Karma configuration +// Use `npm run browser-test` to run browser tests with Karma. +const isDocker = require('is-docker')(); + +const webpackConfig = require('./webpack-tests.config.js'); +process.env.CHROME_BIN = require('puppeteer').executablePath(); + +module.exports = function (config) { + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'], + + // list of files / patterns to load in the browser + files: ['./browser-test/test.*.ts'], + + // list of files / patterns to exclude + exclude: [], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + './src/*.ts': ['coverage'], + './src/**/*.ts': ['coverage'], + './browser-test/*.ts': ['webpack', 'sourcemap'] + }, + + webpack: webpackConfig, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress', 'coverage', 'remap-coverage'], + + coverageReporter: { type: 'in-memory' }, + remapCoverageReporter: { html: './coverage' }, + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['ChromeCustom'], + customLaunchers: { + ChromeCustom: { + base: 'ChromeHeadless', + // We must disable the Chrome sandbox when running Chrome inside Docker (Chrome's sandbox needs + // more permissions than Docker allows by default) + flags: isDocker ? ['--no-sandbox'] : [] + } + }, + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true, + + // Concurrency level + // how many browser should be started simultaneous + concurrency: Infinity, + + // set correct MIME type when serving .ts files (already compiled to JavaScript): + mime: { + 'text/javascript': ['ts'] + } + }); +}; diff --git a/package.json b/package.json index c2c95456..60d53ff8 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "prepare": "npm run compile", "pretest": "npm run compile", "codecov": "nyc report --reporter=json && codecov -f coverage/*.json", - "commitlint": "git log -1 --pretty=%B | commitlint" + "commitlint": "git log -1 --pretty=%B | commitlint", + "webpack": "webpack", + "browser-test": "sh browser-test/browser-test.sh" }, "repository": "JustinBeckwith/gaxios", "keywords": [ @@ -28,6 +30,7 @@ "devDependencies": { "@commitlint/cli": "^7.2.1", "@commitlint/config-conventional": "^7.1.2", + "@types/express": "^4.16.1", "@types/extend": "^3.0.0", "@types/mocha": "^5.2.5", "@types/nock": "^9.3.0", @@ -36,15 +39,30 @@ "@types/sinon": "^7.0.0", "assert-rejects": "^1.0.0", "codecov": "^3.0.4", + "express": "^4.16.4", "gts": "^0.9.0", + "is-docker": "^1.1.0", + "karma": "^4.0.0", + "karma-chrome-launcher": "^2.2.0", + "karma-coverage": "^1.1.2", + "karma-firefox-launcher": "^1.1.0", + "karma-mocha": "^1.3.0", + "karma-remap-coverage": "^0.1.5", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^3.0.5", "mocha": "^5.2.0", "nock": "^9.6.0", + "null-loader": "^0.1.1", "nyc": "^12.0.2", + "puppeteer": "^1.12.2", "semantic-release": "^15.13.2", "semistandard": "^13.0.1", "sinon": "^7.1.1", "source-map-support": "^0.5.6", - "typescript": "~3.3.0" + "ts-loader": "^5.3.3", + "typescript": "~3.3.0", + "webpack": "^4.29.3", + "webpack-cli": "^3.2.3" }, "dependencies": { "extend": "^3.0.2", diff --git a/src/gaxios.ts b/src/gaxios.ts index 086ffaec..65528bf1 100644 --- a/src/gaxios.ts +++ b/src/gaxios.ts @@ -16,9 +16,10 @@ import {Agent} from 'https'; import fetch, {Response} from 'node-fetch'; import * as qs from 'querystring'; import * as stream from 'stream'; -import {URL} from 'url'; +import * as URL from 'url'; import {GaxiosError, GaxiosOptions, GaxiosPromise, GaxiosResponse, Headers} from './common'; +import {isBrowser} from './isbrowser'; import {getRetryConfig} from './retry'; // tslint:disable-next-line variable-name no-any @@ -148,7 +149,8 @@ export class Gaxios { opts.method = opts.method || 'GET'; if (opts.params) { - const parts = new URL(opts.url); + const parts = + isBrowser() ? new window.URL(opts.url) : new URL.URL(opts.url); parts.search = opts.paramsSerializer(opts.params); opts.url = parts.href; } diff --git a/src/isbrowser.ts b/src/isbrowser.ts new file mode 100644 index 00000000..5ded266e --- /dev/null +++ b/src/isbrowser.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2019 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function isBrowser(): boolean { + return typeof (window) !== 'undefined'; +} diff --git a/tsconfig.json b/tsconfig.json index b10ee498..05941e51 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,14 @@ { "extends": "./node_modules/gts/tsconfig-google.json", "compilerOptions": { + "lib": ["es2015", "dom"], "rootDir": ".", "outDir": "build" }, "include": [ "src/*.ts", "test/*.ts", + "browser-test/*.ts", "system-test/*.ts" ] } diff --git a/webpack-tests.config.js b/webpack-tests.config.js new file mode 100644 index 00000000..eb9c9bb0 --- /dev/null +++ b/webpack-tests.config.js @@ -0,0 +1,48 @@ +/** + * Copyright 2019 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Use `npm run webpack` to produce Webpack bundle for this library. + +const path = require('path'); + +module.exports = { + resolve: { + extensions: ['.ts', '.js', '.json'], + alias: { + '../../package.json': path.resolve(__dirname, 'package.json') + } + }, + node: { + child_process: 'empty', + fs: 'empty', + crypto: 'empty' + }, + module: { + rules: [ + { + test: /node_modules\/https-proxy-agent\//, + use: 'null-loader' + }, + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + mode: 'production', + plugins: [] +}; diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..7536c2e2 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,54 @@ +/** + * Copyright 2019 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Use `npm run webpack` to produce Webpack bundle for this library. + +const path = require('path'); + +module.exports = { + entry: './src/index.ts', + resolve: { + extensions: ['.ts', '.js', '.json'], + alias: { + '../../package.json': path.resolve(__dirname, 'package.json') + } + }, + output: { + library: 'Gaxios', + filename: 'gaxios.min.js', + path: path.resolve(__dirname, 'dist') + }, + node: { + child_process: 'empty', + fs: 'empty', + crypto: 'empty' + }, + module: { + rules: [ + { + test: /node_modules\/https-proxy-agent\//, + use: 'null-loader' + }, + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + mode: 'production', + plugins: [] +}; From 1a2e6ab0a5190f9b538580ebed607670790d4e58 Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Tue, 12 Feb 2019 09:24:38 -0800 Subject: [PATCH 2/7] fix: pr feedback part 1 --- browser-test/browser-test.sh | 4 +++- browser-test/test.browser.ts | 6 +++--- browser-test/webserver.ts | 2 +- src/gaxios.ts | 7 ++++--- webpack.config.js | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/browser-test/browser-test.sh b/browser-test/browser-test.sh index 40036737..f5950d16 100644 --- a/browser-test/browser-test.sh +++ b/browser-test/browser-test.sh @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +PORT=7172 + node build/browser-test/webserver.js & while : ; do - if curl http://localhost:3000/path > /dev/null 2>&1 ; then + if curl http://localhost:$PORT/path > /dev/null 2>&1 ; then break fi echo '[script] Still waiting for server to start...' diff --git a/browser-test/test.browser.ts b/browser-test/test.browser.ts index e59439a0..d01c8bc1 100644 --- a/browser-test/test.browser.ts +++ b/browser-test/test.browser.ts @@ -1,9 +1,9 @@ import * as assert from 'assert'; import {request} from '../src/index'; -const port = 3000; // should match the port defined in `webserver.ts` +const port = 7172; // should match the port defined in `webserver.ts` -describe('💻 browser tests', async () => { +describe('💻 browser tests', () => { it('should just work from browser', async () => { const result = await request({url: `http://localhost:${port}/path`}); assert.strictEqual(result.status, 200); @@ -20,7 +20,7 @@ describe('💻 browser tests', async () => { }); after(async () => { - const result = await request({url: `http://localhost:${port}/enough`}); + await request({url: `http://localhost:${port}/enough`}); // webserver will die now }); }); diff --git a/browser-test/webserver.ts b/browser-test/webserver.ts index a71db900..537e5900 100644 --- a/browser-test/webserver.ts +++ b/browser-test/webserver.ts @@ -1,7 +1,7 @@ import * as express from 'express'; import * as http from 'http'; -const port = 3000; +const port = 7172; function main() { const app = express(); diff --git a/src/gaxios.ts b/src/gaxios.ts index 65528bf1..73120013 100644 --- a/src/gaxios.ts +++ b/src/gaxios.ts @@ -16,12 +16,14 @@ import {Agent} from 'https'; import fetch, {Response} from 'node-fetch'; import * as qs from 'querystring'; import * as stream from 'stream'; -import * as URL from 'url'; +import * as url from 'url'; import {GaxiosError, GaxiosOptions, GaxiosPromise, GaxiosResponse, Headers} from './common'; import {isBrowser} from './isbrowser'; import {getRetryConfig} from './retry'; +const URL = isBrowser() ? window.URL : url.URL; + // tslint:disable-next-line variable-name no-any let HttpsProxyAgent: any; @@ -149,8 +151,7 @@ export class Gaxios { opts.method = opts.method || 'GET'; if (opts.params) { - const parts = - isBrowser() ? new window.URL(opts.url) : new URL.URL(opts.url); + const parts = new URL(opts.url); parts.search = opts.paramsSerializer(opts.params); opts.url = parts.href; } diff --git a/webpack.config.js b/webpack.config.js index 7536c2e2..d579ed4e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -27,7 +27,7 @@ module.exports = { } }, output: { - library: 'Gaxios', + library: 'gaxios', filename: 'gaxios.min.js', path: path.resolve(__dirname, 'dist') }, From 8141956e942b28f6de512e0c66479ef93d5490b2 Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Tue, 12 Feb 2019 10:24:54 -0800 Subject: [PATCH 3/7] fix: pr feedback part 2 --- browser-test/browser-test-runner.ts | 76 +++++++++++++++++++++++++++++ browser-test/browser-test.sh | 32 ------------ browser-test/test.browser.ts | 5 -- package.json | 2 +- 4 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 browser-test/browser-test-runner.ts delete mode 100644 browser-test/browser-test.sh diff --git a/browser-test/browser-test-runner.ts b/browser-test/browser-test-runner.ts new file mode 100644 index 00000000..dbcc091e --- /dev/null +++ b/browser-test/browser-test-runner.ts @@ -0,0 +1,76 @@ +// Copyright 2019, Google, LLC. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as child_process from 'child_process'; +import * as express from 'express'; +import * as http from 'http'; + +const port = 7172; + +async function listen( + app: express.Express, port: number): Promise { + return new Promise((resolve, reject) => { + const server = app.listen(port, (err: Error) => { + if (err) { + reject(err); + } + resolve(server); + }); + }); +} + +async function spawn(cmd: string, options: [string]): Promise { + return new Promise((resolve, reject) => { + console.log(process.env['PATH']); + child_process.spawn(cmd, options, {stdio: 'inherit'}) + .on('error', reject) + .on('exit', (code, signal) => { + if (signal) { + resolve(1); + } + resolve(code || 0); + }); + }); +} + +// Starts a web server that browser tests will use, then runs actual browser +// tests. +async function main() { + const app = express(); + app.get('/path', (req: express.Request, res: express.Response) => { + if (req.header('origin')) { + res.set('Access-Control-Allow-Origin', req.header('origin')); + } + res.send('response'); + }); + app.get('/querystring', (req: express.Request, res: express.Response) => { + if (req.header('origin')) { + res.set('Access-Control-Allow-Origin', req.header('origin')); + } + const query = req.query.query; + res.send(query || ''); + }); + + const server = await listen(app, port); + console.log(`[http server] I'm listening on port ${port}! Starting karma.`); + const exitCode = await spawn('karma', ['start']); + server.close(); + console.log( + `[http server] Karma has finished! I'm no longer listening on port ${ + port}!`); + process.exit(exitCode); +} + +main().catch(err => { + console.log('Error:', err); +}); diff --git a/browser-test/browser-test.sh b/browser-test/browser-test.sh deleted file mode 100644 index f5950d16..00000000 --- a/browser-test/browser-test.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -# Copyright 2019, Google, LLC. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -PORT=7172 - -node build/browser-test/webserver.js & -while : ; do - if curl http://localhost:$PORT/path > /dev/null 2>&1 ; then - break - fi - echo '[script] Still waiting for server to start...' - sleep 1 -done - -echo '[script] Server is running, starting Karma!' -npx karma start -result=$? -echo "[script] Karma has finished with code $result" -wait -exit $result diff --git a/browser-test/test.browser.ts b/browser-test/test.browser.ts index d01c8bc1..c007869c 100644 --- a/browser-test/test.browser.ts +++ b/browser-test/test.browser.ts @@ -18,9 +18,4 @@ describe('💻 browser tests', () => { assert.strictEqual(result.status, 200); assert.strictEqual(result.data, 'value'); }); - - after(async () => { - await request({url: `http://localhost:${port}/enough`}); - // webserver will die now - }); }); diff --git a/package.json b/package.json index 60d53ff8..761d219e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json", "commitlint": "git log -1 --pretty=%B | commitlint", "webpack": "webpack", - "browser-test": "sh browser-test/browser-test.sh" + "browser-test": "node build/browser-test/browser-test-runner.js" }, "repository": "JustinBeckwith/gaxios", "keywords": [ From 35ed3958e3a7d48663051d0c91f28c883bd3e901 Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Tue, 12 Feb 2019 11:19:56 -0800 Subject: [PATCH 4/7] fix: use execa instead of child_process --- browser-test/browser-test-runner.ts | 20 +++----------------- package.json | 2 +- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/browser-test/browser-test-runner.ts b/browser-test/browser-test-runner.ts index dbcc091e..c540c2dd 100644 --- a/browser-test/browser-test-runner.ts +++ b/browser-test/browser-test-runner.ts @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import * as child_process from 'child_process'; +import * as execa from 'execa'; import * as express from 'express'; import * as http from 'http'; @@ -29,20 +29,6 @@ async function listen( }); } -async function spawn(cmd: string, options: [string]): Promise { - return new Promise((resolve, reject) => { - console.log(process.env['PATH']); - child_process.spawn(cmd, options, {stdio: 'inherit'}) - .on('error', reject) - .on('exit', (code, signal) => { - if (signal) { - resolve(1); - } - resolve(code || 0); - }); - }); -} - // Starts a web server that browser tests will use, then runs actual browser // tests. async function main() { @@ -63,12 +49,12 @@ async function main() { const server = await listen(app, port); console.log(`[http server] I'm listening on port ${port}! Starting karma.`); - const exitCode = await spawn('karma', ['start']); + const result = await execa('karma', ['start'], {stdio: 'inherit'}); server.close(); console.log( `[http server] Karma has finished! I'm no longer listening on port ${ port}!`); - process.exit(exitCode); + process.exit(result.failed ? 1 : 0); } main().catch(err => { diff --git a/package.json b/package.json index ea9aa1aa..28388eb6 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "ts-loader": "^5.3.3", "typescript": "~3.3.0", "webpack": "^4.29.3", - "webpack-cli": "^3.2.3", + "webpack-cli": "^3.2.3" }, "dependencies": { "abort-controller": "^2.0.2", From 4cb6d2ccf2af05b8a6e9a65da7479ba72f3b08ae Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Tue, 12 Feb 2019 11:33:25 -0800 Subject: [PATCH 5/7] test: run webpack in system test --- browser-test/webserver.ts | 36 ------------- package.json | 1 + system-test/fixtures/sample/package.json | 6 ++- system-test/fixtures/sample/webpack.config.js | 53 +++++++++++++++++++ system-test/test.install.ts | 16 +++++- 5 files changed, 74 insertions(+), 38 deletions(-) delete mode 100644 browser-test/webserver.ts create mode 100644 system-test/fixtures/sample/webpack.config.js diff --git a/browser-test/webserver.ts b/browser-test/webserver.ts deleted file mode 100644 index 537e5900..00000000 --- a/browser-test/webserver.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as express from 'express'; -import * as http from 'http'; - -const port = 7172; - -function main() { - const app = express(); - let server: http.Server; - app.get('/path', (req: express.Request, res: express.Response) => { - if (req.header('origin')) { - res.set('Access-Control-Allow-Origin', req.header('origin')); - } - res.send('response'); - }); - app.get('/querystring', (req: express.Request, res: express.Response) => { - if (req.header('origin')) { - res.set('Access-Control-Allow-Origin', req.header('origin')); - } - const query = req.query.query; - res.send(query || ''); - }); - app.get('/enough', (req: express.Request, res: express.Response) => { - if (req.header('origin')) { - res.set('Access-Control-Allow-Origin', req.header('origin')); - } - res.send('have a great rest of your day'); - server.close(); - console.log(`[http server] I'm no longer listening on port ${port}!`); - process.exit(0); - }); - server = app.listen(port, () => { - console.log(`[http server] I'm listening on port ${port}!`); - }); -} - -main(); diff --git a/package.json b/package.json index 28388eb6..a07b187c 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "codecov": "nyc report --reporter=json && codecov -f coverage/*.json", "commitlint": "git log -1 --pretty=%B | commitlint", "webpack": "webpack", + "prebrowser-test": "npm run compile", "browser-test": "node build/browser-test/browser-test-runner.js" }, "repository": "JustinBeckwith/gaxios", diff --git a/system-test/fixtures/sample/package.json b/system-test/fixtures/sample/package.json index e478263c..e5b74322 100644 --- a/system-test/fixtures/sample/package.json +++ b/system-test/fixtures/sample/package.json @@ -18,6 +18,10 @@ "devDependencies": { "@types/node": "^10.3.0", "typescript": "^3.0.0", - "gts": "^0.9.0" + "gts": "^0.9.0", + "null-loader": "^0.1.1", + "ts-loader": "^5.3.3", + "webpack": "^4.29.3", + "webpack-cli": "^3.2.3" } } diff --git a/system-test/fixtures/sample/webpack.config.js b/system-test/fixtures/sample/webpack.config.js new file mode 100644 index 00000000..6ddbd844 --- /dev/null +++ b/system-test/fixtures/sample/webpack.config.js @@ -0,0 +1,53 @@ +/** + * Copyright 2019 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Use `npm run webpack` to produce Webpack bundle for this library. + +const path = require('path'); + +module.exports = { + entry: './src/index.ts', + resolve: { + extensions: ['.ts', '.js', '.json'], + alias: { + '../../package.json': path.resolve(__dirname, 'package.json') + } + }, + output: { + filename: 'bundle.min.js', + path: path.resolve(__dirname, 'dist') + }, + node: { + child_process: 'empty', + fs: 'empty', + crypto: 'empty' + }, + module: { + rules: [ + { + test: /node_modules\/https-proxy-agent\//, + use: 'null-loader' + }, + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + mode: 'production', + plugins: [] +}; diff --git a/system-test/test.install.ts b/system-test/test.install.ts index 4f7fe3a1..1e9c0411 100644 --- a/system-test/test.install.ts +++ b/system-test/test.install.ts @@ -14,9 +14,12 @@ * limitations under the License. */ +import * as assert from 'assert'; import * as execa from 'execa'; +import * as fs from 'fs'; import * as mv from 'mv'; import {ncp} from 'ncp'; +import * as path from 'path'; import * as tmp from 'tmp'; import {promisify} from 'util'; @@ -32,7 +35,7 @@ describe('📦 pack and install', () => { * Create a staging directory with temp fixtures used to test on a fresh * application. */ - it('should be able to use the d.ts', async () => { + before('pack and install', async () => { await execa('npm', ['pack', '--unsafe-perm']); const tarball = `${pkg.name}-${pkg.version}.tgz`; await mvp(tarball, `${stagingPath}/gaxios.tgz`); @@ -40,11 +43,22 @@ describe('📦 pack and install', () => { await execa( 'npm', ['install', '--unsafe-perm'], {cwd: `${stagingPath}/`, stdio: 'inherit'}); + }); + + it('should run the sample', async () => { await execa( 'node', ['--throw-deprecation', 'build/src/index.js'], {cwd: `${stagingPath}/`, stdio: 'inherit'}); }); + it('should be able to webpack the library', async () => { + // we expect npm install is executed in the before hook + await execa('npx', ['webpack'], {cwd: `${stagingPath}/`, stdio: 'inherit'}); + const bundle = path.join(stagingPath, 'dist', 'bundle.min.js'); + const stat = fs.statSync(bundle); + assert(stat.size < 256 * 1024); + }).timeout(20000); + /** * CLEAN UP - remove the staging directory when done. */ From 2856c7ce2a3ac0da83c8494635ec493f4fb7df63 Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Tue, 12 Feb 2019 11:35:01 -0800 Subject: [PATCH 6/7] chore: run browser test from CI --- .cirrus.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.cirrus.yml b/.cirrus.yml index 1b9e38da..6ba7912d 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -9,6 +9,10 @@ system_test_task: install_script: npm install test_script: npm run system-test +browser_test_task: + install_script: npm install + test_script: npm run browser-test + test_task: container: matrix: From 709d78bcfa8c98df6494b64d9a27a920e93e5b5f Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Tue, 12 Feb 2019 12:12:29 -0800 Subject: [PATCH 7/7] chore: use different docker image for browsers --- .cirrus.yml | 4 ++++ karma.conf.js | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 6ba7912d..4f47ccaf 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -10,6 +10,10 @@ system_test_task: test_script: npm run system-test browser_test_task: + container: + image: gmathieu/node-browsers + # the most popular image on Dockerhub with both node8, chromium, and + # all required dependencies install_script: npm install test_script: npm run browser-test diff --git a/karma.conf.js b/karma.conf.js index 54ed5276..a4c90b2a 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -16,10 +16,13 @@ // Karma configuration // Use `npm run browser-test` to run browser tests with Karma. +const fs = require('fs'); const isDocker = require('is-docker')(); const webpackConfig = require('./webpack-tests.config.js'); -process.env.CHROME_BIN = require('puppeteer').executablePath(); +process.env.CHROME_BIN = fs.existsSync('/usr/bin/chromium-browser') + ? '/usr/bin/chromium-browser' + : require('puppeteer').executablePath(); module.exports = function (config) { config.set({