Skip to content

Commit c56e8d7

Browse files
committed
wip: ci/cd
1 parent 45739aa commit c56e8d7

File tree

6 files changed

+313
-85
lines changed

6 files changed

+313
-85
lines changed

.github/workflows/ci.yml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: React Native CI
2+
3+
on:
4+
pull_request:
5+
branches: main
6+
push:
7+
branches: main
8+
schedule:
9+
- cron: '0 0 * * *' # Runs at 00:00 UTC every day
10+
11+
jobs:
12+
ios-build:
13+
name: iOS Build
14+
runs-on: macos-latest
15+
defaults:
16+
run:
17+
working-directory: example
18+
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v3
22+
23+
- name: Setup Node.js
24+
uses: actions/setup-node@v3
25+
with:
26+
node-version: '22'
27+
28+
- name: Install dependencies
29+
run: |
30+
npm install --frozen-lockfile
31+
cd ios && pod install
32+
33+
- name: Install Maestro CLI
34+
run: |
35+
export MAESTRO_VERSION=1.31.0; curl -Ls "https://get.maestro.mobile.dev" | bash
36+
brew tap facebook/fb
37+
brew install facebook/fb/idb-companion
38+
39+
- name: Add Maestro to path
40+
run: echo "${HOME}/.maestro/bin" >> $GITHUB_PATH
41+
42+
- name: Bundle iOS
43+
run: npm run build:ios
44+
45+
- name: Build iOS
46+
run: |
47+
npm run ios:release
48+
49+
- name: Run iOS tests
50+
run: npm run test:e2e
51+
52+
android-build:
53+
name: Android Build
54+
runs-on: ubuntu-latest
55+
defaults:
56+
run:
57+
working-directory: example
58+
59+
steps:
60+
- name: Checkout repository
61+
uses: actions/checkout@v3
62+
63+
- name: Setup Node.js
64+
uses: actions/setup-node@v3
65+
with:
66+
node-version: '18'
67+
cache: 'npm'
68+
cache-dependency-path: example/package-lock.json
69+
70+
- name: Setup Java
71+
uses: actions/setup-java@v3
72+
with:
73+
distribution: 'zulu'
74+
java-version: '17'
75+
76+
- name: Install dependencies
77+
run: npm install --frozen-lockfile
78+
79+
- name: Bundle Android
80+
run: npm run build:android
81+
82+
- name: Install Maestro CLI
83+
run: |
84+
export MAESTRO_VERSION=1.31.0; curl -Ls "https://get.maestro.mobile.dev" | bash
85+
86+
- name: Add Maestro to path
87+
run: echo "${HOME}/.maestro/bin" >> $GITHUB_PATH
88+
89+
- name: Create AVD and generate snapshot for caching
90+
uses: reactivecircus/android-emulator-runner@v2
91+
with:
92+
target: aosp_atd
93+
api-level: 30
94+
arch: x86
95+
ram-size: 4096M
96+
channel: canary
97+
profile: pixel
98+
avd-name: Pixel_3a_API_30_AOSP
99+
force-avd-creation: false
100+
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
101+
emulator-boot-timeout: 12000
102+
disable-animations: false
103+
working-directory: example
104+
script: |
105+
npm run android:release
106+
npm run test:e2e

example/App.tsx

