From 23c76e0f52563d46c88a6a730fc9713182d2526e Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 8 May 2025 14:42:20 +0300 Subject: [PATCH 1/5] Test bundling RN project --- e2e-tests/tests/react-native.test.ts | 28 +++++++++++--- e2e-tests/utils/index.ts | 55 ++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 6 deletions(-) diff --git a/e2e-tests/tests/react-native.test.ts b/e2e-tests/tests/react-native.test.ts index 9955ce450..f1086d859 100644 --- a/e2e-tests/tests/react-native.test.ts +++ b/e2e-tests/tests/react-native.test.ts @@ -1,9 +1,15 @@ import * as path from 'node:path'; import { Integration } from '../../lib/Constants'; -import { KEYS, TEST_ARGS, cleanupGit, revertLocalChanges } from '../utils'; -import { startWizardInstance } from '../utils'; -import { checkFileContents } from '../utils'; -import { afterAll, beforeAll, describe, test } from 'vitest'; +import { + KEYS, + TEST_ARGS, + cleanupGit, + checkFileContents, + checkIfReactNativeBundles, + revertLocalChanges, + startWizardInstance +} from '../utils'; +import { afterAll, beforeAll, describe, test, expect } from 'vitest'; describe('ReactNative', () => { const integration = Integration.reactNative; @@ -45,7 +51,7 @@ describe('ReactNative', () => { optional: true, timeout: 5000, }, - )); + )); const prettierPrompted = podInstallPrompted && @@ -62,7 +68,7 @@ describe('ReactNative', () => { [KEYS.DOWN, KEYS.ENTER], 'Have you successfully sent a test event?', )); - + testEventPrompted && (await wizardInstance.sendStdinAndWaitForOutput( // Respond that test event was sent @@ -168,4 +174,14 @@ defaults.url=https://sentry.io/`, `../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh`, ); }); + + test('android project is bundled correctly', async () => { + const bundled = await checkIfReactNativeBundles(projectDir, 'android'); + expect(bundled).toBe(true); + }); + + test('ios project is bundled correctly', async () => { + const bundled = await checkIfReactNativeBundles(projectDir, 'ios'); + expect(bundled).toBe(true); + }); }); diff --git a/e2e-tests/utils/index.ts b/e2e-tests/utils/index.ts index 4573aa2de..b94d3c3f4 100644 --- a/e2e-tests/utils/index.ts +++ b/e2e-tests/utils/index.ts @@ -472,6 +472,61 @@ export async function checkIfFlutterBuilds( expect(outputReceived).toBe(true); } +/** + * Check if the React Native project bundles successfully for the specified platform. + * Returns a boolean indicating if the process exits with status code 0. + * @param projectDir The root directory of the React Native project. + * @param platform The platform to bundle for ('ios' or 'android'). + * @param debug runs the command in debug mode if true + */ +export async function checkIfReactNativeBundles( + projectDir: string, + platform: 'ios' | 'android', + debug = false, +): Promise { + const entryFile = 'index.js'; + const dev = 'false'; // Test a production-like bundle + let bundleOutput: string; + let assetsDest: string; + + if (platform === 'ios') { + bundleOutput = './ios/main.jsbundle'; + assetsDest = './ios'; + } else { + // android + bundleOutput = './android/app/src/main/assets/index.android.bundle'; + assetsDest = './android/app/src/main/res'; + } + + const bundleCommandArgs = [ + 'react-native', + 'bundle', + '--entry-file', + entryFile, + '--platform', + platform, + '--dev', + dev, + '--bundle-output', + bundleOutput, + '--assets-dest', + assetsDest, + ]; + + const testEnv = new WizardTestEnv('npx', bundleCommandArgs, { + cwd: projectDir, + debug: debug, + }); + + const builtSuccessfully = await testEnv.waitForStatusCode(0, { + timeout: 300_000, + }); + + testEnv.kill(); + + return builtSuccessfully; +} + /** * Check if the project runs on dev mode * @param projectDir From f2ac2367d17aceadc7c5e060daf4801e6f2cc629 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 8 May 2025 15:26:38 +0300 Subject: [PATCH 2/5] Test bundling Expo project --- .../react-native-expo-test-app/app.json | 6 ++-- .../react-native-expo-test-app/package.json | 4 +-- e2e-tests/tests/expo.test.ts | 22 +++++++++++-- e2e-tests/utils/index.ts | 32 +++++++++++++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/e2e-tests/test-applications/react-native-expo-test-app/app.json b/e2e-tests/test-applications/react-native-expo-test-app/app.json index 9621646bd..462de2fa0 100644 --- a/e2e-tests/test-applications/react-native-expo-test-app/app.json +++ b/e2e-tests/test-applications/react-native-expo-test-app/app.json @@ -1,13 +1,15 @@ { "expo": { - "name": "react-native-expo-52", - "slug": "react-native-expo-52", + "name": "react-native-expo-53", + "slug": "react-native-expo-53", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/images/icon.png", "scheme": "myapp", "userInterfaceStyle": "automatic", "newArchEnabled": true, + "entryPoint": "./node_modules/expo-router/entry", + "platforms": ["ios", "android", "web"], "ios": { "supportsTablet": true }, diff --git a/e2e-tests/test-applications/react-native-expo-test-app/package.json b/e2e-tests/test-applications/react-native-expo-test-app/package.json index 483c883b3..493e627e4 100644 --- a/e2e-tests/test-applications/react-native-expo-test-app/package.json +++ b/e2e-tests/test-applications/react-native-expo-test-app/package.json @@ -1,5 +1,5 @@ { - "name": "react-native-expo-52", + "name": "react-native-expo-53", "main": "expo-router/entry", "version": "1.0.0", "scripts": { @@ -18,7 +18,7 @@ "@expo/vector-icons": "^14.0.2", "@react-navigation/bottom-tabs": "^7.2.0", "@react-navigation/native": "^7.0.14", - "expo": "~52.0.39", + "expo": "^53.0.8", "expo-blur": "~14.0.3", "expo-constants": "~17.0.8", "expo-font": "~13.0.4", diff --git a/e2e-tests/tests/expo.test.ts b/e2e-tests/tests/expo.test.ts index 8579b34d5..bdedafc63 100644 --- a/e2e-tests/tests/expo.test.ts +++ b/e2e-tests/tests/expo.test.ts @@ -3,13 +3,14 @@ import { Integration } from '../../lib/Constants'; import { KEYS, TEST_ARGS, + checkFileContents, checkFileExists, + checkIfExpoBundles, cleanupGit, revertLocalChanges, + startWizardInstance, } from '../utils'; -import { startWizardInstance } from '../utils'; -import { checkFileContents } from '../utils'; -import { afterAll, beforeAll, describe, test } from 'vitest'; +import { afterAll, beforeAll, describe, test, expect } from 'vitest'; describe('Expo', () => { const integration = Integration.reactNative; @@ -116,4 +117,19 @@ module.exports = config;`, test('.gitignore is updated correctly', () => { checkFileContents(`${projectDir}/.gitignore`, `.env.local`); }); + + test('android project is bundled correctly', async () => { + const bundled = await checkIfExpoBundles(projectDir, 'android', true); + expect(bundled).toBe(true); + }); + + test('ios project is bundled correctly', async () => { + const bundled = await checkIfExpoBundles(projectDir, 'ios', true); + expect(bundled).toBe(true); + }); + + test('web project is bundled correctly', async () => { + const bundled = await checkIfExpoBundles(projectDir, 'web', true); + expect(bundled).toBe(true); + }); }); diff --git a/e2e-tests/utils/index.ts b/e2e-tests/utils/index.ts index b94d3c3f4..346b92d16 100644 --- a/e2e-tests/utils/index.ts +++ b/e2e-tests/utils/index.ts @@ -527,6 +527,38 @@ export async function checkIfReactNativeBundles( return builtSuccessfully; } +/** + * Check if the Expo project exports successfully for the specified platform. + * Returns a boolean indicating if the process exits with status code 0. + * @param projectDir The root directory of the Expo project. + * @param platform The platform to export for ('ios', 'android', or 'web'). + * @param debug runs the command in debug mode if true + */ +export async function checkIfExpoBundles( + projectDir: string, + platform: 'ios' | 'android' | 'web', + debug = false, +): Promise { + const exportCommandArgs = [ + 'expo', + 'export', + '--platform', + platform, + ]; + + const testEnv = new WizardTestEnv('npx', exportCommandArgs, { + cwd: projectDir, + debug: debug, + }); + + const builtSuccessfully = await testEnv.waitForStatusCode(0, { + timeout: 300_000, + }); + + testEnv.kill(); + return builtSuccessfully; +} + /** * Check if the project runs on dev mode * @param projectDir From b3168ed90a6f286e50790a40d50f8ea3a6b81dae Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 8 May 2025 15:31:27 +0300 Subject: [PATCH 3/5] Disable debug logging --- e2e-tests/tests/expo.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e-tests/tests/expo.test.ts b/e2e-tests/tests/expo.test.ts index bdedafc63..c0fc18817 100644 --- a/e2e-tests/tests/expo.test.ts +++ b/e2e-tests/tests/expo.test.ts @@ -119,17 +119,17 @@ module.exports = config;`, }); test('android project is bundled correctly', async () => { - const bundled = await checkIfExpoBundles(projectDir, 'android', true); + const bundled = await checkIfExpoBundles(projectDir, 'android'); expect(bundled).toBe(true); }); test('ios project is bundled correctly', async () => { - const bundled = await checkIfExpoBundles(projectDir, 'ios', true); + const bundled = await checkIfExpoBundles(projectDir, 'ios'); expect(bundled).toBe(true); }); test('web project is bundled correctly', async () => { - const bundled = await checkIfExpoBundles(projectDir, 'web', true); + const bundled = await checkIfExpoBundles(projectDir, 'web'); expect(bundled).toBe(true); }); }); From f929d8834fc4c05cd440282c0c163cce49ca3a67 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 8 May 2025 18:22:00 +0300 Subject: [PATCH 4/5] Test Build React Native Android --- e2e-tests/tests/react-native.test.ts | 6 ++++ e2e-tests/utils/index.ts | 51 +++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/e2e-tests/tests/react-native.test.ts b/e2e-tests/tests/react-native.test.ts index f1086d859..3c47613a9 100644 --- a/e2e-tests/tests/react-native.test.ts +++ b/e2e-tests/tests/react-native.test.ts @@ -6,6 +6,7 @@ import { cleanupGit, checkFileContents, checkIfReactNativeBundles, + checkIfReactNativeReleaseBuilds, revertLocalChanges, startWizardInstance } from '../utils'; @@ -184,4 +185,9 @@ defaults.url=https://sentry.io/`, const bundled = await checkIfReactNativeBundles(projectDir, 'ios'); expect(bundled).toBe(true); }); + + test('android project builds correctly', async () => { + const builds = await checkIfReactNativeReleaseBuilds(projectDir, 'android', true); + expect(builds).toBe(true); + }); }); diff --git a/e2e-tests/utils/index.ts b/e2e-tests/utils/index.ts index 346b92d16..8f48015db 100644 --- a/e2e-tests/utils/index.ts +++ b/e2e-tests/utils/index.ts @@ -68,9 +68,14 @@ export class WizardTestEnv { opts?: { cwd?: string; debug?: boolean; + env?: NodeJS.ProcessEnv; }, ) { - this.taskHandle = spawn(cmd, args, { cwd: opts?.cwd, stdio: 'pipe' }); + if (opts?.env) { + this.taskHandle = spawn(cmd, args, { cwd: opts?.cwd, stdio: 'pipe', env: { ...process.env, ...opts?.env } }); + } else { + this.taskHandle = spawn(cmd, args, { cwd: opts?.cwd, stdio: 'pipe' }); + } if (opts?.debug) { this.taskHandle.stdout?.pipe(process.stdout); @@ -527,6 +532,50 @@ export async function checkIfReactNativeBundles( return builtSuccessfully; } +/** + * Check if the React Native project creates a release build locally for the specified platform. + * Returns a boolean indicating if the process exits with status code 0. + * @param projectDir The root directory of the React Native project. + * @param platform The platform to build for ('ios' or 'android'). + * @param debug runs the command in debug mode if true + */ +export async function checkIfReactNativeReleaseBuilds( + projectDir: string, + platform: 'ios' | 'android', + debug = false, +): Promise { + let command: string; + let args: string[]; + let cwd: string; + let env: NodeJS.ProcessEnv; + + if (platform === 'android') { + command = './gradlew'; + args = ['assembleRelease']; + cwd = path.join(projectDir, 'android'); + env = { SENTRY_DISABLE_AUTO_UPLOAD: 'true' }; + } else { + // ios + command = 'TODO'; + args = ['TODO']; + cwd = path.join(projectDir, 'ios'); + env = {}; + } + + const testEnv = new WizardTestEnv(command, args, { + cwd: cwd, + debug: debug, + env: env, + }); + + const builtSuccessfully = await testEnv.waitForStatusCode(0, { + timeout: 1_200_000, + }); + + testEnv.kill(); + return builtSuccessfully; +} + /** * Check if the Expo project exports successfully for the specified platform. * Returns a boolean indicating if the process exits with status code 0. From 7cf90fcfffb3254e05c3bc7c2d43d1715a93b0a8 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 8 May 2025 18:49:34 +0300 Subject: [PATCH 5/5] Disable debug logging --- e2e-tests/tests/react-native.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/react-native.test.ts b/e2e-tests/tests/react-native.test.ts index 3c47613a9..84d8b2917 100644 --- a/e2e-tests/tests/react-native.test.ts +++ b/e2e-tests/tests/react-native.test.ts @@ -187,7 +187,7 @@ defaults.url=https://sentry.io/`, }); test('android project builds correctly', async () => { - const builds = await checkIfReactNativeReleaseBuilds(projectDir, 'android', true); + const builds = await checkIfReactNativeReleaseBuilds(projectDir, 'android'); expect(builds).toBe(true); }); });