Skip to content

Commit 1f964aa

Browse files
committed
feat: post-rebase tweaks
1 parent c7a934f commit 1f964aa

4 files changed

Lines changed: 173 additions & 52 deletions

File tree

packages/platform-android/src/adb.ts

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -122,50 +122,3 @@ export const isAppRunning = async (
122122
]);
123123
return stdout.trim() !== '';
124124
};
125-
126-
export const getUiHierarchy = async (adbId: string): Promise<string> => {
127-
const dumpPath = '/data/local/tmp/uidump.xml';
128-
await spawn('adb', ['-s', adbId, 'shell', 'uiautomator', 'dump', dumpPath]);
129-
const { stdout } = await spawn('adb', [
130-
'-s',
131-
adbId,
132-
'shell',
133-
'cat',
134-
dumpPath,
135-
]);
136-
await spawn('adb', ['-s', adbId, 'shell', 'rm', dumpPath]);
137-
return stdout;
138-
};
139-
140-
export const tap = async (
141-
adbId: string,
142-
x: number,
143-
y: number
144-
): Promise<void> => {
145-
await spawn('adb', [
146-
'-s',
147-
adbId,
148-
'shell',
149-
'input',
150-
'tap',
151-
x.toString(),
152-
y.toString(),
153-
]);
154-
};
155-
156-
export const inputText = async (adbId: string, text: string): Promise<void> => {
157-
// ADB input text requires spaces to be escaped as %s
158-
const escapedText = text.replace(/ /g, '%s');
159-
await spawn('adb', ['-s', adbId, 'shell', 'input', 'text', escapedText]);
160-
};
161-
162-
export const screenshot = async (
163-
adbId: string,
164-
destination: string
165-
): Promise<string> => {
166-
const deviceTempPath = '/data/local/tmp/screenshot.png';
167-
await spawn('adb', ['-s', adbId, 'shell', 'screencap', '-p', deviceTempPath]);
168-
await spawn('adb', ['-s', adbId, 'pull', deviceTempPath, destination]);
169-
await spawn('adb', ['-s', adbId, 'shell', 'rm', deviceTempPath]);
170-
return destination;
171-
};

