Skip to content

Commit 6e64572

Browse files
authored
Add Windows C++ implementation (#239)
Add module implementation using C++ WinRT. This implementation supports all react-native-windows since 0.61, and includes autolinking support for react-native-windows>=0.63. Add test and CI for the Windows implementation. Separate PR will follow with documentation changes.
1 parent bab8b8f commit 6e64572

66 files changed

Lines changed: 6691 additions & 272 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/windows-ci.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Windows CI
2+
on: [pull_request]
3+
4+
jobs:
5+
run-windows-tests:
6+
name: Build & run tests
7+
runs-on: windows-2019
8+
9+
steps:
10+
- uses: actions/checkout@v2
11+
name: Checkout Code
12+
13+
- name: Setup Node.js
14+
uses: actions/setup-node@v1
15+
with:
16+
node-version: '12.9.1'
17+
18+
- name: Setup MSBuild
19+
uses: microsoft/setup-msbuild@v1.0.0
20+
with:
21+
vs-version: 16.5
22+
23+
- name: Build the module
24+
run: |
25+
yarn
26+
yarn localPublish
27+
cd example
28+
yarn
29+
30+
- name: Build x64 release
31+
run: |
32+
cd example
33+
npx react-native run-windows --release --no-packager --no-launch --logging
34+
35+
- name: Start Appium server
36+
shell: powershell
37+
run: |
38+
cd example
39+
Start-Process PowerShell -ArgumentList "yarn appium"
40+
41+
- name: Run tests
42+
run: |
43+
cd example
44+
yarn test:windows

example/__tests__/App-test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import 'react-native';
66
import React from 'react';
7-
import App from '../App';
7+
import App from '../src/routes';
88

99
// Note: test renderer must be required after react-native.
1010
import renderer from 'react-test-renderer';

example/__tests__/CheckStore.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { driver, By2 } from 'selenium-appium'
2+
import { until } from 'selenium-webdriver';
3+
4+
const setup = require('../jest-setups/jest.setup');
5+
jest.setTimeout(60000);
6+
7+
beforeAll(() => {
8+
return driver.startWithCapabilities(setup.capabilites);
9+
});
10+
11+
afterAll(() => {
12+
return driver.quit();
13+
});
14+
15+
describe('Test App', () => {
16+
17+
test('Log present', async () => {
18+
// Get the element by label, will fail if the element is not present
19+
// We will look for the expected log from the app
20+
await driver.wait(until.elementLocated(By2.nativeName('setItem(key1, value1): value1\nsetItem(key2, value2): value2\nsetItem(key3, value3): value3\ngetItem(key2): value2\ndelItem(key2): key2\ngetAllItems():\n - key1 : value1\n - key3 : value3\n')));
21+
});
22+
23+
})

example/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'react-native-gesture-handler';
2-
31
import { AppRegistry } from 'react-native';
42

53
import App from './src/routes';

example/jest-setups/jest.setup.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { windowsAppDriverCapabilities } from 'selenium-appium'
2+
3+
switch (platform) {
4+
case "windows":
5+
const webViewWindowsAppId = 'RNSIExample_nsp2ha5jnb6xr!App';
6+
module.exports = {
7+
capabilites: windowsAppDriverCapabilities(webViewWindowsAppId)
8+
}
9+
break;
10+
default:
11+
throw "Unknown platform: " + platform;
12+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
platform = "windows"

example/metro.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,20 @@
44
*
55
* @format
66
*/
7+
const path = require('path');
8+
const blacklist = require('metro-config/src/defaults/blacklist');
79

810
module.exports = {
11+
resolver: {
12+
blacklistRE: blacklist([
13+
// This stops "react-native run-windows" from causing the metro server to crash if its already running
14+
new RegExp(
15+
`${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`,
16+
),
17+
// This prevents "react-native run-windows" from hitting: EBUSY: resource busy or locked, open msbuild.ProjectImports.zip
18+
/.*\.ProjectImports\.zip/,
19+
]),
20+
},
921
transformer: {
1022
getTransformOptions: async () => ({
1123
transform: {

example/package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,29 @@
44
"private": true,
55
"scripts": {
66
"android": "react-native run-android",
7+
"appium": "appium",
78
"ios": "react-native run-ios",
9+
"windows": "react-native run-windows",
810
"start": "react-native start",
911
"test": "jest",
12+
"test:windows": "yarn jest --setupFiles=./jest-setups/jest.setup.windows.js",
1013
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
1114
},
1215
"dependencies": {
1316
"@react-native-community/masked-view": "^0.1.10",
1417
"@react-navigation/native": "^5.7.2",
1518
"@react-navigation/stack": "^5.8.0",
19+
"appium": "^1.18.3",
1620
"react": "16.13.1",
1721
"react-native": "0.63.2",
1822
"react-native-gesture-handler": "^1.7.0",
1923
"react-native-reanimated": "^1.10.1",
2024
"react-native-safe-area-context": "^3.1.1",
2125
"react-native-screens": "^2.9.0",
22-
"react-native-sensitive-info": "file:.yalc/react-native-sensitive-info"
26+
"react-native-sensitive-info": "file:.yalc/react-native-sensitive-info",
27+
"react-native-windows": "^0.63.0-0",
28+
"selenium-appium": "^0.0.15",
29+
"selenium-webdriver": "^4.0.0-alpha.7"
2330
},
2431
"devDependencies": {
2532
"@babel/core": "^7.10.5",

example/src/pages/Home/index.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { useCallback } from 'react';
2-
import { View, Button, Alert } from 'react-native';
1+
import React, { useCallback, useState } from 'react';
2+
import { View, Button, Alert, Text } from 'react-native';
33
import SInfo from 'react-native-sensitive-info';
44

55
const Home: React.FC = () => {
@@ -72,6 +72,27 @@ const Home: React.FC = () => {
7272
}
7373
}, []);
7474

75+
const [logText, setLogText] = useState('')
76+
async function runTest(){
77+
const options = {
78+
sharedPreferencesName: 'exampleAppTest',
79+
keychainService: 'exampleAppTest',
80+
};
81+
let dbgText = '';
82+
dbgText += `setItem(key1, value1): ${await SInfo.setItem('key1', 'value1', options)}\n`;
83+
dbgText += `setItem(key2, value2): ${await SInfo.setItem('key2', 'value2', options)}\n`;
84+
dbgText += `setItem(key3, value3): ${await SInfo.setItem('key3', 'value3', options)}\n`;
85+
dbgText += `getItem(key2): ${await SInfo.getItem('key2', options)}\n`;
86+
dbgText += `delItem(key2): ${await SInfo.deleteItem('key2', options)}\n`;
87+
dbgText += `getAllItems():\n`
88+
const allItems = await SInfo.getAllItems(options);
89+
for (const key in allItems) {
90+
dbgText += ` - ${key} : ${allItems[key]}\n`;
91+
}
92+
setLogText(dbgText);
93+
};
94+
runTest();
95+
7596
return (
7697
<View>
7798
<Button
@@ -88,6 +109,8 @@ const Home: React.FC = () => {
88109
/>
89110

90111
<Button title="Get TouchID Data" onPress={getTouchIDItem} />
112+
113+
<Text>{logText}</Text>
91114
</View>
92115
);
93116
};

example/src/routes/index.tsx

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
import React from 'react';
2-
import { NavigationContainer } from '@react-navigation/native';
3-
import { createStackNavigator } from '@react-navigation/stack';
4-
51
import HomeScreen from '../pages/Home';
6-
7-
const Stack = createStackNavigator();
8-
9-
const RootRoute: React.FC = () => (
10-
<NavigationContainer>
11-
<Stack.Navigator>
12-
<Stack.Screen name="Home" component={HomeScreen} />
13-
</Stack.Navigator>
14-
</NavigationContainer>
15-
);
16-
2+
const RootRoute = HomeScreen;
173
export default RootRoute;

0 commit comments

Comments
 (0)