Skip to content

Commit ab4501c

Browse files
committed
Fix #131: match issue ids exactly, not as substrings
1 parent d652b41 commit ab4501c

3 files changed

Lines changed: 41 additions & 3 deletions

File tree

ui2/src/components/AppSidebar.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {Collapsible, CollapsibleContent, CollapsibleTrigger,} from "@/components
1212
import {Popover, PopoverContent, PopoverTrigger,} from "@/components/ui/popover"
1313
import {Kbd, KbdGroup} from "@/components/ui/kbd"
1414
import {useConfig} from "@/contexts/ConfigContext"
15+
import {matchesAnyIssue} from "@/util/issueMatch"
1516

1617
interface StateCounts {
1718
passed: number;
@@ -215,7 +216,7 @@ export function AppSidebar({indices, searchQuery, onSearchChange, onSelect, sele
215216

216217
// Class issues...
217218
const classMatchesIssue = requiredIssues.length === 0 ||
218-
nodeIssues.some(ni => requiredIssues.some(ri => ni.includes(ri.toLowerCase())));
219+
matchesAnyIssue(nodeIssues, requiredIssues);
219220

220221
// If we have state/issue filters, we MUST filter children
221222
if (node.children && (requiredStates.length > 0 || requiredIssues.length > 0)) {
@@ -230,8 +231,7 @@ export function AppSidebar({indices, searchQuery, onSearchChange, onSelect, sele
230231
return childMatchesState;
231232
}
232233
// Otherwise, check if the child has the issue
233-
const childIssues = (child.issues || []).map((i: string) => i.toLowerCase());
234-
const childMatchesIssue = childIssues.some(ci => requiredIssues.some(ri => ci.includes(ri.toLowerCase())));
234+
const childMatchesIssue = matchesAnyIssue(child.issues || [], requiredIssues);
235235
return childMatchesIssue && childMatchesState;
236236
}
237237

ui2/src/util/issueMatch.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { matchesAnyIssue } from './issueMatch';
3+
4+
describe('matchesAnyIssue', () => {
5+
it('matches when the node has the exact issue id', () => {
6+
expect(matchesAnyIssue(['TEAM-1'], ['TEAM-1'])).toBe(true);
7+
});
8+
9+
it('does not match TEAM-10 when the filter is TEAM-1', () => {
10+
expect(matchesAnyIssue(['TEAM-10'], ['TEAM-1'])).toBe(false);
11+
});
12+
13+
it('does not match TEAM-123 when the filter is TEAM-1', () => {
14+
expect(matchesAnyIssue(['TEAM-123'], ['TEAM-1'])).toBe(false);
15+
});
16+
17+
it('is case-insensitive', () => {
18+
expect(matchesAnyIssue(['team-1'], ['TEAM-1'])).toBe(true);
19+
expect(matchesAnyIssue(['TEAM-1'], ['team-1'])).toBe(true);
20+
});
21+
22+
it('matches if any required issue is present', () => {
23+
expect(matchesAnyIssue(['TEAM-2', 'TEAM-7'], ['TEAM-1', 'TEAM-7'])).toBe(true);
24+
});
25+
26+
it('returns false when no issues match', () => {
27+
expect(matchesAnyIssue(['TEAM-2'], ['TEAM-1'])).toBe(false);
28+
});
29+
30+
it('returns false when the node has no issues', () => {
31+
expect(matchesAnyIssue([], ['TEAM-1'])).toBe(false);
32+
});
33+
});

ui2/src/util/issueMatch.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function matchesAnyIssue(nodeIssues: string[], requiredIssues: string[]): boolean {
2+
const required = requiredIssues.map(i => i.toLowerCase());
3+
const have = nodeIssues.map(i => i.toLowerCase());
4+
return have.some(ni => required.includes(ni));
5+
}

0 commit comments

Comments
 (0)