From 783cdc00bb3f702de726b275770c0c0aa5e1d6c7 Mon Sep 17 00:00:00 2001 From: svozza Date: Fri, 14 Nov 2025 15:00:24 +0000 Subject: [PATCH] chore(testing): remove unnecessary esbuild banner from e2e tests --- .../src/resources/TestNodejsFunction.ts | 3 +- packages/testing/src/types.ts | 7 + packages/tracer/tests/e2e/decorator.test.ts | 308 +++++++++--------- packages/tracer/tests/e2e/manual.test.ts | 240 +++++++------- packages/tracer/tests/e2e/middy.test.ts | 1 + 5 files changed, 294 insertions(+), 265 deletions(-) diff --git a/packages/testing/src/resources/TestNodejsFunction.ts b/packages/testing/src/resources/TestNodejsFunction.ts index 56b0799a58..aae1629e45 100644 --- a/packages/testing/src/resources/TestNodejsFunction.ts +++ b/packages/testing/src/resources/TestNodejsFunction.ts @@ -24,6 +24,7 @@ class TestNodejsFunction extends NodejsFunction { extraProps: ExtraTestProps ) { const isESM = extraProps.outputFormat === 'ESM'; + const { shouldPolyfillRequire = false } = extraProps; const { bundling, ...restProps } = props; const functionName = concatenateResourceName({ testName: stack.testName, @@ -45,7 +46,7 @@ class TestNodejsFunction extends NodejsFunction { mainFields: isESM ? ['module', 'main'] : ['main', 'module'], sourceMap: false, format: isESM ? OutputFormat.ESM : OutputFormat.CJS, - banner: isESM + banner: shouldPolyfillRequire ? `import { createRequire } from 'module';const require = createRequire(import.meta.url);` : '', }, diff --git a/packages/testing/src/types.ts b/packages/testing/src/types.ts index 432f01e42f..3fa4c307da 100644 --- a/packages/testing/src/types.ts +++ b/packages/testing/src/types.ts @@ -19,6 +19,13 @@ interface ExtraTestProps { * @default 'CJS' */ outputFormat?: 'CJS' | 'ESM'; + /** + * Determines whether to polyfil the `require` function, this is useful when the bundler + * output is ESM and you are using a package that only ships ESM + * + * @default 'false' + */ + shouldPolyfillRequire?: boolean; /** * Whether to create an alias for the function. * diff --git a/packages/tracer/tests/e2e/decorator.test.ts b/packages/tracer/tests/e2e/decorator.test.ts index 70425b88d8..b773b80b57 100644 --- a/packages/tracer/tests/e2e/decorator.test.ts +++ b/packages/tracer/tests/e2e/decorator.test.ts @@ -17,159 +17,171 @@ import { RESOURCE_NAME_PREFIX, } from './constants.js'; -describe('Tracer E2E tests, decorator instrumentation', () => { - const testStack = new TestStack({ - stackNameProps: { - stackNamePrefix: RESOURCE_NAME_PREFIX, - testName: 'Decorator', - }, - }); - - // Location of the lambda function code - const lambdaFunctionCodeFilePath = join( - __dirname, - 'decorator.test.functionCode.ts' - ); - const startTime = new Date(); - - const testTable = new TestDynamodbTable( - testStack, - {}, - { - nameSuffix: 'TestTable', - } - ); - - const fnDecorator = new TestNodejsFunction( - testStack, - { - entry: lambdaFunctionCodeFilePath, - environment: { - TEST_TABLE_NAME: testTable.tableName, - POWERTOOLS_SERVICE_NAME: 'Decorator', - }, - }, - { - nameSuffix: 'Decorator', - } - ); - testTable.grantWriteData(fnDecorator); - - const invocationCount = 2; - let traceData: EnrichedXRayTraceDocumentParsed[] = []; - - beforeAll(async () => { - // Deploy the stack - await testStack.deploy(); - - // Get the actual function names from the stack outputs - const fnNameDecorator = testStack.findAndGetStackOutputValue('Decorator'); - - // Act - await invokeAllTestCases(fnNameDecorator, invocationCount); - traceData = await getTraces({ - startTime, - resourceName: fnNameDecorator, - expectedTracesCount: invocationCount, - /** - * The trace should have 4 segments: - * 1. Lambda Context (AWS::Lambda) - * 2. Lambda Function (AWS::Lambda::Function) - * 4. DynamoDB (AWS::DynamoDB) - * 4. Remote call (docs.aws.amazon.com) - */ - expectedSegmentsCount: 4, - }); - }); - - afterAll(async () => { - if (!process.env.DISABLE_TEARDOWN) { - await testStack.destroy(); - } - }); - - it('should generate all trace data correctly', () => { - // Assess - const mainSubsegment = traceData[0]; - const { subsegments, annotations, metadata } = mainSubsegment; - - // Check the main segment name - expect(mainSubsegment.name).toBe('## index.handler'); - - // Check the subsegments of the main segment - expect(subsegments.size).toBe(3); - - // Check remote call subsegment - expect(subsegments.has('docs.aws.amazon.com')).toBe(true); - const httpSubsegment = subsegments.get('docs.aws.amazon.com'); - expect(httpSubsegment?.namespace).toBe('remote'); - expect(httpSubsegment?.http?.request?.url).toEqual( - 'https://docs.aws.amazon.com/powertools/typescript/latest/' - ); - expect(httpSubsegment?.http?.request?.method).toBe('GET'); - expect(httpSubsegment?.http?.response?.status).toEqual(expect.any(Number)); - expect(httpSubsegment?.http?.response?.status).toEqual(expect.any(Number)); - - // Check the custom subsegment name & metadata - expect(subsegments.has(expectedCustomSubSegmentName)).toBe(true); - expect( - subsegments.get(expectedCustomSubSegmentName)?.metadata - ).toStrictEqual({ - Decorator: { - 'myMethod response': expectedCustomResponseValue, +describe.each([ + { outputFormat: 'CJS' as const }, + { outputFormat: 'ESM' as const }, +])( + 'Tracer E2E tests, decorator instrumentation ($outputFormat)', + ({ outputFormat }) => { + const testStack = new TestStack({ + stackNameProps: { + stackNamePrefix: RESOURCE_NAME_PREFIX, + testName: `Decorator${outputFormat}`, }, }); - // Check the other custom subsegment and its subsegments - expect(subsegments.has('### methodNoResponse')).toBe(true); - expect(subsegments.get('### methodNoResponse')?.metadata).toBeUndefined(); - expect(subsegments.get('### methodNoResponse')?.subsegments?.length).toBe( - 1 + // Location of the lambda function code + const lambdaFunctionCodeFilePath = join( + __dirname, + 'decorator.test.functionCode.ts' ); - expect( - subsegments.get('### methodNoResponse')?.subsegments?.[0]?.name === - 'DynamoDB' - ).toBe(true); - - // Check the annotations of the main segment - if (!annotations) { - throw new Error('No annotations found on the main segment'); - } - expect(annotations.ColdStart).toEqual(true); - expect(annotations.Service).toEqual('Decorator'); - expect(annotations[expectedCustomAnnotationKey]).toEqual( - expectedCustomAnnotationValue + const startTime = new Date(); + + const testTable = new TestDynamodbTable( + testStack, + {}, + { + nameSuffix: 'TestTable', + } ); - // Check the metadata of the main segment - if (!metadata) { - throw new Error('No metadata found on the main segment'); - } - expect(metadata.Decorator[expectedCustomMetadataKey]).toEqual( - expectedCustomMetadataValue + const fnDecorator = new TestNodejsFunction( + testStack, + { + entry: lambdaFunctionCodeFilePath, + environment: { + TEST_TABLE_NAME: testTable.tableName, + POWERTOOLS_SERVICE_NAME: 'Decorator', + }, + }, + { + nameSuffix: 'Decorator', + outputFormat, + shouldPolyfillRequire: outputFormat === 'ESM', + } ); + testTable.grantWriteData(fnDecorator); + + const invocationCount = 2; + let traceData: EnrichedXRayTraceDocumentParsed[] = []; + + beforeAll(async () => { + // Deploy the stack + await testStack.deploy(); + + // Get the actual function names from the stack outputs + const fnNameDecorator = testStack.findAndGetStackOutputValue('Decorator'); + + // Act + await invokeAllTestCases(fnNameDecorator, invocationCount); + traceData = await getTraces({ + startTime, + resourceName: fnNameDecorator, + expectedTracesCount: invocationCount, + /** + * The trace should have 4 segments: + * 1. Lambda Context (AWS::Lambda) + * 2. Lambda Function (AWS::Lambda::Function) + * 4. DynamoDB (AWS::DynamoDB) + * 4. Remote call (docs.aws.amazon.com) + */ + expectedSegmentsCount: 4, + }); + }); - // Check the response is present in the metadata - expect(metadata.Decorator['index.handler response']).toEqual( - expectedCustomResponseValue - ); - }); - - it('should annotate the trace with error data correctly', () => { - const mainSubsegment = traceData[1]; - const { annotations } = mainSubsegment; - - // Check the annotations of the main segment - if (!annotations) { - throw new Error('No annotations found on the main segment'); - } - expect(annotations.ColdStart).toEqual(false); - - // Check that the main segment has error data - expect(mainSubsegment.fault).toBe(true); - expect(Object.hasOwn(mainSubsegment, 'cause')).toBe(true); - expect(mainSubsegment.cause?.exceptions[0].message).toBe( - expectedCustomErrorMessage - ); - }); -}); + afterAll(async () => { + if (!process.env.DISABLE_TEARDOWN) { + await testStack.destroy(); + } + }); + + it('should generate all trace data correctly', () => { + // Assess + const mainSubsegment = traceData[0]; + const { subsegments, annotations, metadata } = mainSubsegment; + + // Check the main segment name + expect(mainSubsegment.name).toBe('## index.handler'); + + // Check the subsegments of the main segment + expect(subsegments.size).toBe(3); + + // Check remote call subsegment + expect(subsegments.has('docs.aws.amazon.com')).toBe(true); + const httpSubsegment = subsegments.get('docs.aws.amazon.com'); + expect(httpSubsegment?.namespace).toBe('remote'); + expect(httpSubsegment?.http?.request?.url).toEqual( + 'https://docs.aws.amazon.com/powertools/typescript/latest/' + ); + expect(httpSubsegment?.http?.request?.method).toBe('GET'); + expect(httpSubsegment?.http?.response?.status).toEqual( + expect.any(Number) + ); + expect(httpSubsegment?.http?.response?.status).toEqual( + expect.any(Number) + ); + + // Check the custom subsegment name & metadata + expect(subsegments.has(expectedCustomSubSegmentName)).toBe(true); + expect( + subsegments.get(expectedCustomSubSegmentName)?.metadata + ).toStrictEqual({ + Decorator: { + 'myMethod response': expectedCustomResponseValue, + }, + }); + + // Check the other custom subsegment and its subsegments + expect(subsegments.has('### methodNoResponse')).toBe(true); + expect(subsegments.get('### methodNoResponse')?.metadata).toBeUndefined(); + expect(subsegments.get('### methodNoResponse')?.subsegments?.length).toBe( + 1 + ); + expect( + subsegments.get('### methodNoResponse')?.subsegments?.[0]?.name === + 'DynamoDB' + ).toBe(true); + + // Check the annotations of the main segment + if (!annotations) { + throw new Error('No annotations found on the main segment'); + } + expect(annotations.ColdStart).toEqual(true); + expect(annotations.Service).toEqual('Decorator'); + expect(annotations[expectedCustomAnnotationKey]).toEqual( + expectedCustomAnnotationValue + ); + + // Check the metadata of the main segment + if (!metadata) { + throw new Error('No metadata found on the main segment'); + } + expect(metadata.Decorator[expectedCustomMetadataKey]).toEqual( + expectedCustomMetadataValue + ); + + // Check the response is present in the metadata + expect(metadata.Decorator['index.handler response']).toEqual( + expectedCustomResponseValue + ); + }); + + it('should annotate the trace with error data correctly', () => { + const mainSubsegment = traceData[1]; + const { annotations } = mainSubsegment; + + // Check the annotations of the main segment + if (!annotations) { + throw new Error('No annotations found on the main segment'); + } + expect(annotations.ColdStart).toEqual(false); + + // Check that the main segment has error data + expect(mainSubsegment.fault).toBe(true); + expect(Object.hasOwn(mainSubsegment, 'cause')).toBe(true); + expect(mainSubsegment.cause?.exceptions[0].message).toBe( + expectedCustomErrorMessage + ); + }); + } +); diff --git a/packages/tracer/tests/e2e/manual.test.ts b/packages/tracer/tests/e2e/manual.test.ts index c2fdf8b12f..8aee095c57 100644 --- a/packages/tracer/tests/e2e/manual.test.ts +++ b/packages/tracer/tests/e2e/manual.test.ts @@ -16,125 +16,133 @@ import { RESOURCE_NAME_PREFIX, } from './constants.js'; -describe('Tracer E2E tests, manual instantiation', () => { - const testStack = new TestStack({ - stackNameProps: { - stackNamePrefix: RESOURCE_NAME_PREFIX, - testName: 'Manual', - }, - }); - - // Location of the lambda function code - const lambdaFunctionCodeFilePath = join( - __dirname, - 'manual.test.functionCode.ts' - ); - const startTime = new Date(); - - const testTable = new TestDynamodbTable( - testStack, - {}, - { - nameSuffix: 'TestTable', - } - ); - - const fnManual = new TestNodejsFunction( - testStack, - { - entry: lambdaFunctionCodeFilePath, - environment: { - TEST_TABLE_NAME: testTable.tableName, - POWERTOOLS_SERVICE_NAME: 'Manual', +describe.each([ + { outputFormat: 'CJS' as const }, + { outputFormat: 'ESM' as const }, +])( + 'Tracer E2E tests, manual instantiation ($outputFormat)', + ({ outputFormat }) => { + const testStack = new TestStack({ + stackNameProps: { + stackNamePrefix: RESOURCE_NAME_PREFIX, + testName: `Manual${outputFormat}`, }, - }, - { - nameSuffix: 'Manual', - } - ); - testTable.grantWriteData(fnManual); - - const invocationCount = 2; - let traceData: EnrichedXRayTraceDocumentParsed[] = []; - - beforeAll(async () => { - // Deploy the stack - await testStack.deploy(); - - // Get the actual function names from the stack outputs - const fnNameManual = testStack.findAndGetStackOutputValue('Manual'); - - // Invoke all test cases - await invokeAllTestCases(fnNameManual, invocationCount); - traceData = await getTraces({ - startTime, - resourceName: fnNameManual, - expectedTracesCount: invocationCount, - /** - * The trace should have 2 segments: - * 1. Lambda Context (AWS::Lambda) - * 2. Lambda Function (AWS::Lambda::Function) - */ - expectedSegmentsCount: 2, }); - }); - - afterAll(async () => { - if (!process.env.DISABLE_TEARDOWN) { - await testStack.destroy(); - } - }); - - it('should generate all trace data correctly', () => { - // Assess - const mainSubsegment = traceData[0]; - const { subsegments, annotations, metadata } = mainSubsegment; - - // Check the main segment name - expect(mainSubsegment.name).toBe('## index.handler'); - - // Since CaptureHTTPsRequests is disabled, we should not have any subsegments - expect(subsegments.size).toBe(0); - - // Check the annotations of the main segment - if (!annotations) { - throw new Error('No annotations found on the main segment'); - } - expect(annotations.ColdStart).toEqual(true); - expect(annotations.Service).toEqual('Manual'); - expect(annotations[expectedCustomAnnotationKey]).toEqual( - expectedCustomAnnotationValue - ); - // Check the metadata of the main segment - if (!metadata) { - throw new Error('No metadata found on the main segment'); - } - expect(metadata.Manual?.[expectedCustomMetadataKey]).toEqual( - expectedCustomMetadataValue + // Location of the lambda function code + const lambdaFunctionCodeFilePath = join( + __dirname, + 'manual.test.functionCode.ts' ); - - // Check the response is present in the metadata - expect(metadata.Manual?.['index.handler response']).toEqual( - expectedCustomResponseValue + const startTime = new Date(); + + const testTable = new TestDynamodbTable( + testStack, + {}, + { + nameSuffix: 'TestTable', + } ); - }); - - it('should annotate the trace with error data correctly', () => { - const mainSubsegment = traceData[1]; - const { annotations } = mainSubsegment; - - // Check the annotations of the main segment - if (!annotations) { - throw new Error('No annotations found on the main segment'); - } - expect(annotations.ColdStart).toEqual(false); - - // Check that the main segment has error data - expect(mainSubsegment.fault).toBe(true); - expect(Object.hasOwn(mainSubsegment, 'cause')).toBe(true); - expect(mainSubsegment.cause?.exceptions[0].message).toBe( - expectedCustomErrorMessage + + const fnManual = new TestNodejsFunction( + testStack, + { + entry: lambdaFunctionCodeFilePath, + environment: { + TEST_TABLE_NAME: testTable.tableName, + POWERTOOLS_SERVICE_NAME: 'Manual', + }, + }, + { + nameSuffix: 'Manual', + outputFormat, + shouldPolyfillRequire: outputFormat === 'ESM', + } ); - }); -}); + testTable.grantWriteData(fnManual); + + const invocationCount = 2; + let traceData: EnrichedXRayTraceDocumentParsed[] = []; + + beforeAll(async () => { + // Deploy the stack + await testStack.deploy(); + + // Get the actual function names from the stack outputs + const fnNameManual = testStack.findAndGetStackOutputValue('Manual'); + + // Invoke all test cases + await invokeAllTestCases(fnNameManual, invocationCount); + traceData = await getTraces({ + startTime, + resourceName: fnNameManual, + expectedTracesCount: invocationCount, + /** + * The trace should have 2 segments: + * 1. Lambda Context (AWS::Lambda) + * 2. Lambda Function (AWS::Lambda::Function) + */ + expectedSegmentsCount: 2, + }); + }); + + afterAll(async () => { + if (!process.env.DISABLE_TEARDOWN) { + await testStack.destroy(); + } + }); + + it('should generate all trace data correctly', () => { + // Assess + const mainSubsegment = traceData[0]; + const { subsegments, annotations, metadata } = mainSubsegment; + + // Check the main segment name + expect(mainSubsegment.name).toBe('## index.handler'); + + // Since CaptureHTTPsRequests is disabled, we should not have any subsegments + expect(subsegments.size).toBe(0); + + // Check the annotations of the main segment + if (!annotations) { + throw new Error('No annotations found on the main segment'); + } + expect(annotations.ColdStart).toEqual(true); + expect(annotations.Service).toEqual('Manual'); + expect(annotations[expectedCustomAnnotationKey]).toEqual( + expectedCustomAnnotationValue + ); + + // Check the metadata of the main segment + if (!metadata) { + throw new Error('No metadata found on the main segment'); + } + expect(metadata.Manual?.[expectedCustomMetadataKey]).toEqual( + expectedCustomMetadataValue + ); + + // Check the response is present in the metadata + expect(metadata.Manual?.['index.handler response']).toEqual( + expectedCustomResponseValue + ); + }); + + it('should annotate the trace with error data correctly', () => { + const mainSubsegment = traceData[1]; + const { annotations } = mainSubsegment; + + // Check the annotations of the main segment + if (!annotations) { + throw new Error('No annotations found on the main segment'); + } + expect(annotations.ColdStart).toEqual(false); + + // Check that the main segment has error data + expect(mainSubsegment.fault).toBe(true); + expect(Object.hasOwn(mainSubsegment, 'cause')).toBe(true); + expect(mainSubsegment.cause?.exceptions[0].message).toBe( + expectedCustomErrorMessage + ); + }); + } +); diff --git a/packages/tracer/tests/e2e/middy.test.ts b/packages/tracer/tests/e2e/middy.test.ts index 26cc09f4fa..e98eb7c4cd 100644 --- a/packages/tracer/tests/e2e/middy.test.ts +++ b/packages/tracer/tests/e2e/middy.test.ts @@ -50,6 +50,7 @@ describe('Tracer E2E tests, middy instrumentation', () => { { nameSuffix: 'Middy', outputFormat: 'ESM', + shouldPolyfillRequire: true, } ); testTable.grantWriteData(fnMiddy);