1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2023 The Android Open Source Project 2*6dbdd20aSAndroid Build Coastguard Worker// 3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*6dbdd20aSAndroid Build Coastguard Worker// 7*6dbdd20aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*6dbdd20aSAndroid Build Coastguard Worker// 9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License. 14*6dbdd20aSAndroid Build Coastguard Worker 15*6dbdd20aSAndroid Build Coastguard Workerimport {FuzzyFinder, fuzzyMatch} from './fuzzy'; 16*6dbdd20aSAndroid Build Coastguard Worker 17*6dbdd20aSAndroid Build Coastguard Workerdescribe('FuzzyFinder', () => { 18*6dbdd20aSAndroid Build Coastguard Worker const items = ['aaa', 'aba', 'zzz', 'c z d z e', 'CAPS', 'ababc']; 19*6dbdd20aSAndroid Build Coastguard Worker const finder = new FuzzyFinder(items, (x) => x); 20*6dbdd20aSAndroid Build Coastguard Worker 21*6dbdd20aSAndroid Build Coastguard Worker it('finds all for empty search term', () => { 22*6dbdd20aSAndroid Build Coastguard Worker const result = finder.find(''); 23*6dbdd20aSAndroid Build Coastguard Worker // Expect all results are returned in original order. 24*6dbdd20aSAndroid Build Coastguard Worker expect(result).toEqual([ 25*6dbdd20aSAndroid Build Coastguard Worker {item: 'aaa', segments: [{matching: false, value: 'aaa'}]}, 26*6dbdd20aSAndroid Build Coastguard Worker {item: 'aba', segments: [{matching: false, value: 'aba'}]}, 27*6dbdd20aSAndroid Build Coastguard Worker {item: 'zzz', segments: [{matching: false, value: 'zzz'}]}, 28*6dbdd20aSAndroid Build Coastguard Worker {item: 'c z d z e', segments: [{matching: false, value: 'c z d z e'}]}, 29*6dbdd20aSAndroid Build Coastguard Worker {item: 'CAPS', segments: [{matching: false, value: 'CAPS'}]}, 30*6dbdd20aSAndroid Build Coastguard Worker {item: 'ababc', segments: [{matching: false, value: 'ababc'}]}, 31*6dbdd20aSAndroid Build Coastguard Worker ]); 32*6dbdd20aSAndroid Build Coastguard Worker }); 33*6dbdd20aSAndroid Build Coastguard Worker 34*6dbdd20aSAndroid Build Coastguard Worker it('finds exact match', () => { 35*6dbdd20aSAndroid Build Coastguard Worker const result = finder.find('aaa'); 36*6dbdd20aSAndroid Build Coastguard Worker expect(result).toEqual( 37*6dbdd20aSAndroid Build Coastguard Worker expect.arrayContaining([ 38*6dbdd20aSAndroid Build Coastguard Worker {item: 'aaa', segments: [{matching: true, value: 'aaa'}]}, 39*6dbdd20aSAndroid Build Coastguard Worker ]), 40*6dbdd20aSAndroid Build Coastguard Worker ); 41*6dbdd20aSAndroid Build Coastguard Worker }); 42*6dbdd20aSAndroid Build Coastguard Worker 43*6dbdd20aSAndroid Build Coastguard Worker it('finds approx matches', () => { 44*6dbdd20aSAndroid Build Coastguard Worker const result = finder.find('aa'); 45*6dbdd20aSAndroid Build Coastguard Worker // Allow finding results in any order. 46*6dbdd20aSAndroid Build Coastguard Worker expect(result).toEqual( 47*6dbdd20aSAndroid Build Coastguard Worker expect.arrayContaining([ 48*6dbdd20aSAndroid Build Coastguard Worker { 49*6dbdd20aSAndroid Build Coastguard Worker item: 'aaa', 50*6dbdd20aSAndroid Build Coastguard Worker // Either |aa|a or a|aa| is valid. 51*6dbdd20aSAndroid Build Coastguard Worker segments: expect.arrayContaining([ 52*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'aa'}, 53*6dbdd20aSAndroid Build Coastguard Worker {matching: false, value: 'a'}, 54*6dbdd20aSAndroid Build Coastguard Worker ]), 55*6dbdd20aSAndroid Build Coastguard Worker }, 56*6dbdd20aSAndroid Build Coastguard Worker { 57*6dbdd20aSAndroid Build Coastguard Worker item: 'aba', 58*6dbdd20aSAndroid Build Coastguard Worker segments: [ 59*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'a'}, 60*6dbdd20aSAndroid Build Coastguard Worker {matching: false, value: 'b'}, 61*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'a'}, 62*6dbdd20aSAndroid Build Coastguard Worker ], 63*6dbdd20aSAndroid Build Coastguard Worker }, 64*6dbdd20aSAndroid Build Coastguard Worker ]), 65*6dbdd20aSAndroid Build Coastguard Worker ); 66*6dbdd20aSAndroid Build Coastguard Worker }); 67*6dbdd20aSAndroid Build Coastguard Worker 68*6dbdd20aSAndroid Build Coastguard Worker it('does not find completely unrelated items', () => { 69*6dbdd20aSAndroid Build Coastguard Worker // |zzz| looks nothing like |aa| and should not be returned. 70*6dbdd20aSAndroid Build Coastguard Worker const result = finder.find('aa'); 71*6dbdd20aSAndroid Build Coastguard Worker expect(result).not.toEqual( 72*6dbdd20aSAndroid Build Coastguard Worker expect.arrayContaining([expect.objectContaining({item: 'zzz'})]), 73*6dbdd20aSAndroid Build Coastguard Worker ); 74*6dbdd20aSAndroid Build Coastguard Worker }); 75*6dbdd20aSAndroid Build Coastguard Worker 76*6dbdd20aSAndroid Build Coastguard Worker it('finds non-consecutive matches', () => { 77*6dbdd20aSAndroid Build Coastguard Worker const result = finder.find('cde'); 78*6dbdd20aSAndroid Build Coastguard Worker expect(result).toEqual( 79*6dbdd20aSAndroid Build Coastguard Worker expect.arrayContaining([ 80*6dbdd20aSAndroid Build Coastguard Worker { 81*6dbdd20aSAndroid Build Coastguard Worker item: 'c z d z e', 82*6dbdd20aSAndroid Build Coastguard Worker segments: [ 83*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'c'}, 84*6dbdd20aSAndroid Build Coastguard Worker {matching: false, value: ' z '}, 85*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'd'}, 86*6dbdd20aSAndroid Build Coastguard Worker {matching: false, value: ' z '}, 87*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'e'}, 88*6dbdd20aSAndroid Build Coastguard Worker ], 89*6dbdd20aSAndroid Build Coastguard Worker }, 90*6dbdd20aSAndroid Build Coastguard Worker ]), 91*6dbdd20aSAndroid Build Coastguard Worker ); 92*6dbdd20aSAndroid Build Coastguard Worker }); 93*6dbdd20aSAndroid Build Coastguard Worker 94*6dbdd20aSAndroid Build Coastguard Worker it('finds caps match when search term is in lower case', () => { 95*6dbdd20aSAndroid Build Coastguard Worker const result = finder.find('caps'); 96*6dbdd20aSAndroid Build Coastguard Worker expect(result).toEqual( 97*6dbdd20aSAndroid Build Coastguard Worker expect.arrayContaining([ 98*6dbdd20aSAndroid Build Coastguard Worker {item: 'CAPS', segments: [{matching: true, value: 'CAPS'}]}, 99*6dbdd20aSAndroid Build Coastguard Worker ]), 100*6dbdd20aSAndroid Build Coastguard Worker ); 101*6dbdd20aSAndroid Build Coastguard Worker }); 102*6dbdd20aSAndroid Build Coastguard Worker 103*6dbdd20aSAndroid Build Coastguard Worker it('finds match with false start', () => { 104*6dbdd20aSAndroid Build Coastguard Worker const result = finder.find('abc'); 105*6dbdd20aSAndroid Build Coastguard Worker expect(result).toEqual( 106*6dbdd20aSAndroid Build Coastguard Worker expect.arrayContaining([ 107*6dbdd20aSAndroid Build Coastguard Worker { 108*6dbdd20aSAndroid Build Coastguard Worker item: 'ababc', 109*6dbdd20aSAndroid Build Coastguard Worker segments: [ 110*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'ab'}, 111*6dbdd20aSAndroid Build Coastguard Worker {matching: false, value: 'ab'}, 112*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'c'}, 113*6dbdd20aSAndroid Build Coastguard Worker ], 114*6dbdd20aSAndroid Build Coastguard Worker }, 115*6dbdd20aSAndroid Build Coastguard Worker ]), 116*6dbdd20aSAndroid Build Coastguard Worker ); 117*6dbdd20aSAndroid Build Coastguard Worker }); 118*6dbdd20aSAndroid Build Coastguard Worker}); 119*6dbdd20aSAndroid Build Coastguard Worker 120*6dbdd20aSAndroid Build Coastguard Workertest('fuzzyMatch', () => { 121*6dbdd20aSAndroid Build Coastguard Worker expect(fuzzyMatch('foo bar baz', 'foo')).toEqual({ 122*6dbdd20aSAndroid Build Coastguard Worker matches: true, 123*6dbdd20aSAndroid Build Coastguard Worker segments: [ 124*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'foo'}, 125*6dbdd20aSAndroid Build Coastguard Worker {matching: false, value: ' bar baz'}, 126*6dbdd20aSAndroid Build Coastguard Worker ], 127*6dbdd20aSAndroid Build Coastguard Worker }); 128*6dbdd20aSAndroid Build Coastguard Worker 129*6dbdd20aSAndroid Build Coastguard Worker expect(fuzzyMatch('foo bar baz', 'qux')).toEqual({ 130*6dbdd20aSAndroid Build Coastguard Worker matches: false, 131*6dbdd20aSAndroid Build Coastguard Worker segments: [], 132*6dbdd20aSAndroid Build Coastguard Worker }); 133*6dbdd20aSAndroid Build Coastguard Worker 134*6dbdd20aSAndroid Build Coastguard Worker expect(fuzzyMatch('bar baz', 'foo', 'bar')).toEqual({ 135*6dbdd20aSAndroid Build Coastguard Worker matches: true, 136*6dbdd20aSAndroid Build Coastguard Worker segments: [ 137*6dbdd20aSAndroid Build Coastguard Worker {matching: true, value: 'bar'}, 138*6dbdd20aSAndroid Build Coastguard Worker {matching: false, value: ' baz'}, 139*6dbdd20aSAndroid Build Coastguard Worker ], 140*6dbdd20aSAndroid Build Coastguard Worker }); 141*6dbdd20aSAndroid Build Coastguard Worker}); 142