@react-native-harness/runtime 1.1.0-rc.2 → 1.1.0-rc.3

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 (169) hide show
  1. package/dist/NativeHarness.d.ts +41 -0
  2. package/dist/NativeHarness.d.ts.map +1 -0
  3. package/dist/NativeHarness.js +2 -0
  4. package/dist/client/getWSServer.d.ts.map +1 -1
  5. package/dist/client/getWSServer.js +4 -5
  6. package/dist/globals.d.ts +0 -1
  7. package/dist/globals.d.ts.map +1 -1
  8. package/dist/render/queries.d.ts +7 -0
  9. package/dist/render/queries.d.ts.map +1 -0
  10. package/dist/render/queries.js +99 -0
  11. package/dist/runHarnessTestsInModule.d.ts +9 -0
  12. package/dist/runHarnessTestsInModule.d.ts.map +1 -0
  13. package/dist/runHarnessTestsInModule.js +57 -0
  14. package/dist/screen/index.d.ts +50 -0
  15. package/dist/screen/index.d.ts.map +1 -0
  16. package/dist/screen/index.js +46 -0
  17. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  18. package/dist/userEvent/index.d.ts +16 -0
  19. package/dist/userEvent/index.d.ts.map +1 -0
  20. package/dist/userEvent/index.js +31 -0
  21. package/dist/utils/hmr.d.ts +2 -0
  22. package/dist/utils/hmr.d.ts.map +1 -0
  23. package/dist/utils/hmr.js +3 -0
  24. package/dist/utils/parse-error-stack.d.ts +9 -0
  25. package/dist/utils/parse-error-stack.d.ts.map +1 -0
  26. package/dist/utils/parse-error-stack.js +56 -0
  27. package/out-tsc/vitest/src/__tests__/collector.test.d.ts +2 -0
  28. package/out-tsc/vitest/src/__tests__/collector.test.d.ts.map +1 -0
  29. package/out-tsc/vitest/src/__tests__/error-handling.test.d.ts +2 -0
  30. package/out-tsc/vitest/src/__tests__/error-handling.test.d.ts.map +1 -0
  31. package/out-tsc/vitest/src/__tests__/expect.test.d.ts +2 -0
  32. package/out-tsc/vitest/src/__tests__/expect.test.d.ts.map +1 -0
  33. package/out-tsc/vitest/src/__tests__/initialize.test.d.ts +2 -0
  34. package/out-tsc/vitest/src/__tests__/initialize.test.d.ts.map +1 -0
  35. package/out-tsc/vitest/src/__tests__/spy.test.d.ts +2 -0
  36. package/out-tsc/vitest/src/__tests__/spy.test.d.ts.map +1 -0
  37. package/out-tsc/vitest/src/bundler/bundle.d.ts +2 -0
  38. package/out-tsc/vitest/src/bundler/bundle.d.ts.map +1 -0
  39. package/out-tsc/vitest/src/bundler/errors.d.ts +15 -0
  40. package/out-tsc/vitest/src/bundler/errors.d.ts.map +1 -0
  41. package/out-tsc/vitest/src/bundler/evaluate.d.ts +2 -0
  42. package/out-tsc/vitest/src/bundler/evaluate.d.ts.map +1 -0
  43. package/out-tsc/vitest/src/bundler/factory.d.ts +3 -0
  44. package/out-tsc/vitest/src/bundler/factory.d.ts.map +1 -0
  45. package/out-tsc/vitest/src/bundler/index.d.ts +4 -0
  46. package/out-tsc/vitest/src/bundler/index.d.ts.map +1 -0
  47. package/out-tsc/vitest/src/bundler/types.d.ts +7 -0
  48. package/out-tsc/vitest/src/bundler/types.d.ts.map +1 -0
  49. package/out-tsc/vitest/src/client/factory.d.ts +2 -0
  50. package/out-tsc/vitest/src/client/factory.d.ts.map +1 -0
  51. package/out-tsc/vitest/src/client/getDeviceDescriptor.d.ts +8 -0
  52. package/out-tsc/vitest/src/client/getDeviceDescriptor.d.ts.map +1 -0
  53. package/out-tsc/vitest/src/client/getWSServer.d.ts +2 -0
  54. package/out-tsc/vitest/src/client/getWSServer.d.ts.map +1 -0
  55. package/out-tsc/vitest/src/client/index.d.ts +2 -0
  56. package/out-tsc/vitest/src/client/index.d.ts.map +1 -0
  57. package/out-tsc/vitest/src/client/setup-files.d.ts +12 -0
  58. package/out-tsc/vitest/src/client/setup-files.d.ts.map +1 -0
  59. package/out-tsc/vitest/src/client/store.d.ts +4 -0
  60. package/out-tsc/vitest/src/client/store.d.ts.map +1 -0
  61. package/out-tsc/vitest/src/collector/errors.d.ts +8 -0
  62. package/out-tsc/vitest/src/collector/errors.d.ts.map +1 -0
  63. package/out-tsc/vitest/src/collector/factory.d.ts +3 -0
  64. package/out-tsc/vitest/src/collector/factory.d.ts.map +1 -0
  65. package/out-tsc/vitest/src/collector/functions.d.ts +22 -0
  66. package/out-tsc/vitest/src/collector/functions.d.ts.map +1 -0
  67. package/out-tsc/vitest/src/collector/index.d.ts +5 -0
  68. package/out-tsc/vitest/src/collector/index.d.ts.map +1 -0
  69. package/out-tsc/vitest/src/collector/types.d.ts +10 -0
  70. package/out-tsc/vitest/src/collector/types.d.ts.map +1 -0
  71. package/out-tsc/vitest/src/collector/validation.d.ts +4 -0
  72. package/out-tsc/vitest/src/collector/validation.d.ts.map +1 -0
  73. package/out-tsc/vitest/src/constants.d.ts +2 -0
  74. package/out-tsc/vitest/src/constants.d.ts.map +1 -0
  75. package/out-tsc/vitest/src/disableHMRWhenReady.d.ts +2 -0
  76. package/out-tsc/vitest/src/disableHMRWhenReady.d.ts.map +1 -0
  77. package/out-tsc/vitest/src/entry-point.d.ts +2 -0
  78. package/out-tsc/vitest/src/entry-point.d.ts.map +1 -0
  79. package/out-tsc/vitest/src/errors.d.ts +6 -0
  80. package/out-tsc/vitest/src/errors.d.ts.map +1 -0
  81. package/out-tsc/vitest/src/expect/expect.d.ts +9 -0
  82. package/out-tsc/vitest/src/expect/expect.d.ts.map +1 -0
  83. package/out-tsc/vitest/src/expect/index.d.ts +2 -0
  84. package/out-tsc/vitest/src/expect/index.d.ts.map +1 -0
  85. package/out-tsc/vitest/src/expect/matchers/toMatchImageSnapshot.d.ts +13 -0
  86. package/out-tsc/vitest/src/expect/matchers/toMatchImageSnapshot.d.ts.map +1 -0
  87. package/out-tsc/vitest/src/expect/setup.d.ts +2 -0
  88. package/out-tsc/vitest/src/expect/setup.d.ts.map +1 -0
  89. package/out-tsc/vitest/src/filtering/index.d.ts +2 -0
  90. package/out-tsc/vitest/src/filtering/index.d.ts.map +1 -0
  91. package/out-tsc/vitest/src/filtering/testNameFilter.d.ts +12 -0
  92. package/out-tsc/vitest/src/filtering/testNameFilter.d.ts.map +1 -0
  93. package/out-tsc/vitest/src/globals.d.ts +19 -0
  94. package/out-tsc/vitest/src/globals.d.ts.map +1 -0
  95. package/out-tsc/vitest/src/index.d.ts +11 -0
  96. package/out-tsc/vitest/src/index.d.ts.map +1 -0
  97. package/out-tsc/vitest/src/initialize.d.ts +2 -0
  98. package/out-tsc/vitest/src/initialize.d.ts.map +1 -0
  99. package/out-tsc/vitest/src/jest-mock.d.ts +2 -0
  100. package/out-tsc/vitest/src/jest-mock.d.ts.map +1 -0
  101. package/out-tsc/vitest/src/jsx/jsx-dev-runtime.d.ts +3 -0
  102. package/out-tsc/vitest/src/jsx/jsx-dev-runtime.d.ts.map +1 -0
  103. package/out-tsc/vitest/src/jsx/jsx-runtime.d.ts +4 -0
  104. package/out-tsc/vitest/src/jsx/jsx-runtime.d.ts.map +1 -0
  105. package/out-tsc/vitest/src/mocker/index.d.ts +2 -0
  106. package/out-tsc/vitest/src/mocker/index.d.ts.map +1 -0
  107. package/out-tsc/vitest/src/mocker/registry.d.ts +6 -0
  108. package/out-tsc/vitest/src/mocker/registry.d.ts.map +1 -0
  109. package/out-tsc/vitest/src/mocker/types.d.ts +6 -0
  110. package/out-tsc/vitest/src/mocker/types.d.ts.map +1 -0
  111. package/out-tsc/vitest/src/namespace.d.ts +18 -0
  112. package/out-tsc/vitest/src/namespace.d.ts.map +1 -0
  113. package/out-tsc/vitest/src/polyfills.d.ts +11 -0
  114. package/out-tsc/vitest/src/polyfills.d.ts.map +1 -0
  115. package/out-tsc/vitest/src/render/ErrorBoundary.d.ts +17 -0
  116. package/out-tsc/vitest/src/render/ErrorBoundary.d.ts.map +1 -0
  117. package/out-tsc/vitest/src/render/TestComponentOverlay.d.ts +3 -0
  118. package/out-tsc/vitest/src/render/TestComponentOverlay.d.ts.map +1 -0
  119. package/out-tsc/vitest/src/render/cleanup.d.ts +2 -0
  120. package/out-tsc/vitest/src/render/cleanup.d.ts.map +1 -0
  121. package/out-tsc/vitest/src/render/index.d.ts +6 -0
  122. package/out-tsc/vitest/src/render/index.d.ts.map +1 -0
  123. package/out-tsc/vitest/src/render/setup.d.ts +2 -0
  124. package/out-tsc/vitest/src/render/setup.d.ts.map +1 -0
  125. package/out-tsc/vitest/src/render/types.d.ts +12 -0
  126. package/out-tsc/vitest/src/render/types.d.ts.map +1 -0
  127. package/out-tsc/vitest/src/runner/context.d.ts +10 -0
  128. package/out-tsc/vitest/src/runner/context.d.ts.map +1 -0
  129. package/out-tsc/vitest/src/runner/errors.d.ts +11 -0
  130. package/out-tsc/vitest/src/runner/errors.d.ts.map +1 -0
  131. package/out-tsc/vitest/src/runner/factory.d.ts +3 -0
  132. package/out-tsc/vitest/src/runner/factory.d.ts.map +1 -0
  133. package/out-tsc/vitest/src/runner/hooks.d.ts +4 -0
  134. package/out-tsc/vitest/src/runner/hooks.d.ts.map +1 -0
  135. package/out-tsc/vitest/src/runner/index.d.ts +5 -0
  136. package/out-tsc/vitest/src/runner/index.d.ts.map +1 -0
  137. package/out-tsc/vitest/src/runner/runSuite.d.ts +7 -0
  138. package/out-tsc/vitest/src/runner/runSuite.d.ts.map +1 -0
  139. package/out-tsc/vitest/src/runner/types.d.ts +18 -0
  140. package/out-tsc/vitest/src/runner/types.d.ts.map +1 -0
  141. package/out-tsc/vitest/src/screen/index.d.ts +8 -0
  142. package/out-tsc/vitest/src/screen/index.d.ts.map +1 -0
  143. package/out-tsc/vitest/src/spy/index.d.ts +2 -0
  144. package/out-tsc/vitest/src/spy/index.d.ts.map +1 -0
  145. package/out-tsc/vitest/src/symbolicate.d.ts +17 -0
  146. package/out-tsc/vitest/src/symbolicate.d.ts.map +1 -0
  147. package/out-tsc/vitest/src/ui/ReadyScreen.d.ts +2 -0
  148. package/out-tsc/vitest/src/ui/ReadyScreen.d.ts.map +1 -0
  149. package/out-tsc/vitest/src/ui/WrongEnvironmentScreen.d.ts +2 -0
  150. package/out-tsc/vitest/src/ui/WrongEnvironmentScreen.d.ts.map +1 -0
  151. package/out-tsc/vitest/src/ui/index.d.ts +2 -0
  152. package/out-tsc/vitest/src/ui/index.d.ts.map +1 -0
  153. package/out-tsc/vitest/src/ui/state.d.ts +20 -0
  154. package/out-tsc/vitest/src/ui/state.d.ts.map +1 -0
  155. package/out-tsc/vitest/src/userEvent/index.d.ts +6 -0
  156. package/out-tsc/vitest/src/userEvent/index.d.ts.map +1 -0
  157. package/out-tsc/vitest/src/utils/dev-server.d.ts +2 -0
  158. package/out-tsc/vitest/src/utils/dev-server.d.ts.map +1 -0
  159. package/out-tsc/vitest/src/utils/emitter.d.ts +16 -0
  160. package/out-tsc/vitest/src/utils/emitter.d.ts.map +1 -0
  161. package/out-tsc/vitest/src/waitFor.d.ts +21 -0
  162. package/out-tsc/vitest/src/waitFor.d.ts.map +1 -0
  163. package/out-tsc/vitest/tsconfig.spec.tsbuildinfo +1 -0
  164. package/out-tsc/vitest/vite.config.d.ts +3 -0
  165. package/out-tsc/vitest/vite.config.d.ts.map +1 -0
  166. package/package.json +2 -2
  167. package/src/client/getWSServer.ts +4 -5
  168. package/src/globals.ts +0 -1
  169. package/src/constants.ts +0 -1
