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
49 changes: 49 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
- android
- ios
- web
- vega
pull_request:
types: [ready_for_review]
branches:
Expand Down Expand Up @@ -559,3 +560,51 @@ jobs:
name: harness-diagnostics-crash-validate-ios
path: apps/playground/.harness/diagnostics
if-no-files-found: ignore

e2e-vega:
name: E2E Vega
# Needs a self-hosted runner with the Vega SDK installed and the "vega"
# label; GitHub-hosted images have no SDK, so this job is dispatch only.
runs-on: [self-hosted, vega]
timeout-minutes: 45
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.platform == 'vega' }}
env:
HARNESS_DEBUG: true
RN_HARNESS_DIAGNOSTICS: true
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
fetch-depth: 0

- name: Install pnpm
uses: pnpm/action-setup@eae0cfeb286e66ffb5155f1a79b90583a127a68b # v2.4.1
with:
version: latest

- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '24.10.0'
cache: 'pnpm'

- name: Install dependencies
run: |
pnpm install

- name: Build packages
run: |
pnpm nx run-many -t build --projects="packages/*"

- name: Build the Vega app
run: |
source ~/vega/env
pnpm --filter @react-native-harness/playground-vega build:debug

- name: Run React Native Harness
uses: ./
with:
runner: vega
projectRoot: apps/playground-vega
app: apps/playground-vega/build/${{ runner.arch == 'ARM64' && 'aarch64' || 'x86_64' }}-debug/playground-vega_${{ runner.arch == 'ARM64' && 'aarch64' || 'x86_64' }}.vpkg
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,6 @@ npm-debug.*
*.mobileprovision
*.orig.*
web-build/

# Vega build metadata
apps/playground-vega/buildinfo.json
5 changes: 5 additions & 0 deletions .nx/version-plans/version-plan-1790754023000.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
__default__: minor
---

The Vega runner now works with current Vega SDKs (0.24 and newer): it drives the `vega` CLI instead of the retired `kepler` binary, starts the Vega Virtual Device when it is not running, supports Fire TV devices in developer mode through `vegaPhysicalDevice(serial)`, installs the app package from `HARNESS_APP_PATH`, forwards Metro's port to the device, captures device logs for failed runs, and configures Metro for React Native for Vega (`kepler` platform, the `@amazon-devices/react-native-kepler` redirect, and Amazon's system bundles so React Native comes from the OS copy). Platforms can also declare a `bundlePlatform` when the app requests Metro bundles under a different platform name than the harness platform id, the runtime no longer depends on a URL polyfill that reads the legacy native module bridge, so it initializes on bridgeless runtimes such as Vega, and test bundles may use string module ids from custom Metro id factories.
6 changes: 3 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name: React Native Harness
description: Run React Native Harness tests on iOS, Android, Web or Windows
description: Run React Native Harness tests on iOS, Android, Web, Windows or Vega
inputs:
runner:
description: The runner to use (must match a runner name defined in your harness config)
required: true
type: string
app:
description: >-
The path to the built app (.app for iOS, .apk for Android). Not required
for web, or for Windows (deploy the app with `react-native run-windows`
The path to the built app (.app for iOS, .apk for Android, .vpkg for
Vega). Not required for web, or for Windows (deploy the app with `react-native run-windows`
before this action runs).
required: false
type: string
Expand Down
32 changes: 32 additions & 0 deletions apps/playground-vega/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Playground for Vega

A React Native for Vega app used to run React Native Harness on the Vega Virtual Device and on Fire TV devices running Vega OS. It mirrors the platform-agnostic test suites of `apps/playground`; the `ui/` suites are left out because `@react-native-harness/ui` has no Vega native module yet.

## Prerequisites

- The [Vega SDK](https://developer.amazon.com/docs/vega/0.24/install-vega-sdk) with the `vega` CLI on your `PATH` (`source ~/vega/env`).
- For Fire TV devices: developer mode enabled on the device (`vega devmode login`, then `vega devmode enable-device --code <code>`), and the device serial from `vega device list` exported as `VEGA_DEVICE_SERIAL`.

## How to run React Native Harness?

Build a debug package first. Debug builds load the JavaScript bundle from Metro, which is what Harness needs:

```sh
pnpm build:debug
```

The package lands in `build/<arch>-debug/playground-vega_<arch>.vpkg`. Use `aarch64` for the virtual device on Apple Silicon, `x86_64` on Intel, and `armv7` for Fire TV.

Then run the tests. Harness starts the virtual device when it is not running, installs the package from `HARNESS_APP_PATH`, and forwards Metro's port to the device:

```sh
HARNESS_APP_PATH=$PWD/build/aarch64-debug/playground-vega_aarch64.vpkg pnpm test:harness --harnessRunner vega
```

For a Fire TV:

```sh
VEGA_DEVICE_SERIAL=<serial> HARNESS_APP_PATH=$PWD/build/armv7-debug/playground-vega_armv7.vpkg pnpm test:harness --harnessRunner fire-tv
```

See [the React Native Harness documentation](https://www.react-native-harness.dev/docs/platforms/vega) for details.
5 changes: 5 additions & 0 deletions apps/playground-vega/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"//": "The Vega runtime launches the app by its interactive component id, so the registered name must match manifest.toml",
"name": "com.harnessplayground.vega.main",
"displayName": "HarnessPlaygroundVega"
}
3 changes: 3 additions & 0 deletions apps/playground-vega/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ['module:@react-native/babel-preset'],
};
9 changes: 9 additions & 0 deletions apps/playground-vega/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @format
*/

import { AppRegistry } from 'react-native';
import App from './src/app/App';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);
12 changes: 12 additions & 0 deletions apps/playground-vega/jest.harness.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default {
preset: 'react-native-harness',
// The playground's ui/ suites are not copied here: @react-native-harness/ui
// has no Vega native module yet.
testMatch: ['<rootDir>/src/__tests__/**/*.harness.[jt]s?(x)'],
setupFiles: ['./src/setupFile.ts'],
setupFilesAfterEnv: ['./src/setupFileAfterEnv.ts'],
// This is necessary to prevent Jest from transforming the workspace packages.
// Not needed in users projects, as they will have the packages installed in their node_modules.
transformIgnorePatterns: ['/packages/', '/node_modules/'],
collectCoverageFrom: ['./src/**/*.(ts|tsx)'],
};
25 changes: 25 additions & 0 deletions apps/playground-vega/manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
schema-version = 1

