1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use dioxus_core::fc_to_builder;
use dioxus_core::{Component, VirtualDom};
use dioxus_core::{Element, Scope};
use dioxus_core_macro::render;
use freya_common::EventMessage;
use freya_core::prelude::*;
use freya_dom::prelude::{FreyaDOM, SafeDOM};
use freya_engine::prelude::*;
use freya_hooks::use_init_accessibility;
use std::sync::{Arc, Mutex};
use tokio::sync::broadcast;
use tokio::sync::mpsc::unbounded_channel;

use crate::config::TestingConfig;
use crate::test_handler::TestingHandler;
use crate::test_utils::TestUtils;

/// Run a Component in a headless testing environment
pub fn launch_test(root: Component<()>) -> TestingHandler {
    launch_test_with_config(root, TestingConfig::default())
}

/// Run a Component in a headless testing environment
pub fn launch_test_with_config(root: Component<()>, config: TestingConfig) -> TestingHandler {
    let vdom = with_accessibility(root);
    let fdom = FreyaDOM::default();
    let sdom = SafeDOM::new(fdom);

    let (event_emitter, event_receiver) = unbounded_channel::<DomEvent>();
    let (platform_event_emitter, platform_event_receiver) = unbounded_channel::<EventMessage>();
    let layers = Arc::new(Mutex::new(Layers::default()));
    let mut font_collection = FontCollection::new();
    font_collection.set_dynamic_font_manager(FontMgr::default());

    let mut handler = TestingHandler {
        vdom,
        events_queue: EventsQueue::new(),
        elements_state: ElementsState::default(),
        font_collection,
        event_emitter,
        event_receiver,
        viewports: Viewports::default(),
        utils: TestUtils { sdom, layers },
        config,
        platform_event_emitter,
        platform_event_receiver,
        accessibility_state: Arc::new(Mutex::new(AccessibilityState::new(ACCESSIBILITY_ROOT_ID))),
        ticker_sender: broadcast::channel(5).0,
    };

    handler.init_dom();

    handler
}

fn with_accessibility(app: Component) -> VirtualDom {
    struct RootProps {
        app: Component,
    }

    #[allow(non_snake_case)]
    fn Root(cx: Scope<RootProps>) -> Element {
        use_init_accessibility(cx);

        #[allow(non_snake_case)]
        let App = cx.props.app;

        render!(App {})
    }

    VirtualDom::new_with_props(Root, RootProps { app })
}