| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- import { http, HttpResponse } from 'msw'
- import type { PatternMetadata, PreviewData } from '@/lib/types'
- // ============================================
- // API Call Tracking for Integration Tests
- // ============================================
- // Track API calls for integration test verification
- export const apiCallLog: Array<{
- endpoint: string
- method: string
- body?: unknown
- timestamp: number
- }> = []
- export function resetApiCallLog() {
- apiCallLog.length = 0
- }
- // Helper to log API calls
- function logApiCall(endpoint: string, method: string, body?: unknown) {
- apiCallLog.push({
- endpoint,
- method,
- body,
- timestamp: Date.now(),
- })
- }
- // ============================================
- // Mock Data Store (mutable for test scenarios)
- // ============================================
- export const mockData = {
- patterns: [
- { path: 'patterns/star.thr', name: 'star.thr', category: 'geometric', date_modified: Date.now(), coordinates_count: 150 },
- { path: 'patterns/spiral.thr', name: 'spiral.thr', category: 'organic', date_modified: Date.now() - 86400000, coordinates_count: 200 },
- { path: 'patterns/wave.thr', name: 'wave.thr', category: 'organic', date_modified: Date.now() - 172800000, coordinates_count: 175 },
- { path: 'patterns/custom/my_design.thr', name: 'my_design.thr', category: 'custom', date_modified: Date.now() - 259200000, coordinates_count: 100 },
- ] as PatternMetadata[],
- playlists: {
- default: ['patterns/star.thr', 'patterns/spiral.thr'],
- favorites: ['patterns/star.thr'],
- geometric: ['patterns/star.thr', 'patterns/wave.thr'],
- } as Record<string, string[]>,
- status: {
- is_running: false,
- is_paused: false,
- current_file: null as string | null,
- speed: 100,
- progress: 0,
- playlist_mode: false,
- playlist_name: null as string | null,
- queue: [] as string[],
- connection_status: 'connected',
- theta: 0,
- rho: 0.5,
- },
- }
- // Reset mock data between tests
- export function resetMockData() {
- mockData.patterns = [
- { path: 'patterns/star.thr', name: 'star.thr', category: 'geometric', date_modified: Date.now(), coordinates_count: 150 },
- { path: 'patterns/spiral.thr', name: 'spiral.thr', category: 'organic', date_modified: Date.now() - 86400000, coordinates_count: 200 },
- { path: 'patterns/wave.thr', name: 'wave.thr', category: 'organic', date_modified: Date.now() - 172800000, coordinates_count: 175 },
- { path: 'patterns/custom/my_design.thr', name: 'my_design.thr', category: 'custom', date_modified: Date.now() - 259200000, coordinates_count: 100 },
- ]
- mockData.playlists = {
- default: ['patterns/star.thr', 'patterns/spiral.thr'],
- favorites: ['patterns/star.thr'],
- geometric: ['patterns/star.thr', 'patterns/wave.thr'],
- }
- mockData.status = {
- is_running: false,
- is_paused: false,
- current_file: null,
- speed: 100,
- progress: 0,
- playlist_mode: false,
- playlist_name: null,
- queue: [],
- connection_status: 'connected',
- theta: 0,
- rho: 0.5,
- }
- }
- // ============================================
- // Handlers
- // ============================================
- export const handlers = [
- // ----------------
- // Pattern Endpoints
- // ----------------
- http.get('/list_theta_rho_files', () => {
- return HttpResponse.json(mockData.patterns.map(p => ({ name: p.name, path: p.path })))
- }),
- http.get('/list_theta_rho_files_with_metadata', () => {
- return HttpResponse.json(mockData.patterns)
- }),
- http.post('/preview_thr_batch', async ({ request }) => {
- const body = await request.json() as { files?: string[]; file_names?: string[] }
- const files = body.files || body.file_names || []
- const previews: Record<string, PreviewData> = {}
- for (const file of files) {
- previews[file] = {
- image_data: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
- first_coordinate: { x: 0, y: 0 },
- last_coordinate: { x: 100, y: 100 },
- }
- }
- return HttpResponse.json(previews)
- }),
- http.post('/get_theta_rho_coordinates', async () => {
- // Return mock coordinates for pattern preview
- return HttpResponse.json({
- coordinates: Array.from({ length: 50 }, (_, i) => ({
- theta: i * 7.2,
- rho: 0.5 + Math.sin(i * 0.2) * 0.3,
- })),
- })
- }),
- http.post('/run_theta_rho', async ({ request }) => {
- const body = await request.json() as { file_name?: string; file?: string; pre_execution?: string }
- const file = body.file_name || body.file
- logApiCall('/run_theta_rho', 'POST', body)
- mockData.status.is_running = true
- mockData.status.current_file = file || null
- return HttpResponse.json({ success: true })
- }),
- http.post('/delete_theta_rho_file', async ({ request }) => {
- const body = await request.json() as { file_path: string }
- mockData.patterns = mockData.patterns.filter(p => p.path !== body.file_path)
- return HttpResponse.json({ success: true })
- }),
- http.post('/upload_theta_rho', async () => {
- return HttpResponse.json({ success: true, path: 'patterns/custom/uploaded.thr' })
- }),
- http.get('/api/pattern_history_all', () => {
- return HttpResponse.json({})
- }),
- http.get('/api/pattern_history/:path', () => {
- return HttpResponse.json({ executions: [] })
- }),
- // ----------------
- // Playlist Endpoints
- // ----------------
- http.get('/list_all_playlists', () => {
- return HttpResponse.json(Object.keys(mockData.playlists))
- }),
- http.get('/get_playlist', ({ request }) => {
- const url = new URL(request.url)
- const name = url.searchParams.get('name')
- if (name && mockData.playlists[name]) {
- return HttpResponse.json({ name, files: mockData.playlists[name] })
- }
- return HttpResponse.json({ name: name || '', files: [] })
- }),
- http.post('/create_playlist', async ({ request }) => {
- const body = await request.json() as { name: string; playlist_name?: string; files?: string[] }
- const name = body.playlist_name || body.name
- logApiCall('/create_playlist', 'POST', body)
- mockData.playlists[name] = body.files || []
- return HttpResponse.json({ success: true })
- }),
- http.post('/modify_playlist', async ({ request }) => {
- const body = await request.json() as { name?: string; playlist_name?: string; files: string[] }
- const name = body.playlist_name || body.name || ''
- logApiCall('/modify_playlist', 'POST', body)
- if (mockData.playlists[name]) {
- mockData.playlists[name] = body.files
- }
- return HttpResponse.json({ success: true })
- }),
- http.post('/rename_playlist', async ({ request }) => {
- const body = await request.json() as { old_name: string; new_name: string }
- logApiCall('/rename_playlist', 'POST', body)
- if (mockData.playlists[body.old_name]) {
- mockData.playlists[body.new_name] = mockData.playlists[body.old_name]
- delete mockData.playlists[body.old_name]
- }
- return HttpResponse.json({ success: true })
- }),
- http.delete('/delete_playlist', async ({ request }) => {
- const body = await request.json() as { name?: string; playlist_name?: string }
- const name = body.playlist_name || body.name || ''
- logApiCall('/delete_playlist', 'DELETE', body)
- delete mockData.playlists[name]
- return HttpResponse.json({ success: true })
- }),
- http.post('/run_playlist', async ({ request }) => {
- const body = await request.json() as { name?: string; playlist_name?: string }
- const name = body.playlist_name || body.name || ''
- logApiCall('/run_playlist', 'POST', body)
- const playlist = mockData.playlists[name]
- if (playlist && playlist.length > 0) {
- mockData.status.is_running = true
- mockData.status.playlist_mode = true
- mockData.status.playlist_name = name
- mockData.status.current_file = playlist[0]
- mockData.status.queue = playlist.slice(1)
- }
- return HttpResponse.json({ success: true })
- }),
- http.post('/add_to_playlist', async ({ request }) => {
- const body = await request.json() as { playlist_name: string; file_path: string }
- if (!mockData.playlists[body.playlist_name]) {
- mockData.playlists[body.playlist_name] = []
- }
- mockData.playlists[body.playlist_name].push(body.file_path)
- return HttpResponse.json({ success: true })
- }),
- // ----------------
- // Playback Control Endpoints
- // ----------------
- http.post('/pause_execution', () => {
- logApiCall('/pause_execution', 'POST')
- mockData.status.is_paused = true
- return HttpResponse.json({ success: true })
- }),
- http.post('/resume_execution', () => {
- logApiCall('/resume_execution', 'POST')
- mockData.status.is_paused = false
- return HttpResponse.json({ success: true })
- }),
- http.post('/stop_execution', () => {
- logApiCall('/stop_execution', 'POST')
- mockData.status.is_running = false
- mockData.status.is_paused = false
- mockData.status.current_file = null
- mockData.status.playlist_mode = false
- mockData.status.playlist_name = null
- mockData.status.queue = []
- return HttpResponse.json({ success: true })
- }),
- http.post('/force_stop', () => {
- mockData.status.is_running = false
- mockData.status.is_paused = false
- mockData.status.current_file = null
- mockData.status.playlist_mode = false
- mockData.status.queue = []
- return HttpResponse.json({ success: true })
- }),
- http.post('/skip_pattern', () => {
- logApiCall('/skip_pattern', 'POST')
- if (mockData.status.queue.length > 0) {
- mockData.status.current_file = mockData.status.queue.shift() || null
- } else {
- mockData.status.is_running = false
- mockData.status.current_file = null
- }
- return HttpResponse.json({ success: true })
- }),
- http.post('/set_speed', async ({ request }) => {
- const body = await request.json() as { speed: number }
- mockData.status.speed = body.speed
- return HttpResponse.json({ success: true })
- }),
- // ----------------
- // Table Control Endpoints
- // ----------------
- http.post('/send_home', () => {
- mockData.status.theta = 0
- mockData.status.rho = 0
- return HttpResponse.json({ success: true })
- }),
- http.post('/soft_reset', () => {
- return HttpResponse.json({ success: true })
- }),
- http.post('/move_to_center', () => {
- mockData.status.rho = 0
- return HttpResponse.json({ success: true })
- }),
- http.post('/move_to_perimeter', () => {
- mockData.status.rho = 1
- return HttpResponse.json({ success: true })
- }),
- http.post('/send_coordinate', async ({ request }) => {
- const body = await request.json() as { theta: number; rho: number }
- mockData.status.theta = body.theta
- mockData.status.rho = body.rho
- return HttpResponse.json({ success: true })
- }),
- // ----------------
- // Status Endpoints
- // ----------------
- http.get('/serial_status', () => {
- return HttpResponse.json(mockData.status)
- }),
- http.get('/list_serial_ports', () => {
- return HttpResponse.json(['/dev/ttyUSB0', '/dev/ttyUSB1'])
- }),
- // Board diagnostics
- http.get('/api/board/logs', () => {
- return HttpResponse.json({ lines: [] })
- }),
- http.get('/api/board/bootlog', () => {
- return HttpResponse.json({ text: '[+0] boot ok\n' })
- }),
- http.get('/api/board/coredump', () => {
- return HttpResponse.json({ present: false })
- }),
- http.post('/api/board/restart', () => {
- return HttpResponse.json({ success: true, rebooting: true })
- }),
- // Debug serial endpoints
- http.post('/api/debug-serial/open', () => {
- return HttpResponse.json({ success: true })
- }),
- http.post('/api/debug-serial/close', () => {
- return HttpResponse.json({ success: true })
- }),
- http.post('/api/debug-serial/send', () => {
- return HttpResponse.json({ success: true, response: 'OK' })
- }),
- ]
|