From 58b47cbe3dc5d46e01f7c40c095dcdbbb00e364b Mon Sep 17 00:00:00 2001 From: Scott Kennedy Date: Wed, 20 May 2026 09:57:44 -0400 Subject: [PATCH] Add published artifact loadability test --- packages/tests/jest.config.ts | 1 + packages/tests/src/_jest/helpers/constants.ts | 2 + packages/tools/src/rollupConfig.test.ts | 51 ++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/packages/tests/jest.config.ts b/packages/tests/jest.config.ts index f11bc3f9a..f50b0576b 100644 --- a/packages/tests/jest.config.ts +++ b/packages/tests/jest.config.ts @@ -15,6 +15,7 @@ const config: JestConfigWithTsJest = { setupFilesAfterEnv: ['/src/_jest/setupAfterEnv.ts'], testEnvironment: 'node', testMatch: ['**/*.test.*'], + testPathIgnorePatterns: ['/node_modules/', '/dist/'], testTimeout: 10000, }; diff --git a/packages/tests/src/_jest/helpers/constants.ts b/packages/tests/src/_jest/helpers/constants.ts index 5279f2531..a90390372 100644 --- a/packages/tests/src/_jest/helpers/constants.ts +++ b/packages/tests/src/_jest/helpers/constants.ts @@ -30,4 +30,6 @@ export const KNOWN_ERRORS: string[] = [ // Jest 30 globalsCleanup warnings for nock's internal properties that can't be protected. "[JEST-01] DeprecationWarning: 'logger' property was accessed on [_FetchInterceptor]", "[JEST-01] DeprecationWarning: 'now' property was accessed on [Function]", + // Local shells may set NO_COLOR while the test script forces color output. + "Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set.", ]; diff --git a/packages/tools/src/rollupConfig.test.ts b/packages/tools/src/rollupConfig.test.ts index 2a2adbb09..a8dc5b846 100644 --- a/packages/tools/src/rollupConfig.test.ts +++ b/packages/tools/src/rollupConfig.test.ts @@ -32,12 +32,13 @@ import { } from '@dd/tests/_jest/helpers/runBundlers'; import type { CleanupFn } from '@dd/tests/_jest/helpers/types'; import { ROOT } from '@dd/tools/constants'; -import { bgGreen, bgYellow, execute, green } from '@dd/tools/helpers'; +import { bgGreen, bgYellow, execute, executeSync, green } from '@dd/tools/helpers'; import type { BuildOptions } from 'esbuild'; import fs from 'fs'; import { glob } from 'glob'; import nock from 'nock'; import path from 'path'; +import { pathToFileURL } from 'url'; import type { BundlerConfig } from './bundlers'; @@ -144,6 +145,31 @@ const getBuiltFiles = () => { return builtFiles; }; +type PublishedPackageJson = { + publishConfig?: { + exports?: { + '.'?: { + import?: string; + require?: string; + types?: string; + }; + }; + }; +}; + +const getPublishedPackageJson = (bundlerName: string): PublishedPackageJson => { + return require(path.resolve(ROOT, `packages/published/${bundlerName}-plugin/package.json`)); +}; + +const getPublishedExports = (bundlerName: string) => { + const packageJson = getPublishedPackageJson(bundlerName); + return packageJson.publishConfig?.exports?.['.']; +}; + +const resolvePublishedExportPath = (bundlerName: string, exportPath: string) => { + return path.resolve(ROOT, `packages/published/${bundlerName}-plugin`, exportPath); +}; + describe('Bundling', () => { let bundlerVersions: Partial> = {}; let processErrors: string[] = []; @@ -233,6 +259,29 @@ describe('Bundling', () => { const existingFiles = fs.readdirSync(getPackagePath(bundlerName)).sort(); expect(existingFiles).toEqual(expectedFiles); }); + + test(`Should expose loadable publish artifacts for @datadog/${bundlerName}-plugin.`, () => { + getPackageDestination(bundlerName); + + const publishedExports = getPublishedExports(bundlerName); + expect(publishedExports?.import).toEqual(expect.stringMatching(/\.mjs$/)); + expect(publishedExports?.require).toEqual(expect.stringMatching(/\.js$/)); + expect(publishedExports?.types).toEqual(expect.stringMatching(/\.d\.ts$/)); + + const esmEntry = resolvePublishedExportPath(bundlerName, publishedExports!.import!); + const cjsEntry = resolvePublishedExportPath(bundlerName, publishedExports!.require!); + const typesEntry = resolvePublishedExportPath(bundlerName, publishedExports!.types!); + expect(fs.existsSync(typesEntry)).toBe(true); + + executeSync(process.execPath, ['--check', esmEntry]); + executeSync(process.execPath, ['--check', cjsEntry]); + executeSync(process.execPath, [ + '--input-type=module', + '--eval', + `await import(${JSON.stringify(pathToFileURL(esmEntry).href)});`, + ]); + executeSync(process.execPath, ['--eval', `require(${JSON.stringify(cjsEntry)});`]); + }); }); describe.each(BUNDLERS)('Bundler: $name', (bundler) => {