Unit tests for shell classifier, executor, tool calling detection, and frontend components. - Add detectToolCalling.test.ts (136 lines) - Add aiProvidersOllamaDropdown.test.tsx (129 lines) - Add selectDropdownViewport.test.tsx (124 lines) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
125 lines
4.0 KiB
TypeScript
125 lines
4.0 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
import { render, screen } from "@testing-library/react";
|
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@/components/ui";
|
|
|
|
describe("Select Dropdown - Viewport Awareness", () => {
|
|
let originalInnerHeight: number;
|
|
|
|
beforeEach(() => {
|
|
originalInnerHeight = window.innerHeight;
|
|
});
|
|
|
|
afterEach(() => {
|
|
// Restore original window height
|
|
Object.defineProperty(window, "innerHeight", {
|
|
writable: true,
|
|
configurable: true,
|
|
value: originalInnerHeight,
|
|
});
|
|
});
|
|
|
|
it("should render Select component with trigger and content", () => {
|
|
render(
|
|
<Select value="" onValueChange={() => {}}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select..." />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="option1">Option 1</SelectItem>
|
|
<SelectItem value="option2">Option 2</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
);
|
|
|
|
// Trigger should be visible
|
|
expect(screen.getByRole("button")).toBeInTheDocument();
|
|
});
|
|
|
|
it("should apply bottom-full class when flipped upward", () => {
|
|
// Test verifies the flip logic when dropdown is near bottom of viewport
|
|
// Simulating a dropdown positioned 10px from viewport bottom
|
|
const dropdownBottom = window.innerHeight - 10;
|
|
const spaceBelow = window.innerHeight - dropdownBottom;
|
|
const shouldFlipUpward = spaceBelow < 20;
|
|
|
|
expect(shouldFlipUpward).toBe(true);
|
|
});
|
|
|
|
it("should apply top-full class when sufficient space below", () => {
|
|
const mockBottom = 300; // Plenty of space below
|
|
const viewportHeight = 1080;
|
|
const spaceBelow = viewportHeight - mockBottom;
|
|
const shouldFlipUpward = spaceBelow < 20;
|
|
|
|
expect(shouldFlipUpward).toBe(false);
|
|
});
|
|
|
|
it("should use 20px threshold for flip decision", () => {
|
|
const threshold = 20;
|
|
|
|
// Just above threshold - should not flip
|
|
const spaceBelowAbove = 21;
|
|
expect(spaceBelowAbove < threshold).toBe(false);
|
|
|
|
// Just below threshold - should flip
|
|
const spaceBelowBelow = 19;
|
|
expect(spaceBelowBelow < threshold).toBe(true);
|
|
|
|
// Exactly at threshold - should flip
|
|
const spaceBelowExact = 20;
|
|
expect(spaceBelowExact < threshold).toBe(false);
|
|
});
|
|
|
|
it("should calculate space below correctly", () => {
|
|
const viewportHeight = 1080;
|
|
const dropdownBottom = 950;
|
|
const expectedSpaceBelow = viewportHeight - dropdownBottom;
|
|
|
|
expect(expectedSpaceBelow).toBe(130);
|
|
expect(expectedSpaceBelow < 20).toBe(false); // Should not flip
|
|
});
|
|
|
|
it("should handle edge case at exact viewport bottom", () => {
|
|
const viewportHeight = 1080;
|
|
const dropdownBottom = 1080; // Exactly at bottom
|
|
const spaceBelow = viewportHeight - dropdownBottom;
|
|
|
|
expect(spaceBelow).toBe(0);
|
|
expect(spaceBelow < 20).toBe(true); // Should flip
|
|
});
|
|
|
|
it("should handle edge case beyond viewport", () => {
|
|
const viewportHeight = 1080;
|
|
const dropdownBottom = 1100; // Beyond viewport
|
|
const spaceBelow = viewportHeight - dropdownBottom;
|
|
|
|
expect(spaceBelow).toBe(-20);
|
|
expect(spaceBelow < 20).toBe(true); // Should flip
|
|
});
|
|
});
|
|
|
|
describe("Select Dropdown - CSS Classes", () => {
|
|
it("should use correct classes for downward expansion", () => {
|
|
const flipUpward = false;
|
|
const classes = flipUpward ? "bottom-full mb-1" : "top-full mt-1";
|
|
|
|
expect(classes).toBe("top-full mt-1");
|
|
});
|
|
|
|
it("should use correct classes for upward expansion", () => {
|
|
const flipUpward = true;
|
|
const classes = flipUpward ? "bottom-full mb-1" : "top-full mt-1";
|
|
|
|
expect(classes).toBe("bottom-full mb-1");
|
|
});
|
|
|
|
it("should include common classes regardless of flip direction", () => {
|
|
const commonClasses = "absolute z-50 max-h-60 w-full overflow-auto rounded-md border bg-card p-1 shadow-md";
|
|
|
|
// These classes should always be present
|
|
expect(commonClasses).toContain("absolute");
|
|
expect(commonClasses).toContain("z-50");
|
|
expect(commonClasses).toContain("max-h-60");
|
|
});
|
|
});
|