//! Convenience crate that re-exports GPUI's platform traits and the//! `current_platform` constructor so consumers don't need `#[cfg]` gating.pub use gpui::Platform;use std::rc::Rc;/// Returns a background executor for the current platform.pub fn background_executor() -> gpui::BackgroundExecutor { current_platform(true).background_executor()}pub fn application() -> gpui::Application { gpui::Application::with_platform(current_platform(false))}pub fn headless() -> gpui::Application { gpui::Application::with_platform(current_platform(true))}/// Returns the default [`Platform`] for the current OS.pub fn current_platform(headless: bool) -> Rc<dyn Platform> { #[cfg(target_os = "macos")] { Rc::new(gpui_macos::MacPlatform::new(headless)) } #[cfg(target_os = "windows")] { Rc::new( gpui_windows::WindowsPlatform::new(headless) .expect("failed to initialize Windows platform"), ) } #[cfg(not(any(target_os = "macos", target_os = "windows")))] { gpui_linux::current_platform(headless) }}#[cfg(all(test, target_os = "macos"))]mod tests { use super::*; use gpui::{AppContext, Empty, VisualTestAppContext}; use std::cell::RefCell; use std::time::Duration; // Note: All VisualTestAppContext tests are ignored by default because they require // the macOS main thread. Standard Rust tests run on worker threads, which causes // SIGABRT when interacting with macOS AppKit/Cocoa APIs. // // To run these tests, use: // cargo test -p gpui visual_test_context -- --ignored --test-threads=1 #[test] #[ignore] // Requires macOS main thread fn test_foreground_tasks_run_with_run_until_parked() { let mut cx = VisualTestAppContext::new(current_platform(false)); let task_ran = Rc::new(RefCell::new(false)); // Spawn a foreground task via the App's spawn method // This should use our TestDispatcher, not the MacDispatcher { let task_ran = task_ran.clone(); cx.update(|cx| { cx.spawn(async move |_| { *task_ran.borrow_mut() = true; }) .detach(); }); } // The task should not have run yet assert!(!*task_ran.borrow()); // Run until parked should execute the foreground task cx.run_until_parked(); // Now the task should have run assert!(*task_ran.borrow()); } #[test] #[ignore] // Requires macOS main thread fn test_advance_clock_triggers_delayed_tasks() { let mut cx = VisualTestAppContext::new(current_platform(false)); let task_ran = Rc::new(RefCell::new(false)); // Spawn a task that waits for a timer { let task_ran = task_ran.clone(); let executor = cx.background_executor.clone(); cx.update(|cx| { cx.spawn(async move |_| { executor.timer(Duration::from_millis(500)).await; *task_ran.borrow_mut() = true; }) .detach(); }); } // Run until parked - the task should be waiting on the timer cx.run_until_parked(); assert!(!*task_ran.borrow()); // Advance clock past the timer duration cx.advance_clock(Duration::from_millis(600)); // Now the task should have completed assert!(*task_ran.borrow()); } #[test] #[ignore] // Requires macOS main thread - window creation fails on test threads fn test_window_spawn_uses_test_dispatcher() { let mut cx = VisualTestAppContext::new(current_platform(false)); let task_ran = Rc::new(RefCell::new(false)); let window = cx .open_offscreen_window_default(|_, cx| cx.new(|_| Empty)) .expect("Failed to open window"); // Spawn a task via window.spawn - this is the critical test case // for tooltip behavior, as tooltips use window.spawn for delayed show { let task_ran = task_ran.clone(); cx.update_window(window.into(), |_, window, cx| { window .spawn(cx, async move |_| { *task_ran.borrow_mut() = true; }) .detach(); }) .ok(); } // The task should not have run yet assert!(!*task_ran.borrow()); // Run until parked should execute the foreground task spawned via window cx.run_until_parked(); // Now the task should have run assert!(*task_ran.borrow()); }}
//! Convenience crate that re-exports GPUI's platform traits and the
//! `current_platform` constructor so consumers don't need `#[cfg]` gating.
pub use gpui::Platform;
use std::rc::Rc;
/// Returns a background executor for the current platform.
pub fn background_executor() -> gpui::BackgroundExecutor {
current_platform(true).background_executor()
}
pub fn application() -> gpui::Application {
gpui::Application::with_platform(current_platform(false))
}
pub fn headless() -> gpui::Application {
gpui::Application::with_platform(current_platform(true))
}
/// Returns the default [`Platform`] for the current OS.
pub fn current_platform(headless: bool) -> Rc<dyn Platform> {
#[cfg(target_os = "macos")]
{
Rc::new(gpui_macos::MacPlatform::new(headless))
}
#[cfg(target_os = "windows")]
{
Rc::new(
gpui_windows::WindowsPlatform::new(headless)
.expect("failed to initialize Windows platform"),
)
}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
{
gpui_linux::current_platform(headless)
}
}
#[cfg(all(test, target_os = "macos"))]
mod tests {
use super::*;
use gpui::{AppContext, Empty, VisualTestAppContext};
use std::cell::RefCell;
use std::time::Duration;
// Note: All VisualTestAppContext tests are ignored by default because they require
// the macOS main thread. Standard Rust tests run on worker threads, which causes
// SIGABRT when interacting with macOS AppKit/Cocoa APIs.
//
// To run these tests, use:
// cargo test -p gpui visual_test_context -- --ignored --test-threads=1
#[test]
#[ignore] // Requires macOS main thread
fn test_foreground_tasks_run_with_run_until_parked() {
let mut cx = VisualTestAppContext::new(current_platform(false));
let task_ran = Rc::new(RefCell::new(false));
// Spawn a foreground task via the App's spawn method
// This should use our TestDispatcher, not the MacDispatcher
{
let task_ran = task_ran.clone();
cx.update(|cx| {
cx.spawn(async move |_| {
*task_ran.borrow_mut() = true;
})
.detach();
});
}
// The task should not have run yet
assert!(!*task_ran.borrow());
// Run until parked should execute the foreground task
cx.run_until_parked();
// Now the task should have run
assert!(*task_ran.borrow());
}
#[test]
#[ignore] // Requires macOS main thread
fn test_advance_clock_triggers_delayed_tasks() {
let mut cx = VisualTestAppContext::new(current_platform(false));
let task_ran = Rc::new(RefCell::new(false));
// Spawn a task that waits for a timer
{
let task_ran = task_ran.clone();
let executor = cx.background_executor.clone();
cx.update(|cx| {
cx.spawn(async move |_| {
executor.timer(Duration::from_millis(500)).await;
*task_ran.borrow_mut() = true;
})
.detach();
});
}
// Run until parked - the task should be waiting on the timer
cx.run_until_parked();
assert!(!*task_ran.borrow());
// Advance clock past the timer duration
cx.advance_clock(Duration::from_millis(600));
// Now the task should have completed
assert!(*task_ran.borrow());
}
#[test]
#[ignore] // Requires macOS main thread - window creation fails on test threads
fn test_window_spawn_uses_test_dispatcher() {
let mut cx = VisualTestAppContext::new(current_platform(false));
let task_ran = Rc::new(RefCell::new(false));
let window = cx
.open_offscreen_window_default(|_, cx| cx.new(|_| Empty))
.expect("Failed to open window");
// Spawn a task via window.spawn - this is the critical test case
// for tooltip behavior, as tooltips use window.spawn for delayed show
{
let task_ran = task_ran.clone();
cx.update_window(window.into(), |_, window, cx| {
window
.spawn(cx, async move |_| {
*task_ran.borrow_mut() = true;
})
.detach();
})
.ok();
}
// The task should not have run yet
assert!(!*task_ran.borrow());
// Run until parked should execute the foreground task spawned via window
cx.run_until_parked();
// Now the task should have run
assert!(*task_ran.borrow());
}
}