use nigig_traffic::game_frame::RenderMode; use nigig_traffic::traffic::TrafficWorld; #[test] fn traffic_world_loads_and_ticks() { let mut world = TrafficWorld::new(); world.load_scenario(0); let scenario = world.scenario().expect("scenario loaded").clone(); assert!(!scenario.title.is_empty()); // Tick a few frames with no input – should stay in Intro then Driving let input = makepad_game_blocks::DriveInput::default(); for _ in 0..70 { world.tick(&input); } assert!(world.run.tick >= 70); // Intro books exactly 60 ticks, then the run goes live. assert_eq!(world.run.phase, nigig_traffic::traffic::Phase::Driving); } #[test] fn traffic_world_navigates_scenarios() { let mut world = TrafficWorld::new(); world.load_scenario(0); let first = world.scenario().expect("scenario loaded").id; world.next(); let second = world.scenario().expect("scenario loaded").id; assert_ne!(first, second); world.prev(); assert_eq!(world.scenario().expect("scenario loaded").id, first); } #[test] fn render_mode_labels_are_stable() { assert_eq!(RenderMode::TopDown.label(), "Top-Down"); assert_eq!(RenderMode::Chase25D.label(), "Chase-Cam (2.5D)"); assert_eq!(RenderMode::Full3D.label(), "Full 3D"); } #[test] fn traffic_world_builds_first_scenarios_without_panic() { // Headless smoke: every scenario must build road geometry and survive a // tick (no panics in `build_world_for`, id ordering, or `evaluate` // with no scenario edge cases). The actual GPU frame // (`window_0_frame_000000.png`) is only written by a real // `MAKEPAD=headless` binary run, not by this test. let all = TrafficWorld::all_scenarios(); assert!(all.len() >= 36); for s in all.iter().take(5) { let mut world = TrafficWorld::new(); let idx = all.iter().position(|x| x.id == s.id).unwrap(); world.load_scenario(idx); // One tick to ensure no panic in road building (oriented slab + large ground) world.tick(&makepad_game_blocks::DriveInput::default()); } }