From a36ee6aa10cab2de5d84b5890ecd210e5afeee4a Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Fri, 29 Jun 2018 12:23:07 -0700 Subject: [PATCH] test: test the typescript install (#183) --- package.json | 8 +++- src/service-object.ts | 2 +- src/service.ts | 3 +- src/util.ts | 24 +++++----- test/fixtures/kitchen/package.json | 25 ++++++++++ test/fixtures/kitchen/src/index.ts | 12 +++++ test/fixtures/kitchen/tsconfig.json | 10 ++++ test/install.ts | 72 +++++++++++++++++++++++++++++ test/service-object.ts | 3 +- tsconfig.json | 3 +- 10 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 test/fixtures/kitchen/package.json create mode 100644 test/fixtures/kitchen/src/index.ts create mode 100644 test/fixtures/kitchen/tsconfig.json create mode 100644 test/install.ts diff --git a/package.json b/package.json index a1582bef..73ef8583 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "publish-module": "node ../../scripts/publish.js common", "generate-scaffolding": "repo-tools generate all", "docs": "jsdoc -c .jsdoc.js", - "cover": "nyc --reporter=lcov mocha --require source-map-support/register intelli-espower-loader build/test && nyc report", + "cover": "nyc --reporter=lcov mocha --require source-map-support/register --require intelli-espower-loader build/test && nyc report", "test-no-cover": "mocha build/test", "test": "npm run test-only", "test-only": "npm run cover", @@ -73,6 +73,8 @@ "@types/extend": "^3.0.0", "@types/is": "0.0.20", "@types/mocha": "^5.2.1", + "@types/mv": "^2.1.0", + "@types/ncp": "^2.0.1", "@types/nock": "^9.1.3", "@types/node": "^10.3.1", "@types/pify": "^3.0.2", @@ -80,6 +82,7 @@ "@types/shimmer": "^1.0.1", "@types/sinon": "^5.0.1", "@types/through2": "^2.0.33", + "@types/tmp": "0.0.33", "@types/uuid": "^3.4.3", "codecov": "^3.0.2", "gts": "^0.7.0", @@ -88,6 +91,8 @@ "js-green-licenses": "^0.5.0", "jsdoc": "^3.5.5", "mocha": "^5.2.0", + "mv": "^2.1.1", + "ncp": "^2.0.0", "nock": "^9.3.1", "nyc": "^12.0.2", "power-assert": "^1.5.0", @@ -95,6 +100,7 @@ "shimmer": "^1.2.0", "sinon": "^6.0.0", "source-map-support": "^0.5.6", + "tmp": "0.0.33", "typescript": "~2.9.1", "uuid": "^3.2.1" } diff --git a/src/service-object.ts b/src/service-object.ts index 96c0ba45..ac4e7249 100644 --- a/src/service-object.ts +++ b/src/service-object.ts @@ -22,7 +22,7 @@ import arrify from 'arrify'; import {EventEmitter} from 'events'; import extend from 'extend'; import is from 'is'; -import r from 'request'; +import * as r from 'request'; import {Service} from '.'; import {ApiError, BodyResponseCallback, DecorateRequestOptions, util} from './util'; diff --git a/src/service.ts b/src/service.ts index abad637e..14f1e5b0 100644 --- a/src/service.ts +++ b/src/service.ts @@ -19,12 +19,11 @@ */ import arrify from 'arrify'; -import {Duplexify} from 'duplexify'; import extend from 'extend'; import {GoogleAuth} from 'google-auth-library'; import is from 'is'; import pify from 'pify'; -import r from 'request'; +import * as r from 'request'; import {StreamRequestOptions} from './service-object'; import {BodyResponseCallback, DecorateRequestOptions, MakeAuthenticatedRequest, PackageJson, util} from './util'; diff --git a/src/util.ts b/src/util.ts index caa3cb62..a070fab8 100644 --- a/src/util.ts +++ b/src/util.ts @@ -18,13 +18,13 @@ * @module common/util */ -import duplexify from 'duplexify'; +import * as d from 'duplexify'; import ent from 'ent'; import extend from 'extend'; import {GoogleAuth, GoogleAuthOptions} from 'google-auth-library'; import {CredentialBody} from 'google-auth-library/build/src/auth/credentials'; import is from 'is'; -import r from 'request'; +import * as r from 'request'; import retryRequest from 'retry-request'; import {Transform, TransformOptions} from 'stream'; import streamEvents from 'stream-events'; @@ -51,14 +51,14 @@ export interface ParsedHttpRespMessage { } export interface MakeAuthenticatedRequest { - (reqOpts: DecorateRequestOptions): duplexify.Duplexify; + (reqOpts: DecorateRequestOptions): d.Duplexify; (reqOpts: DecorateRequestOptions, options?: MakeAuthenticatedRequestOptions): void|Abortable; (reqOpts: DecorateRequestOptions, callback?: BodyResponseCallback): void|Abortable; (reqOpts: DecorateRequestOptions, optionsOrCallback?: MakeAuthenticatedRequestOptions| - BodyResponseCallback): void|Abortable|duplexify.Duplexify; + BodyResponseCallback): void|Abortable|d.Duplexify; getCredentials: (callback: (err?: Error|null, credentials?: CredentialBody) => void) => void; @@ -68,7 +68,7 @@ export interface MakeAuthenticatedRequest { export type Abortable = { abort(): void }; -export type AbortableDuplex = duplexify.Duplexify&Abortable; +export type AbortableDuplex = d.Duplexify&Abortable; export interface PromisifyAllOptions extends PromisifyOptions { /** @@ -141,7 +141,7 @@ export interface MakeAuthenticatedRequestFactoryConfig extends */ maxRetries?: number; - stream?: duplexify.Duplexify; + stream?: d.Duplexify; } export interface MakeAuthenticatedRequestOptions { @@ -298,7 +298,7 @@ export interface MakeRequestConfig { retries?: number; - stream?: duplexify.Duplexify; + stream?: d.Duplexify; request?: {}; @@ -418,7 +418,7 @@ export class Util { * @param {function} onComplete - Callback, executed after the writable Request stream has completed. */ makeWritableStream( - dup: duplexify.Duplexify, options: MakeWritableStreamOptions, + dup: d.Duplexify, options: MakeWritableStreamOptions, onComplete?: Function) { onComplete = onComplete || util.noop; @@ -537,7 +537,7 @@ export class Util { * authenticated request options. */ function makeAuthenticatedRequest(reqOpts: DecorateRequestOptions): - duplexify.Duplexify; + d.Duplexify; function makeAuthenticatedRequest( reqOpts: DecorateRequestOptions, options?: MakeAuthenticatedRequestOptions): void|Abortable; @@ -547,13 +547,13 @@ export class Util { function makeAuthenticatedRequest( reqOpts: DecorateRequestOptions, optionsOrCallback?: MakeAuthenticatedRequestOptions| - BodyResponseCallback): void|Abortable|duplexify.Duplexify { - let stream: duplexify.Duplexify; + BodyResponseCallback): void|Abortable|d.Duplexify { + let stream: d.Duplexify; const reqConfig = extend({}, config); let activeRequest_: void|Abortable|null; if (!optionsOrCallback) { - stream = duplexify(); + stream = d.default(); reqConfig.stream = stream; } diff --git a/test/fixtures/kitchen/package.json b/test/fixtures/kitchen/package.json new file mode 100644 index 00000000..00880a26 --- /dev/null +++ b/test/fixtures/kitchen/package.json @@ -0,0 +1,25 @@ +{ + "name": "fixture", + "version": "1.0.0", + "private": true, + "description": "An app we're using to test the library.", + "scripts": { + "check": "gts check", + "clean": "gts clean", + "compile": "tsc -p .", + "fix": "gts fix", + "prepare": "npm run compile", + "pretest": "npm run compile", + "posttest": "npm run check", + "start": "node build/src/index.js" + }, + "license": "Apache-2.0", + "dependencies": { + "@google-cloud/common": "file:./google-cloud-common.tgz" + }, + "devDependencies": { + "@types/node": "^10.3.0", + "typescript": "^2.9.1", + "gts": "^0.7.0" + } +} diff --git a/test/fixtures/kitchen/src/index.ts b/test/fixtures/kitchen/src/index.ts new file mode 100644 index 00000000..0b7bb3e6 --- /dev/null +++ b/test/fixtures/kitchen/src/index.ts @@ -0,0 +1,12 @@ +import {GoogleAuthOptions, Logger, LoggerConfig, CustomLevelsLogger, + CustomLevelsLoggerConfig, logger, Operation, paginator, Paginator, + ParsedArguments, Service, ServiceConfig, ServiceOptions, CreateOptions, + DeleteCallback, ExistsCallback, GetConfig, GetMetadataCallback, + InstanceResponseCallback, Interceptor, Metadata, Methods, ServiceObject, + ServiceObjectConfig, StreamRequestOptions, Abortable, AbortableDuplex, + ApiError, util} from '@google-cloud/common'; + +util.makeRequest({url: 'test'}, (err, body, res) => { + console.log(err); +}); + diff --git a/test/fixtures/kitchen/tsconfig.json b/test/fixtures/kitchen/tsconfig.json new file mode 100644 index 00000000..48d92fd3 --- /dev/null +++ b/test/fixtures/kitchen/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "./node_modules/gts/tsconfig-google.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "build", + "esModuleInterop": false, + "allowSyntheticDefaultImports": false + }, + "include": ["src/*.ts"] +} diff --git a/test/install.ts b/test/install.ts new file mode 100644 index 00000000..e1e15996 --- /dev/null +++ b/test/install.ts @@ -0,0 +1,72 @@ +/** + * Copyright 2018 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. + */ + +import cp from 'child_process'; +import mv from 'mv'; +import {ncp} from 'ncp'; +import os from 'os'; +import pify from 'pify'; +import tmp from 'tmp'; + +const mvp = pify(mv); +const ncpp = pify(ncp); +const keep = !!process.env.KEEP_TEMPDIRS; +const stagingDir = tmp.dirSync({keep, unsafeCleanup: true}); +const stagingPath = stagingDir.name; +const pkg = require('../../package.json'); +const pkgName = 'google-cloud-common'; +const npm = os.platform() === 'win32' ? 'npm.cmd' : 'npm'; + +const spawnp = + (command: string, args: string[], options: cp.SpawnOptions = {}) => { + return new Promise((resolve, reject) => { + cp.spawn(command, args, Object.assign(options, {stdio: 'inherit'})) + .on('close', + code => { + if (code === 0) { + resolve(); + } else { + reject( + new Error(`Spawn failed with an exit code of ${code}`)); + } + }) + .on('error', reject); + }); + }; + +/** + * Create a staging directory with temp fixtures used to test on a fresh + * application. + */ +it('should be able to use the d.ts', async () => { + console.log(`${__filename} staging area: ${stagingPath}`); + await spawnp(npm, ['pack']); + const tarball = `${pkgName}-${pkg.version}.tgz`; + // stagingPath can be on another filesystem so fs.rename() will fail + // with EXDEV, hence we use `mv` module here. + await mvp(tarball, `${stagingPath}/${pkgName}.tgz`); + await ncpp('test/fixtures/kitchen', `${stagingPath}/`); + await spawnp(npm, ['install'], {cwd: `${stagingPath}/`}); +}).timeout(40000); + +/** + * CLEAN UP - remove the staging directory when done. + */ +after('cleanup staging', async () => { + if (!keep) { + stagingDir.removeCallback(); + } +}); diff --git a/test/service-object.ts b/test/service-object.ts index 61d32411..656dd7ea 100644 --- a/test/service-object.ts +++ b/test/service-object.ts @@ -16,8 +16,7 @@ import assert from 'assert'; import extend from 'extend'; -import {RequestError} from 'google-auth-library/build/src/transporters'; -import r from 'request'; +import * as r from 'request'; import sinon from 'sinon'; import {Service} from '../src'; diff --git a/tsconfig.json b/tsconfig.json index 11720320..9e7359eb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ "test/**/*.ts" ], "exclude": [ - "node_modules" + "node_modules", + "test/fixtures" ] }