Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
],
"scripts": {
"docs": "jsdoc -c .jsdoc.js",
"test": "node ../../bin/run-test.cjs --proxyquire-shim build/test",
"test": "node ../../bin/run-test.cjs build/test",
"prepare": "npm run compile",
"pretest": "npm run compile",
"compile": "tsc -p .",
Expand Down
115 changes: 115 additions & 0 deletions core/common/test/proxyquire.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2026 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 Module from 'module';
import * as path from 'path';

delete require.cache[require.resolve(__filename)];

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Stubs = Record<string, any>;
const mod = Module as unknown as {
prototype: {require: NodeRequire};
_resolveFilename: (request: string, parent: NodeModule) => string;
};
const {hasOwnProperty} = Object.prototype;
const hasOwn = (o: unknown, k: string) =>
Boolean(o && typeof o === 'object' && hasOwnProperty.call(o, k));
const isGlobal = (s: unknown) =>
hasOwn(s, '@global') || hasOwn(s, '@runtimeGlobal');
const resolveFrom = (base: string, req: string) => {
try {
return require.resolve(req, {paths: [path.dirname(base)]});
} catch {
return req[0] === '.' ? path.resolve(path.dirname(base), req) : req;
}
};

const parent = module.parent || module;
let skipCallThru = false;
let keepCache = true;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function proxyquire<T = any>(request: string, stubs: Stubs = {}): T {
const sut = mod._resolveFilename(request, parent);
const resolved: Stubs = {};
let global = false;
for (const [k, v] of Object.entries(stubs)) {
if (isGlobal(v)) global = true;
resolved[resolveFrom(sut, k)] = v;
}
const cache = require.cache;
const keys = global
? Object.keys(cache).filter(id => !id.endsWith('.node'))
: [sut];
const saved = keys.map(id => [id, cache[id]] as const);
for (const id of keys) delete cache[id];
const prev = mod.prototype.require;
const req = function (this: NodeModule, id: string) {
const isSut = this?.filename === sut;
if (this?.filename && (isSut || global)) {
const hit = (isSut || !id.startsWith('.')) && hasOwn(stubs, id);
const rId = hit ? '' : resolveFrom(this.filename, id);
if (hit || hasOwn(resolved, rId)) {
const stub = hit ? stubs[id] : resolved[rId];
if (isSut || isGlobal(stub)) {
if (stub === null) {
const e = new Error(`Cannot find module '${id}'`);
throw Object.assign(e, {code: 'MODULE_NOT_FOUND'});
}
const skip = hasOwn(stub, '@noCallThru')
? stub['@noCallThru']
: skipCallThru;
if (!skip && stub && ['object', 'function'].includes(typeof stub)) {
try {
const real = prev.call(this, id);
if (real && ['object', 'function'].includes(typeof real)) {
for (const k of Object.keys(real)) {
if (!(k in stub)) stub[k] = real[k];
}
}
} catch {
// ignore
}
}
return stub;
}
}
}
return prev.call(this, id);
};
mod.prototype.require = Object.assign(req, prev);
try {
return prev.call(parent, request);
} finally {
mod.prototype.require = prev;
for (const id of global ? Object.keys(cache) : [sut]) {
if (!id.endsWith('.node')) delete cache[id];
}
for (const [id, m] of saved) {
if (m && (keepCache || id !== sut)) cache[id] = m;
}
}
}

// eslint-disable-next-line @typescript-eslint/no-namespace
namespace proxyquire {
export const load = proxyquire;
export const noCallThru = () => ((skipCallThru = true), proxyquire);
export const callThru = () => ((skipCallThru = false), proxyquire);
export const noPreserveCache = () => ((keepCache = false), proxyquire);
export const preserveCache = () => ((keepCache = true), proxyquire);
}

export = proxyquire;
3 changes: 2 additions & 1 deletion core/common/test/service-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
import * as assert from 'assert';
import {describe, it, beforeEach, afterEach} from 'mocha';
import * as extend from 'extend';
import * as proxyquire from 'proxyquire';
import * as proxyquire from './proxyquire';
// eslint-disable-next-line import/namespace
import * as r from 'teeny-request';
import * as sinon from 'sinon';

Expand Down Expand Up @@ -298,7 +299,7 @@
);
assert.strictEqual((reqOpts as DecorateRequestOptions).uri, '');
done();
(callback as any)(null, null, {} as r.Response);

