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
2 changes: 2 additions & 0 deletions apps/playground/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module.exports = {
testMatch: [
'<rootDir>/src/__tests__/**/*.(test|spec|harness).(js|jsx|ts|tsx)',
],
setupFiles: ['./src/setupFile.ts'],
setupFilesAfterEnv: ['./src/setupFileAfterEnv.ts'],
},
],
};
11 changes: 11 additions & 0 deletions apps/playground/src/__tests__/setup-files.harness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { describe, test, expect } from 'react-native-harness';

describe('Setup files', () => {
test('should execute setup file', () => {
expect(global.SETUP_FILE_EXECUTED).toBe(true);
});

test('should execute setup file after env', () => {
expect(global.SETUP_FILE_EXECUTED_AFTER_ENV).toBe(true);
});
});
6 changes: 6 additions & 0 deletions apps/playground/src/setupFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare global {
var SETUP_FILE_EXECUTED: boolean;
}

global.SETUP_FILE_EXECUTED = true;
export {};
6 changes: 6 additions & 0 deletions apps/playground/src/setupFileAfterEnv.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare global {
var SETUP_FILE_EXECUTED_AFTER_ENV: boolean;
}

global.SETUP_FILE_EXECUTED_AFTER_ENV = true;
export {};
5 changes: 5 additions & 0 deletions packages/bridge/src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export type {
ModuleBundlingStartedEvent,
ModuleBundlingFinishedEvent,
ModuleBundlingFailedEvent,
SetupFileBundlingStartedEvent,
SetupFileBundlingFinishedEvent,
SetupFileBundlingFailedEvent,
BundlerEvents,
} from './shared/bundler.js';

Expand All @@ -54,6 +57,8 @@ export type BridgeEventsMap = {

export type TestExecutionOptions = {
testNamePattern?: string;
setupFiles?: string[];
setupFilesAfterEnv?: string[];
};

export type BridgeClientFunctions = {
Expand Down
26 changes: 25 additions & 1 deletion packages/bridge/src/shared/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,31 @@ export type ModuleBundlingFailedEvent = {
error: string;
};

export type SetupFileBundlingStartedEvent = {
type: 'setup-file-bundling-started';
file: string;
setupType: 'setupFiles' | 'setupFilesAfterEnv';
};

export type SetupFileBundlingFinishedEvent = {
type: 'setup-file-bundling-finished';
file: string;
setupType: 'setupFiles' | 'setupFilesAfterEnv';
duration: number;
};

export type SetupFileBundlingFailedEvent = {
type: 'setup-file-bundling-failed';
file: string;
setupType: 'setupFiles' | 'setupFilesAfterEnv';
duration: number;
error: string;
};

export type BundlerEvents =
| ModuleBundlingStartedEvent
| ModuleBundlingFinishedEvent
| ModuleBundlingFailedEvent;
| ModuleBundlingFailedEvent
| SetupFileBundlingStartedEvent
| SetupFileBundlingFinishedEvent
| SetupFileBundlingFailedEvent;
12 changes: 12 additions & 0 deletions packages/jest/src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,25 @@ export type RunHarnessTestFile = (options: {
export const runHarnessTestFile: RunHarnessTestFile = async ({
testPath,
globalConfig,
projectConfig,
harness,
}) => {
const start = Date.now();
const relativeTestPath = path.relative(globalConfig.rootDir, testPath);

// Extract setup files from Jest config and convert to relative paths
const setupFiles = projectConfig.setupFiles?.map((setupFile) =>
path.relative(globalConfig.rootDir, setupFile)
);
const setupFilesAfterEnv = projectConfig.setupFilesAfterEnv?.map(
(setupFile) => path.relative(globalConfig.rootDir, setupFile)
);

const client = harness.bridge.rpc.clients.at(-1)!;
const results = await client.runTests(relativeTestPath, {
testNamePattern: globalConfig.testNamePattern,
setupFiles,
setupFilesAfterEnv,
});
const end = Date.now();

Expand Down
67 changes: 67 additions & 0 deletions packages/runtime/src/client/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,73 @@ export const getClient = async () => {
client.rpc.emitEvent(event.type, event);
});

// Execute setup files before test collection
if (options.setupFiles) {
for (const setupFile of options.setupFiles) {
const startTime = Date.now();
events.emit({
type: 'setup-file-bundling-started',
file: setupFile,
setupType: 'setupFiles',
});

try {
const setupModuleJs = await bundler.getModule(setupFile);
events.emit({
type: 'setup-file-bundling-finished',
file: setupFile,
setupType: 'setupFiles',
duration: Date.now() - startTime,
});
evaluateModule(setupModuleJs, setupFile);
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error';
events.emit({
type: 'setup-file-bundling-failed',
file: setupFile,
setupType: 'setupFiles',
duration: Date.now() - startTime,
error: errorMessage,
});
throw error;
}
}
}

if (options.setupFilesAfterEnv) {
for (const setupFile of options.setupFilesAfterEnv) {
const startTime = Date.now();
events.emit({
type: 'setup-file-bundling-started',
file: setupFile,
setupType: 'setupFilesAfterEnv',
});

try {
const setupModuleJs = await bundler.getModule(setupFile);
events.emit({
type: 'setup-file-bundling-finished',
file: setupFile,
setupType: 'setupFilesAfterEnv',
duration: Date.now() - startTime,
});
evaluateModule(setupModuleJs, setupFile);
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Unknown error';
events.emit({
type: 'setup-file-bundling-failed',
file: setupFile,
setupType: 'setupFilesAfterEnv',
duration: Date.now() - startTime,
error: errorMessage,
});
throw error;
}
}
}

const moduleJs = await bundler.getModule(path);
const collectionResult = await collector.collect(
() => evaluateModule(moduleJs, path),
Expand Down