Files
Timmy-time-dashboard/mobile-app/tests/chat.test.ts
Manus AI b4b508ff5a feat: add Timmy Chat mobile app (Expo/React Native)
- Single-screen chat interface with Timmy's sovereign AI personality
- Text messaging with real-time AI responses via server chat API
- Voice recording and playback with waveform visualization
- Image sharing (camera + photo library) with full-screen viewer
- File attachments via document picker
- Dark arcane theme matching the Timmy Time dashboard
- Custom app icon with glowing T circuit design
- Timmy system prompt ported from dashboard prompts.py
- Unit tests for chat utilities and message types
2026-02-26 21:55:41 -05:00

136 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
// Test the utility functions from chat-store
// We can't directly test React hooks here, but we can test the pure functions
describe("formatBytes", () => {
// Re-implement locally since the module uses React context
function formatBytes(bytes: number): string {
if (bytes === 0) return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
}
it("formats 0 bytes", () => {
expect(formatBytes(0)).toBe("0 B");
});
it("formats bytes", () => {
expect(formatBytes(500)).toBe("500 B");
});
it("formats kilobytes", () => {
expect(formatBytes(1024)).toBe("1 KB");
expect(formatBytes(1536)).toBe("1.5 KB");
});
it("formats megabytes", () => {
expect(formatBytes(1048576)).toBe("1 MB");
expect(formatBytes(5242880)).toBe("5 MB");
});
});
describe("formatDuration", () => {
function formatDuration(seconds: number): string {
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s.toString().padStart(2, "0")}`;
}
it("formats zero seconds", () => {
expect(formatDuration(0)).toBe("0:00");
});
it("formats seconds only", () => {
expect(formatDuration(45)).toBe("0:45");
});
it("formats minutes and seconds", () => {
expect(formatDuration(125)).toBe("2:05");
});
it("formats exact minutes", () => {
expect(formatDuration(60)).toBe("1:00");
});
});
describe("ChatMessage type structure", () => {
it("creates a valid text message", () => {
const msg = {
id: "msg_1",
role: "user" as const,
contentType: "text" as const,
text: "Hello Timmy",
timestamp: Date.now(),
};
expect(msg.role).toBe("user");
expect(msg.contentType).toBe("text");
expect(msg.text).toBe("Hello Timmy");
});
it("creates a valid image message", () => {
const msg = {
id: "msg_2",
role: "user" as const,
contentType: "image" as const,
uri: "file:///photo.jpg",
fileName: "photo.jpg",
mimeType: "image/jpeg",
timestamp: Date.now(),
};
expect(msg.contentType).toBe("image");
expect(msg.mimeType).toBe("image/jpeg");
});
it("creates a valid voice message", () => {
const msg = {
id: "msg_3",
role: "user" as const,
contentType: "voice" as const,
uri: "file:///voice.m4a",
duration: 5.2,
mimeType: "audio/m4a",
timestamp: Date.now(),
};
expect(msg.contentType).toBe("voice");
expect(msg.duration).toBe(5.2);
});
it("creates a valid file message", () => {
const msg = {
id: "msg_4",
role: "user" as const,
contentType: "file" as const,
uri: "file:///document.pdf",
fileName: "document.pdf",
fileSize: 1048576,
mimeType: "application/pdf",
timestamp: Date.now(),
};
expect(msg.contentType).toBe("file");
expect(msg.fileSize).toBe(1048576);
});
it("creates a valid assistant message", () => {
const msg = {
id: "msg_5",
role: "assistant" as const,
contentType: "text" as const,
text: "Sir, affirmative.",
timestamp: Date.now(),
};
expect(msg.role).toBe("assistant");
});
});
describe("Timmy system prompt", () => {
const TIMMY_SYSTEM_PROMPT = `You are Timmy — a sovereign AI agent.`;
it("contains Timmy identity", () => {
expect(TIMMY_SYSTEM_PROMPT).toContain("Timmy");
expect(TIMMY_SYSTEM_PROMPT).toContain("sovereign");
});
});