From 889ef31badb9218f98776d7ca4ff2fc6a3ad647f Mon Sep 17 00:00:00 2001 From: wadii Date: Mon, 1 Dec 2025 16:27:03 +0100 Subject: [PATCH 1/3] fix: use-default-on-jsonpath-import --- flagsmith-engine/segments/evaluators.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flagsmith-engine/segments/evaluators.ts b/flagsmith-engine/segments/evaluators.ts index 08b5717..3d2c1ad 100644 --- a/flagsmith-engine/segments/evaluators.ts +++ b/flagsmith-engine/segments/evaluators.ts @@ -1,4 +1,4 @@ -import * as jsonpath from 'jsonpath'; +import * as jsonpathModule from 'jsonpath'; import { GenericEvaluationContext, InSegmentCondition, @@ -10,6 +10,9 @@ import { getHashedPercentageForObjIds } from '../utils/hashing/index.js'; import { SegmentConditionModel } from './models.js'; import { IS_NOT_SET, IS_SET, PERCENTAGE_SPLIT } from './constants.js'; +// Handle ESM/CJS interop - jsonpath exports default in ESM +const jsonpath = (jsonpathModule as any).default || jsonpathModule; + /** * Returns all segments that the identity belongs to based on segment rules evaluation. * From 22b87d631f9b888cb8656cba09adfbd01adf99f2 Mon Sep 17 00:00:00 2001 From: wadii Date: Mon, 1 Dec 2025 17:36:40 +0100 Subject: [PATCH 2/3] fix: added-esm-like-tests --- .github/workflows/pull_request.yaml | 3 ++ package.json | 1 + .../unit/segments/segment_evaluators.test.ts | 5 ++- tests/sdk/flagsmith.test.ts | 12 +++++-- tests/sdk/offline-handlers.test.ts | 4 ++- vitest.config.esm.ts | 34 +++++++++++++++++++ 6 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 vitest.config.esm.ts diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index 09a0e57..b981546 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -35,3 +35,6 @@ jobs: - run: npm test env: CI: true + - run: npm run test:esm-build + env: + CI: true diff --git a/package.json b/package.json index dff70e4..d1817ca 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "scripts": { "lint": "prettier --write .", "test": "vitest --coverage --run", + "test:esm-build": "npm run build && ESM_BUILD=true vitest --config vitest.config.esm.ts --run", "test:watch": "vitest", "test:debug": "vitest --inspect-brk --no-file-parallelism --coverage", "prebuild": "rm -rf ./build", diff --git a/tests/engine/unit/segments/segment_evaluators.test.ts b/tests/engine/unit/segments/segment_evaluators.test.ts index cc28f5c..74c63e9 100644 --- a/tests/engine/unit/segments/segment_evaluators.test.ts +++ b/tests/engine/unit/segments/segment_evaluators.test.ts @@ -14,6 +14,8 @@ import { SegmentCondition1 } from '../../../../flagsmith-engine/evaluation/models.js'; +const isEsmBuild = process.env.ESM_BUILD === 'true'; + // todo: work out how to implement this in a test function or before hook vi.mock('../../../../flagsmith-engine/utils/hashing', () => ({ getHashedPercentageForObjIds: vi.fn(() => 1) @@ -395,7 +397,8 @@ describe('getContextValue', () => { }); }); -describe('percentage split operator', () => { +// Skip in ESM build: vi.mock doesn't work with external modules +describe.skipIf(isEsmBuild)('percentage split operator', () => { const mockContext: EvaluationContext = { environment: { key: 'env', name: 'Test Env' }, identity: { diff --git a/tests/sdk/flagsmith.test.ts b/tests/sdk/flagsmith.test.ts index b0b66f3..be64a1d 100644 --- a/tests/sdk/flagsmith.test.ts +++ b/tests/sdk/flagsmith.test.ts @@ -14,8 +14,12 @@ import { EnvironmentModel } from '../../flagsmith-engine/environments/models.js' import { BaseOfflineHandler } from '../../sdk/offline_handlers.js'; import { Agent } from 'undici'; +const isEsmBuild = process.env.ESM_BUILD === 'true'; + vi.mock('../../sdk/polling_manager'); -test('test_flagsmith_starts_polling_manager_on_init_if_enabled', () => { + +// Skip in ESM build: vi.mock doesn't work with external modules +test.skipIf(isEsmBuild)('test_flagsmith_starts_polling_manager_on_init_if_enabled', () => { new Flagsmith({ environmentKey: 'ser.key', enableLocalEvaluation: true @@ -32,7 +36,8 @@ test('test_flagsmith_local_evaluation_key_required', () => { }).toThrow('Using local evaluation requires a server-side environment key'); }); -test('test_update_environment_sets_environment', async () => { +// Skip in ESM build: instanceof fails across module boundaries +test.skipIf(isEsmBuild)('test_update_environment_sets_environment', async () => { const flg = flagsmith({ environmentKey: 'ser.key' }); @@ -513,7 +518,8 @@ test('getIdentityFlags succeeds if initial fetch failed then succeeded', async ( expect(flags2.isFeatureEnabled('some_feature')).toBe(true); }); -test('get_user_agent_extracts_version_from_package_json', async () => { +// Skip in ESM build: require() path resolution differs +test.skipIf(isEsmBuild)('get_user_agent_extracts_version_from_package_json', async () => { const userAgent = getUserAgent(); const packageJson = require('../../package.json'); diff --git a/tests/sdk/offline-handlers.test.ts b/tests/sdk/offline-handlers.test.ts index 09b6482..1362ceb 100644 --- a/tests/sdk/offline-handlers.test.ts +++ b/tests/sdk/offline-handlers.test.ts @@ -7,8 +7,10 @@ import * as offlineEnvironment from './data/offline-environment.json'; vi.mock('fs'); const offlineEnvironmentString = JSON.stringify(offlineEnvironment); +const isEsmBuild = process.env.ESM_BUILD === 'true'; -test('local file handler', () => { +// Skip in ESM build: instanceof fails across module boundaries +test.skipIf(isEsmBuild)('local file handler', () => { const environmentDocumentFilePath = '/some/path/environment.json'; // Mock the fs.readFileSync function to return environmentJson diff --git a/vitest.config.esm.ts b/vitest.config.esm.ts new file mode 100644 index 0000000..2cc8767 --- /dev/null +++ b/vitest.config.esm.ts @@ -0,0 +1,34 @@ +import { defineConfig } from 'vitest/config'; +import path from 'path'; + +/** + * Vitest config for testing against the built ESM output. + * This catches CJS/ESM interop issues (like jsonpath) that don't surface + * when testing TypeScript source directly. + * + * Run with: npm run test:esm-build (after npm run build) + */ +export default defineConfig({ + test: { + globals: true, + restoreMocks: true, + exclude: ['**/node_modules/**'], + server: { + deps: { + // Don't transform built ESM - test it as-is + external: [/build\/esm/] + } + } + }, + resolve: { + alias: { + // Redirect source imports to built ESM output + '../../../flagsmith-engine': path.resolve(__dirname, 'build/esm/flagsmith-engine'), + '../../../../flagsmith-engine': path.resolve(__dirname, 'build/esm/flagsmith-engine'), + '../../../sdk': path.resolve(__dirname, 'build/esm/sdk'), + '../../../../sdk': path.resolve(__dirname, 'build/esm/sdk'), + '../../sdk': path.resolve(__dirname, 'build/esm/sdk'), + '../sdk': path.resolve(__dirname, 'build/esm/sdk'), + } + } +}); From ecbcdca64aa38dd775ecb5462ad694c09624c151 Mon Sep 17 00:00:00 2001 From: wadii Date: Mon, 1 Dec 2025 17:37:03 +0100 Subject: [PATCH 3/3] fix: vitest-config-esm --- vitest.config.esm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vitest.config.esm.ts b/vitest.config.esm.ts index 2cc8767..a21f2a8 100644 --- a/vitest.config.esm.ts +++ b/vitest.config.esm.ts @@ -28,7 +28,7 @@ export default defineConfig({ '../../../sdk': path.resolve(__dirname, 'build/esm/sdk'), '../../../../sdk': path.resolve(__dirname, 'build/esm/sdk'), '../../sdk': path.resolve(__dirname, 'build/esm/sdk'), - '../sdk': path.resolve(__dirname, 'build/esm/sdk'), + '../sdk': path.resolve(__dirname, 'build/esm/sdk') } } });