1- import { describe , expect , it , vi } from "vitest" ;
2- import { getDescription } from "../description" ;
1+ import { beforeEach , describe , expect , it , vi } from "vitest" ;
2+ import {
3+ getDescription ,
4+ getGrabSelectionTitle ,
5+ GRAB_HOST_LIKE_COMPONENT_NAMES ,
6+ isHostLikeComponentName ,
7+ } from "../description" ;
38import { composeGrabContextValue , ReactNativeGrabInternalContext } from "../grab-context" ;
9+ import type { RenderedByFrame } from "../get-rendered-by" ;
410import type { ReactNativeFiberNode } from "../types" ;
511
612vi . mock ( "../get-rendered-by" , ( ) => ( {
713 getRenderedBy : vi . fn ( async ( ) => [ ] ) ,
814} ) ) ;
915
16+ import { getRenderedBy } from "../get-rendered-by" ;
17+
18+ const mockedGetRenderedBy = vi . mocked ( getRenderedBy ) ;
19+
1020const createHostFiber = (
1121 props : Record < string , unknown > ,
1222 parent : ReactNativeFiberNode | null = null ,
@@ -31,6 +41,88 @@ const createContextProviderFiber = (
3141 _debugOwner : null ,
3242} ) ;
3343
44+ const frame = ( name : string ) : RenderedByFrame => ( {
45+ name,
46+ file : null ,
47+ line : null ,
48+ column : null ,
49+ collapse : false ,
50+ } ) ;
51+
52+ describe ( "isHostLikeComponentName" , ( ) => {
53+ it ( "treats View and Text as host-like" , ( ) => {
54+ for ( const name of GRAB_HOST_LIKE_COMPONENT_NAMES ) {
55+ expect ( isHostLikeComponentName ( name ) ) . toBe ( true ) ;
56+ }
57+ expect ( isHostLikeComponentName ( "InstallTabs" ) ) . toBe ( false ) ;
58+ } ) ;
59+
60+ it ( "trims names before matching" , ( ) => {
61+ expect ( isHostLikeComponentName ( " Text " ) ) . toBe ( true ) ;
62+ } ) ;
63+ } ) ;
64+
65+ describe ( "getGrabSelectionTitle" , ( ) => {
66+ it ( "skips host-like owners to show Text (in InstallTabs)" , ( ) => {
67+ const fiber = createHostFiber ( { children : "x" } ) ;
68+ expect ( getGrabSelectionTitle ( fiber , [ frame ( "Text" ) , frame ( "InstallTabs" ) ] ) ) . toBe (
69+ "Text (in InstallTabs)" ,
70+ ) ;
71+ } ) ;
72+
73+ it ( "skips multiple host-like owners" , ( ) => {
74+ const viewFiber : ReactNativeFiberNode = {
75+ type : "View" ,
76+ memoizedProps : { } ,
77+ return : null ,
78+ stateNode : null ,
79+ _debugStack : new Error ( ) ,
80+ _debugOwner : null ,
81+ } ;
82+ expect ( getGrabSelectionTitle ( viewFiber , [ frame ( "View" ) , frame ( "Text" ) , frame ( "Screen" ) ] ) ) . toBe (
83+ "View (in Screen)" ,
84+ ) ;
85+ } ) ;
86+
87+ it ( "returns host only when every owner is host-like" , ( ) => {
88+ const viewFiber : ReactNativeFiberNode = {
89+ type : "View" ,
90+ memoizedProps : { } ,
91+ return : null ,
92+ stateNode : null ,
93+ _debugStack : new Error ( ) ,
94+ _debugOwner : null ,
95+ } ;
96+ expect ( getGrabSelectionTitle ( viewFiber , [ frame ( "View" ) , frame ( "Text" ) ] ) ) . toBe ( "View" ) ;
97+ } ) ;
98+
99+ it ( "returns Selected element when host is unknown" , ( ) => {
100+ const fiber = {
101+ type : ( ) => null ,
102+ memoizedProps : { } ,
103+ return : null ,
104+ stateNode : null ,
105+ _debugStack : new Error ( ) ,
106+ _debugOwner : null ,
107+ } as ReactNativeFiberNode ;
108+ expect ( getGrabSelectionTitle ( fiber , [ ] ) ) . toBe ( "Selected element" ) ;
109+ } ) ;
110+
111+ it ( "uses host-like name from renderedBy when the fiber has no string host" , ( ) => {
112+ const fiber = {
113+ type : ( ) => null ,
114+ memoizedProps : { } ,
115+ return : null ,
116+ stateNode : null ,
117+ _debugStack : new Error ( ) ,
118+ _debugOwner : null ,
119+ } as ReactNativeFiberNode ;
120+ expect ( getGrabSelectionTitle ( fiber , [ frame ( "Text" ) , frame ( "InstallTabs" ) ] ) ) . toBe (
121+ "Text (in InstallTabs)" ,
122+ ) ;
123+ } ) ;
124+ } ) ;
125+
34126describe ( "composeGrabContextValue" , ( ) => {
35127 it ( "returns shallow copy when parent context does not exist" , ( ) => {
36128 const result = composeGrabContextValue ( null , { screen : "home" , attempt : 1 } ) ;
@@ -54,6 +146,11 @@ describe("composeGrabContextValue", () => {
54146} ) ;
55147
56148describe ( "getDescription with grab context" , ( ) => {
149+ beforeEach ( ( ) => {
150+ mockedGetRenderedBy . mockReset ( ) ;
151+ mockedGetRenderedBy . mockResolvedValue ( [ ] ) ;
152+ } ) ;
153+
57154 it ( "keeps current output format when no context provider is in ancestors" , async ( ) => {
58155 const selectedFiber = createHostFiber ( { children : "Hello" } ) ;
59156
@@ -64,6 +161,16 @@ describe("getDescription with grab context", () => {
64161 expect ( description ) . not . toContain ( "Context:" ) ;
65162 } ) ;
66163
164+ it ( "uses first non-host-like renderedBy name for the preview tag" , async ( ) => {
165+ mockedGetRenderedBy . mockResolvedValue ( [ frame ( "Text" ) , frame ( "InstallTabs" ) ] ) ;
166+ const selectedFiber = createHostFiber ( { children : "Hello" } ) ;
167+
168+ const description = await getDescription ( selectedFiber ) ;
169+
170+ expect ( description . startsWith ( "<InstallTabs" ) ) . toBe ( true ) ;
171+ expect ( description ) . toContain ( "Hello" ) ;
172+ } ) ;
173+
67174 it ( "appends Context block from nearest provider value" , async ( ) => {
68175 const parentProvider = createContextProviderFiber ( { screen : "home" , locale : "en" } ) ;
69176 const childProvider = createContextProviderFiber (
0 commit comments