@react-native-harness/ui 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/Package.swift +40 -0
  2. package/README.md +7 -0
  3. package/android/src/main/java/com/harnessui/HarnessUIModule.kt +2 -1
  4. package/android/src/main/java/com/harnessui/UIHelperImpl.kt +409 -74
  5. package/dist/NativeHarnessUI.d.ts +3 -1
  6. package/dist/NativeHarnessUI.d.ts.map +1 -1
  7. package/dist/WebHarnessUI.js +2 -2
  8. package/dist/screen.d.ts.map +1 -1
  9. package/dist/screen.js +1 -1
  10. package/dist/types.d.ts +6 -4
  11. package/dist/types.d.ts.map +1 -1
  12. package/ios/HarnessUI.h +2 -0
  13. package/ios/HarnessUI.mm +6 -4
  14. package/ios/ViewQueryHelper.mm +16 -14
  15. package/package.json +6 -2
  16. package/src/NativeHarnessUI.ts +1 -1
  17. package/src/WebHarnessUI.ts +2 -2
  18. package/src/screen.ts +3 -1
  19. package/src/types.ts +4 -4
  20. package/dist/HarnessUI.d.ts +0 -17
  21. package/dist/HarnessUI.d.ts.map +0 -1
  22. package/dist/HarnessUI.js +0 -2
  23. package/dist/HarnessUI.web.d.ts +0 -14
  24. package/dist/HarnessUI.web.d.ts.map +0 -1
  25. package/dist/HarnessUI.web.js +0 -46
  26. package/dist/NativeHarness.d.ts +0 -22
  27. package/dist/NativeHarness.d.ts.map +0 -1
  28. package/dist/NativeHarness.js +0 -2
  29. package/dist/WebHarness.d.ts +0 -14
  30. package/dist/WebHarness.d.ts.map +0 -1
  31. package/dist/WebHarness.js +0 -53
  32. package/dist/harness/NativeHarness.d.ts +0 -17
  33. package/dist/harness/NativeHarness.d.ts.map +0 -1
  34. package/dist/harness/NativeHarness.js +0 -2
  35. package/dist/harness/WebHarness.d.ts +0 -14
  36. package/dist/harness/WebHarness.d.ts.map +0 -1
  37. package/dist/harness/WebHarness.js +0 -53
  38. package/dist/harness/index.d.ts +0 -4
  39. package/dist/harness/index.d.ts.map +0 -1
  40. package/dist/harness/index.js +0 -8
  41. package/dist/harness/native-harness.d.ts +0 -17
  42. package/dist/harness/native-harness.d.ts.map +0 -1
  43. package/dist/harness/native-harness.js +0 -2
  44. package/dist/harness/web-harness.d.ts +0 -14
  45. package/dist/harness/web-harness.d.ts.map +0 -1
  46. package/dist/harness/web-harness.js +0 -53
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { ViewInfo } from "./NativeHarnessUI.js";
2
- export type { ViewInfo, BoundingBox } from "./NativeHarnessUI.js";
1
+ import type { ViewInfo } from './NativeHarnessUI.js';
2
+ export type { ViewInfo, BoundingBox } from './NativeHarnessUI.js';
3
3
  export interface HarnessUIModule {
4
4
  /**
5
5
  * Simulates a native press on a view identified by nativeId, or at coordinates if nativeId is empty.
@@ -28,10 +28,12 @@ export interface HarnessUIModule {
28
28
  queryAllByAccessibilityLabel(label: string): ViewInfo[];
29
29
  /**
30
30
  * Captures a screenshot of the app UI.
31
- * @param bounds Optional bounds to capture a specific region. Pass null to capture the entire window.
31
+ * @param options.bounds Bounds to capture a specific region. Omit to capture the entire window.
32
32
  * @returns Promise resolving to Base64 encoded string containing PNG data, or null on failure.
33
33
  */
34
- captureScreenshot(bounds: ViewInfo | null): Promise<string | null>;
34
+ captureScreenshot(options: {
35
+ bounds?: ViewInfo;
36
+ }): Promise<string | null>;
35
37
  /**
36
38
  * Types a single character into the currently focused text input.
37
39
  * If no text input is focused, this is a no-op.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAE/C;;;OAGG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAE7C;;;OAGG;IACH,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAE1D;;;OAGG;IACH,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAExD;;;;OAIG;IACH,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEnE;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3C;;;OAGG;IACH,IAAI,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErE;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAE/C;;;OAGG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAE7C;;;OAGG;IACH,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAE1D;;;OAGG;IACH,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAExD;;;;OAIG;IACH,iBAAiB,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1E;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3C;;;OAGG;IACH,IAAI,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D"}
package/ios/HarnessUI.h CHANGED
@@ -1,3 +1,5 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <UIKit/UIKit.h>
1
3
  #import <HarnessUISpec/HarnessUISpec.h>
2
4
 
3
5
  @interface HarnessUI : NSObject <NativeHarnessUISpec>
package/ios/HarnessUI.mm CHANGED
@@ -414,11 +414,12 @@ static NSTimeInterval _lastTapTime = 0;
414
414
 
415
415
  #pragma mark - Screenshot API
416
416
 
417
- - (void)captureScreenshot:(JS::NativeHarnessUI::ViewInfo *)bounds
417
+ - (void)captureScreenshot:(JS::NativeHarnessUI::SpecCaptureScreenshotOptions &)options
418
418
  resolve:(RCTPromiseResolveBlock)resolve
419
419
  reject:(RCTPromiseRejectBlock)reject {
420
420
  RCTLogInfo(@"[HarnessUI] captureScreenshot called");
421
421
 
422
+ auto bounds = options.bounds();
422
423
  CGRect captureRect = CGRectNull;
423
424
  NSString *nativeId = nil;
424
425
 
@@ -445,7 +446,9 @@ static NSTimeInterval _lastTapTime = 0;
445
446
 
446
447
  if (nativeId) {
447
448
  UIView *targetView = [ViewRegistry getView:nativeId];
448
- if (targetView) {
449
+ if (targetView && (targetView.bounds.size.width <= 0 || targetView.bounds.size.height <= 0)) {
450
+ RCTLogWarn(@"[HarnessUI] View %@ has zero size. Nothing to capture.", nativeId);
451
+ } else if (targetView) {
449
452
  UIWindow *window = [self getActiveWindow];
450
453
  if (window) {
451
454
  CGRect frameInWindow = [targetView convertRect:targetView.bounds toView:window];
@@ -463,8 +466,7 @@ static NSTimeInterval _lastTapTime = 0;
463
466
  pngData = [ViewQueryHelper captureScreenshotOfView:targetView];
464
467
  }
465
468
  } else {
466
- RCTLogWarn(@"[HarnessUI] View with nativeId %@ not found. Falling back to window bounds capture.", nativeId);
467
- pngData = [ViewQueryHelper captureScreenshotWithBounds:captureRect];
469
+ RCTLogWarn(@"[HarnessUI] View with nativeId %@ not found. Nothing to capture.", nativeId);
468
470
  }
469
471
  } else {
470
472
  pngData = [ViewQueryHelper captureScreenshotWithBounds:captureRect];
@@ -29,23 +29,19 @@
29
29
 
30
30
  + (nullable UIWindow *)getActiveWindow {
31
31
  UIWindow *window = nil;
32
- if (@available(iOS 13.0, *)) {
33
- for (UIWindowScene *scene in [UIApplication sharedApplication].connectedScenes) {
34
- if (scene.activationState == UISceneActivationStateForegroundActive) {
35
- for (UIWindow *w in scene.windows) {
36
- if (w.isKeyWindow) {
37
- window = w;
38
- break;
39
- }
32
+ for (UIWindowScene *scene in [UIApplication sharedApplication].connectedScenes) {
33
+ if (scene.activationState == UISceneActivationStateForegroundActive) {
34
+ for (UIWindow *w in scene.windows) {
35
+ if (w.isKeyWindow) {
36
+ window = w;
37
+ break;
40
38
  }
41
- if (!window) {
42
- window = scene.windows.firstObject;
43
- }
44
- break;
45
39
  }
40
+ if (!window) {
41
+ window = scene.windows.firstObject;
42
+ }
43
+ break;
46
44
  }
47
- } else {
48
- window = [UIApplication sharedApplication].keyWindow;
49
45
  }
50
46
  return window;
51
47
  }
@@ -172,6 +168,9 @@
172
168
  UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init];
173
169
  format.scale = [UIScreen mainScreen].scale;
174
170
  format.opaque = YES;
171
+ // Pin to 8-bit sRGB so captures are consistent regardless of capture path
172
+ // (the default range can yield 16-bit Display P3 on wide-colour devices).
173
+ format.preferredRange = UIGraphicsImageRendererFormatRangeStandard;
175
174
 
176
175
  UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:captureRect.size format:format];
177
176
 
@@ -196,6 +195,9 @@
196
195
  UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init];
197
196
  format.scale = [UIScreen mainScreen].scale;
198
197
  format.opaque = NO; // Allow transparency if the view has it
198
+ // Pin to 8-bit sRGB so captures are consistent regardless of capture path
199
+ // (the default range can yield 16-bit Display P3 on wide-colour devices).
200
+ format.preferredRange = UIGraphicsImageRendererFormatRangeStandard;
199
201
 
200
202
  UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:view.bounds.size format:format];
201
203
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@react-native-harness/ui",
3
3
  "description": "Native UI testing module for React Native Harness.",
4
- "version": "1.6.0",
4
+ "version": "1.7.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -11,6 +11,7 @@
11
11
  "dist",
12
12
  "android",
13
13
  "ios",
14
+ "Package.swift",
14
15
  "*.podspec",
15
16
  "react-native.config.js",
16
17
  "!ios/build",
@@ -39,7 +40,7 @@
39
40
  },
40
41
  "dependencies": {
41
42
  "tslib": "^2.3.0",
42
- "@react-native-harness/runtime": "1.6.0"
43
+ "@react-native-harness/runtime": "1.7.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "react-native": "*"
@@ -52,6 +53,9 @@
52
53
  "javaPackageName": "com.harnessui"
53
54
  }
54
55
  },
56
+ "swiftpmConfig": {
57
+ "name": "HarnessUI"
58
+ },
55
59
  "author": {
56
60
  "name": "Szymon Chmal",
57
61
  "email": "szymon.chmal@callstack.com"
@@ -24,7 +24,7 @@ interface Spec extends TurboModule {
24
24
  queryAllByTestId(testId: string): ViewInfo[];
25
25
  queryByAccessibilityLabel(label: string): ViewInfo | null;
26
26
  queryAllByAccessibilityLabel(label: string): ViewInfo[];
27
- captureScreenshot(bounds: ViewInfo | null): Promise<string | null>;
27
+ captureScreenshot(options: { bounds?: ViewInfo }): Promise<string | null>;
28
28
  typeChar(character: string): Promise<void>;
29
29
  blur(options: { submitEditing?: boolean }): Promise<void>;
30
30
  }
@@ -81,8 +81,8 @@ const WebHarnessUI: HarnessUIModule = {
81
81
  return Array.from(elements).map(getElementViewInfo);
82
82
  },
83
83
 
84
- captureScreenshot: async (bounds) => {
85
- let captureBounds = bounds;
84
+ captureScreenshot: async ({ bounds }) => {
85
+ let captureBounds = bounds ?? null;
86
86
  if (bounds?.nativeId && bounds.width === 0 && bounds.height === 0) {
87
87
  const element = window.__RN_HARNESS_VIEW_REGISTRY__.get(bounds.nativeId);
88
88
  if (element) {
package/src/screen.ts CHANGED
@@ -181,7 +181,9 @@ const createScreen = (): Screen => {
181
181
  }
182
182
  }
183
183
 
184
- const base64String = await HarnessUI.captureScreenshot(captureBounds);
184
+ const base64String = await HarnessUI.captureScreenshot(
185
+ captureBounds ? { bounds: captureBounds } : {}
186
+ );
185
187
 
186
188
  if (!base64String) {
187
189
  return null;
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { ViewInfo } from "./NativeHarnessUI.js";
1
+ import type { ViewInfo } from './NativeHarnessUI.js';
2
2
 
3
- export type { ViewInfo, BoundingBox } from "./NativeHarnessUI.js";
3
+ export type { ViewInfo, BoundingBox } from './NativeHarnessUI.js';
4
4
 
5
5
  export interface HarnessUIModule {
6
6
  /**
@@ -35,10 +35,10 @@ export interface HarnessUIModule {
35
35
 
36
36
  /**
37
37
  * Captures a screenshot of the app UI.
38
- * @param bounds Optional bounds to capture a specific region. Pass null to capture the entire window.
38
+ * @param options.bounds Bounds to capture a specific region. Omit to capture the entire window.
39
39
  * @returns Promise resolving to Base64 encoded string containing PNG data, or null on failure.
40
40
  */
41
- captureScreenshot(bounds: ViewInfo | null): Promise<string | null>;
41
+ captureScreenshot(options: { bounds?: ViewInfo }): Promise<string | null>;
42
42
 
43
43
  /**
44
44
  * Types a single character into the currently focused text input.
@@ -1,17 +0,0 @@
1
- import { type TurboModule } from 'react-native';
2
- import { type ViewInfo } from './types.js';
3
- interface Spec extends TurboModule {
4
- simulatePress(x: number, y: number): Promise<void>;
5
- queryByTestId(testId: string): ViewInfo | null;
6
- queryAllByTestId(testId: string): ViewInfo[];
7
- queryByAccessibilityLabel(label: string): ViewInfo | null;
8
- queryAllByAccessibilityLabel(label: string): ViewInfo[];
9
- captureScreenshot(bounds: ViewInfo | null): Promise<string | null>;
10
- typeChar(character: string): Promise<void>;
11
- blur(options: {
12
- submitEditing?: boolean;
13
- }): Promise<void>;
14
- }
15
- declare const _default: Spec;
16
- export default _default;
17
- //# sourceMappingURL=HarnessUI.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HarnessUI.d.ts","sourceRoot":"","sources":["../src/HarnessUI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,UAAU,IAAK,SAAQ,WAAW;IAChC,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC7C,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC1D,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IACxD,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;;AAED,wBAAmE"}
package/dist/HarnessUI.js DELETED
@@ -1,2 +0,0 @@
1
- import { TurboModuleRegistry } from 'react-native';
2
- export default TurboModuleRegistry.getEnforcing('HarnessUI');
@@ -1,14 +0,0 @@
1
- import { type HarnessUIModule, type ViewInfo } from './types.js';
2
- declare global {
3
- interface Window {
4
- __RN_HARNESS_CAPTURE_SCREENSHOT__: (bounds: ViewInfo | null) => Promise<string | null>;
5
- __RN_HARNESS_SIMULATE_PRESS__: (x: number, y: number) => Promise<void>;
6
- __RN_HARNESS_TYPE_CHAR__: (character: string) => Promise<void>;
7
- __RN_HARNESS_BLUR__: (options: {
8
- submitEditing?: boolean;
9
- }) => Promise<void>;
10
- }
11
- }
12
- declare const WebHarnessUI: HarnessUIModule;
13
- export default WebHarnessUI;
14
- //# sourceMappingURL=HarnessUI.web.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HarnessUI.web.d.ts","sourceRoot":"","sources":["../src/HarnessUI.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEjE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,iCAAiC,EAAE,CACjC,MAAM,EAAE,QAAQ,GAAG,IAAI,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC5B,6BAA6B,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACvE,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/D,mBAAmB,EAAE,CAAC,OAAO,EAAE;YAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB;CACF;AAYD,QAAA,MAAM,YAAY,EAAE,eA4CnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,46 +0,0 @@
1
- const getElementViewInfo = (element) => {
2
- const rect = element.getBoundingClientRect();
3
- return {
4
- x: rect.left,
5
- y: rect.top,
6
- width: rect.width,
7
- height: rect.height,
8
- };
9
- };
10
- const WebHarnessUI = {
11
- simulatePress: async (x, y) => {
12
- await window.__RN_HARNESS_SIMULATE_PRESS__(x, y);
13
- },
14
- queryByTestId: (testId) => {
15
- const element = document.querySelector(`[data-testid="${testId}"]`);
16
- return element ? getElementViewInfo(element) : null;
17
- },
18
- queryAllByTestId: (testId) => {
19
- const elements = document.querySelectorAll(`[data-testid="${testId}"]`);
20
- return Array.from(elements).map(getElementViewInfo);
21
- },
22
- queryByAccessibilityLabel: (label) => {
23
- const element = document.querySelector(`[aria-label="${label}"]`);
24
- return element ? getElementViewInfo(element) : null;
25
- },
26
- queryAllByAccessibilityLabel: (label) => {
27
- const elements = document.querySelectorAll(`[aria-label="${label}"]`);
28
- return Array.from(elements).map(getElementViewInfo);
29
- },
30
- captureScreenshot: async (bounds) => {
31
- return await window.__RN_HARNESS_CAPTURE_SCREENSHOT__(bounds);
32
- },
33
- typeChar: async (character) => {
34
- await window.__RN_HARNESS_TYPE_CHAR__(character);
35
- },
36
- blur: async (options) => {
37
- // If there is a focused element, blur it directly in the DOM first
38
- // to trigger local events, then call the runner-side bridge.
39
- if (document.activeElement instanceof HTMLElement ||
40
- document.activeElement instanceof SVGElement) {
41
- document.activeElement.blur();
42
- }
43
- await window.__RN_HARNESS_BLUR__(options);
44
- },
45
- };
46
- export default WebHarnessUI;
@@ -1,22 +0,0 @@
1
- import { type TurboModule } from 'react-native';
2
- export interface ViewInfo {
3
- x: number;
4
- y: number;
5
- width: number;
6
- height: number;
7
- }
8
- interface Spec extends TurboModule {
9
- simulatePress(x: number, y: number): Promise<void>;
10
- queryByTestId(testId: string): ViewInfo | null;
11
- queryAllByTestId(testId: string): ViewInfo[];
12
- queryByAccessibilityLabel(label: string): ViewInfo | null;
13
- queryAllByAccessibilityLabel(label: string): ViewInfo[];
14
- captureScreenshot(bounds: ViewInfo | null): Promise<string | null>;
15
- typeChar(character: string): Promise<void>;
16
- blur(options: {
17
- submitEditing?: boolean;
18
- }): Promise<void>;
19
- }
20
- declare const _default: Spec;
21
- export default _default;
22
- //# sourceMappingURL=NativeHarness.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NativeHarness.d.ts","sourceRoot":"","sources":["../src/NativeHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAGrE,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,IAAK,SAAQ,WAAW;IAChC,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC7C,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC1D,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IACxD,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;;AAED,wBAAmE"}
@@ -1,2 +0,0 @@
1
- import { TurboModuleRegistry } from 'react-native';
2
- export default TurboModuleRegistry.getEnforcing('HarnessUI');
@@ -1,14 +0,0 @@
1
- import { type HarnessUIModule, type ViewInfo } from './types.js';
2
- declare global {
3
- interface Window {
4
- __RN_HARNESS_CAPTURE_SCREENSHOT__: (bounds: ViewInfo | null) => Promise<string | null>;
5
- __RN_HARNESS_SIMULATE_PRESS__: (x: number, y: number) => Promise<void>;
6
- __RN_HARNESS_TYPE_CHAR__: (character: string) => Promise<void>;
7
- __RN_HARNESS_BLUR__: (options: {
8
- submitEditing?: boolean;
9
- }) => Promise<void>;
10
- }
11
- }
12
- declare const WebHarnessUI: HarnessUIModule;
13
- export default WebHarnessUI;
14
- //# sourceMappingURL=WebHarness.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"WebHarness.d.ts","sourceRoot":"","sources":["../src/WebHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEjE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,iCAAiC,EAAE,CACjC,MAAM,EAAE,QAAQ,GAAG,IAAI,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC5B,6BAA6B,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACvE,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/D,mBAAmB,EAAE,CAAC,OAAO,EAAE;YAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB;CACF;AAYD,QAAA,MAAM,YAAY,EAAE,eAkDnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,53 +0,0 @@
1
- const getElementViewInfo = (element) => {
2
- const rect = element.getBoundingClientRect();
3
- return {
4
- x: rect.left,
5
- y: rect.top,
6
- width: rect.width,
7
- height: rect.height,
8
- };
9
- };
10
- const WebHarnessUI = {
11
- simulatePress: async (x, y) => {
12
- await window.__RN_HARNESS_SIMULATE_PRESS__(x, y);
13
- },
14
- queryByTestId: (testId) => {
15
- const element = document.querySelector(`[data-testid="${testId}"]`);
16
- return element ? getElementViewInfo(element) : null;
17
- },
18
- queryAllByTestId: (testId) => {
19
- const elements = document.querySelectorAll(`[data-testid="${testId}"]`);
20
- return Array.from(elements).map(getElementViewInfo);
21
- },
22
- queryByAccessibilityLabel: (label) => {
23
- const element = document.querySelector(`[aria-label="${label}"]`);
24
- return element ? getElementViewInfo(element) : null;
25
- },
26
- queryAllByAccessibilityLabel: (label) => {
27
- const elements = document.querySelectorAll(`[aria-label="${label}"]`);
28
- return Array.from(elements).map(getElementViewInfo);
29
- },
30
- captureScreenshot: async (bounds) => {
31
- return await window.__RN_HARNESS_CAPTURE_SCREENSHOT__(bounds);
32
- },
33
- typeChar: async (character) => {
34
- await window.__RN_HARNESS_TYPE_CHAR__(character);
35
- },
36
- blur: async (options) => {
37
- if (options.submitEditing) {
38
- // If we want to submit, we must NOT blur before pressing Enter.
39
- // We let the runner-side bridge handle both Enter and the subsequent blur.
40
- await window.__RN_HARNESS_BLUR__(options);
41
- }
42
- else {
43
- // If there is a focused element, blur it directly in the DOM first
44
- // to trigger local events, then call the runner-side bridge.
45
- if (document.activeElement instanceof HTMLElement ||
46
- document.activeElement instanceof SVGElement) {
47
- document.activeElement.blur();
48
- }
49
- await window.__RN_HARNESS_BLUR__(options);
50
- }
51
- },
52
- };
53
- export default WebHarnessUI;
@@ -1,17 +0,0 @@
1
- import { type TurboModule } from 'react-native';
2
- import { type ViewInfo } from '../types.js';
3
- interface Spec extends TurboModule {
4
- simulatePress(x: number, y: number): Promise<void>;
5
- queryByTestId(testId: string): ViewInfo | null;
6
- queryAllByTestId(testId: string): ViewInfo[];
7
- queryByAccessibilityLabel(label: string): ViewInfo | null;
8
- queryAllByAccessibilityLabel(label: string): ViewInfo[];
9
- captureScreenshot(bounds: ViewInfo | null): Promise<string | null>;
10
- typeChar(character: string): Promise<void>;
11
- blur(options: {
12
- submitEditing?: boolean;
13
- }): Promise<void>;
14
- }
15
- declare const _default: Spec;
16
- export default _default;
17
- //# sourceMappingURL=NativeHarness.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NativeHarness.d.ts","sourceRoot":"","sources":["../../src/harness/NativeHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,UAAU,IAAK,SAAQ,WAAW;IAChC,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC7C,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC1D,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IACxD,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;;AAED,wBAAmE"}
@@ -1,2 +0,0 @@
1
- import { TurboModuleRegistry } from 'react-native';
2
- export default TurboModuleRegistry.getEnforcing('HarnessUI');
@@ -1,14 +0,0 @@
1
- import { type HarnessUIModule, type ViewInfo } from '../types.js';
2
- declare global {
3
- interface Window {
4
- __RN_HARNESS_CAPTURE_SCREENSHOT__: (bounds: ViewInfo | null) => Promise<string | null>;
5
- __RN_HARNESS_SIMULATE_PRESS__: (x: number, y: number) => Promise<void>;
6
- __RN_HARNESS_TYPE_CHAR__: (character: string) => Promise<void>;
7
- __RN_HARNESS_BLUR__: (options: {
8
- submitEditing?: boolean;
9
- }) => Promise<void>;
10
- }
11
- }
12
- declare const WebHarnessUI: HarnessUIModule;
13
- export default WebHarnessUI;
14
- //# sourceMappingURL=WebHarness.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"WebHarness.d.ts","sourceRoot":"","sources":["../../src/harness/WebHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,iCAAiC,EAAE,CACjC,MAAM,EAAE,QAAQ,GAAG,IAAI,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC5B,6BAA6B,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACvE,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/D,mBAAmB,EAAE,CAAC,OAAO,EAAE;YAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB;CACF;AAYD,QAAA,MAAM,YAAY,EAAE,eAkDnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,53 +0,0 @@
1
- const getElementViewInfo = (element) => {
2
- const rect = element.getBoundingClientRect();
3
- return {
4
- x: rect.left,
5
- y: rect.top,
6
- width: rect.width,
7
- height: rect.height,
8
- };
9
- };
10
- const WebHarnessUI = {
11
- simulatePress: async (x, y) => {
12
- await window.__RN_HARNESS_SIMULATE_PRESS__(x, y);
13
- },
14
- queryByTestId: (testId) => {
15
- const element = document.querySelector(`[data-testid="${testId}"]`);
16
- return element ? getElementViewInfo(element) : null;
17
- },
18
- queryAllByTestId: (testId) => {
19
- const elements = document.querySelectorAll(`[data-testid="${testId}"]`);
20
- return Array.from(elements).map(getElementViewInfo);
21
- },
22
- queryByAccessibilityLabel: (label) => {
23
- const element = document.querySelector(`[aria-label="${label}"]`);
24
- return element ? getElementViewInfo(element) : null;
25
- },
26
- queryAllByAccessibilityLabel: (label) => {
27
- const elements = document.querySelectorAll(`[aria-label="${label}"]`);
28
- return Array.from(elements).map(getElementViewInfo);
29
- },
30
- captureScreenshot: async (bounds) => {
31
- return await window.__RN_HARNESS_CAPTURE_SCREENSHOT__(bounds);
32
- },
33
- typeChar: async (character) => {
34
- await window.__RN_HARNESS_TYPE_CHAR__(character);
35
- },
36
- blur: async (options) => {
37
- if (options.submitEditing) {
38
- // If we want to submit, we must NOT blur before pressing Enter.
39
- // We let the runner-side bridge handle both Enter and the subsequent blur.
40
- await window.__RN_HARNESS_BLUR__(options);
41
- }
42
- else {
43
- // If there is a focused element, blur it directly in the DOM first
44
- // to trigger local events, then call the runner-side bridge.
45
- if (document.activeElement instanceof HTMLElement ||
46
- document.activeElement instanceof SVGElement) {
47
- document.activeElement.blur();
48
- }
49
- await window.__RN_HARNESS_BLUR__(options);
50
- }
51
- },
52
- };
53
- export default WebHarnessUI;
@@ -1,4 +0,0 @@
1
- import { HarnessUIModule } from "../types.js";
2
- declare const _default: HarnessUIModule;
3
- export default _default;
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/harness/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;;AAU9C,wBAA8B"}
@@ -1,8 +0,0 @@
1
- import { Platform } from "react-native";
2
- const getHarnessUI = () => {
3
- if (Platform.OS === 'web') {
4
- return require('./WebHarness.js').default;
5
- }
6
- return require('./NativeHarness.js').default;
7
- };
8
- export default getHarnessUI();
@@ -1,17 +0,0 @@
1
- import { type TurboModule } from 'react-native';
2
- import { type ViewInfo } from '../types.js';
3
- interface Spec extends TurboModule {
4
- simulatePress(x: number, y: number): Promise<void>;
5
- queryByTestId(testId: string): ViewInfo | null;
6
- queryAllByTestId(testId: string): ViewInfo[];
7
- queryByAccessibilityLabel(label: string): ViewInfo | null;
8
- queryAllByAccessibilityLabel(label: string): ViewInfo[];
9
- captureScreenshot(bounds: ViewInfo | null): Promise<string | null>;
10
- typeChar(character: string): Promise<void>;
11
- blur(options: {
12
- submitEditing?: boolean;
13
- }): Promise<void>;
14
- }
15
- declare const _default: Spec;
16
- export default _default;
17
- //# sourceMappingURL=native-harness.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"native-harness.d.ts","sourceRoot":"","sources":["../../src/harness/native-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,UAAU,IAAK,SAAQ,WAAW;IAChC,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC7C,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC1D,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;IACxD,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;;AAED,wBAAmE"}
@@ -1,2 +0,0 @@
1
- import { TurboModuleRegistry } from 'react-native';
2
- export default TurboModuleRegistry.getEnforcing('HarnessUI');
@@ -1,14 +0,0 @@
1
- import { type HarnessUIModule, type ViewInfo } from '../types.js';
2
- declare global {
3
- interface Window {
4
- __RN_HARNESS_CAPTURE_SCREENSHOT__: (bounds: ViewInfo | null) => Promise<string | null>;
5
- __RN_HARNESS_SIMULATE_PRESS__: (x: number, y: number) => Promise<void>;
6
- __RN_HARNESS_TYPE_CHAR__: (character: string) => Promise<void>;
7
- __RN_HARNESS_BLUR__: (options: {
8
- submitEditing?: boolean;
9
- }) => Promise<void>;
10
- }
11
- }
12
- declare const WebHarnessUI: HarnessUIModule;
13
- export default WebHarnessUI;
14
- //# sourceMappingURL=web-harness.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"web-harness.d.ts","sourceRoot":"","sources":["../../src/harness/web-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,iCAAiC,EAAE,CACjC,MAAM,EAAE,QAAQ,GAAG,IAAI,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC5B,6BAA6B,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACvE,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/D,mBAAmB,EAAE,CAAC,OAAO,EAAE;YAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB;CACF;AAYD,QAAA,MAAM,YAAY,EAAE,eAkDnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1,53 +0,0 @@
1
- const getElementViewInfo = (element) => {
2
- const rect = element.getBoundingClientRect();
3
- return {
4
- x: rect.left,
5
- y: rect.top,
6
- width: rect.width,
7
- height: rect.height,
8
- };
9
- };
10
- const WebHarnessUI = {
11
- simulatePress: async (x, y) => {
12
- await window.__RN_HARNESS_SIMULATE_PRESS__(x, y);
13
- },
14
- queryByTestId: (testId) => {
15
- const element = document.querySelector(`[data-testid="${testId}"]`);
16
- return element ? getElementViewInfo(element) : null;
17
- },
18
- queryAllByTestId: (testId) => {
19
- const elements = document.querySelectorAll(`[data-testid="${testId}"]`);
20
- return Array.from(elements).map(getElementViewInfo);
21
- },
22
- queryByAccessibilityLabel: (label) => {
23
- const element = document.querySelector(`[aria-label="${label}"]`);
24
- return element ? getElementViewInfo(element) : null;
25
- },
26
- queryAllByAccessibilityLabel: (label) => {
27
- const elements = document.querySelectorAll(`[aria-label="${label}"]`);
28
- return Array.from(elements).map(getElementViewInfo);
29
- },
30
- captureScreenshot: async (bounds) => {
31
- return await window.__RN_HARNESS_CAPTURE_SCREENSHOT__(bounds);
32
- },
33
- typeChar: async (character) => {
34
- await window.__RN_HARNESS_TYPE_CHAR__(character);
35
- },
36
- blur: async (options) => {
37
- if (options.submitEditing) {
38
- // If we want to submit, we must NOT blur before pressing Enter.
39
- // We let the runner-side bridge handle both Enter and the subsequent blur.
40
- await window.__RN_HARNESS_BLUR__(options);
41
- }
42
- else {
43
- // If there is a focused element, blur it directly in the DOM first
44
- // to trigger local events, then call the runner-side bridge.
45
- if (document.activeElement instanceof HTMLElement ||
46
- document.activeElement instanceof SVGElement) {
47
- document.activeElement.blur();
48
- }
49
- await window.__RN_HARNESS_BLUR__(options);
50
- }
51
- },
52
- };
53
- export default WebHarnessUI;