1#![expect(clippy::result_large_err)]
2use std::iter::zip;
3
4use crate::{
5 debugger_panel::DebugPanel,
6 persistence::SerializedPaneLayout,
7 tests::{init_test, init_test_workspace, start_debug_session},
8};
9use dap::{StoppedEvent, StoppedEventReason, messages::Events};
10use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
11use project::{FakeFs, Project};
12use serde_json::json;
13use util::path;
14use workspace::{Panel, dock::DockPosition};
15
16#[gpui::test]
17async fn test_invert_axis_on_panel_position_change(
18 executor: BackgroundExecutor,
19 cx: &mut TestAppContext,
20) {
21 init_test(cx);
22
23 let fs = FakeFs::new(executor.clone());
24 fs.insert_tree(
25 path!("/project"),
26 json!({
27 "main.rs": "fn main() {\n println!(\"Hello, world!\");\n}",
28 }),
29 )
30 .await;
31
32 let project = Project::test(fs, [path!("/project").as_ref()], cx).await;
33 let workspace = init_test_workspace(&project, cx).await;
34 let cx = &mut VisualTestContext::from_window(*workspace, cx);
35
36 // Start a debug session
37 let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
38 let client = session.update(cx, |session, _| session.adapter_client().unwrap());
39
40 // Setup thread response
41 client.on_request::<dap::requests::Threads, _>(move |_, _| {
42 Ok(dap::ThreadsResponse { threads: vec![] })
43 });
44
45 cx.run_until_parked();
46
47 client
48 .fake_event(Events::Stopped(StoppedEvent {
49 reason: StoppedEventReason::Pause,
50 description: None,
51 thread_id: Some(1),
52 preserve_focus_hint: None,
53 text: None,
54 all_threads_stopped: None,
55 hit_breakpoint_ids: None,
56 }))
57 .await;
58
59 cx.run_until_parked();
60
61 let (debug_panel, dock_position) = workspace
62 .update(cx, |workspace, window, cx| {
63 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
64 let dock_position = debug_panel.read(cx).position(window, cx);
65 (debug_panel, dock_position)
66 })
67 .unwrap();
68
69 assert_eq!(
70 dock_position,
71 DockPosition::Bottom,
72 "Default dock position should be bottom for debug panel"
73 );
74
75 let pre_serialized_layout = debug_panel
76 .read_with(cx, |panel, cx| {
77 panel
78 .active_session()
79 .unwrap()
80 .read(cx)
81 .running_state()
82 .read(cx)
83 .serialized_layout(cx)
84 })
85 .panes;
86
87 let post_serialized_layout = debug_panel
88 .update_in(cx, |panel, window, cx| {
89 panel.set_position(DockPosition::Right, window, cx);
90
91 panel
92 .active_session()
93 .unwrap()
94 .read(cx)
95 .running_state()
96 .read(cx)
97 .serialized_layout(cx)
98 })
99 .panes;
100
101 let pre_panes = pre_serialized_layout.in_order();
102 let post_panes = post_serialized_layout.in_order();
103
104 assert_eq!(pre_panes.len(), post_panes.len());
105
106 for (pre, post) in zip(pre_panes, post_panes) {
107 match (pre, post) {
108 (
109 SerializedPaneLayout::Group {
110 axis: pre_axis,
111 flexes: pre_flexes,
112 children: _,
113 },
114 SerializedPaneLayout::Group {
115 axis: post_axis,
116 flexes: post_flexes,
117 children: _,
118 },
119 ) => {
120 assert_ne!(pre_axis, post_axis);
121 assert_eq!(pre_flexes, post_flexes);
122 }
123 (SerializedPaneLayout::Pane(pre_pane), SerializedPaneLayout::Pane(post_pane)) => {
124 assert_eq!(pre_pane.children, post_pane.children);
125 assert_eq!(pre_pane.active_item, post_pane.active_item);
126 }
127 _ => {
128 panic!("Variants don't match")
129 }
130 }
131 }
132}