@@ -0,0 +1,41 @@
1
+ import { type TurboModule } from 'react-native';
2
+ /**
3
+ * Represents the position and dimensions of a view in screen coordinates (points/dp).
4
+ */
5
+ export interface ViewInfo {
6
+ x: number;
7
+ y: number;
8
+ width: number;
9
+ height: number;
10
+ }
11
+ interface Spec extends TurboModule {
12
+ /**
13
+ * Simulates a native tap at the specified screen coordinates.
14
+ * Returns a promise that resolves when the tap action is complete.
15
+ */
16
+ simulateTap(x: number, y: number): Promise<void>;
17
+ /**
18
+ * Finds a view by its testID (accessibilityIdentifier on iOS, tag on Android).
19
+ * Returns null if no view is found.
20
+ */
21
+ queryByTestId(testId: string): ViewInfo | null;
22
+ /**
23
+ * Finds all views by testID (accessibilityIdentifier on iOS, tag on Android).
24
+ * Returns an empty array if no views are found.
25
+ */
26
+ queryAllByTestId(testId: string): ViewInfo[];
27
+ /**
28
+ * Finds a view by its accessibility label.
29
+ * Returns null if no view is found.
30
+ */
31
+ queryByAccessibilityLabel(label: string): ViewInfo | null;
32
+ /**
33
+ * Finds all views by accessibility label.
34
+ * Returns an empty array if no views are found.
35
+ */
36
+ queryAllByAccessibilityLabel(label: string): ViewInfo[];
37
+ }
38
+ export type HarnessModule = Spec;
39
+ declare const _default: Spec;
40
+ export default _default;
41
+ //# sourceMappingURL=NativeHarness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeHarness.d.ts","sourceRoot":"","sources":["../src/NativeHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE;;GAEG;AACH,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;;;OAGG;IACH,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;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;CACzD;AAED,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC;;AAEjC,wBAAiE"}
@@ -0,0 +1,2 @@
1
+ import { TurboModuleRegistry } from 'react-native';
2
+ export default TurboModuleRegistry.getEnforcing('Harness');
@@ -1 +1 @@
1
- {"version":3,"file":"getWSServer.d.ts","sourceRoot":"","sources":["../../src/client/getWSServer.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,QAAO,MAM9B,CAAC"}
1
+ {"version":3,"file":"getWSServer.d.ts","sourceRoot":"","sources":["../../src/client/getWSServer.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,QAAO,MAK9B,CAAC"}
@@ -1,8 +1,7 @@
1
+ import { HARNESS_BRIDGE_PATH } from '@react-native-harness/bridge';
1
2
  import { getDevServerUrl } from '../utils/dev-server.js';
2
- import { WS_SERVER_PORT } from '../constants.js';
3
3
  export const getWSServer = () => {
4
- const devServerUrl = getDevServerUrl();
5
- const hostname = devServerUrl.split('://')[1].split(':')[0];
6
- const port = global.RN_HARNESS?.webSocketPort || WS_SERVER_PORT;
7
- return `ws://${hostname}:${port}`;
4
+ const devServerUrl = new URL(getDevServerUrl());
5
+ const protocol = devServerUrl.protocol === 'https:' ? 'wss:' : 'ws:';
6
+ return `${protocol}//${devServerUrl.host}${HARNESS_BRIDGE_PATH}`;
8
7
  };
package/dist/globals.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import type { ImageSnapshotOptions } from '@react-native-harness/bridge';
2
2
  export type HarnessGlobal = {
3
3
  appRegistryComponentName: string;
4
- webSocketPort?: number;
5
4
  disableViewFlattening?: boolean;
6
5
  };
7
6
  declare global {
@@ -1 +1 @@
1
- {"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../src/globals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,MAAM,aAAa,GAAG;IAC1B,wBAAwB,EAAE,MAAM,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,UAAU,EAAE,aAAa,GAAG,SAAS,CAAC;CAC3C;AAED,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,QAAQ;QAChB;;;WAGG;QACH,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACpE;CACF;AAED,eAAO,MAAM,gBAAgB,QAAO,aAQnC,CAAC"}
1
+ {"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../src/globals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,MAAM,aAAa,GAAG;IAC1B,wBAAwB,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,UAAU,EAAE,aAAa,GAAG,SAAS,CAAC;CAC3C;AAED,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,QAAQ;QAChB;;;WAGG;QACH,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACpE;CACF;AAED,eAAO,MAAM,gBAAgB,QAAO,aAQnC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { HostInstance } from 'react-native';
2
+ export declare const setRoot: (rootInstance: HostInstance) => void;
3
+ declare const queryByTestId: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default | null, queryAllByTestId: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default[], getByTestId: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default | null, getAllByTestId: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default[], findByTestId: (params: string) => Promise<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default>, findAllByTestId: (params: string) => Promise<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default[]>;
4
+ declare const queryById: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default | null, queryAllById: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default[], getId: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default | null, getAllById: (params: string) => import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default[], findById: (params: string) => Promise<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default>, findAllById: (params: string) => Promise<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default[]>;
5
+ export { queryByTestId, queryAllByTestId, getByTestId, getAllByTestId, findByTestId, findAllByTestId, };
6
+ export { queryById, queryAllById, getId, getAllById, findById, findAllById };
7
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/render/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAM5C,eAAO,MAAM,OAAO,GAAI,cAAc,YAAY,SAEjD,CAAC;AA6IF,QAAA,MACW,aAAa,8HACV,gBAAgB,yHACrB,WAAW,8HACR,cAAc,yHAChB,YAAY,gIACT,eAAe,gIAG3B,CAAC;AACF,QAAA,MACW,SAAS,8HACN,YAAY,yHACjB,KAAK,8HACF,UAAU,yHACZ,QAAQ,gIACL,WAAW,gIAC+B,CAAC;AAExD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,eAAe,GAChB,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,99 @@
1
+ // import { store } from '../ui/state.js';
2
+ import { waitUntil } from '../waitFor.js';
3
+ let root = null;
4
+ export const setRoot = (rootInstance) => {
5
+ root = rootInstance;
6
+ };
7
+ const getRoot = () => {
8
+ const container = root;
9
+ if (!container) {
10
+ throw new Error('You need to render a component first!');
11
+ }
12
+ const ownerDocument = container.ownerDocument;
13
+ if (!ownerDocument) {
14
+ throw new Error('This feature is supported in React Native 0.82 and later!');
15
+ }
16
+ return ownerDocument.getRootNode();
17
+ };
18
+ const findNodeByPredicate = (predicate) => {
19
+ const queue = [getRoot()];
20
+ while (queue.length > 0) {
21
+ const node = queue.shift();
22
+ if (predicate(node)) {
23
+ return node;
24
+ }
25
+ for (const child of node.children) {
26
+ queue.push(child);
27
+ }
28
+ }
29
+ return null;
30
+ };
31
+ const findNodesByPredicate = (predicate) => {
32
+ const nodes = [];
33
+ const queue = [getRoot()];
34
+ while (queue.length > 0) {
35
+ const node = queue.shift();
36
+ if (predicate(node)) {
37
+ nodes.push(node);
38
+ }
39
+ for (const child of node.children) {
40
+ queue.push(child);
41
+ }
42
+ }
43
+ return nodes;
44
+ };
45
+ const getFiberOfHostInstance = (hostInstance) => {
46
+ // This should be considered as 'reaching into the implementation details' of React Native.
47
+ // Not perfect, but it's the only way to get the props of the host instance.
48
+ return (hostInstance
49
+ .__internalInstanceHandle || null);
50
+ };
51
+ const getPropsOfHostInstance = (hostInstance) => {
52
+ return getFiberOfHostInstance(hostInstance)?.memoizedProps || {};
53
+ };
54
+ const findBy = (predicate, options) => {
55
+ return waitUntil(() => findNodeByPredicate(predicate), options);
56
+ };
57
+ const findAllBy = (predicate, options) => {
58
+ return waitUntil(() => {
59
+ const nodes = findNodesByPredicate(predicate);
60
+ if (nodes.length === 0) {
61
+ return null;
62
+ }
63
+ return nodes;
64
+ }, options);
65
+ };
66
+ const queryBy = (predicate) => {
67
+ return findNodeByPredicate(predicate);
68
+ };
69
+ const queryAllBy = (predicate) => {
70
+ return findNodesByPredicate(predicate);
71
+ };
72
+ const getBy = (predicate) => {
73
+ const node = queryBy(predicate);
74
+ if (!node) {
75
+ throw new Error(`No node found with predicate ${predicate}`);
76
+ }
77
+ return node;
78
+ };
79
+ const getAllBy = (predicate) => {
80
+ const nodes = queryAllBy(predicate);
81
+ if (nodes.length === 0) {
82
+ throw new Error(`No nodes found with predicate ${predicate}`);
83
+ }
84
+ return nodes;
85
+ };
86
+ const createQueries = (predicate) => {
87
+ return {
88
+ findBy: (params) => findBy((node) => predicate(node, params)),
89
+ findAllBy: (params) => findAllBy((node) => predicate(node, params)),
90
+ queryBy: (params) => queryBy((node) => predicate(node, params)),
91
+ queryAllBy: (params) => queryAllBy((node) => predicate(node, params)),
92
+ getBy: (params) => getBy((node) => predicate(node, params)),
93
+ getAllBy: (params) => getAllBy((node) => predicate(node, params)),
94
+ };
95
+ };
96
+ const { queryBy: queryByTestId, queryAllBy: queryAllByTestId, getBy: getByTestId, getAllBy: getAllByTestId, findBy: findByTestId, findAllBy: findAllByTestId, } = createQueries((node, testId) => getPropsOfHostInstance(node).testID === testId);
97
+ const { queryBy: queryById, queryAllBy: queryAllById, getBy: getId, getAllBy: getAllById, findBy: findById, findAllBy: findAllById, } = createQueries((node, id) => node.id === id);
98
+ export { queryByTestId, queryAllByTestId, getByTestId, getAllByTestId, findByTestId, findAllByTestId, };
99
+ export { queryById, queryAllById, getId, getAllById, findById, findAllById };
@@ -0,0 +1,9 @@
1
+ import type { TestSuiteResult } from '@react-native-harness/bridge';
2
+ /**
3
+ * Runs tests from a specific module programmatically and returns the results.
4
+ *
5
+ * @param moduleId The require.resolveWeak call to the module, returning the module ID
6
+ * @returns The result of the test suite execution
7
+ */
8
+ export declare const runHarnessTestsInModule: (loader: () => unknown) => Promise<TestSuiteResult>;
9
+ //# sourceMappingURL=runHarnessTestsInModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runHarnessTestsInModule.d.ts","sourceRoot":"","sources":["../src/runHarnessTestsInModule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,8BAA8B,CAAC;AAoCtC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,OAAO,KACpB,OAAO,CAAC,eAAe,CAuBzB,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { collectTests } from './collector/functions.js';
2
+ import { runSuite } from './runner/runSuite.js';
3
+ import { getEmitter } from './utils/emitter.js';
4
+ const metroRequire = global.__r;
5
+ /**
6
+ * Patches the require function to clear the module cache for the first module that's going to be required after patching.
7
+ * @returns A function to unpatch the require function.
8
+ */
9
+ const patchRequire = () => {
10
+ let wasRootModuleRequired = false;
11
+ global.__r = (moduleId) => {
12
+ if (!wasRootModuleRequired) {
13
+ // The first module that's going to be required after patching will be the module with tests.
14
+ // We need to clear the module cache for this module, so it ends up re-evaluated.
15
+ const module = metroRequire.getModules().get(moduleId);
16
+ if (module) {
17
+ module.hasError = false;
18
+ module.error = undefined;
19
+ module.isInitialized = false;
20
+ }
21
+ }
22
+ wasRootModuleRequired = true;
23
+ return metroRequire(moduleId);
24
+ };
25
+ return () => {
26
+ global.__r = metroRequire;
27
+ };
28
+ };
29
+ /**
30
+ * Runs tests from a specific module programmatically and returns the results.
31
+ *
32
+ * @param moduleId The require.resolveWeak call to the module, returning the module ID
33
+ * @returns The result of the test suite execution
34
+ */
35
+ export const runHarnessTestsInModule = async (loader) => {
36
+ // 1. Collect tests by executing the loader
37
+ // This expects the loader to call describe/it/test functions which register to the global collector
38
+ const { testSuite } = await collectTests(async () => {
39
+ const unpatchRequire = patchRequire();
40
+ try {
41
+ await loader();
42
+ }
43
+ finally {
44
+ unpatchRequire();
45
+ }
46
+ });
47
+ // 2. Prepare the runner context
48
+ // We use a local emitter as we are not reporting to the CLI bridge,
49
+ // but the runner internals expect an emitter.
50
+ const events = getEmitter();
51
+ const context = {
52
+ events,
53
+ testFilePath: 'unknown',
54
+ };
55
+ // 3. Run the collected suite
56
+ return runSuite(testSuite, context);
57
+ };
@@ -0,0 +1,50 @@
1
+ import { type ViewInfo } from '../NativeHarness.js';
2
+ /**
3
+ * Represents an element found on screen with its position and dimensions.
4
+ * This can be used with userEvent.tap() to interact with the element.
5
+ */
6
+ export type ElementReference = ViewInfo;
7
+ export type Screen = {
8
+ /**
9
+ * Finds an element by its testID (accessibilityIdentifier on iOS, tag on Android).
10
+ * @throws Error if no element is found with the given testID.
11
+ */
12
+ findByTestId: (testId: string) => ElementReference;
13
+ /**
14
+ * Finds all elements by testID (accessibilityIdentifier on iOS, tag on Android).
15
+ * @throws Error if no elements are found with the given testID.
16
+ */
17
+ findAllByTestId: (testId: string) => ElementReference[];
18
+ /**
19
+ * Queries for an element by its testID without throwing.
20
+ * Returns null if no element is found.
21
+ */
22
+ queryByTestId: (testId: string) => ElementReference | null;
23
+ /**
24
+ * Queries for all elements by testID without throwing.
25
+ * Returns an empty array if no elements are found.
26
+ */
27
+ queryAllByTestId: (testId: string) => ElementReference[];
28
+ /**
29
+ * Finds an element by its accessibility label.
30
+ * @throws Error if no element is found with the given label.
31
+ */
32
+ findByAccessibilityLabel: (label: string) => ElementReference;
33
+ /**
34
+ * Finds all elements by accessibility label.
35
+ * @throws Error if no elements are found with the given label.
36
+ */
37
+ findAllByAccessibilityLabel: (label: string) => ElementReference[];
38
+ /**
39
+ * Queries for an element by its accessibility label without throwing.
40
+ * Returns null if no element is found.
41
+ */
42
+ queryByAccessibilityLabel: (label: string) => ElementReference | null;
43
+ /**
44
+ * Queries for all elements by accessibility label without throwing.
45
+ * Returns an empty array if no elements are found.
46
+ */
47
+ queryAllByAccessibilityLabel: (label: string) => ElementReference[];
48
+ };
49
+ export declare const screen: Screen;
50
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/screen/index.ts"],"names":[],"mappings":"AAAA,OAAsB,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAExC,MAAM,MAAM,MAAM,GAAG;IACnB;;;OAGG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,gBAAgB,CAAC;IAEnD;;;OAGG;IACH,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;IAExD;;;OAGG;IACH,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAC;IAE3D;;;OAGG;IACH,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;IAEzD;;;OAGG;IACH,wBAAwB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,gBAAgB,CAAC;IAE9D;;;OAGG;IACH,2BAA2B,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;IAEnE;;;OAGG;IACH,yBAAyB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAC;IAEtE;;;OAGG;IACH,4BAA4B,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;CACrE,CAAC;AA0DF,eAAO,MAAM,MAAM,QAAiB,CAAC"}
@@ -0,0 +1,46 @@
1
+ import NativeHarness from '../NativeHarness.js';
2
+ const createScreen = () => {
3
+ return {
4
+ findByTestId: (testId) => {
5
+ const result = NativeHarness.queryByTestId(testId);
6
+ if (!result) {
7
+ throw new Error(`Unable to find element with testID: ${testId}`);
8
+ }
9
+ return result;
10
+ },
11
+ findAllByTestId: (testId) => {
12
+ const results = NativeHarness.queryAllByTestId(testId);
13
+ if (results.length === 0) {
14
+ throw new Error(`Unable to find any elements with testID: ${testId}`);
15
+ }
16
+ return results;
17
+ },
18
+ queryByTestId: (testId) => {
19
+ return NativeHarness.queryByTestId(testId);
20
+ },
21
+ queryAllByTestId: (testId) => {
22
+ return NativeHarness.queryAllByTestId(testId);
23
+ },
24
+ findByAccessibilityLabel: (label) => {
25
+ const result = NativeHarness.queryByAccessibilityLabel(label);
26
+ if (!result) {
27
+ throw new Error(`Unable to find element with accessibility label: ${label}`);
28
+ }
29
+ return result;
30
+ },
31
+ findAllByAccessibilityLabel: (label) => {
32
+ const results = NativeHarness.queryAllByAccessibilityLabel(label);
33
+ if (results.length === 0) {
34
+ throw new Error(`Unable to find any elements with accessibility label: ${label}`);
35
+ }
36
+ return results;
37
+ },
38
+ queryByAccessibilityLabel: (label) => {
39
+ return NativeHarness.queryByAccessibilityLabel(label);
40
+ },
41
+ queryAllByAccessibilityLabel: (label) => {
42
+ return NativeHarness.queryAllByAccessibilityLabel(label);
43
+ },
44
+ };
45
+ };
46
+ export const screen = createScreen();