-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExamples.tsx
More file actions
116 lines (107 loc) · 5.66 KB
/
Copy pathExamples.tsx
File metadata and controls
116 lines (107 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import React, {useMemo, useState} from "react";
import {Accordion, AccordionContent, AccordionItem, AccordionTrigger} from "@/components/ui/accordion.tsx";
import {useAppContext} from "@/AppProvider.tsx";
import {ChevronRight, Code} from "lucide-react";
interface IProps {
addTestTab: (testName: string, event: React.MouseEvent<HTMLElement>) => void;
openExamples: string[];
setOpenExamples: (value: string[]) => void;
}
interface ExampleEntry {
name: string;
cases: Array<{id: string; name: string}>;
}
export const Examples: React.FC<IProps> = ({addTestTab, openExamples, setOpenExamples}) => {
const {data} = useAppContext();
const testCases = useMemo(() => data?.testCases ?? [], [data]);
const [filter, setFilter] = useState("");
const namedExamples = useMemo<ExampleEntry[]>(() => {
const map = new Map<string, Array<{id: string; name: string}>>();
for (const tc of testCases) {
if (!tc.namedExamples || !tc.id) continue;
const tcId = tc.id;
const tcName = tc.name ?? tc.id;
for (const ex of tc.namedExamples) {
if (!ex) continue;
const arr = map.get(ex) ?? [];
if (!arr.some(existing => existing.id === tcId)) {
arr.push({id: tcId, name: tcName});
}
map.set(ex, arr);
}
}
const out: ExampleEntry[] = Array.from(map.entries()).map(([name, cases]) => ({name, cases}));
out.sort((a, b) => a.name.localeCompare(b.name));
return out;
}, [testCases]);
const filteredExamples = useMemo(() => {
const q = filter.trim().toLowerCase();
if (!q) return namedExamples;
return namedExamples.filter(e => e.name.toLowerCase().includes(q));
}, [namedExamples, filter]);
return (
<div className="border-2 border-black p-3 sm:p-6 rounded-none" data-testid="examples-page">
<div className="flex flex-wrap items-center gap-2 mb-4">
<h2 className="text-lg font-bold">Named Examples</h2>
<span className="ml-2 font-mono text-xs px-2 py-1 border-2 border-black bg-white" data-testid="examples-count">
{namedExamples.length}
</span>
</div>
<p className="text-sm text-gray-700 mb-4">
Unique named examples used across the generated test cases (sorted alphabetically).
Click on one to see all test cases that include it.
</p>
{namedExamples.length > 0 && (
<input
type="text"
placeholder="Filter by name..."
value={filter}
onChange={e => setFilter(e.target.value)}
className="border-2 border-black px-2 py-1 mb-4 w-full sm:w-80 font-mono text-sm"
data-testid="examples-filter"
/>
)}
{namedExamples.length === 0 ? (
<div className="border-2 border-dashed border-gray-400 bg-gray-50 p-6 text-center text-sm text-gray-600 font-mono" data-testid="examples-empty">
No named examples recorded.
</div>
) : filteredExamples.length === 0 ? (
<div className="text-gray-500 italic text-sm">No named examples match the current filter.</div>
) : (
<Accordion type="multiple" value={openExamples} onValueChange={setOpenExamples} className="w-full">
{filteredExamples.map((ex, idx) => (
<AccordionItem
key={ex.name}
value={ex.name}
className="border-2 border-black mb-4 overflow-hidden"
data-testid={`example-${idx}`}
>
<AccordionTrigger className="bg-blue-100 px-3 sm:px-4 py-3 text-sm sm:text-lg font-bold hover:no-underline hover:bg-blue-200">
<div className="flex-1 font-mono text-left break-all">{ex.name}</div>
<div className="mr-4 font-mono text-sm">{ex.cases.length}</div>
</AccordionTrigger>
<AccordionContent className="p-3 sm:p-4">
<div className="flex flex-col gap-2">
{ex.cases.map((tc, j) => (
<button
key={`${tc.id}-${j}`}
onClick={(event) => addTestTab(tc.id, event)}
className="w-full flex items-center justify-between p-3 border border-gray-200 hover:bg-blue-50 hover:border-blue-300 text-left transition-colors"
data-testid={`example-${idx}-test-${j}`}
>
<div className="flex items-center">
<Code className="mr-3 text-gray-500 shrink-0" size={20}/>
<span className="font-mono text-sm break-all">{tc.name}</span>
</div>
<ChevronRight className="text-gray-400 shrink-0" size={18}/>
</button>
))}
</div>
</AccordionContent>
</AccordionItem>
))}
</Accordion>
)}
</div>
);
};