comparison infinite_canvas/canvas_test.c @ 280:49e9e591c9bb

Add persistent dictation, prewarmed WebRTC speech input, Copilot SDK routing, animated conversation lifecycle controls, parking, and architecture coverage.
author MrJuneJune <me@mrjunejune.com>
date Tue, 18 Aug 2026 19:14:53 -0700
parents 8d560f50ed4c
children c57149ad216e
comparison
equal deleted inserted replaced
279:b3b547563ec7 280:49e9e591c9bb
524 assert(small_context[sizeof(small_context) - 1] == '\0'); 524 assert(small_context[sizeof(small_context) - 1] == '\0');
525 525
526 Dowa_Arena_Free(p_arena); 526 Dowa_Arena_Free(p_arena);
527 } 527 }
528 528
529 static void Test_Dictation_Scratchpad_Is_Not_A_Routing_Target(void)
530 {
531 Dowa_Arena *p_arena = Dowa_Arena_Create(ONE_MEGA_BYTE);
532 assert(p_arena);
533
534 Canvas_Camera camera;
535 Canvas_Camera_Init(&camera, 800, 600);
536 Canvas_Scene scene;
537 Canvas_Scene_Init(&scene, p_arena);
538 assert(Canvas_Scene_Add(
539 &scene,
540 CANVAS_ENTITY_TEXT_AREA,
541 (Vector2){-260.0f, -120.0f}));
542 snprintf(
543 scene.p_entities[0].label,
544 sizeof(scene.p_entities[0].label),
545 "Dictation");
546 snprintf(
547 scene.p_entities[0].text,
548 sizeof(scene.p_entities[0].text),
549 "Route this thought");
550 uint32 conversation_id = Canvas_Scene_Add_Conversation(
551 &scene,
552 "Visible session",
553 "Earlier thought",
554 "Earlier response",
555 (Vector2){40.0f, -120.0f});
556 assert(conversation_id != 0);
557
558 char context[4096];
559 Canvas_Context_Snapshot snapshot = Canvas_Scene_Build_Visible_Context(
560 &scene,
561 &camera,
562 context,
563 sizeof(context));
564 assert(snapshot.visible_count == 1);
565 assert(!strstr(context, "Route this thought"));
566 assert(strstr(context, "Visible session"));
567 assert(strstr(context, TextFormat("id=%u", conversation_id)));
568
569 Dowa_Arena_Free(p_arena);
570 }
571
572 static void Test_Conversation_Create_And_Append(void)
573 {
574 Dowa_Arena *p_arena = Dowa_Arena_Create(ONE_MEGA_BYTE);
575 assert(p_arena);
576 Canvas_Scene scene;
577 Canvas_Scene_Init(&scene, p_arena);
578
579 uint32 id = Canvas_Scene_Add_Conversation(
580 &scene,
581 "Rendering architecture",
582 "How should images render?",
583 "Use a rich entity with typed resources.",
584 (Vector2){10.0f, 20.0f});
585 assert(id != 0);
586 assert(Dowa_Array_Length(scene.p_entities) == 1);
587 assert(scene.p_entities[0].type == CANVAS_ENTITY_CONVERSATION);
588 assert(strcmp(scene.p_entities[0].label, "Rendering architecture") == 0);
589 assert(strstr(scene.p_entities[0].text, "How should images render?"));
590
591 assert(Canvas_Scene_Append_Conversation(
592 &scene,
593 id,
594 "What about browser content?",
595 "Keep the resource typed and composited by its backend."));
596 assert(strstr(scene.p_entities[0].text, "What about browser content?"));
597 assert(strstr(scene.p_entities[0].text, "composited by its backend"));
598 assert(!Canvas_Scene_Append_Conversation(
599 &scene,
600 id + 1,
601 "Missing",
602 "Missing"));
603 Dowa_Arena_Free(p_arena);
604 }
605
606 static void Test_Conversation_Collapse_And_Parking(void)
607 {
608 Dowa_Arena *p_arena = Dowa_Arena_Create(ONE_MEGA_BYTE);
609 assert(p_arena);
610 Canvas_Camera camera;
611 Canvas_Camera_Init(&camera, 800, 600);
612 Canvas_Scene scene;
613 Canvas_Scene_Init(&scene, p_arena);
614
615 Vector2 original = {20.0f, 30.0f};
616 uint32 id = Canvas_Scene_Add_Conversation(
617 &scene,
618 "Parkable session",
619 "Question",
620 "Answer",
621 original);
622 Canvas_Entity *p_conversation = &scene.p_entities[0];
623 assert(Near(p_conversation->animation_amount, 1.0f));
624 Canvas_Conversation_Set_Collapsed(p_conversation, TRUE);
625 assert(p_conversation->active);
626 Canvas_Conversation_Set_Collapsed(p_conversation, FALSE);
627 assert(!p_conversation->active);
628
629 assert(Canvas_Scene_Set_Conversation_Parked(&scene, id, TRUE));
630 assert(p_conversation->parked);
631 assert(Canvas_Scene_Parked_Conversation_Count(&scene) == 1);
632 assert(!Near(p_conversation->position.x, original.x));
633 char context[4096];
634 Canvas_Context_Snapshot snapshot = Canvas_Scene_Build_Visible_Context(
635 &scene,
636 &camera,
637 context,
638 sizeof(context));
639 assert(snapshot.visible_count == 0);
640 assert(Canvas_Scene_Show_Parking_Lot(&scene, &camera));
641 snapshot = Canvas_Scene_Build_Visible_Context(
642 &scene,
643 &camera,
644 context,
645 sizeof(context));
646 assert(snapshot.visible_count == 0);
647
648 assert(Canvas_Scene_Set_Conversation_Parked(&scene, id, FALSE));
649 assert(!p_conversation->parked);
650 assert(Canvas_Scene_Parked_Conversation_Count(&scene) == 0);
651 assert(Near(p_conversation->position.x, original.x));
652 assert(Near(p_conversation->position.y, original.y));
653 Dowa_Arena_Free(p_arena);
654 }
655
529 int main(void) 656 int main(void)
530 { 657 {
531 Test_Theme_Resolution(); 658 Test_Theme_Resolution();
532 Test_Camera_Round_Trip(); 659 Test_Camera_Round_Trip();
533 Test_Anchored_Zoom(); 660 Test_Anchored_Zoom();
541 Test_Entity_Fade_Lifecycle_Commands(); 668 Test_Entity_Fade_Lifecycle_Commands();
542 Test_Browser_Grid(); 669 Test_Browser_Grid();
543 Test_Lucide_Gallery_Reuses_Entity_And_Fits_Camera(); 670 Test_Lucide_Gallery_Reuses_Entity_And_Fits_Camera();
544 Test_Lucide_Search_Is_Case_Insensitive(); 671 Test_Lucide_Search_Is_Case_Insensitive();
545 Test_Demo_Contains_Every_Entity_Type(); 672 Test_Demo_Contains_Every_Entity_Type();
673 Test_Conversation_Create_And_Append();
546 Test_Pinned_Entity_Stays_In_Screen_Space(); 674 Test_Pinned_Entity_Stays_In_Screen_Space();
547 Test_Visible_Context_Tracks_Camera_And_Values(); 675 Test_Visible_Context_Tracks_Camera_And_Values();
676 Test_Dictation_Scratchpad_Is_Not_A_Routing_Target();
677 Test_Conversation_Collapse_And_Parking();
548 printf("Infinite canvas tests passed.\n"); 678 printf("Infinite canvas tests passed.\n");
549 return 0; 679 return 0;
550 } 680 }