[package]
title = "Harness Playground for Vega"
version = "0.0.1"
id = "com.harnessplayground.vega"

[os.version]
min = "1.2"
target = "1.2"

[needs]
[[needs.module]]
id = "/com.amazon.vega.os@IVega_1_2"

[[needs.module]]
id = "/com.amazon.kepler.keplerscript_4@IKeplerScript_0"


[components]
[[components.interactive]]
id = "com.harnessplayground.vega.main"
runtime-module = "/com.amazon.kepler.runtime.react_native_kepler_4@IReactNativeKepler_0"
launch-type = "singleton"
categories = ["com.amazon.category.main"]
35 changes: 35 additions & 0 deletions apps/playground-vega/metro.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const exclusionList =
require('metro-config/private/defaults/exclusionList').default;
const path = require('path');

const projectRoot = __dirname;
const monorepoRoot = path.resolve(projectRoot, '../..');

/**
* Metro configuration
* https://reactnative.dev/docs/metro
*
* The `kepler` platform and the `react-native` redirect to
* `@amazon-devices/react-native-kepler` are added by the Vega CLI plugin for
* `react-native start` / `build-vega`, and by the Harness Vega platform for
* harness runs, so they are not configured here.
*
* @type {import('metro-config').MetroConfig}
*/
const config = {
cacheVersion: '@react-native-harness/playground-vega',
watchFolders: [monorepoRoot],
resolver: {
unstable_enablePackageExports: true,
nodeModulesPaths: [
path.resolve(projectRoot, 'node_modules'),
path.resolve(monorepoRoot, 'node_modules'),
],
// The monorepo root is a watch folder, so keep Nx's local cache and
// workspace data out of Metro's file map.
blockList: exclusionList([/\.nx\/.*/]),
},
};

module.exports = mergeConfig(getDefaultConfig(projectRoot), config);
34 changes: 34 additions & 0 deletions apps/playground-vega/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@react-native-harness/playground-vega",
"version": "0.0.1",
"private": true,
"scripts": {
"build:debug": "react-native build-vega --build-type Debug",
"build:release": "react-native build-vega --build-type Release",
"test:harness": "node ../../packages/react-native-harness/bin.js"
},
"kepler": {
"projectType": "application",
"appName": "HarnessPlaygroundVega",
"targets": [
"tv"
]
},
"dependencies": {
"@amazon-devices/react-native-kepler": "~4.0.0",
"react": "19.2.3",
"react-native": "0.83.0"
},
"devDependencies": {
"@amazon-devices/kepler-cli-platform": "^0.22.14",
"@react-native-community/cli": "20.0.0",
"@react-native-harness/jest": "workspace:*",
"@react-native-harness/platform-vega": "workspace:*",
"@react-native-harness/runtime": "workspace:*",
"@react-native/babel-preset": "0.83.0",
"@react-native/metro-config": "0.83.0",
"@react-native/typescript-config": "0.83.0",
"jest": "^30.2.0",
"react-native-harness": "workspace:*"
}
}
13 changes: 13 additions & 0 deletions apps/playground-vega/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@react-native-harness/playground-vega",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"targets": {
"start": {
"executor": "nx:run-commands",
"options": {
"command": "node ../../packages/react-native-harness/bin.js",
"cwd": "apps/playground-vega"
}
}
}
}
35 changes: 35 additions & 0 deletions apps/playground-vega/rn-harness.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
vegaPlatform,
vegaVirtualDevice,
vegaPhysicalDevice,
} from '@react-native-harness/platform-vega';

// The [package] id from manifest.toml.
const bundleId = 'com.harnessplayground.vega';

export default {
entryPoint: './index.js',
// The Vega runtime runs the component registered under the interactive
// component id from manifest.toml.
appRegistryComponentName: 'com.harnessplayground.vega.main',
runners: [
vegaPlatform({
name: 'vega',
device: vegaVirtualDevice(),
bundleId,
}),
vegaPlatform({
name: 'fire-tv',
// Replace with the serial number printed by `vega device list`.
device: vegaPhysicalDevice(process.env.VEGA_DEVICE_SERIAL ?? 'FIRE_TV_SERIAL'),
bundleId,
}),
],
defaultRunner: 'vega',
// The virtual device can take a few minutes to boot on first start.
platformReadyTimeout: 600000,
bridgeTimeout: 120000,
testTimeout: 10000,
resetEnvironmentBetweenTestFiles: 'runtime',
forwardClientLogs: true,
};
Loading
Loading