packages/ui/README.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
![harness-banner](https://react-native-harness.dev/harness-banner.jpg)
2+
3+
### Native UI Testing Module for React Native Harness
4+
5+
[![mit licence][license-badge]][license]
6+
[![npm downloads][npm-downloads-badge]][npm-downloads]
7+
[![Chat][chat-badge]][chat]
8+
[![PRs Welcome][prs-welcome-badge]][prs-welcome]
9+
10+
Native UI testing module for React Native Harness that provides view queries and touch simulation capabilities. This module enables finding UI elements and simulating user interactions in your React Native tests.
11+
12+
## Features
13+
14+
- **View Queries**: Find elements by testID or accessibility label
15+
- **Touch Simulation**: Simulate user presses and text input
16+
- **Screenshot Capture**: Capture screenshots of the entire screen or specific elements
17+
- **Debug-Only**: Automatically excluded from release builds, only available in debug builds
18+
19+
## Installation
20+
21+
```bash
22+
npm install @react-native-harness/ui
23+
# or
24+
pnpm add @react-native-harness/ui
25+
# or
26+
yarn add @react-native-harness/ui
27+
```
28+
29+
## Usage
30+
31+
Import the UI testing utilities in your test files:
32+
33+
```javascript
34+
import { screen, userEvent } from '@react-native-harness/ui';
35+
36+
describe('My Component', () => {
37+
it('should handle user interactions', async () => {
38+
// Find elements on screen
39+
const button = await screen.findByTestId('my-button');
40+
const input = await screen.findByAccessibilityLabel('Username input');
41+
42+
// Simulate user interactions
43+
await userEvent.type(input, 'testuser');
44+
await userEvent.press(button);
45+
46+
// Take screenshots for debugging
47+
const screenshot = await screen.screenshot();
48+
});
49+
});
50+
```
51+
52+
## API
53+
54+
### `screen`
55+
56+
Provides methods to query and interact with UI elements on screen.
57+
58+
#### `findByTestId(testId: string): Promise<ElementReference>`
59+
60+
Finds an element by its testID (accessibilityIdentifier on iOS, tag on Android).
61+
Throws an error if no element is found.
62+
63+
#### `findAllByTestId(testId: string): Promise<ElementReference[]>`
64+
65+
Finds all elements by testID. Throws an error if no elements are found.
66+
67+
#### `queryByTestId(testId: string): ElementReference | null`
68+
69+
Queries for an element by testID without throwing. Returns null if not found.
70+
71+
#### `queryAllByTestId(testId: string): ElementReference[]`
72+
73+
Queries for all elements by testID without throwing. Returns an empty array if none found.
74+
75+
#### `findByAccessibilityLabel(label: string): Promise<ElementReference>`
76+
77+
Finds an element by its accessibility label. Throws an error if no element is found.
78+
79+
#### `findAllByAccessibilityLabel(label: string): Promise<ElementReference[]>`
80+
81+
Finds all elements by accessibility label. Throws an error if no elements are found.
82+
83+
#### `queryByAccessibilityLabel(label: string): ElementReference | null`
84+
85+
Queries for an element by accessibility label without throwing. Returns null if not found.
86+
87+
#### `queryAllByAccessibilityLabel(label: string): ElementReference[]`
88+
89+
Queries for all elements by accessibility label without throwing. Returns an empty array if none found.
90+
91+
#### `screenshot(element?: ElementReference): Promise<ScreenshotResult | null>`
92+
93+
Captures a screenshot of the entire app window or a specific element.
94+
Returns a ScreenshotResult with PNG data, or null if capture fails.
95+
96+
### `userEvent`
97+
98+
Provides methods to simulate user interactions.
99+
100+
#### `press(element: ElementReference): Promise<void>`
101+
102+
Simulates a press on the given element at its center point.
103+
104+
#### `pressAt(x: number, y: number): Promise<void>`
105+
106+
Simulates a press at the specified screen coordinates.
107+
108+
#### `type(element: ElementReference, text: string, options?: TypeOptions): Promise<void>`
109+
110+
Simulates typing text into a text input element. Focuses the element, types each character, and blurs the element.
111+
112+
**TypeOptions:**
113+
- `skipPress?: boolean` - If true, pressIn and pressOut events will not be triggered
114+
- `skipBlur?: boolean` - If true, endEditing and blur events will not be triggered
115+
- `submitEditing?: boolean` - If true, submitEditing event will be triggered after typing
116+
117+
## Types
118+
119+
### `ElementReference`
120+
121+
Represents an element found on screen with its position and dimensions.
122+
123+
```typescript
124+
type ElementReference = {
125+
x: number;
126+
y: number;
127+
width: number;
128+
height: number;
129+
// ... additional view info
130+
};
131+
```
132+
133+
### `ScreenshotResult`
134+
135+
Screenshot result containing PNG image data.
136+
137+
```typescript
138+
interface ScreenshotResult {
139+
data: Uint8Array; // PNG image data
140+
width: number; // Width in logical pixels
141+
height: number; // Height in logical pixels
142+
}
143+
```
144+
145+
## Requirements
146+
147+
- React Native project with React Native Harness configured
148+
- This module is only available in debug builds and is automatically excluded from release builds
149+
150+
## Made with ❤️ at Callstack
151+
152+
`@react-native-harness/ui` is an open source project and will always remain free to use. If you think it's cool, please star it 🌟. [Callstack][callstack-readme-with-love] is a group of React and React Native geeks, contact us at [hello@callstack.com](mailto:hello@callstack.com) if you need any help with these or just want to say hi!
153+
154+
Like the project? ⚛️ [Join the team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥
155+
156+
[callstack-readme-with-love]: https://callstack.com/?utm_source=github.com&utm_medium=referral&utm_campaign=react-native-harness&utm_term=readme-with-love
157+
[license-badge]: https://img.shields.io/npm/l/@react-native-harness/ui?style=for-the-badge
158+
[license]: https://github.com/callstackincubator/react-native-harness/blob/main/LICENSE
159+
[npm-downloads-badge]: https://img.shields.io/npm/dm/@react-native-harness/ui?style=for-the-badge
160+
[npm-downloads]: https://www.npmjs.com/package/@react-native-harness/ui
161+
[prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge
162+
[prs-welcome]: ../../CONTRIBUTING.md
163+
[chat-badge]: https://img.shields.io/discord/426714625279524876.svg?style=for-the-badge
164+
[chat]: https://discord.gg/xgGt7KAjxv

packages/ui/tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"files": [],
44
"include": [],
55
"references": [
6+
{
7+
"path": "../runtime"
8+
},
69
{
710
"path": "./tsconfig.lib.json"
811
}

packages/ui/tsconfig.lib.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
"types": ["node"]
1111
},
1212
"include": ["src/**/*.ts"],
13-
"references": [],
14-
"exclude": [
15-
"src/**/*.test.ts",
16-
"src/**/*.spec.ts"
17-
]
13+
"references": [
14+
{
15+
"path": "../runtime/tsconfig.lib.json"
16+
}
17+
],
18+
"exclude": ["src/**/*.test.ts", "src/**/*.spec.ts"]
1819
}

0 commit comments

Comments
 (0)