Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ jobs:
- run: npm test
env:
CI: true
- run: npm run test:esm-build
env:
CI: true
5 changes: 4 additions & 1 deletion flagsmith-engine/segments/evaluators.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as jsonpath from 'jsonpath';
import * as jsonpathModule from 'jsonpath';
import {
GenericEvaluationContext,
InSegmentCondition,
Expand All @@ -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.
*
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 4 additions & 1 deletion tests/engine/unit/segments/segment_evaluators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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: {
Expand Down
12 changes: 9 additions & 3 deletions tests/sdk/flagsmith.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'
});
Expand Down Expand Up @@ -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');

Expand Down
4 changes: 3 additions & 1 deletion tests/sdk/offline-handlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 34 additions & 0 deletions vitest.config.esm.ts
Original file line number Diff line number Diff line change
@@ -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')
}
}
});