handlers.ts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /**
  2. * MSW request handlers for mocking API responses in tests.
  3. */
  4. import { http, HttpResponse } from 'msw';
  5. // Sample data
  6. const mockSmartPlugs = [
  7. {
  8. id: 1,
  9. name: 'Test Plug',
  10. ip_address: '192.168.1.100',
  11. printer_id: 1,
  12. enabled: true,
  13. auto_on: true,
  14. auto_off: true,
  15. off_delay_mode: 'time',
  16. off_delay_minutes: 5,
  17. off_temp_threshold: 70,
  18. username: null,
  19. password: null,
  20. power_alert_enabled: false,
  21. power_alert_high: null,
  22. power_alert_low: null,
  23. power_alert_last_triggered: null,
  24. schedule_enabled: false,
  25. schedule_on_time: null,
  26. schedule_off_time: null,
  27. last_state: 'ON',
  28. last_checked: null,
  29. auto_off_executed: false,
  30. auto_off_pending: false,
  31. auto_off_pending_since: null,
  32. created_at: '2024-01-01T00:00:00Z',
  33. updated_at: '2024-01-01T00:00:00Z',
  34. },
  35. ];
  36. const mockNotificationProviders = [
  37. {
  38. id: 1,
  39. name: 'Test Webhook',
  40. provider_type: 'webhook',
  41. enabled: true,
  42. config: { webhook_url: 'http://test.local/webhook' },
  43. on_print_start: true,
  44. on_print_complete: true,
  45. on_print_failed: true,
  46. on_print_stopped: false,
  47. on_print_progress: false,
  48. on_printer_offline: false,
  49. on_printer_error: false,
  50. on_filament_low: false,
  51. on_maintenance_due: false,
  52. on_ams_humidity_high: false,
  53. on_ams_temperature_high: false,
  54. on_ams_ht_humidity_high: false,
  55. on_ams_ht_temperature_high: false,
  56. quiet_hours_enabled: false,
  57. quiet_hours_start: null,
  58. quiet_hours_end: null,
  59. daily_digest_enabled: false,
  60. daily_digest_time: null,
  61. printer_id: null,
  62. last_success: null,
  63. last_error: null,
  64. last_error_at: null,
  65. created_at: '2024-01-01T00:00:00Z',
  66. updated_at: '2024-01-01T00:00:00Z',
  67. },
  68. ];
  69. const mockPrinters = [
  70. {
  71. id: 1,
  72. name: 'Test Printer',
  73. serial_number: '00M09A000000000',
  74. ip_address: '192.168.1.200',
  75. is_active: true,
  76. model: 'X1C',
  77. nozzle_count: 1,
  78. auto_archive: true,
  79. location: null,
  80. created_at: '2024-01-01T00:00:00Z',
  81. updated_at: '2024-01-01T00:00:00Z',
  82. },
  83. ];
  84. export const handlers = [
  85. // ========================================================================
  86. // Smart Plugs
  87. // ========================================================================
  88. http.get('/api/v1/smart-plugs/', () => {
  89. return HttpResponse.json(mockSmartPlugs);
  90. }),
  91. http.get('/api/v1/smart-plugs/:id', ({ params }) => {
  92. const plug = mockSmartPlugs.find((p) => p.id === Number(params.id));
  93. if (!plug) {
  94. return new HttpResponse(null, { status: 404 });
  95. }
  96. return HttpResponse.json(plug);
  97. }),
  98. http.post('/api/v1/smart-plugs/', async ({ request }) => {
  99. const body = (await request.json()) as Record<string, unknown>;
  100. const { id: _id, ...baseData } = mockSmartPlugs[0];
  101. const newPlug = {
  102. id: mockSmartPlugs.length + 1,
  103. ...baseData,
  104. ...body,
  105. };
  106. return HttpResponse.json(newPlug);
  107. }),
  108. http.patch('/api/v1/smart-plugs/:id', async ({ params, request }) => {
  109. const body = (await request.json()) as Record<string, unknown>;
  110. const plug = mockSmartPlugs.find((p) => p.id === Number(params.id));
  111. if (!plug) {
  112. return new HttpResponse(null, { status: 404 });
  113. }
  114. return HttpResponse.json({ ...plug, ...body });
  115. }),
  116. http.delete('/api/v1/smart-plugs/:id', ({ params }) => {
  117. const index = mockSmartPlugs.findIndex((p) => p.id === Number(params.id));
  118. if (index === -1) {
  119. return new HttpResponse(null, { status: 404 });
  120. }
  121. return HttpResponse.json({ success: true });
  122. }),
  123. http.get('/api/v1/smart-plugs/:id/status', () => {
  124. return HttpResponse.json({
  125. state: 'ON',
  126. reachable: true,
  127. device_name: 'Test Plug',
  128. energy: {
  129. power: 150.5,
  130. voltage: 120.0,
  131. current: 1.25,
  132. today: 2.5,
  133. total: 100.0,
  134. },
  135. });
  136. }),
  137. http.post('/api/v1/smart-plugs/:id/control', async ({ request }) => {
  138. const body = (await request.json()) as { action: string };
  139. return HttpResponse.json({
  140. success: true,
  141. action: body.action,
  142. });
  143. }),
  144. // ========================================================================
  145. // Notification Providers
  146. // ========================================================================
  147. http.get('/api/v1/notifications/', () => {
  148. return HttpResponse.json(mockNotificationProviders);
  149. }),
  150. http.get('/api/v1/notifications/:id', ({ params }) => {
  151. const provider = mockNotificationProviders.find(
  152. (p) => p.id === Number(params.id)
  153. );
  154. if (!provider) {
  155. return new HttpResponse(null, { status: 404 });
  156. }
  157. return HttpResponse.json(provider);
  158. }),
  159. http.post('/api/v1/notifications/', async ({ request }) => {
  160. const body = (await request.json()) as Record<string, unknown>;
  161. const { id: _id, ...baseData } = mockNotificationProviders[0];
  162. const newProvider = {
  163. id: mockNotificationProviders.length + 1,
  164. ...baseData,
  165. ...body,
  166. };
  167. return HttpResponse.json(newProvider);
  168. }),
  169. http.patch('/api/v1/notifications/:id', async ({ params, request }) => {
  170. const body = (await request.json()) as Record<string, unknown>;
  171. const provider = mockNotificationProviders.find(
  172. (p) => p.id === Number(params.id)
  173. );
  174. if (!provider) {
  175. return new HttpResponse(null, { status: 404 });
  176. }
  177. return HttpResponse.json({ ...provider, ...body });
  178. }),
  179. http.delete('/api/v1/notifications/:id', ({ params }) => {
  180. const index = mockNotificationProviders.findIndex(
  181. (p) => p.id === Number(params.id)
  182. );
  183. if (index === -1) {
  184. return new HttpResponse(null, { status: 404 });
  185. }
  186. return HttpResponse.json({ success: true });
  187. }),
  188. http.post('/api/v1/notifications/:id/test', () => {
  189. return HttpResponse.json({
  190. success: true,
  191. message: 'Test notification sent',
  192. });
  193. }),
  194. // ========================================================================
  195. // Printers
  196. // ========================================================================
  197. http.get('/api/v1/printers/', () => {
  198. return HttpResponse.json(mockPrinters);
  199. }),
  200. http.get('/api/v1/printers/:id', ({ params }) => {
  201. const printer = mockPrinters.find((p) => p.id === Number(params.id));
  202. if (!printer) {
  203. return new HttpResponse(null, { status: 404 });
  204. }
  205. return HttpResponse.json(printer);
  206. }),
  207. http.get('/api/v1/printers/:id/status', ({ params }) => {
  208. return HttpResponse.json({
  209. id: Number(params.id),
  210. name: 'Test Printer',
  211. connected: true,
  212. state: 'IDLE',
  213. progress: 0,
  214. layer_num: 0,
  215. total_layers: 0,
  216. temperatures: {
  217. nozzle: 25,
  218. bed: 25,
  219. chamber: 25,
  220. },
  221. remaining_time: 0,
  222. filename: null,
  223. });
  224. }),
  225. // ========================================================================
  226. // Settings
  227. // ========================================================================
  228. http.get('/api/v1/settings/', () => {
  229. return HttpResponse.json({
  230. auto_archive: true,
  231. save_thumbnails: true,
  232. capture_finish_photo: true,
  233. default_filament_cost: 25.0,
  234. currency: 'USD',
  235. ams_humidity_good: 40,
  236. ams_humidity_fair: 60,
  237. ams_temp_good: 30,
  238. ams_temp_fair: 35,
  239. });
  240. }),
  241. http.patch('/api/v1/settings/', async ({ request }) => {
  242. const body = (await request.json()) as Record<string, unknown>;
  243. return HttpResponse.json(body);
  244. }),
  245. // ========================================================================
  246. // Version / Health
  247. // ========================================================================
  248. http.get('/api/v1/version', () => {
  249. return HttpResponse.json({
  250. version: '0.1.5',
  251. build: 'test',
  252. });
  253. }),
  254. http.get('/health', () => {
  255. return HttpResponse.json({ status: 'healthy' });
  256. }),
  257. // ========================================================================
  258. // Archives
  259. // ========================================================================
  260. http.get('/api/v1/archives/:id/plates', () => {
  261. return HttpResponse.json([]);
  262. }),
  263. http.get('/api/v1/archives/:id/filament-requirements', () => {
  264. return HttpResponse.json([]);
  265. }),
  266. // ========================================================================
  267. // Library
  268. // ========================================================================
  269. http.get('/api/v1/library/stats', () => {
  270. return HttpResponse.json({
  271. total_files: 0,
  272. total_size: 0,
  273. total_folders: 0,
  274. });
  275. }),
  276. ];