1
1
// @flow
2
2
import * as React from 'react' ;
3
- import { View , Text , TouchableOpacity , Image } from 'react-native' ;
4
- import { render } from '..' ;
3
+ import {
4
+ View ,
5
+ Text ,
6
+ TouchableOpacity ,
7
+ Image ,
8
+ Button ,
9
+ TextInput ,
10
+ } from 'react-native' ;
11
+ import { render , getDefaultNormalizer } from '..' ;
5
12
6
13
const MyButton = ( { children, onPress } ) => (
7
14
< TouchableOpacity onPress = { onPress } >
@@ -88,8 +95,8 @@ test('getAllByText, queryAllByText', () => {
88
95
test ( 'findByText queries work asynchronously' , async ( ) => {
89
96
const options = { timeout : 10 } ; // Short timeout so that this test runs quickly
90
97
const { rerender, findByText, findAllByText } = render ( < View /> ) ;
91
- await expect ( findByText ( 'Some Text' , options ) ) . rejects . toBeTruthy ( ) ;
92
- await expect ( findAllByText ( 'Some Text' , options ) ) . rejects . toBeTruthy ( ) ;
98
+ await expect ( findByText ( 'Some Text' , { } , options ) ) . rejects . toBeTruthy ( ) ;
99
+ await expect ( findAllByText ( 'Some Text' , { } , options ) ) . rejects . toBeTruthy ( ) ;
93
100
94
101
setTimeout (
95
102
( ) =>
@@ -105,6 +112,39 @@ test('findByText queries work asynchronously', async () => {
105
112
await expect ( findAllByText ( 'Some Text' ) ) . resolves . toHaveLength ( 1 ) ;
106
113
} , 20000 ) ;
107
114
115
+ describe ( 'findBy options deprecations' , ( ) => {
116
+ let warnSpy ;
117
+ beforeEach ( ( ) => {
118
+ warnSpy = jest . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
119
+ } ) ;
120
+ afterEach ( ( ) => {
121
+ warnSpy . mockRestore ( ) ;
122
+ } ) ;
123
+
124
+ test ( 'findByText queries warn on deprecated use of WaitForOptions' , async ( ) => {
125
+ const options = { timeout : 10 } ;
126
+ // mock implementation to avoid warning in the test suite
127
+ const { rerender, findByText } = render ( < View /> ) ;
128
+ await expect ( findByText ( 'Some Text' , options ) ) . rejects . toBeTruthy ( ) ;
129
+
130
+ setTimeout (
131
+ ( ) =>
132
+ rerender (
133
+ < View >
134
+ < Text > Some Text</ Text >
135
+ </ View >
136
+ ) ,
137
+ 20
138
+ ) ;
139
+
140
+ await expect ( findByText ( 'Some Text' ) ) . resolves . toBeTruthy ( ) ;
141
+
142
+ expect ( warnSpy ) . toHaveBeenCalledWith (
143
+ expect . stringContaining ( 'Use of option "timeout"' )
144
+ ) ;
145
+ } , 20000 ) ;
146
+ } ) ;
147
+
108
148
test . skip ( 'getByText works properly with custom text component' , ( ) => {
109
149
function BoldText ( { children } ) {
110
150
return < Text > { children } </ Text > ;
@@ -181,7 +221,7 @@ test('queryByText not found', () => {
181
221
) . toBeFalsy ( ) ;
182
222
} ) ;
183
223
184
- test ( 'queryByText nested text across multiple <Text> in <Text>' , ( ) => {
224
+ test ( 'queryByText does not match nested text across multiple <Text> in <Text>' , ( ) => {
185
225
const { queryByText } = render (
186
226
< Text nativeID = "1" >
187
227
Hello{ ' ' }
@@ -192,7 +232,7 @@ test('queryByText nested text across multiple <Text> in <Text>', () => {
192
232
</ Text >
193
233
) ;
194
234
195
- expect ( queryByText ( 'Hello World!' ) ?. props . nativeID ) . toBe ( '1' ) ;
235
+ expect ( queryByText ( 'Hello World!' ) ) . toBe ( null ) ;
196
236
} ) ;
197
237
198
238
test ( 'queryByText with nested Text components return the closest Text' , ( ) => {
@@ -204,7 +244,7 @@ test('queryByText with nested Text components return the closest Text', () => {
204
244
205
245
const { queryByText } = render ( < NestedTexts /> ) ;
206
246
207
- expect ( queryByText ( 'My text' ) ?. props . nativeID ) . toBe ( '2' ) ;
247
+ expect ( queryByText ( 'My text' , { exact : false } ) ?. props . nativeID ) . toBe ( '2' ) ;
208
248
} ) ;
209
249
210
250
test ( 'queryByText with nested Text components each with text return the lowest one' , ( ) => {
@@ -217,33 +257,182 @@ test('queryByText with nested Text components each with text return the lowest o
217
257
218
258
const { queryByText } = render ( < NestedTexts /> ) ;
219
259
220
- expect ( queryByText ( 'My text' ) ?. props . nativeID ) . toBe ( '2' ) ;
260
+ expect ( queryByText ( 'My text' , { exact : false } ) ?. props . nativeID ) . toBe ( '2' ) ;
221
261
} ) ;
222
262
223
- test ( 'queryByText nested <CustomText> in <Text>' , ( ) => {
263
+ test ( 'queryByText nested deep <CustomText> in <Text>' , ( ) => {
224
264
const CustomText = ( { children } ) => {
225
265
return < Text > { children } </ Text > ;
226
266
} ;
227
267
228
268
expect (
229
269
render (
230
270
< Text >
231
- Hello < CustomText > World!</ CustomText >
271
+ < CustomText > Hello</ CustomText > < CustomText > World!</ CustomText >
232
272
</ Text >
233
273
) . queryByText ( 'Hello World!' )
234
- ) . toBeTruthy ( ) ;
274
+ ) . toBe ( null ) ;
235
275
} ) ;
236
276
237
- test ( 'queryByText nested deep <CustomText> in <Text>' , ( ) => {
238
- const CustomText = ( { children } ) => {
239
- return < Text > { children } </ Text > ;
240
- } ;
277
+ test ( 'queryByText with nested Text components: not-exact text match returns the most deeply nested common component' , ( ) => {
278
+ const { queryByText : queryByTextFirstCase } = render (
279
+ < Text nativeID = "1" >
280
+ bob
281
+ < Text nativeID = "2" > My </ Text >
282
+ < Text nativeID = "3" > text</ Text >
283
+ </ Text >
284
+ ) ;
285
+
286
+ const { queryByText : queryByTextSecondCase } = render (
287
+ < Text nativeID = "1" >
288
+ bob
289
+ < Text nativeID = "2" > My text for test</ Text >
290
+ </ Text >
291
+ ) ;
241
292
293
+ expect ( queryByTextFirstCase ( 'My text' ) ) . toBe ( null ) ;
242
294
expect (
243
- render (
244
- < Text >
245
- < CustomText > Hello</ CustomText > < CustomText > World!</ CustomText >
246
- </ Text >
247
- ) . queryByText ( 'Hello World!' )
248
- ) . toBeTruthy ( ) ;
295
+ queryByTextSecondCase ( 'My text' , { exact : false } ) ?. props . nativeID
296
+ ) . toBe ( '2' ) ;
297
+ } ) ;
298
+
299
+ test ( 'queryAllByText does not match several times the same text' , ( ) => {
300
+ const allMatched = render (
301
+ < Text nativeID = "1" >
302
+ Start
303
+ < Text nativeID = "2" > This is a long text</ Text >
304
+ </ Text >
305
+ ) . queryAllByText ( 'long text' , { exact : false } ) ;
306
+ expect ( allMatched . length ) . toBe ( 1 ) ;
307
+ expect ( allMatched [ 0 ] . props . nativeID ) . toBe ( '2' ) ;
308
+ } ) ;
309
+
310
+ test ( 'queryAllByText matches all the matching nodes' , ( ) => {
311
+ const allMatched = render (
312
+ < Text nativeID = "1" >
313
+ Start
314
+ < Text nativeID = "2" > This is a long text</ Text >
315
+ < Text nativeID = "3" > This is another long text</ Text >
316
+ </ Text >
317
+ ) . queryAllByText ( 'long text' , { exact : false } ) ;
318
+ expect ( allMatched . length ) . toBe ( 2 ) ;
319
+ expect ( allMatched . map ( ( node ) => node . props . nativeID ) ) . toEqual ( [ '2' , '3' ] ) ;
320
+ } ) ;
321
+
322
+ describe ( 'supports TextMatch options' , ( ) => {
323
+ test ( 'getByText, getAllByText' , ( ) => {
324
+ const { getByText, getAllByText } = render (
325
+ < View >
326
+ < Text testID = "text" > Text and details</ Text >
327
+ < Button
328
+ testID = "button"
329
+ title = "Button and a detail"
330
+ onPress = { jest . fn ( ) }
331
+ />
332
+ </ View >
333
+ ) ;
334
+
335
+ expect ( getByText ( 'details' , { exact : false } ) ) . toBeTruthy ( ) ;
336
+ expect ( getAllByText ( 'detail' , { exact : false } ) ) . toHaveLength ( 2 ) ;
337
+ } ) ;
338
+
339
+ test ( 'getByPlaceholderText, getAllByPlaceholderText' , ( ) => {
340
+ const { getByPlaceholderText, getAllByPlaceholderText } = render (
341
+ < View >
342
+ < TextInput placeholder = { 'Placeholder with details' } />
343
+ < TextInput placeholder = { 'Placeholder with a DETAIL' } />
344
+ </ View >
345
+ ) ;
346
+
347
+ expect ( getByPlaceholderText ( 'details' , { exact : false } ) ) . toBeTruthy ( ) ;
348
+ expect ( getAllByPlaceholderText ( 'detail' , { exact : false } ) ) . toHaveLength ( 2 ) ;
349
+ } ) ;
350
+
351
+ test ( 'getByDisplayValue, getAllByDisplayValue' , ( ) => {
352
+ const { getByDisplayValue, getAllByDisplayValue } = render (
353
+ < View >
354
+ < TextInput value = { 'Value with details' } />
355
+ < TextInput value = { 'Value with a detail' } />
356
+ </ View >
357
+ ) ;
358
+
359
+ expect ( getByDisplayValue ( 'details' , { exact : false } ) ) . toBeTruthy ( ) ;
360
+ expect ( getAllByDisplayValue ( 'detail' , { exact : false } ) ) . toHaveLength ( 2 ) ;
361
+ } ) ;
362
+
363
+ test ( 'getByTestId, getAllByTestId' , ( ) => {
364
+ const { getByTestId, getAllByTestId } = render (
365
+ < View >
366
+ < View testID = "test" />
367
+ < View testID = "tests id" />
368
+ </ View >
369
+ ) ;
370
+ expect ( getByTestId ( 'id' , { exact : false } ) ) . toBeTruthy ( ) ;
371
+ expect ( getAllByTestId ( 'test' , { exact : false } ) ) . toHaveLength ( 2 ) ;
372
+ } ) ;
373
+
374
+ test ( 'with TextMatch option exact === false text search is NOT case sensitive' , ( ) => {
375
+ const { getByText, getAllByText } = render (
376
+ < View >
377
+ < Text testID = "text" > Text and details</ Text >
378
+ < Button
379
+ testID = "button"
380
+ title = "Button and a DeTAil"
381
+ onPress = { jest . fn ( ) }
382
+ />
383
+ </ View >
384
+ ) ;
385
+
386
+ expect ( getByText ( 'DeTaIlS' , { exact : false } ) ) . toBeTruthy ( ) ;
387
+ expect ( getAllByText ( 'detail' , { exact : false } ) ) . toHaveLength ( 2 ) ;
388
+ } ) ;
389
+ } ) ;
390
+
391
+ describe ( 'Supports normalization' , ( ) => {
392
+ test ( 'trims and collapses whitespace by default' , ( ) => {
393
+ const { getByText } = render (
394
+ < View >
395
+ < Text > { ` Text and
396
+
397
+
398
+ whitespace` } </ Text >
399
+ </ View >
400
+ ) ;
401
+
402
+ expect ( getByText ( 'Text and whitespace' ) ) . toBeTruthy ( ) ;
403
+ } ) ;
404
+
405
+ test ( 'trim and collapseWhitespace is customizable by getDefaultNormalizer param' , ( ) => {
406
+ const testTextWithWhitespace = ` Text and
407
+
408
+
409
+ whitespace` ;
410
+ const { getByText } = render (
411
+ < View >
412
+ < Text > { testTextWithWhitespace } </ Text >
413
+ </ View >
414
+ ) ;
415
+
416
+ expect (
417
+ getByText ( testTextWithWhitespace , {
418
+ normalizer : getDefaultNormalizer ( {
419
+ trim : false ,
420
+ collapseWhitespace : false ,
421
+ } ) ,
422
+ } )
423
+ ) . toBeTruthy ( ) ;
424
+ } ) ;
425
+
426
+ test ( 'normalizer function is customisable' , ( ) => {
427
+ const testText = 'A TO REMOVE text' ;
428
+ const normalizerFn = ( textToNormalize ) =>
429
+ textToNormalize . replace ( 'TO REMOVE ' , '' ) ;
430
+ const { getByText } = render (
431
+ < View >
432
+ < Text > { testText } </ Text >
433
+ </ View >
434
+ ) ;
435
+
436
+ expect ( getByText ( 'A text' , { normalizer : normalizerFn } ) ) . toBeTruthy ( ) ;
437
+ } ) ;
249
438
} ) ;
0 commit comments