diff --git a/.github/workflows/android.unit-test.yml b/.github/workflows/android.unit-test.yml new file mode 100644 index 00000000..dc102fcc --- /dev/null +++ b/.github/workflows/android.unit-test.yml @@ -0,0 +1,54 @@ +name: Android Unit Tests + +on: + push: + branches: [main] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x] + jdk-version: ["17"] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Node (${{ matrix.node-version }}) + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + + - name: Enables corepack + run: corepack enable + + - uses: dorny/paths-filter@v2 + id: changed_files + with: + list-files: shell + filters: | + android: + - 'packages/**/gradle.properties' + - 'packages/**/*.gradle' + - 'packages/**/*.kt' + - 'packages/**/*.java' + + - name: Install Root Node Modules + run: yarn install + if: steps.changed_files.outputs.android == 'true' + + - name: Install JDK ${{ matrix.jdk-version }} + uses: actions/setup-java@v4 + with: + distribution: 'adopt' + java-version: ${{ matrix.jdk-version }} + if: steps.changed_files.outputs.android == 'true' + + - name: Run Android Unit Tests + run: yarn run android:test $(./scopes-from-file-changes.ts ${{ steps.changed_files.outputs.android_files }}) + if: steps.changed_files.outputs.android == 'true' diff --git a/.prettierignore b/.prettierignore index ab57381f..51cd08ae 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ node_modules build dist +Pods diff --git a/DEVELOPING.md b/DEVELOPING.md index f158d4cf..f7c12c89 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -34,7 +34,7 @@ yarn lint yarn test ``` -## Manual integration testing +## Manual integration testing (TODO update after changes to integration testing workflow) The [example app](examples/react-native-test-suite/) allows you to test out the React Native Embrace SDK in a representative app. @@ -74,7 +74,7 @@ pushd ios; pod install; popd; yarn ios --mode=Release ``` -## Testing against new Embrace Android SDK versions +## Testing against new Embrace Android SDK versions (TODO update after changes to integration testing workflow) You can test Embrace Android SDK changes by altering the dependency in the core package's [build.gradle](./packages/core/android/build.gradle). And then either publish a local artifact or if you need CI to pass - publish a beta: @@ -94,7 +94,7 @@ And then either publish a local artifact or if you need CI to pass - publish a b 4. Set the correct `embrace-android-sdk` version in `examples/react-native-test-suite/node_modules/embrace-io/android/build.gradle` 5. Run the app in the normal way -## Testing against new Embrace iOS SDK versions +## Testing against new Embrace iOS SDK versions (TODO update after changes to integration testing workflow) ### Local artifact @@ -111,6 +111,12 @@ You can test local changes to the iOS SDK by updating the example app's `podspec 3. In `examples/react-native-test-suite/ios/Podfile`, add the following line `pod 'EmbraceIO-DEV'` 4. In `examples/react-native-test-suite/ios`, run the `pod update` command +## Updating native SDK dependencies + +1. Bump the Android (SDK + Swazzler)/iOS dependencies to the latest available stable versions in `./yarn.config.cjs` +2. Run `yarn constraints --fix` to propagate this change to all package.json files +3. Run `yarn build` to update build files to the latest versions + ## Automated integration testing Automated integration testing is being actively developed to replace some of the manual testing outlined above, see [here](./integration-tests/README.md) for more details. @@ -132,4 +138,4 @@ unreleased changes on `main` and a patch release will be cut from that new branc 7. Run an example app and point to the latest released packages to confirm basic behaviour 8. Update and publish the [Changelog](https://github.com/embrace-io/embrace-docs/blob/main/docs/react-native/changelog.md) for the release -NOTE: If you make a mistake while publishing you can remove the specific version w/ `npm unpublish @`, see [Unpublishing a single version of a package](https://docs.npmjs.com/unpublishing-packages-from-the-registry#unpublishing-a-single-version-of-a-package) +NOTE: If you make a mistake while publishing you can remove the specific version w/ `npm unpublish @`, see [Unpublishing a single version of a package](https://docs.npmjs.com/unpublishing-packages-from-the-registry#unpublishing-a-single-version-of-a-package) \ No newline at end of file diff --git a/integration-tests/README.md b/integration-tests/README.md index e13708b7..fdedabbb 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -6,33 +6,33 @@ verifications on the payloads that would have been sent to Embrace. The harness uses WebdriverIO's [Testrunner](https://webdriver.io/docs/testrunner/) to spin up a [Appium](http://appium.io/docs/en/latest/intro/) client and server to perform the device automation. [Mockserver](https://www.mock-server.com/#what-is-mockserver) is launched for the suite run so that requests sent from the device can be inspected. -```bash -npm install -``` + ```bash + npm install + ``` For any future updates the [Appium Installer](https://webdriver.io/docs/appium) provides a handy setup wizard: -```bash -npx appium-installer -``` + ```bash + npx appium-installer + ``` ## Run tests Make sure the test apps have the latest local @embrace-io/react-native changes: -```bash -npm run update-local-embrace -``` + ```bash + npm run update-local-embrace + ``` Make sure the test apps are installed on the device/emulator before running tests. Note that building the debug variant of the app may interfere with the tests as the debug menu gets in the way of UI elements. Android can run in release mode: -```bash -cd basic-test-app -npx expo run:android --variant release -``` + ```bash + cd basic-test-app + npx expo run:android --variant release + ``` For ios it doesn't apply the `--variant release` mode, so we can do it through xcode: @@ -41,17 +41,17 @@ For ios it doesn't apply the `--variant release` mode, so we can do it through x - Under the Run section, change the Build Configuration from Debug to Release. - Press Cmd + R to build and run the app in release mode. -or simple run +or simply run -```bash -npx expo run:ios --configuration Release -``` + ```bash + npx expo run:ios --configuration Release + ``` Run the test suite: -```bash -npm test -``` + ```bash + npm test + ``` ## Debugging tips @@ -60,11 +60,11 @@ npm test To help figure out the selectors to use for grabbing UI elements it can be useful to interact with Appium using the Appium Inspector. First install the Appium server and drivers globally: -```bash -npm install -g appium -appium driver install uiautomator2 # android / ios -appium driver install xcuitest # ios -``` + ```bash + npm install -g appium + appium driver install uiautomator2 # android / ios + appium driver install xcuitest # ios + ``` Then install [Appium Inspector](https://github.com/appium/appium-inspector) @@ -73,12 +73,30 @@ Then install [Appium Inspector](https://github.com/appium/appium-inspector) You can invoke the Mockserver and watch its output directly to get a look at the payloads it is receiving at different endpoints (Note this may include some binary output that doesn't play nice with your terminal): -```bash -npx tsx helpers/invoke_embrace_server.ts -``` + ```bash + npx tsx helpers/invoke_embrace_server.ts + ``` ## CI TODO for the moment the utility here is to be able to run tests locally during development, as a next task need to hook this up to CI tools to verify a passing suite for new releases. Likely this means updating or creating a new `wdio.conf.ts` that can be configured to point to a remote environment. See what capabilities are available for that [here](https://appium.io/docs/en/2.1/guides/caps/) + +## Troubleshooting + + +### Appium gives 500 during test run + +"Could not proxy command to remote server. Original error: Error: socket hang up" + +Try: + ```bash + # Android + adb uninstall io.appium.uiautomator2.server + adb uninstall io.appium.uiautomator2.server.test + + # iOS + xcrun simctl uninstall booted io.appium.uiautomator2.server + xcrun simctl uninstall booted io.appium.uiautomator2.server.test + ``` \ No newline at end of file diff --git a/integration-tests/artifacts/.gitignore b/integration-tests/artifacts/.gitignore index aa1ec1ea..ca300f44 100644 --- a/integration-tests/artifacts/.gitignore +++ b/integration-tests/artifacts/.gitignore @@ -1 +1 @@ -*.tgz +*-local.tgz diff --git a/integration-tests/artifacts/opentelemetry-instrumentation-react-native-navigation-0.1.0.tgz b/integration-tests/artifacts/opentelemetry-instrumentation-react-native-navigation-0.1.0.tgz new file mode 100644 index 00000000..311d7af9 Binary files /dev/null and b/integration-tests/artifacts/opentelemetry-instrumentation-react-native-navigation-0.1.0.tgz differ diff --git a/integration-tests/basic-test-app/README.md b/integration-tests/basic-test-app/README.md index dff4cbd7..1cfb2219 100644 --- a/integration-tests/basic-test-app/README.md +++ b/integration-tests/basic-test-app/README.md @@ -70,11 +70,12 @@ Use the following when creating `./ios/Embrace-Info.plist`: Then build: ```bash - npx expo run:ios + pushd ios; pod install; popd + npx expo run:ios ``` ## Pull in local @embrace-io/react-native changes Because RN doesn't support symlinked packages whenever any changes are made under packages/core (or any other local package that the test app depends on) they need to be copied into -the app's node_modules/, there is a script in integration-tests that manages this \ No newline at end of file +the app's node_modules/, there is a script in integration-tests that manages this diff --git a/integration-tests/basic-test-app/android/app/src/main/AndroidManifest.xml b/integration-tests/basic-test-app/android/app/src/main/AndroidManifest.xml index c081525d..b6a41a61 100644 --- a/integration-tests/basic-test-app/android/app/src/main/AndroidManifest.xml +++ b/integration-tests/basic-test-app/android/app/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ - + diff --git a/integration-tests/basic-test-app/android/app/src/main/res/xml/network_security_config.xml b/integration-tests/basic-test-app/android/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 00000000..dca93c07 --- /dev/null +++ b/integration-tests/basic-test-app/android/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/integration-tests/basic-test-app/app/(tabs)/_layout.tsx b/integration-tests/basic-test-app/app/(tabs)/_layout.tsx index b54968cd..54c48c80 100644 --- a/integration-tests/basic-test-app/app/(tabs)/_layout.tsx +++ b/integration-tests/basic-test-app/app/(tabs)/_layout.tsx @@ -17,7 +17,8 @@ export default function TabLayout() { ( ( - + ), }} /> diff --git a/integration-tests/basic-test-app/app/(tabs)/explore.tsx b/integration-tests/basic-test-app/app/(tabs)/explore.tsx deleted file mode 100644 index 6788a21d..00000000 --- a/integration-tests/basic-test-app/app/(tabs)/explore.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import Ionicons from "@expo/vector-icons/Ionicons"; -import {StyleSheet, Image, Platform} from "react-native"; - -import {Collapsible} from "@/components/Collapsible"; -import {ExternalLink} from "@/components/ExternalLink"; -import ParallaxScrollView from "@/components/ParallaxScrollView"; -import {ThemedText} from "@/components/ThemedText"; -import {ThemedView} from "@/components/ThemedView"; - -export default function TabTwoScreen() { - return ( - - }> - - Explore - - - This app includes example code to help you get started. - - - - This app has two screens:{" "} - app/(tabs)/index.tsx{" "} - and{" "} - app/(tabs)/explore.tsx - - - The layout file in{" "} - app/(tabs)/_layout.tsx{" "} - sets up the tab navigator. - - - Learn more - - - - - You can open this project on Android, iOS, and the web. To open the - web version, press w{" "} - in the terminal running this project. - - - - - For static images, you can use the{" "} - @2x and{" "} - @3x suffixes to - provide files for different screen densities - - - - Learn more - - - - - Open app/_layout.tsx{" "} - to see how to load{" "} - - custom fonts such as this one. - - - - Learn more - - - - - This template has light and dark mode support. The{" "} - useColorScheme() hook - lets you inspect what the user's current color scheme is, and so you - can adjust UI colors accordingly. - - - Learn more - - - - - This template includes an example of an animated component. The{" "} - - components/HelloWave.tsx - {" "} - component uses the powerful{" "} - - react-native-reanimated - {" "} - library to create a waving hand animation. - - {Platform.select({ - ios: ( - - The{" "} - - components/ParallaxScrollView.tsx - {" "} - component provides a parallax effect for the header image. - - ), - })} - - - ); -} - -const styles = StyleSheet.create({ - headerImage: { - color: "#808080", - bottom: -90, - left: -35, - position: "absolute", - }, - titleContainer: { - flexDirection: "row", - gap: 8, - }, -}); diff --git a/integration-tests/basic-test-app/app/(tabs)/index.tsx b/integration-tests/basic-test-app/app/(tabs)/index.tsx index 14900b98..e4d7ef5a 100644 --- a/integration-tests/basic-test-app/app/(tabs)/index.tsx +++ b/integration-tests/basic-test-app/app/(tabs)/index.tsx @@ -1,5 +1,5 @@ import {Image, StyleSheet, Button} from "react-native"; -import {useCallback} from "react"; +import {useCallback, useMemo} from "react"; import {ThemedView} from "@/components/ThemedView"; import {ThemedText} from "@/components/ThemedText"; @@ -13,12 +13,28 @@ import { logMessage, logWarning, } from "@embrace-io/react-native"; +import { + generateBasicSpan, + generateNestedSpans, + generateTestSpans, +} from "@/helpers/generateSpans"; +import {Tracer} from "@opentelemetry/api"; +import {useEmbraceNativeTracerProvider} from "@embrace-io/react-native-tracer-provider"; const HomeScreen = () => { const handleEndSession = useCallback(() => { endSession(); }, []); + const {isLoading, isError, error, tracerProvider} = + useEmbraceNativeTracerProvider(); + + const tracer = useMemo(() => { + if (tracerProvider) { + return tracerProvider.getTracer("span-test", "1.0"); + } + }, [isLoading, isError, error, tracerProvider]); + const handleErrorLog = useCallback(() => { logHandledError( new TypeError("triggering handled error (will show js stacktrace)"), @@ -55,6 +71,14 @@ const HomeScreen = () => { }); }, []); + if (isLoading) { + return Loading Tracer Provider; + } + + if (isError) { + return {error}; + } + return ( { /> }> - End Session + Session