diff --git a/jest/integration/config/jest.config.js b/jest/integration/config/jest.config.js index b00053063fe..cd047bfaae4 100644 --- a/jest/integration/config/jest.config.js +++ b/jest/integration/config/jest.config.js @@ -25,4 +25,5 @@ module.exports = { transformIgnorePatterns: ['.*'], testRunner: './jest/integration/runner/index.js', watchPathIgnorePatterns: ['/jest/integration/build/'], + globalSetup: './jest/integration/runner/warmup/index.js', }; diff --git a/jest/integration/runner/warmup/index.js b/jest/integration/runner/warmup/index.js new file mode 100644 index 00000000000..1e3f3ef54ba --- /dev/null +++ b/jest/integration/runner/warmup/index.js @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @oncall react_native + */ + +require('../../../../scripts/build/babel-register').registerForMonorepo(); + +module.exports = require('./warmup'); diff --git a/jest/integration/runner/warmup/warmup.js b/jest/integration/runner/warmup/warmup.js new file mode 100644 index 00000000000..9836209b84a --- /dev/null +++ b/jest/integration/runner/warmup/warmup.js @@ -0,0 +1,113 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import {getBuckModeForPlatform, runBuck2} from '../utils'; +// $FlowExpectedError[untyped-import] +import fs from 'fs'; +import Metro from 'metro'; +import os from 'os'; +import path from 'path'; + +export default async function warmUp( + globalConfig: {...}, + projectConfig: {...}, +): Promise { + try { + warmUpHermesCompiler(); + warmUpRNTesterCLI(); + await warmUpMetro(); + } catch (e) { + // Sandcastle fails to parse the test output if we log stuff to stdout/stderr. + if ((process.env.SANDCASTLE ?? '') !== '') { + console.error( + 'Global warmup failed. Tests will continue to run but will likely fail. Details:\n', + e, + ); + } + } +} + +async function warmUpMetro(): Promise { + const metroConfig = await Metro.loadConfig({ + config: path.resolve(__dirname, '..', '..', 'config', 'metro.config.js'), + }); + + const entrypointPath = path.resolve( + __dirname, + '..', + '..', + 'runtime', + 'WarmUpEntryPoint.js', + ); + + const bundlePath = path.join( + os.tmpdir(), + `fantom-warmup-bundle-${Date.now()}.js`, + ); + + await Metro.runBuild(metroConfig, { + entry: entrypointPath, + out: bundlePath, + platform: 'android', + minify: false, + dev: true, + }); + + try { + fs.unlinkSync(bundlePath); + } catch {} +} + +function warmUpHermesCompiler(): void { + const buildHermesCompilerCommandResult = runBuck2([ + 'build', + getBuckModeForPlatform(), + '//xplat/hermes/tools/hermesc:hermesc', + ]); + + if (buildHermesCompilerCommandResult.status !== 0) { + throw new Error( + [ + 'Failed to build Hermes compiler. Full output:', + buildHermesCompilerCommandResult.originalCommand, + 'stdout:', + buildHermesCompilerCommandResult.stdout, + 'stderr:', + buildHermesCompilerCommandResult.stderr, + 'error:', + buildHermesCompilerCommandResult.error, + ].join('\n'), + ); + } +} + +function warmUpRNTesterCLI(): void { + const buildRNTesterCommandResult = runBuck2([ + 'build', + getBuckModeForPlatform(), + '//xplat/ReactNative/react-native-cxx/samples/tester:tester', + ]); + + if (buildRNTesterCommandResult.status !== 0) { + throw new Error( + [ + 'Failed to build RN tester binary. Full output:', + buildRNTesterCommandResult.originalCommand, + 'stdout:', + buildRNTesterCommandResult.stdout, + 'stderr:', + buildRNTesterCommandResult.stderr, + 'error:', + buildRNTesterCommandResult.error, + ].join('\n'), + ); + } +} diff --git a/jest/integration/runtime/WarmUpEntryPoint.js b/jest/integration/runtime/WarmUpEntryPoint.js new file mode 100644 index 00000000000..faf4f6c45ee --- /dev/null +++ b/jest/integration/runtime/WarmUpEntryPoint.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @oncall react_native + */ + +/** + * This is just an entrypoint to warm up the Metro cache before the tests run. + */ + +import 'react-native/Libraries/Core/InitializeCore.js'; +import 'react-native/src/private/__tests__/ReactNativeTester'; +import './setup';