xref: /aosp_15_r20/external/perfetto/ui/src/base/fuzzy_unittest.ts (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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