Check warning on line 302 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});
serviceObject.delete(assert.ifError);
});
Expand All @@ -313,7 +314,7 @@
options,
);
done();
(callback as any)(null, null, {} as r.Response);

Check warning on line 317 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});
serviceObject.delete(options, assert.ifError);
});
Expand Down Expand Up @@ -344,7 +345,7 @@
'PATCH',
);
done();
(callback as any)(null, null, null!);

Check warning on line 348 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});

const serviceObject = new ServiceObject(CONFIG) as FakeServiceObject;
Expand Down Expand Up @@ -384,7 +385,7 @@
undefined,
);
done();
(callback as any)(null, null, {} as r.Response);

Check warning on line 388 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});
serviceObject.delete(options, assert.ifError);
});
Expand Down Expand Up @@ -414,7 +415,7 @@
thisPropertyWasOverridden: true,
});
done();
(callback as any)(null, null, null!);

Check warning on line 418 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});

const serviceObject = new ServiceObject(CONFIG) as FakeServiceObject;
Expand Down Expand Up @@ -459,7 +460,7 @@
.callsFake((options_, callback) => {
assert.deepStrictEqual(options_, options);
done();
(callback as any)(null, null, {} as r.Response);

Check warning on line 463 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});
serviceObject.exists(options, assert.ifError);
});
Expand Down Expand Up @@ -664,7 +665,7 @@
assert.strictEqual(this, serviceObject);
assert.strictEqual((reqOpts as DecorateRequestOptions).uri, '');
done();
(callback as any)(null, null, {} as r.Response);

Check warning on line 668 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});
void serviceObject.getMetadata(() => {});
});
Expand All @@ -679,7 +680,7 @@
options,
);
done();
(callback as any)(null, null, {} as r.Response);

Check warning on line 683 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});
serviceObject.getMetadata(options, assert.ifError);
});
Expand All @@ -705,7 +706,7 @@
'v2',
);
done();
(callback as any)(null, null, null!);

Check warning on line 709 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});

const serviceObject = new ServiceObject(CONFIG) as FakeServiceObject;
Expand Down Expand Up @@ -738,7 +739,7 @@
thisPropertyWasOverridden: true,
});
done();
(callback as any)(null, null, null!);

Check warning on line 742 in core/common/test/service-object.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
});

const serviceObject = new ServiceObject(CONFIG) as FakeServiceObject;
Expand Down
2 changes: 1 addition & 1 deletion core/common/test/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import * as assert from 'assert';
import {describe, it, before, beforeEach, after} from 'mocha';
import * as extend from 'extend';
import * as proxyquire from 'proxyquire';
import * as proxyquire from './proxyquire';
import {Request} from 'teeny-request';
import {AuthClient, GoogleAuth, OAuth2Client} from 'google-auth-library';

