Skip to content

Commit 3ece952

Browse files
committed
tests: add logging tests to interceptors
1 parent c737b47 commit 3ece952

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

src/auth/authclient.ts

+1
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ export abstract class AuthClient
440440
// Logging must not create new errors; swallow them all.
441441
}
442442

443+
// Re-throw the error.
443444
throw error;
444445
},
445446
};

test/test.authclient.ts

+120-1
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,36 @@
1414

1515
import {strict as assert} from 'assert';
1616

17-
import {Gaxios, GaxiosOptionsPrepared} from 'gaxios';
17+
import {Gaxios, GaxiosError, GaxiosOptionsPrepared, GaxiosResponse} from 'gaxios';
1818

1919
import {AuthClient, PassThroughClient} from '../src';
2020
import {snakeToCamel} from '../src/util';
2121
import {PRODUCT_NAME, USER_AGENT} from '../src/shared.cjs';
22+
import * as logging from 'google-logging-utils';
23+
24+
// Fakes for the logger, to capture logs that would've happened.
25+
interface TestLog {
26+
namespace: string;
27+
fields: logging.LogFields;
28+
args: unknown[];
29+
}
30+
31+
class TestLogSink extends logging.DebugLogBackendBase {
32+
logs: TestLog[] = [];
33+
34+
makeLogger(namespace: string): logging.AdhocDebugLogCallable {
35+
return (fields: logging.LogFields, ...args: unknown[]) => {
36+
this.logs.push({namespace, fields, args});
37+
};
38+
}
39+
40+
setFilters(): void {}
41+
42+
reset() {
43+
this.filters = [];
44+
this.logs = [];
45+
}
46+
}
2247

2348
describe('AuthClient', () => {
2449
it('should accept and normalize snake case options to camel case', () => {
@@ -162,5 +187,99 @@ describe('AuthClient', () => {
162187
assert.equal(options.headers.get('x-goog-api-client'), expected);
163188
});
164189
});
190+
191+
describe('logging', () => {
192+
// Enable and capture any log lines that happen during these tests.
193+
let testLogSink: TestLogSink;
194+
let replacementLogger: logging.AdhocDebugLogFunction;
195+
beforeEach(() => {
196+
process.env[logging.env.nodeEnables] = 'auth';
197+
testLogSink = new TestLogSink();
198+
logging.setBackend(testLogSink);
199+
replacementLogger = logging.log('auth');
200+
});
201+
after(() => {
202+
delete process.env[logging.env.nodeEnables];
203+
logging.setBackend(null);
204+
})
205+
206+
it('logs requests', async () => {
207+
const options: GaxiosOptionsPrepared = {
208+
headers: new Headers({
209+
'x-goog-api-client': 'something',
210+
}),
211+
url: new URL('https://google.com'),
212+
};
213+
AuthClient.setMethodName(options, 'testMethod');
214+
215+
// This will become nicer with the 1.1.0 release of google-logging-utils.
216+
AuthClient.log = replacementLogger;
217+
const returned = await AuthClient.DEFAULT_REQUEST_INTERCEPTOR?.resolved?.(options);
218+
assert.strictEqual(returned, options);
219+
220+
// Unfortunately, there is a fair amount of entropy and changeable formatting in the
221+
// actual logs, so this mostly validates that a few key pieces of info are in there.
222+
assert.deepStrictEqual(testLogSink.logs.length, 1);
223+
assert.deepStrictEqual(testLogSink.logs[0].namespace, 'auth');
224+
assert.deepStrictEqual(testLogSink.logs[0].args.length, 4);
225+
assert.strictEqual((testLogSink.logs[0].args[0] as string).includes('request'), true);
226+
assert.deepStrictEqual(testLogSink.logs[0].args[1], 'testMethod');
227+
assert.deepStrictEqual((testLogSink.logs[0].args[3] as GaxiosOptionsPrepared).headers.get('x-goog-api-client'), 'something');
228+
assert.deepStrictEqual((testLogSink.logs[0].args[3] as GaxiosOptionsPrepared).url.href, 'https://google.com/');
229+
});
230+
231+
it('logs responses', async () => {
232+
const response = {
233+
config: {
234+
headers: new Headers({
235+
'x-goog-api-client': 'something',
236+
}),
237+
url: new URL('https://google.com'),
238+
} as GaxiosOptionsPrepared,
239+
headers: new Headers({
240+
'x-goog-api-client': 'something',
241+
}),
242+
url: new URL('https://google.com'),
243+
data: {
244+
test:'test!'
245+
},
246+
} as unknown as GaxiosResponse<{test: string}>;
247+
AuthClient.setMethodName(response.config, 'testMethod');
248+
249+
// This will become nicer with the 1.1.0 release of google-logging-utils.
250+
AuthClient.log = replacementLogger;
251+
const resolvedReturned = await AuthClient.DEFAULT_RESPONSE_INTERCEPTOR?.resolved?.(response);
252+
assert.strictEqual(resolvedReturned, response);
253+
254+
// Unfortunately, there is a fair amount of entropy and changeable formatting in the
255+
// actual logs, so this mostly validates that a few key pieces of info are in there.
256+
assert.deepStrictEqual(testLogSink.logs.length, 1);
257+
assert.deepStrictEqual(testLogSink.logs[0].namespace, 'auth');
258+
assert.deepStrictEqual(testLogSink.logs[0].args.length, 4);
259+
assert.strictEqual((testLogSink.logs[0].args[0] as string).includes('response'), true);
260+
assert.deepStrictEqual(testLogSink.logs[0].args[1], 'testMethod');
261+
assert.deepStrictEqual((testLogSink.logs[0].args[3] as {test: string}), {test: 'test!'});
262+
263+
const error = {
264+
config: response.config,
265+
response: {
266+
data: {
267+
message: 'boo!',
268+
}
269+
}
270+
} as unknown as GaxiosError<{test: string}>;
271+
testLogSink.reset();
272+
AuthClient.DEFAULT_RESPONSE_INTERCEPTOR?.rejected?.(error);
273+
274+
// Unfortunately, there is a fair amount of entropy and changeable formatting in the
275+
// actual logs, so this mostly validates that a few key pieces of info are in there.
276+
assert.deepStrictEqual(testLogSink.logs.length, 1);
277+
assert.deepStrictEqual(testLogSink.logs[0].namespace, 'auth');
278+
assert.deepStrictEqual(testLogSink.logs[0].args.length, 4);
279+
assert.strictEqual((testLogSink.logs[0].args[0] as string).includes('error'), true);
280+
assert.deepStrictEqual(testLogSink.logs[0].args[1], 'testMethod');
281+
assert.deepStrictEqual((testLogSink.logs[0].args[3] as {test: string}), {message: 'boo!'});
282+
});
283+
});
165284
});
166285
});

0 commit comments

Comments
 (0)