Skip to content

Commit bf4499d

Browse files
committed
Refactor sample app structure and add mock for mParticle integration
1 parent 0bfa737 commit bf4499d

File tree

11 files changed

+599
-496
lines changed

11 files changed

+599
-496
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,6 @@ package-lock.json
8282

8383
# TypeScript build output
8484
lib/
85+
86+
# Development package
87+
*.tgz

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
"build": "tsc",
1212
"clean": "rm -rf lib",
1313
"prepare": "yarn clean && yarn build",
14+
"dev:pack": "yarn build && yarn pack --filename react-native-mparticle-latest.tgz",
15+
"dev:link": "yarn build && yarn pack --filename react-native-mparticle-latest.tgz && cd sample && yarn install && cd ..",
1416
"test": "./node_modules/standard/bin/cmd.js",
1517
"fix": "./node_modules/standard/bin/cmd.js --fix"
1618
},

sample/README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# mParticle React Native Sample App
2+
3+
This sample app demonstrates how to integrate and use the mParticle React Native SDK.
4+
5+
## Prerequisites
6+
7+
- Node.js (>= 18)
8+
- Yarn package manager
9+
- React Native development environment set up
10+
- For iOS: Xcode and iOS Simulator
11+
- For Android: Android Studio and Android SDK
12+
13+
## Setup Instructions
14+
15+
### 1. Configure mParticle Keys
16+
17+
Before running the sample app, you need to replace the placeholder mParticle keys with your actual mParticle app credentials.
18+
19+
#### iOS Configuration
20+
21+
Edit `ios/MParticleSample/AppDelegate.mm` and replace the placeholder keys:
22+
23+
```objc
24+
MParticleOptions *mParticleOptions = [MParticleOptions optionsWithKey:@"YOUR_IOS_API_KEY"
25+
secret:@"YOUR_IOS_SECRET_KEY"];
26+
```
27+
28+
#### Android Configuration
29+
30+
Edit `android/app/src/main/java/com/mparticlesample/MainApplication.kt` and replace the placeholder keys:
31+
32+
```kotlin
33+
val options = MParticleOptions.builder(this)
34+
.credentials("YOUR_ANDROID_API_KEY", "YOUR_ANDROID_SECRET_KEY")
35+
.logLevel(MParticle.LogLevel.VERBOSE)
36+
.identify(identityRequest.build())
37+
.build()
38+
```
39+
40+
### 2. Build and Install the Package
41+
42+
From the **root directory**, run the following commands:
43+
44+
```bash
45+
# Build the TypeScript source and create a package
46+
yarn dev:pack
47+
48+
# Install dependencies in the sample app
49+
cd sample
50+
yarn install
51+
```
52+
53+
Alternatively, you can use the combined command from the root directory:
54+
55+
```bash
56+
# Build, pack, and install in sample directory in one command
57+
yarn dev:link
58+
```
59+
60+
### 3. Install iOS Dependencies (iOS only)
61+
62+
```bash
63+
cd sample/ios
64+
pod install
65+
```
66+
67+
## Running the Sample App
68+
69+
### iOS
70+
71+
From the **sample directory**:
72+
73+
```bash
74+
yarn ios
75+
```
76+
77+
### Android
78+
79+
From the **sample directory**:
80+
81+
```bash
82+
yarn android
83+
```
84+
85+
## Development Workflow
86+
87+
When making changes to the mParticle React Native SDK:
88+
89+
1. Make your changes to the SDK source code
90+
2. Rebuild and reinstall the package:
91+
92+
```bash
93+
# From root directory
94+
yarn dev:link
95+
```
96+
97+
3. Restart the sample app to see your changes
98+
99+
## Troubleshooting
100+
101+
### Common Issues
102+
103+
1. **Metro bundler cache issues**: Clear the cache with:
104+
105+
```bash
106+
cd sample
107+
npx react-native start --reset-cache
108+
```
109+
110+
2. **iOS build issues**: Clean and rebuild:
111+
112+
```bash
113+
cd sample/ios
114+
xcodebuild clean
115+
cd ..
116+
yarn ios
117+
```
118+
119+
3. **Android build issues**: Clean and rebuild:
120+
121+
```bash
122+
cd sample/android
123+
./gradlew clean
124+
cd ..
125+
yarn android
126+
```
127+
128+
4. **Package not found**: Make sure you've run `yarn dev:pack` or `yarn dev:link` from the root directory
129+
130+
## Available Scripts
131+
132+
From the sample directory:
133+
134+
- `yarn start` - Start the Metro bundler
135+
- `yarn ios` - Run on iOS simulator
136+
- `yarn android` - Run on Android emulator
137+
- `yarn lint` - Run ESLint
138+
- `yarn test` - Run Jest tests
139+
140+
## Additional Resources
141+
142+
- [mParticle Documentation](https://docs.mparticle.com/)
143+
- [React Native mParticle SDK Documentation](https://github.com/mParticle/react-native-mparticle)
144+
- [React Native Documentation](https://reactnative.dev/)
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/* eslint-disable */
2+
/**
3+
* Mock for react-native-mparticle
4+
* This mock provides a simple API that mimics the essential functionality
5+
*/
6+
7+
// Mock classes
8+
class User {
9+
constructor(userId) {
10+
this.userId = userId;
11+
}
12+
13+
getMpid() {
14+
return this.userId;
15+
}
16+
17+
setUserAttribute() {}
18+
getUserAttributes(callback) {
19+
callback({ testAttribute: 'testValue' });
20+
}
21+
setUserTag() {}
22+
incrementUserAttribute() {}
23+
removeUserAttribute() {}
24+
getUserIdentities(callback) {
25+
callback({ email: '[email protected]' });
26+
}
27+
getFirstSeen(callback) {
28+
callback(Date.now() - 86400000);
29+
}
30+
getLastSeen(callback) {
31+
callback(Date.now());
32+
}
33+
}
34+
35+
class IdentityRequest {
36+
setEmail(email) {
37+
this.email = email;
38+
return this;
39+
}
40+
41+
setCustomerID(customerId) {
42+
this.customerId = customerId;
43+
return this;
44+
}
45+
46+
setUserIdentity(userIdentity, identityType) {
47+
this[identityType] = userIdentity;
48+
return this;
49+
}
50+
}
51+
52+
class Identity {
53+
static getCurrentUser(completion) {
54+
var currentUser = new User('mockUserId123');
55+
completion(currentUser);
56+
}
57+
58+
static login(request, completion) {
59+
completion(null, 'mockUserId123', 'mockPreviousUserId456');
60+
}
61+
62+
static logout(request, completion) {
63+
completion(null, 'mockUserId123');
64+
}
65+
66+
static identify(request, completion) {
67+
completion(null, 'mockUserId123', 'mockPreviousUserId456');
68+
}
69+
70+
static modify(request, completion) {
71+
completion(null, 'mockUserId123', 'mockPreviousUserId456');
72+
}
73+
74+
static aliasUsers(request, completion) {
75+
completion(true, null);
76+
}
77+
}
78+
79+
class Product {
80+
constructor(name, sku, price, quantity = 1) {
81+
this.name = name;
82+
this.sku = sku;
83+
this.price = price;
84+
this.quantity = quantity;
85+
}
86+
}
87+
88+
class TransactionAttributes {
89+
constructor(transactionId) {
90+
this.transactionId = transactionId;
91+
}
92+
}
93+
94+
class CommerceEvent {
95+
static createProductActionEvent(productActionType, products, transactionAttributes) {
96+
return new CommerceEvent();
97+
}
98+
}
99+
100+
class AliasRequest {
101+
sourceMpid(mpid) {
102+
this.sourceMpid = mpid;
103+
return this;
104+
}
105+
106+
destinationMpid(mpid) {
107+
this.destinationMpid = mpid;
108+
return this;
109+
}
110+
111+
startTime(time) {
112+
this.startTime = time;
113+
return this;
114+
}
115+
116+
endTime(time) {
117+
this.endTime = time;
118+
return this;
119+
}
120+
}
121+
122+
// Mock Rokt
123+
const Rokt = {
124+
selectPlacements: () => Promise.resolve()
125+
};
126+
127+
// Constants
128+
const EventType = {
129+
Navigation: 1,
130+
Location: 2,
131+
Search: 3,
132+
Transaction: 4,
133+
UserContent: 5,
134+
UserPreference: 6,
135+
Social: 7,
136+
Other: 8,
137+
Media: 9
138+
};
139+
140+
const UserIdentityType = {
141+
Email: 7,
142+
CustomerId: 1,
143+
Alias: 8
144+
};
145+
146+
const ProductActionType = {
147+
AddToCart: 1,
148+
RemoveFromCart: 2,
149+
Checkout: 3,
150+
Purchase: 7
151+
};
152+
153+
// Main mock object
154+
const MParticle = {
155+
// Classes
156+
User,
157+
IdentityRequest,
158+
Identity,
159+
Product,
160+
TransactionAttributes,
161+
CommerceEvent,
162+
AliasRequest,
163+
Rokt,
164+
165+
// Constants
166+
EventType,
167+
UserIdentityType,
168+
ProductActionType,
169+
170+
// Methods
171+
logEvent: () => {},
172+
logCommerceEvent: () => {},
173+
logPushRegistration: () => {},
174+
getSession: (callback) => callback({ sessionId: 'mockSessionId123' }),
175+
setOptOut: () => {},
176+
getOptOut: (callback) => callback(false),
177+
isKitActive: (kitId, callback) => callback(true),
178+
getAttributions: (callback) => callback({ attributionResults: 'mock results' }),
179+
upload: () => {},
180+
setUploadInterval: () => {},
181+
setLocation: () => {}
182+
};
183+
184+
module.exports = MParticle;

sample/__tests__/index.ios.js

Lines changed: 0 additions & 12 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
import 'react-native';
22
import React from 'react';
3-
import Index from '../index.android.js';
3+
import Index from '../index.js';
44

55
// Note: test renderer must be required after react-native.
66
import renderer from 'react-test-renderer';
77

8+
// Use fake timers to avoid async issues
9+
jest.useFakeTimers();
10+
811
it('renders correctly', () => {
912
const tree = renderer.create(
1013
<Index />
1114
);
15+
16+
// Clean up any timers that might be running
17+
jest.runOnlyPendingTimers();
18+
jest.clearAllTimers();
19+
20+
expect(tree.toJSON()).toBeTruthy();
1221
});

0 commit comments

Comments
 (0)