Lines changed: 142 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
1-
/**
2-
* Sample React Native App
3-
* https://github.com/facebook/react-native
4-
*
5-
* @format
6-
*/
7-
8-
import React from 'react';
9-
import type {PropsWithChildren} from 'react';
1+
import React, { useState } from 'react';
102
import {
3+
Button,
114
SafeAreaView,
125
ScrollView,
136
StatusBar,
@@ -16,52 +9,127 @@ import {
169
useColorScheme,
1710
View,
1811
} from 'react-native';
19-
2012
import {
2113
Colors,
22-
DebugInstructions,
2314
Header,
24-
LearnMoreLinks,
25-
ReloadInstructions,
2615
} from 'react-native/Libraries/NewAppScreen';
2716

28-
type SectionProps = PropsWithChildren<{
29-
title: string;
30-
}>;
31-
32-
function Section({children, title}: SectionProps): React.JSX.Element {
33-
const isDarkMode = useColorScheme() === 'dark';
34-
return (
35-
<View style={styles.sectionContainer}>
36-
<Text
37-
style={[
38-
styles.sectionTitle,
39-
{
40-
color: isDarkMode ? Colors.white : Colors.black,
41-
},
42-
]}>
43-
{title}
44-
</Text>
45-
<Text
46-
style={[
47-
styles.sectionDescription,
48-
{
49-
color: isDarkMode ? Colors.light : Colors.dark,
50-
},
51-
]}>
52-
{children}
53-
</Text>
54-
</View>
55-
);
56-
}
57-
5817
function App(): React.JSX.Element {
5918
const isDarkMode = useColorScheme() === 'dark';
19+
const [testResult, setTestResult] = useState('No test run yet');
20+
const [testName, setTestName] = useState('');
6021

6122
const backgroundStyle = {
6223
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
6324
};
6425

26+
const testConsoleLog = () => {
27+
console.log('Hello from JSC');
28+
setTestName('Console Test Result');
29+
setTestResult('Hello from JSC');
30+
};
31+
32+
const testBasicOperations = () => {
33+
const mathResult = 2 + 2;
34+
const stringResult = 'Hello ' + 'World';
35+
const arrayResult = [1, 2, 3].map(x => x * 2);
36+
37+
const result = `Math: ${mathResult}\nString: ${stringResult}\nArray: ${arrayResult}`;
38+
console.log(result);
39+
setTestName('Basic Operations Result');
40+
setTestResult(result);
41+
};
42+
43+
const testComplexOperations = () => {
44+
const obj = { a: 1, b: 2 };
45+
const square = (x: number) => x * x;
46+
const squareResult = square(4);
47+
48+
let result = `Object: ${JSON.stringify(obj)}\nSquare(4): ${squareResult}`;
49+
50+
try {
51+
// eslint-disable-next-line no-eval
52+
const dynamicFn = eval('(x) => x * 3');
53+
const dynamicResult = dynamicFn(4);
54+
result += `\nDynamic function(4): ${dynamicResult}`;
55+
} catch (error) {
56+
result += `\nDynamic function error: ${error}`;
57+
}
58+
59+
console.log(result);
60+
setTestName('Complex Operations Result');
61+
setTestResult(result);
62+
};
63+
64+
const testGlobalAccess = () => {
65+
const result = `SetTimeout exists: ${typeof global.setTimeout === 'function'}`;
66+
console.log(result);
67+
setTestName('Global Access Result');
68+
setTestResult(result);
69+
};
70+
71+
const testErrorHandling = () => {
72+
let results: string[] = [];
73+
74+
try {
75+
throw new Error('Custom error');
76+
} catch (error) {
77+
if (error instanceof Error) {
78+
results.push(`Regular error: ${error.message}`);
79+
}
80+
}
81+
82+
try {
83+
const undefined1 = undefined;
84+
// @ts-ignore
85+
undefined1.someMethod();
86+
} catch (error) {
87+
if (error instanceof Error) {
88+
results.push(`Type error: ${error.message}`);
89+
}
90+
}
91+
92+
try {
93+
// eslint-disable-next-line no-eval
94+
eval('syntax error{');
95+
} catch (error) {
96+
if (error instanceof Error) {
97+
results.push(`Eval error: ${error.message}`);
98+
}
99+
}
100+
101+
const result = results.join('\n');
102+
console.log(result);
103+
setTestName('Error Handling Result');
104+
setTestResult(result);
105+
};
106+
107+
const testAsync = async () => {
108+
try {
109+
const result = await new Promise((resolve) => {
110+
setTimeout(() => resolve('Regular async completed'), 1000);
111+
});
112+
console.log('Regular async result:', result);
113+
setTestName('Async Test Result');
114+
setTestResult(String(result));
115+
} catch (error) {
116+
setTestName('Async Error');
117+
setTestResult(String(error));
118+
}
119+
};
120+
121+
const testMemoryAndPerformance = () => {
122+
const arr = new Array(1000000);
123+
for (let i = 0; i < arr.length; i++) {
124+
arr[i] = i;
125+
}
126+
const result = `Array length: ${arr.length}`;
127+
128+
console.log(result);
129+
setTestName('Memory & Performance Result');
130+
setTestResult(result);
131+
};
132+
65133
return (
66134
<SafeAreaView style={backgroundStyle}>
67135
<StatusBar
@@ -73,45 +141,47 @@ function App(): React.JSX.Element {
73141
style={backgroundStyle}>
74142
<Header />
75143
<View
76-
style={{
77-
backgroundColor: isDarkMode ? Colors.black : Colors.white,
78-
}}>
79-
<Section title="Step One">
80-
Edit <Text style={styles.highlight}>App.tsx</Text> to change this
81-
screen and then come back to see your edits.
82-
</Section>
83-
<Section title="See Your Changes">
84-
<ReloadInstructions />
85-
</Section>
86-
<Section title="Debug">
87-
<DebugInstructions />
88-
</Section>
89-
<Section title="Learn More">
90-
Read the docs to discover what to do next:
91-
</Section>
92-
<LearnMoreLinks />
144+
style={[
145+
styles.container,
146+
{backgroundColor: isDarkMode ? Colors.black : Colors.white},
147+
]}>
148+
<Button title="Console Log Test" onPress={testConsoleLog} />
149+
<Button title="Basic Operations" onPress={testBasicOperations} />
150+
<Button title="Complex Operations" onPress={testComplexOperations} />
151+
<Button title="Global Access Test" onPress={testGlobalAccess} />
152+
<Button title="Error Handling Test" onPress={testErrorHandling} />
153+
<Button title="Async Test" onPress={testAsync} />
154+
<Button title="Memory & Performance" onPress={testMemoryAndPerformance} />
155+
<View style={styles.resultContainer}>
156+
<Text style={styles.resultTitle} testID="resultTitle">
157+
{testName || 'Test Results'}
158+
</Text>
159+
<Text style={styles.resultContent} testID="resultContent">
160+
{testResult}
161+
</Text>
162+
</View>
93163
</View>
94164
</ScrollView>
95165
</SafeAreaView>
96166
);
97167
}
98168

99169
const styles = StyleSheet.create({
100-
sectionContainer: {
101-
marginTop: 32,
102-
paddingHorizontal: 24,
170+
container: {
171+
padding: 12,
103172
},
104-
sectionTitle: {
105-
fontSize: 24,
106-
fontWeight: '600',
173+
resultContainer: {
174+
marginTop: 20,
175+
padding: 10,
176+
backgroundColor: '#f0f0f0',
107177
},
108-
sectionDescription: {
109-
marginTop: 8,
110-
fontSize: 18,
111-
fontWeight: '400',
178+
resultTitle: {
179+
fontSize: 16,
180+
fontWeight: 'bold',
181+
marginBottom: 8,
112182
},
113-
highlight: {
114-
fontWeight: '700',
183+
resultContent: {
184+
fontSize: 14,
115185
},
116186
});
117187

0 commit comments

Comments
 (0)