@@ -108,8 +108,10 @@ describe("Screen.", () => {
108
108
it ( "should reject with insufficient confidence." , async ( ) => {
109
109
110
110
// GIVEN
111
- const matchResult = new MatchResult ( 0.8 , searchRegion ) ;
112
- const findMatchMock = jest . fn ( ( ) => Promise . resolve ( matchResult ) ) ;
111
+ const minConfidence = 0.95 ;
112
+ const failingConfidence = 0.8 ;
113
+ const expectedReason = `No match with required confidence ${ minConfidence } . Best match: ${ failingConfidence } ` ;
114
+ const findMatchMock = jest . fn ( ( ) => Promise . reject ( expectedReason ) ) ;
113
115
providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
114
116
findMatch : findMatchMock
115
117
} ) ) ;
@@ -119,12 +121,12 @@ describe("Screen.", () => {
119
121
const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , id ) ;
120
122
121
123
// WHEN
122
- const resultRegion = SUT . find ( needle ) ;
124
+ const resultRegion = SUT . find ( needle , { confidence : minConfidence } ) ;
123
125
124
126
// THEN
125
127
await expect ( resultRegion )
126
128
. rejects
127
- . toEqual ( `No match for ${ id } . Required: ${ SUT . config . confidence } , given: ${ matchResult . confidence } ` ) ;
129
+ . toEqual ( `Searching for ${ id } failed. Reason: ' ${ expectedReason } ' ` ) ;
128
130
} ) ;
129
131
130
132
it ( "should reject when search fails." , async ( ) => {
@@ -327,6 +329,254 @@ describe("Screen.", () => {
327
329
} )
328
330
} ) ;
329
331
332
+ describe ( "findAll" , ( ) => {
333
+ it ( "should call registered hook before resolve" , async ( ) => {
334
+ // GIVEN
335
+ const matchResult = new MatchResult ( 0.99 , searchRegion ) ;
336
+ const matchResults = [ matchResult , matchResult , matchResult ] ;
337
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( matchResults ) ) ;
338
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
339
+ findMatches : findMatchesMock
340
+ } ) ) ;
341
+
342
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
343
+ const testCallback = jest . fn ( ( ) => Promise . resolve ( ) ) ;
344
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , "needle_image" ) ;
345
+ SUT . on ( needle , testCallback ) ;
346
+
347
+ // WHEN
348
+ await SUT . findAll ( needle ) ;
349
+
350
+ // THEN
351
+ expect ( testCallback ) . toBeCalledTimes ( matchResults . length ) ;
352
+ expect ( testCallback ) . toBeCalledWith ( matchResult ) ;
353
+ } ) ;
354
+
355
+ it ( "should call multiple registered hooks before resolve" , async ( ) => {
356
+ // GIVEN
357
+ const matchResult = new MatchResult ( 0.99 , searchRegion ) ;
358
+ const matchResults = [ matchResult , matchResult , matchResult ] ;
359
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( matchResults ) ) ;
360
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
361
+ findMatches : findMatchesMock
362
+ } ) ) ;
363
+
364
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
365
+ const testCallback = jest . fn ( ( ) => Promise . resolve ( ) ) ;
366
+ const secondCallback = jest . fn ( ( ) => Promise . resolve ( ) ) ;
367
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , "needle_image" ) ;
368
+ SUT . on ( needle , testCallback ) ;
369
+ SUT . on ( needle , secondCallback ) ;
370
+
371
+ // WHEN
372
+ await SUT . findAll ( needle ) ;
373
+
374
+ // THEN
375
+ for ( const callback of [ testCallback , secondCallback ] ) {
376
+ expect ( callback ) . toBeCalledTimes ( matchResults . length ) ;
377
+ expect ( callback ) . toBeCalledWith ( matchResult ) ;
378
+ }
379
+ } ) ;
380
+
381
+ it ( "should reject when search fails." , async ( ) => {
382
+
383
+ // GIVEN
384
+ const rejectionReason = "Search failed." ;
385
+ const findMatchesMock = jest . fn ( ( ) => Promise . reject ( rejectionReason ) ) ;
386
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
387
+ findMatches : findMatchesMock
388
+ } ) ) ;
389
+
390
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
391
+ const id = "needle_image" ;
392
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , id ) ;
393
+
394
+ // WHEN
395
+ const resultRegion = SUT . findAll ( needle ) ;
396
+
397
+ // THEN
398
+ await expect ( resultRegion )
399
+ . rejects
400
+ . toEqual ( `Searching for ${ id } failed. Reason: '${ rejectionReason } '` ) ;
401
+ } ) ;
402
+
403
+ it ( "should override default confidence value with parameter." , async ( ) => {
404
+ // GIVEN
405
+ const minMatch = 0.8 ;
406
+ const matchResult = new MatchResult ( minMatch , searchRegion ) ;
407
+
408
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( [ matchResult ] ) ) ;
409
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
410
+ findMatches : findMatchesMock
411
+ } ) ) ;
412
+
413
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
414
+
415
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , "needle_image" ) ;
416
+ const parameters = new LocationParameters ( undefined , minMatch ) ;
417
+
418
+ // WHEN
419
+ const [ resultRegion ] = await SUT . findAll ( needle , parameters ) ;
420
+
421
+ // THEN
422
+ expect ( resultRegion ) . toEqual ( matchResult . location ) ;
423
+ const matchRequest = new MatchRequest (
424
+ expect . any ( Image ) ,
425
+ needle ,
426
+ minMatch ,
427
+ true ) ;
428
+ expect ( findMatchesMock ) . toHaveBeenCalledWith ( matchRequest ) ;
429
+ } ) ;
430
+
431
+ it ( "should override default search region with parameter." , async ( ) => {
432
+ // GIVEN
433
+ const customSearchRegion = new Region ( 10 , 10 , 90 , 90 ) ;
434
+ const matchResult = new MatchResult ( 0.99 , searchRegion ) ;
435
+
436
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( [ matchResult ] ) ) ;
437
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
438
+ findMatches : findMatchesMock
439
+ } ) ) ;
440
+
441
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
442
+
443
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , "needle_image" ) ;
444
+ const parameters = new LocationParameters ( customSearchRegion ) ;
445
+ const expectedMatchRequest = new MatchRequest (
446
+ expect . any ( Image ) ,
447
+ needle ,
448
+ SUT . config . confidence ,
449
+ true ) ;
450
+
451
+ // WHEN
452
+ await SUT . findAll ( needle , parameters ) ;
453
+
454
+ // THEN
455
+ expect ( findMatchesMock ) . toHaveBeenCalledWith ( expectedMatchRequest ) ;
456
+ } ) ;
457
+
458
+ it ( "should override searchMultipleScales with parameter." , async ( ) => {
459
+ // GIVEN
460
+ const matchResult = new MatchResult ( 0.99 , searchRegion ) ;
461
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( [ matchResult ] ) ) ;
462
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
463
+ findMatches : findMatchesMock
464
+ } ) ) ;
465
+
466
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
467
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , "needle_image" ) ;
468
+
469
+ const parameters = new LocationParameters ( searchRegion , undefined , false ) ;
470
+ const expectedMatchRequest = new MatchRequest (
471
+ expect . any ( Image ) ,
472
+ needle ,
473
+ SUT . config . confidence ,
474
+ false ) ;
475
+
476
+ // WHEN
477
+ await SUT . findAll ( needle , parameters ) ;
478
+
479
+ // THEN
480
+ expect ( findMatchesMock ) . toHaveBeenCalledWith ( expectedMatchRequest ) ;
481
+ } ) ;
482
+
483
+ it ( "should override both confidence and search region with parameter." , async ( ) => {
484
+ // GIVEN
485
+ const minMatch = 0.8 ;
486
+ const customSearchRegion = new Region ( 10 , 10 , 90 , 90 ) ;
487
+ const matchResult = new MatchResult ( minMatch , searchRegion ) ;
488
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( [ matchResult ] ) ) ;
489
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
490
+ findMatches : findMatchesMock
491
+ } ) ) ;
492
+
493
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
494
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , "needle_image" ) ;
495
+ const parameters = new LocationParameters ( customSearchRegion , minMatch ) ;
496
+ const expectedMatchRequest = new MatchRequest (
497
+ expect . any ( Image ) ,
498
+ needle ,
499
+ minMatch ,
500
+ true ) ;
501
+
502
+ // WHEN
503
+ await SUT . findAll ( needle , parameters ) ;
504
+
505
+ // THEN
506
+ expect ( findMatchesMock ) . toHaveBeenCalledWith ( expectedMatchRequest ) ;
507
+ } ) ;
508
+
509
+ it ( "should add search region offset to result image location" , async ( ) => {
510
+ // GIVEN
511
+ const limitedSearchRegion = new Region ( 100 , 200 , 300 , 400 ) ;
512
+ const resultRegion = new Region ( 50 , 100 , 150 , 200 ) ;
513
+ const matchResult = new MatchResult ( 0.99 , resultRegion ) ;
514
+
515
+ const expectedMatchRegion = new Region (
516
+ limitedSearchRegion . left + resultRegion . left ,
517
+ limitedSearchRegion . top + resultRegion . top ,
518
+ resultRegion . width ,
519
+ resultRegion . height ) ;
520
+
521
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( [ matchResult ] ) ) ;
522
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
523
+ findMatches : findMatchesMock
524
+ } ) ) ;
525
+
526
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
527
+ // WHEN
528
+ const [ matchRegion ] = await SUT . findAll (
529
+ new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , "needle_image" ) ,
530
+ {
531
+ searchRegion : limitedSearchRegion
532
+ }
533
+ ) ;
534
+
535
+ // THEN
536
+ expect ( matchRegion ) . toEqual ( expectedMatchRegion ) ;
537
+ } )
538
+
539
+ it . each ( [
540
+ [ "with negative x coordinate" , new Region ( - 1 , 0 , 100 , 100 ) ] ,
541
+ [ "with negative y coordinate" , new Region ( 0 , - 1 , 100 , 100 ) ] ,
542
+ [ "with negative width" , new Region ( 0 , 0 , - 100 , 100 ) ] ,
543
+ [ "with negative height" , new Region ( 0 , 0 , 100 , - 100 ) ] ,
544
+ [ "with region outside screen on x axis" , new Region ( 1100 , 0 , 100 , 100 ) ] ,
545
+ [ "with region outside screen on y axis" , new Region ( 0 , 1100 , 100 , 100 ) ] ,
546
+ [ "with region bigger than screen on x axis" , new Region ( 0 , 0 , 1100 , 100 ) ] ,
547
+ [ "with region bigger than screen on y axis" , new Region ( 0 , 0 , 1000 , 1100 ) ] ,
548
+ [ "with region of 1 px width" , new Region ( 0 , 0 , 1 , 1100 ) ] ,
549
+ [ "with region of 1 px height" , new Region ( 0 , 0 , 100 , 1 ) ] ,
550
+ [ "with region leaving screen on x axis" , new Region ( 600 , 0 , 500 , 100 ) ] ,
551
+ [ "with region leaving screen on y axis" , new Region ( 0 , 500 , 100 , 600 ) ] ,
552
+ [ "with NaN x coordinate" , new Region ( "a" as unknown as number , 0 , 100 , 100 ) ] ,
553
+ [ "with NaN y coordinate" , new Region ( 0 , "a" as unknown as number , 100 , 600 ) ] ,
554
+ [ "with NaN on width" , new Region ( 0 , 0 , "a" as unknown as number , 100 ) ] ,
555
+ [ "with NaN on height" , new Region ( 0 , 0 , 100 , "a" as unknown as number ) ] ,
556
+ ] ) ( "should reject search regions %s" , async ( _ , region ) => {
557
+ // GIVEN
558
+ const id = "needle_image" ;
559
+ const needle = new Image ( 100 , 100 , Buffer . from ( [ ] ) , 3 , id ) ;
560
+ const matchResult = new MatchResult ( 0.99 , region ) ;
561
+ const findMatchesMock = jest . fn ( ( ) => Promise . resolve ( [ matchResult ] ) ) ;
562
+ providerRegistryMock . getImageFinder = jest . fn ( ( ) => mockPartial < ImageFinderInterface > ( {
563
+ findMatches : findMatchesMock
564
+ } ) ) ;
565
+
566
+ const SUT = new ScreenClass ( providerRegistryMock ) ;
567
+
568
+ // WHEN
569
+ const findPromise = SUT . findAll (
570
+ needle ,
571
+ {
572
+ searchRegion : region
573
+ } ) ;
574
+
575
+ // THEN
576
+ await expect ( findPromise ) . rejects . toContain ( `Searching for ${ id } failed. Reason:` ) ;
577
+ } )
578
+ } ) ;
579
+
330
580
it ( "should return region to highlight for chaining" , async ( ) => {
331
581
// GIVEN
332
582
const highlightRegion = new Region ( 10 , 20 , 30 , 40 ) ;
0 commit comments