Skip to content

Commit 718f2ae

Browse files
committed
test: update tests to avoid mocks
1 parent 886e015 commit 718f2ae

File tree

2 files changed

+86
-46
lines changed

2 files changed

+86
-46
lines changed

packages/core/src/shared/awsClientBuilderV3.ts

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import { CredentialsShim } from '../auth/deprecated/loginManager'
77
import { AwsContext } from './awsContext'
88
import {
99
AwsCredentialIdentityProvider,
10+
BuildHandlerArguments,
11+
DeserializeHandlerArguments,
12+
DeserializeHandlerOutput,
13+
FinalizeHandlerArguments,
1014
Logger,
1115
RetryStrategyV2,
1216
TokenIdentity,
@@ -213,26 +217,34 @@ export function recordErrorTelemetry(err: Error, serviceName?: string) {
213217
}
214218

215219
export const defaultDeserializeMiddleware: DeserializeMiddleware<any, any> =
216-
(next: DeserializeHandler<any, any>, context: HandlerExecutionContext) => async (args: any) =>
220+
(next: DeserializeHandler<any, any>, context: HandlerExecutionContext) =>
221+
async (args: DeserializeHandlerArguments<any>) =>
217222
onDeserialize(next, context, args)
218223

219224
export const finalizeLoggingMiddleware: FinalizeRequestMiddleware<any, any> =
220-
(next: FinalizeHandler<any, any>) => async (args: any) =>
225+
(next: FinalizeHandler<any, any>) => async (args: FinalizeHandlerArguments<any>) =>
221226
logOnFinalize(next, args)
222227

223228
function getEndpointMiddleware(settings: DevSettings = DevSettings.instance): BuildMiddleware<any, any> {
224-
return (next: BuildHandler<any, any>, context: HandlerExecutionContext) => async (args: any) =>
225-
overwriteEndpoint(next, context, settings, args)
229+
return (next: BuildHandler<any, any>, context: HandlerExecutionContext) =>
230+
async (args: BuildHandlerArguments<any>) =>
231+
overwriteEndpoint(next, context, settings, args)
226232
}
227233

228-
const keepAliveMiddleware: BuildMiddleware<any, any> = (next: BuildHandler<any, any>) => async (args: any) =>
229-
addKeepAliveHeader(next, args)
234+
const keepAliveMiddleware: BuildMiddleware<any, any> =
235+
(next: BuildHandler<any, any>) => async (args: BuildHandlerArguments<any>) =>
236+
addKeepAliveHeader(next, args)
230237

231-
export async function onDeserialize(next: DeserializeHandler<any, any>, context: HandlerExecutionContext, args: any) {
232-
if (!HttpResponse.isInstance(args.request)) {
238+
export async function onDeserialize(
239+
next: DeserializeHandler<any, any>,
240+
context: HandlerExecutionContext,
241+
args: DeserializeHandlerArguments<any>
242+
): Promise<DeserializeHandlerOutput<any>> {
243+
const request = args.request
244+
if (!HttpRequest.isInstance(request)) {
233245
return next(args)
234246
}
235-
const { hostname, path } = args.request
247+
const { hostname, path } = request
236248
const serviceId = getServiceId(context as object)
237249
const logTail = `(${hostname} ${path})`
238250
try {
@@ -247,15 +259,15 @@ export async function onDeserialize(next: DeserializeHandler<any, any>, context:
247259
const err = { ...e, name: e.name, mesage: e.message }
248260
delete err['stack']
249261
recordErrorTelemetry(err, serviceId)
250-
getLogger().error('API Response %s: %O', logTail, err)
262+
logErrorWithHeaders(request, err, logTail)
251263
}
252264
throw e
253265
}
254266
}
255267

256-
export async function logOnFinalize(next: FinalizeHandler<any, any>, args: any) {
268+
export async function logOnFinalize(next: FinalizeHandler<any, any>, args: FinalizeHandlerArguments<any>) {
257269
const request = args.request
258-
if (HttpRequest.isInstance(args.request)) {
270+
if (HttpRequest.isInstance(request)) {
259271
const { hostname, path } = request
260272
const input = partialClone(args.input, 3, ['clientSecret', 'accessToken', 'refreshToken'], '[omitted]')
261273
getLogger().debug(`API Request (%s %s): %O`, hostname, path, input)
@@ -267,7 +279,7 @@ export function overwriteEndpoint(
267279
next: BuildHandler<any, any>,
268280
context: HandlerExecutionContext,
269281
settings: DevSettings,
270-
args: any
282+
args: BuildHandlerArguments<any>
271283
) {
272284
const request = args.request
273285
if (HttpRequest.isInstance(request)) {
@@ -289,10 +301,25 @@ export function overwriteEndpoint(
289301
* @param args
290302
* @returns
291303
*/
292-
export function addKeepAliveHeader(next: BuildHandler<any, any>, args: any) {
304+
export function addKeepAliveHeader(next: BuildHandler<any, any>, args: BuildHandlerArguments<any>) {
293305
const request = args.request
294306
if (HttpRequest.isInstance(request)) {
295307
request.headers['Connection'] = 'keep-alive'
296308
}
297309
return next(args)
298310
}
311+
312+
export function logErrorWithHeaders(response: HttpRequest, err: Omit<Error, 'stack'>, logTail?: string) {
313+
const logHeaderNames = [
314+
'x-amzn-requestid',
315+
'x-amzn-trace-id',
316+
'x-amzn-served-from',
317+
'x-cache',
318+
'x-amz-cf-id',
319+
'x-amz-cf-pop',
320+
]
321+
const filteredHeaders = Object.fromEntries(
322+
Object.entries(response.headers).filter(([k, v]) => logHeaderNames.includes(k))
323+
)
324+
getLogger().error('API request failed %s\n headers: %O\n %O', logTail, filteredHeaders, err)
325+
}

packages/core/src/test/shared/awsClientBuilderV3.test.ts

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ import {
1919
logOnFinalize,
2020
overwriteEndpoint,
2121
recordErrorTelemetry,
22+
logErrorWithHeaders,
2223
} from '../../shared/awsClientBuilderV3'
2324
import { Client } from '@aws-sdk/smithy-client'
2425
import { DevSettings, extensionVersion } from '../../shared'
2526
import { assertTelemetry } from '../testUtil'
2627
import { telemetry } from '../../shared/telemetry'
27-
import { HttpRequest, HttpResponse } from '@aws-sdk/protocol-http'
2828
import { assertLogsContain, assertLogsContainAllOf } from '../globalSetup.test'
2929
import { TestSettings } from '../utilities/testSettingsConfiguration'
3030
import { CredentialsShim } from '../../auth/deprecated/loginManager'
@@ -33,6 +33,7 @@ import { oneDay } from '../../shared/datetime'
3333
import { ConfiguredRetryStrategy } from '@smithy/util-retry'
3434
import { StandardRetryStrategy } from '@smithy/util-retry'
3535
import { NodeHttpHandler } from '@smithy/node-http-handler'
36+
import { HttpRequest, HttpResponse } from '@smithy/protocol-http'
3637

3738
describe('AwsClientBuilderV3', function () {
3839
let builder: AWSClientBuilderV3
@@ -197,55 +198,51 @@ describe('AwsClientBuilderV3', function () {
197198
})
198199

199200
describe('middlewareStack', function () {
200-
let args: { request: { hostname: string; path: string }; input: any }
201+
let args: { request: HttpRequest; input: any }
201202
let context: { clientName?: string; commandName?: string }
202-
let response: { response: { statusCode: number }; output: { message: string } }
203-
let httpRequestStub: sinon.SinonStub
204-
let httpResponseStub: sinon.SinonStub
205-
206-
before(function () {
207-
httpRequestStub = sinon.stub(HttpRequest, 'isInstance')
208-
httpResponseStub = sinon.stub(HttpResponse, 'isInstance')
209-
httpRequestStub.callsFake(() => true)
210-
httpResponseStub.callsFake(() => true)
211-
})
203+
let output: { response: HttpResponse }
212204

213205
beforeEach(function () {
214206
args = {
215-
request: {
207+
request: new HttpRequest({
216208
hostname: 'testHost',
217209
path: 'testPath',
218-
},
219-
input: {
220-
testKey: 'testValue',
221-
},
210+
headers: {
211+
'x-amzn-RequestId': 'fakeId',
212+
'x-amzn-requestid': 'realId',
213+
},
214+
}),
215+
input: {},
222216
}
223-
context = {
224-
clientName: 'fooClient',
225-
}
226-
response = {
227-
response: {
217+
output = {
218+
response: new HttpResponse({
228219
statusCode: 200,
229-
},
230-
output: {
231-
message: 'test output',
232-
},
220+
body: 'test body',
221+
headers: {
222+
'x-amzn-RequestId': 'fakeId',
223+
'x-amzn-requestid': 'realId',
224+
},
225+
}),
226+
}
227+
context = {
228+
clientName: 'foo',
229+
commandName: 'bar',
233230
}
234231
})
235232
after(function () {
236233
sinon.restore()
237234
})
238235

239236
it('logs messages on request', async function () {
240-
await logOnFinalize((_: any) => _, args as any)
237+
await logOnFinalize((_: any) => _, args)
241238
assertLogsContainAllOf(['testHost', 'testPath'], false, 'debug')
242239
})
243240

244241
it('adds telemetry metadata and logs on error failure', async function () {
245242
const next = (_: any) => {
246243
throw new Error('test error')
247244
}
248-
await telemetry.vscode_executeCommand.run(async (span) => {
245+
await telemetry.vscode_executeCommand.run(async (_span) => {
249246
await assert.rejects(onDeserialize(next, context, args))
250247
})
251248
assertLogsContain('test error', false, 'error')
@@ -254,10 +251,10 @@ describe('AwsClientBuilderV3', function () {
254251

255252
it('does not emit telemetry, but still logs on successes', async function () {
256253
const next = async (_: any) => {
257-
return response
254+
return output
258255
}
259-
await telemetry.vscode_executeCommand.run(async (span) => {
260-
assert.deepStrictEqual(await onDeserialize(next, context, args), response)
256+
await telemetry.vscode_executeCommand.run(async (_span) => {
257+
assert.deepStrictEqual(await onDeserialize(next, context, args), output)
261258
})
262259
assertLogsContainAllOf(['testHost', 'testPath'], false, 'debug')
263260
assert.throws(() => assertTelemetry('vscode_executeCommand', { requestServiceType: 'foo' }))
@@ -281,7 +278,23 @@ describe('AwsClientBuilderV3', function () {
281278
const newArgs: any = await overwriteEndpoint(next, context, new DevSettings(settings), args)
282279

283280
assert.strictEqual(newArgs.request.hostname, 'testHost')
284-
assert.strictEqual(newArgs.request.path, 'testPath')
281+
assert.strictEqual(newArgs.request.path, '/testPath')
282+
})
283+
284+
it('logs specific headers on request failure', async function () {
285+
const response = new HttpRequest({
286+
body: 'test body',
287+
headers: {
288+
'x-amzn-RequestId': 'fakeId',
289+
'x-amzn-requestid': 'realId',
290+
'x-amz-id-2': 'otherId',
291+
},
292+
})
293+
294+
logErrorWithHeaders(response, new Error('test error'), 'host-path')
295+
assertLogsContain('realId', false, 'error')
296+
assert.throws(() => assertLogsContain('fakeId', false, 'error'))
297+
assert.throws(() => assertLogsContain('otherId', false, 'error'))
285298
})
286299
})
287300

0 commit comments

Comments
 (0)