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
19 changes: 5 additions & 14 deletions apps/react-native-branch/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,13 @@
"splash": {
"image": "https://github.com/expo.png"
},
"ios": {
"config": {
"branch": {
"apiKey": "key_live_f9f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8"
}
}
},
"android": {
"config": {
"branch": {
"plugins": [
[
"@config-plugins/react-native-branch",
{
"apiKey": "key_live_f9f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8"
}
}
},
"plugins": [
"@config-plugins/react-native-branch"
]
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.branch.rnbranch.RNBranchModule


class BranchReactActivityLifecycleListener(activityContext: Context) : ReactActivityLifecycleListener {
override fun onCreate(activity: Activity, savedInstanceState: Bundle?) {
override fun onResume(activity: Activity) {
RNBranchModule.initSession(activity.getIntent().getData(), activity);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import RNBranch

public class BranchAppDelegate: ExpoAppDelegateSubscriber {
public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
if Bundle.main.object(forInfoDictionaryKey: "branch_test_environment") as? Bool ?? false {
RNBranch.useTestInstance()
}

RNBranch.initSession(launchOptions: launchOptions, isReferrable: true)
return true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { AndroidConfig } from "expo/config-plugins";
import { resolve } from "path";

import { getBranchApiKey, setBranchApiKey } from "../withBranchAndroid";
import {
setBranchApiKeys,
enableBranchTestEnvironment,
} from "../withBranchAndroid";

const { findMetaDataItem, getMainApplication, readAndroidManifestAsync } =
AndroidConfig.Manifest;
Expand All @@ -12,41 +15,52 @@ const sampleManifestPath = resolve(
"react-native-AndroidManifest.xml",
);

describe(getBranchApiKey, () => {
it(`returns null if no android branch api key is provided`, () => {
expect(getBranchApiKey({ android: { config: {} } } as any)).toBe(null);
});

it(`returns apikey if android branch api key is provided`, () => {
expect(
getBranchApiKey({
android: { config: { branch: { apiKey: "MY-API-KEY" } } },
} as any),
).toBe("MY-API-KEY");
});
});

describe(setBranchApiKey, () => {
describe(setBranchApiKeys, () => {
it("sets branch api key in AndroidManifest.xml if given", async () => {
let androidManifestJson =
await readAndroidManifestAsync(sampleManifestPath);
androidManifestJson = await setBranchApiKey(
"MY-API-KEY",
androidManifestJson = await setBranchApiKeys(
{ apiKey: "MY-API-KEY", testApiKey: "MY-TEST-API-KEY" },
androidManifestJson,
);
let mainApplication = getMainApplication(androidManifestJson);

expect(
findMetaDataItem(mainApplication, "io.branch.sdk.BranchKey"),
).toBeGreaterThan(-1);
expect(
findMetaDataItem(mainApplication, "io.branch.sdk.BranchKey.test"),
).toBeGreaterThan(-1);

// Unset the item

androidManifestJson = await setBranchApiKey(null, androidManifestJson);
// @ts-expect-error Explicitly unset the API keys to ensure its removed
androidManifestJson = setBranchApiKeys({}, androidManifestJson);
mainApplication = getMainApplication(androidManifestJson);

expect(findMetaDataItem(mainApplication, "io.branch.sdk.BranchKey")).toBe(
-1,
);
expect(
findMetaDataItem(mainApplication, "io.branch.sdk.BranchKey.test"),
).toBe(-1);
});
});

describe(enableBranchTestEnvironment, () => {
it("sets branch test mode meta data item in AndroidManifest.xml", async () => {
let androidManifestJson =
await readAndroidManifestAsync(sampleManifestPath);

androidManifestJson = await enableBranchTestEnvironment(
true,
androidManifestJson,
);

const mainApplication = getMainApplication(androidManifestJson);

expect(
findMetaDataItem(mainApplication, "io.branch.sdk.TestMode"),
).toBeGreaterThan(-1);
});
});
41 changes: 25 additions & 16 deletions packages/react-native-branch/src/__tests__/withBranchIOS.test.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
import { getBranchApiKey, setBranchApiKey } from "../withBranchIOS";
import {
setBranchApiKeys,
enableBranchTestEnvironment,
} from "../withBranchIOS";

describe(getBranchApiKey, () => {
it(`returns null if no api key is provided`, () => {
expect(getBranchApiKey({})).toBe(null);
describe(setBranchApiKeys, () => {
it(`sets branch_key.live if the api key is given`, () => {
expect(setBranchApiKeys({ apiKey: "LIVE-API-KEY" }, {})).toMatchObject({
branch_key: {
live: "LIVE-API-KEY",
},
});
});

it(`returns the api key if provided`, () => {
it(`sets branch_key.test if the test api key is given`, () => {
expect(
getBranchApiKey({ ios: { config: { branch: { apiKey: "123" } } } }),
).toBe("123");
});
});

describe(setBranchApiKey, () => {
it(`sets branch_key.live if the api key is given`, () => {
expect(setBranchApiKey("123", {})).toMatchObject({
setBranchApiKeys(
{ apiKey: "LIVE-API-KEY", testApiKey: "TEST-API-KEY" },
{},
),
).toMatchObject({
branch_key: {
live: "123",
live: "LIVE-API-KEY",
test: "TEST-API-KEY",
},
});
});
});

it(`makes no changes to the infoPlist no api key is provided`, () => {
expect(setBranchApiKey(null, {})).toMatchObject({});
describe(enableBranchTestEnvironment, () => {
it(`must assign the passed boolean value into branch_key.branch_test_mode`, () => {
expect(enableBranchTestEnvironment(true, {})).toMatchObject({
branch_test_environment: true,
});
});
});
7 changes: 7 additions & 0 deletions packages/react-native-branch/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
export type ConfigData = {
apiKey?: string;
testApiKey?: string;
iosAppDomain?: string;
iosUniversalLinkDomains?: string[];
enableTestEnvironment?: boolean;
};

export type BranchKeys = {
apiKey: string;
testApiKey?: string;
};
15 changes: 5 additions & 10 deletions packages/react-native-branch/src/withBranch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,17 @@ import { ConfigData } from "./types";
import { withBranchAndroid } from "./withBranchAndroid";
import { withBranchIOS } from "./withBranchIOS";

const withBranch: ConfigPlugin<ConfigData> = (
config,
{ apiKey, iosAppDomain, iosUniversalLinkDomains } = {},
) => {
config = withBranchAndroid(config, { apiKey });
config = withBranchIOS(config, {
apiKey,
iosAppDomain,
iosUniversalLinkDomains,
});
const withBranch: ConfigPlugin<ConfigData> = (config, branchConfig = {}) => {
config = withBranchAndroid(config, branchConfig);
config = withBranchIOS(config, branchConfig);

return config;
};

let pkg: { name: string; version?: string } = {
name: "react-native-branch",
};

try {
const branchPkg = require("react-native-branch/package.json");
pkg = branchPkg;
Expand Down
77 changes: 59 additions & 18 deletions packages/react-native-branch/src/withBranchAndroid.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,93 @@
import { ExpoConfig } from "expo/config";
import {
AndroidConfig,
ConfigPlugin,
withAndroidManifest,
} from "expo/config-plugins";

import { BranchKeys, ConfigData } from "./types";

const {
addMetaDataItemToMainApplication,
getMainApplicationOrThrow,
removeMetaDataItemFromMainApplication,
} = AndroidConfig.Manifest;

const META_BRANCH_KEY = "io.branch.sdk.BranchKey";
const META_BRANCH_KEY_TEST = "io.branch.sdk.BranchKey.test";
const META_BRANCH_KEY_TEST_MODE = "io.branch.sdk.TestMode";

export function getBranchApiKey(config: ExpoConfig) {
return config.android?.config?.branch?.apiKey ?? null;
}

export function setBranchApiKey(
apiKey: string,
export function setBranchApiKeys(
{ apiKey, testApiKey }: BranchKeys,
androidManifest: AndroidConfig.Manifest.AndroidManifest,
) {
const mainApplication = getMainApplicationOrThrow(androidManifest);

if (apiKey) {
// If the item exists, add it back
addMetaDataItemToMainApplication(mainApplication, META_BRANCH_KEY, apiKey);
} else {
// Remove any existing item
removeMetaDataItemFromMainApplication(mainApplication, META_BRANCH_KEY);
}

if (testApiKey) {
addMetaDataItemToMainApplication(
mainApplication,
META_BRANCH_KEY_TEST,
testApiKey,
);
} else {
removeMetaDataItemFromMainApplication(
mainApplication,
META_BRANCH_KEY_TEST,
);
}

return androidManifest;
}

export const withBranchAndroid: ConfigPlugin<{ apiKey?: string }> = (
config,
data,
) => {
const apiKey = data.apiKey ?? getBranchApiKey(config);
if (!apiKey) {
throw new Error(
"Branch API key is required: expo.android.config.branch.apiKey",
export function enableBranchTestEnvironment(
enableTestEnvironment: boolean,
androidManifest: AndroidConfig.Manifest.AndroidManifest,
) {
const mainApplication = getMainApplicationOrThrow(androidManifest);

addMetaDataItemToMainApplication(
mainApplication,
META_BRANCH_KEY_TEST_MODE,
`${enableTestEnvironment}`,
);

return androidManifest;
}

export const withBranchAndroid: ConfigPlugin<ConfigData> = (config, data) => {
// Fall back to the Expo Config `branch.apiKey` if not provided in plugin
// config. The `branch` property in the Expo Config is deprecated and will be
// removed in SDK 56.
// TODO(@hassankhan): Remove fallback when updating for SDK 56
if (config.android?.config?.branch?.apiKey) {
console.warn(
"react-native-branch: Using `config.android.config.branch.apiKey` is deprecated. " +
"Pass `apiKey` directly in the plugin config instead.",
);
}
const apiKey = data.apiKey ?? config.android?.config?.branch?.apiKey;
const { testApiKey, enableTestEnvironment = false } = data;

if (!apiKey) {
throw new Error("Branch API key is required: apiKey must be provided");
}

config = withAndroidManifest(config, (config) => {
config.modResults = setBranchApiKey(apiKey, config.modResults);
config.modResults = setBranchApiKeys(
{ apiKey, testApiKey },
config.modResults,
);

config.modResults = enableBranchTestEnvironment(
enableTestEnvironment,
config.modResults,
);

return config;
});

Expand Down
Loading
Loading