Expand Down
3 changes: 2 additions & 1 deletion core/common/test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import {
OAuth2Client,
} from 'google-auth-library';
import * as nock from 'nock';
import * as proxyquire from 'proxyquire';
import * as proxyquire from './proxyquire';
// eslint-disable-next-line import/namespace
import * as r from 'teeny-request';
import * as retryRequest from 'retry-request';
import * as sinon from 'sinon';
Expand Down
2 changes: 1 addition & 1 deletion core/packages/gax/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"scripts": {
"docs": "jsdoc -c .jsdoc.js",
"pretest": "pnpm run compile",
"test": "node ../../../bin/run-test.cjs --proxyquire-shim build/test/unit",
"test": "node ../../../bin/run-test.cjs build/test/unit",
"lint": "gts check src samples test",
"clean": "gts clean",
"compile": "node ./scripts/copy-protos.js && tsc -p . && cp src/*.json build/src && cp -r test/fixtures build/test && cp -r protos build/",
Expand Down
35 changes: 17 additions & 18 deletions core/packages/gax/test/unit/grpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@

import assert from 'assert';
import * as path from 'path';
import proxyquire from 'proxyquire';
import * as sinon from 'sinon';
import {mkdirSync, writeFileSync} from 'fs';
import fs, {mkdirSync, writeFileSync} from 'fs';
import * as fsp from 'fs/promises';
import {afterEach, describe, it, beforeEach} from 'mocha';

Expand Down Expand Up @@ -613,28 +612,28 @@ describe('grpc', () => {
const originPath = path.join('test', 'path', 'location');
const includePath = path.join('example', 'import.proto');

afterEach(() => {
sinon.restore();
});

it('should throw an error if a file is not found', () => {
const findIncludePath = proxyquire('../../src/grpc', {
fs: {
existsSync: () => {
return false;
},
},
}).GoogleProtoFilesRoot._findIncludePath;
assert.throws(findIncludePath.bind(null, originPath, includePath));
sinon.stub(fs, 'existsSync').returns(false);
assert.throws(
GoogleProtoFilesRoot._findIncludePath.bind(
null,
originPath,
includePath,
),
);
});

it('should return the correct resolved import path', () => {
const correctPath = path.join('test', 'example', 'import.proto');
const findIncludePath = proxyquire('../../src/grpc', {
fs: {
existsSync(path: string) {
return path === correctPath;
},
},
}).GoogleProtoFilesRoot._findIncludePath;
sinon
.stub(fs, 'existsSync')
.callsFake((p: fs.PathLike) => p === correctPath);
assert.strictEqual(
findIncludePath(originPath, includePath),
GoogleProtoFilesRoot._findIncludePath(originPath, includePath),
correctPath,
);
});
Expand Down
2 changes: 1 addition & 1 deletion core/packages/nodejs-googleapis-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"prebenchmark": "npm run compile",
"benchmark": "node build/benchmark/bench.js",
"compile": "tsc -p .",
"test": "node ../../../bin/run-test.cjs --proxyquire-shim build/test",
"test": "node ../../../bin/run-test.cjs build/test",
"system-test": "node ../../../bin/run-test.cjs build/system-test --timeout 600000",
"presystem-test": "npm run compile",
"fix": "gts fix",
Expand Down
25 changes: 12 additions & 13 deletions core/packages/nodejs-googleapis-common/test/test.authplus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,17 @@
// limitations under the License.

import * as assert from 'assert';
import {describe, it} from 'mocha';
import * as proxyquire from 'proxyquire';
import * as AuthPlus from '../src/authplus';
import {afterEach, describe, it} from 'mocha';
import * as sinon from 'sinon';
import {AuthPlus} from '../src/authplus';

describe(__filename, () => {
const AuthyPlus: typeof AuthPlus = proxyquire('../src/authplus', {
'google-auth-library': {
GoogleAuth: class {
async getClient() {
return {};
}
},
},
afterEach(() => {
sinon.restore();
});

it('should expose auth classes', () => {
const auth = new AuthyPlus.AuthPlus();
const auth = new AuthPlus();
assert.ok(auth.JWT);
assert.ok(auth.Compute);
assert.ok(auth.OAuth2);
Expand All @@ -40,8 +34,13 @@ describe(__filename, () => {
});

it('should get a new client', async () => {
const auth = new AuthyPlus.AuthPlus();
const auth = new AuthPlus();
const getClientStub = sinon
.stub(auth.GoogleAuth.prototype, 'getClient')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.resolves({} as any);
const client = await auth.getClient();
assert.deepStrictEqual(client, {});
assert.strictEqual(getClientStub.calledOnce, true);
});
});
21 changes: 11 additions & 10 deletions core/packages/nodejs-googleapis-common/test/test.http2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@

import * as assert from 'assert';
import * as coreHttp2 from 'http2';
import {describe, it, before, beforeEach} from 'mocha';
import {describe, it, before, beforeEach, after} from 'mocha';
import {gzipSync} from 'zlib';
import * as proxyquire from 'proxyquire';
import * as sinon from 'sinon';
import {Duplex, Readable} from 'stream';
import {EventEmitter} from 'events';
import {GaxiosResponse} from 'gaxios';
import * as http2Types from '../src/http2';
import * as http2 from '../src/http2';

import {GoogleAuth} from '../src';

Expand Down Expand Up @@ -59,13 +58,15 @@ describe('http2', () => {
return (connectStub || (() => {}))(host);
}
let connectStub: Function;
let http2: typeof http2Types;
let connectSinonStub: sinon.SinonStub;
before(() => {
http2 = proxyquire('../src/http2', {
http2: {
connect: fakeConnect,
},
});
connectSinonStub = sinon
.stub(coreHttp2, 'connect')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.callsFake(fakeConnect as any);
});
after(() => {
connectSinonStub.restore();
});

let requestStream: Duplex;
Expand Down Expand Up @@ -153,7 +154,7 @@ describe('http2', () => {
requestStream.push(Buffer.from('{}'));
requestStream.push(null);
await resPromise;
await new Promise(r => setTimeout(r, 500));
await new Promise(resolve => setTimeout(resolve, 500));
assert.strictEqual(Object.keys(http2.sessions).length, 0);
});

Expand Down
2 changes: 1 addition & 1 deletion handwritten/bigquery/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"docs": "jsdoc -c .jsdoc.js",
"lint": "gts check",
"samples-test": "cd samples/ && pnpm link ../ && pnpm test && cd ../",
"test": "node ../../bin/run-test.cjs --proxyquire-shim build/test",
"test": "node ../../bin/run-test.cjs build/test",
"system-test": "node ../../bin/run-test.cjs build/system-test --timeout 600000",
"presystem-test": "pnpm run compile",
"clean": "gts clean",
Expand Down
2 changes: 1 addition & 1 deletion handwritten/bigquery/test/bigquery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import * as assert from 'assert';
import {describe, it, after, afterEach, before, beforeEach} from 'mocha';
import * as Big from 'big.js';
import * as extend from 'extend';
import * as proxyquire from 'proxyquire';
import * as proxyquire from './proxyquire';
import * as sinon from 'sinon';
import * as crypto from 'crypto';

Expand Down
2 changes: 1 addition & 1 deletion handwritten/bigquery/test/dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import * as pfy from '@google-cloud/promisify';
import * as assert from 'assert';
import {describe, it, before, beforeEach} from 'mocha';
import * as extend from 'extend';
import * as proxyquire from 'proxyquire';
import * as proxyquire from './proxyquire';

import * as _root from '../src';
import {toArray} from '../src/util';
Expand Down
2 changes: 1 addition & 1 deletion handwritten/bigquery/test/job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {DecorateRequestOptions, util} from '@google-cloud/common';
import * as pfy from '@google-cloud/promisify';
import * as assert from 'assert';
import {describe, it, beforeEach, afterEach, before} from 'mocha';
import * as proxyquire from 'proxyquire';
import * as proxyquire from './proxyquire';
import * as sinon from 'sinon';

import {BigQuery} from '../src/bigquery';
Expand Down
2 changes: 1 addition & 1 deletion handwritten/bigquery/test/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import * as assert from 'assert';
import {describe, it, before, beforeEach, afterEach} from 'mocha';
import * as sinon from 'sinon';
import * as proxyquire from 'proxyquire';
import * as proxyquire from './proxyquire';
import * as pfy from '@google-cloud/promisify';
import {EventEmitter} from 'events';
import {JobOptions} from '../src/job';
Expand Down
Loading
Loading