Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:31:47.726Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

test.rs

294 lines · 9.8 KB · rust
1pub mod editor_lsp_test_context;
2pub mod editor_test_context;
3
4use std::{rc::Rc, sync::LazyLock};
5
6pub use crate::rust_analyzer_ext::expand_macro_recursively;
7use crate::{
8    DisplayPoint, Editor, EditorMode, FoldPlaceholder, MultiBuffer, SelectionEffects, Size,
9    display_map::{Block, CustomBlockId, DisplayMap, DisplayRow, DisplaySnapshot, ToDisplayPoint},
10};
11use collections::HashMap;
12use gpui::{
13    AppContext as _, Context, Entity, EntityId, Font, FontFeatures, FontStyle, FontWeight, Pixels,
14    VisualTestContext, Window, font, size,
15};
16use multi_buffer::MultiBufferOffset;
17use pretty_assertions::assert_eq;
18use project::{Project, project_settings::DiagnosticSeverity};
19use ui::{App, BorrowAppContext, IntoElement, px};
20use util::test::{generate_marked_text, marked_text_offsets, marked_text_ranges};
21
22#[cfg(test)]
23#[ctor::ctor(unsafe)]
24fn init_logger() {
25    zlog::init_test();
26}
27
28pub fn test_font() -> Font {
29    static TEST_FONT: LazyLock<Font> = LazyLock::new(|| {
30        #[cfg(not(target_os = "windows"))]
31        {
32            font("Helvetica")
33        }
34
35        #[cfg(target_os = "windows")]
36        {
37            font("Courier New")
38        }
39    });
40
41    TEST_FONT.clone()
42}
43
44// Returns a snapshot from text containing '|' character markers with the markers removed, and DisplayPoints for each one.
45#[track_caller]
46pub fn marked_display_snapshot(
47    text: &str,
48    cx: &mut gpui::App,
49) -> (DisplaySnapshot, Vec<DisplayPoint>) {
50    let (unmarked_text, markers) = marked_text_offsets(text);
51
52    let font = Font {
53        family: ".ZedMono".into(),
54        features: FontFeatures::default(),
55        fallbacks: None,
56        weight: FontWeight::default(),
57        style: FontStyle::default(),
58    };
59    let font_size: Pixels = 14usize.into();
60
61    let buffer = MultiBuffer::build_simple(&unmarked_text, cx);
62    let display_map = cx.new(|cx| {
63        DisplayMap::new(
64            buffer,
65            font,
66            font_size,
67            None,
68            1,
69            1,
70            FoldPlaceholder::test(),
71            DiagnosticSeverity::Warning,
72            cx,
73        )
74    });
75    let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
76    let markers = markers
77        .into_iter()
78        .map(|offset| MultiBufferOffset(offset).to_display_point(&snapshot))
79        .collect();
80
81    (snapshot, markers)
82}
83
84#[track_caller]
85pub fn select_ranges(
86    editor: &mut Editor,
87    marked_text: &str,
88    window: &mut Window,
89    cx: &mut Context<Editor>,
90) {
91    let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
92    assert_eq!(editor.text(cx), unmarked_text);
93    editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
94        s.select_ranges(
95            text_ranges
96                .into_iter()
97                .map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end)),
98        )
99    });
100}
101
102#[track_caller]
103pub fn assert_text_with_selections(
104    editor: &mut Editor,
105    marked_text: &str,
106    cx: &mut Context<Editor>,
107) {
108    let (unmarked_text, _text_ranges) = marked_text_ranges(marked_text, true);
109    assert_eq!(editor.text(cx), unmarked_text, "text doesn't match");
110    let actual = generate_marked_text(
111        &editor.text(cx),
112        &editor
113            .selections
114            .ranges::<MultiBufferOffset>(&editor.display_snapshot(cx))
115            .into_iter()
116            .map(|range| range.start.0..range.end.0)
117            .collect::<Vec<_>>(),
118        marked_text.contains("«"),
119    );
120    assert_eq!(actual, marked_text, "Selections don't match");
121}
122
123#[cfg(any(test, feature = "test-support"))]
124pub(crate) fn build_editor(
125    buffer: Entity<MultiBuffer>,
126    window: &mut Window,
127    cx: &mut Context<Editor>,
128) -> Editor {
129    Editor::new(EditorMode::full(), buffer, None, window, cx)
130}
131
132pub(crate) fn build_editor_with_project(
133    project: Entity<Project>,
134    buffer: Entity<MultiBuffer>,
135    window: &mut Window,
136    cx: &mut Context<Editor>,
137) -> Editor {
138    Editor::new(EditorMode::full(), buffer, Some(project), window, cx)
139}
140
141#[derive(Default)]
142struct TestBlockContent(
143    HashMap<(EntityId, CustomBlockId), Rc<dyn Fn(&mut VisualTestContext) -> String>>,
144);
145
146impl gpui::Global for TestBlockContent {}
147
148pub fn set_block_content_for_tests(
149    editor: &Entity<Editor>,
150    id: CustomBlockId,
151    cx: &mut App,
152    f: impl Fn(&mut VisualTestContext) -> String + 'static,
153) {
154    cx.update_default_global::<TestBlockContent, _>(|bc, _| {
155        bc.0.insert((editor.entity_id(), id), Rc::new(f))
156    });
157}
158
159pub fn block_content_for_tests(
160    editor: &Entity<Editor>,
161    id: CustomBlockId,
162    cx: &mut VisualTestContext,
163) -> Option<String> {
164    let f = cx.update(|_, cx| {
165        cx.default_global::<TestBlockContent>()
166            .0
167            .get(&(editor.entity_id(), id))
168            .cloned()
169    })?;
170    Some(f(cx))
171}
172
173pub fn editor_content_with_blocks(editor: &Entity<Editor>, cx: &mut VisualTestContext) -> String {
174    editor_content_with_blocks_and_width(editor, px(3000.), cx)
175}
176
177pub fn editor_content_with_blocks_and_width(
178    editor: &Entity<Editor>,
179    width: Pixels,
180    cx: &mut VisualTestContext,
181) -> String {
182    editor_content_with_blocks_and_size(editor, size(width, px(3000.0)), cx)
183}
184
185pub fn editor_content_with_blocks_and_size(
186    editor: &Entity<Editor>,
187    draw_size: Size<Pixels>,
188    cx: &mut VisualTestContext,
189) -> String {
190    cx.simulate_resize(draw_size);
191    cx.draw(gpui::Point::default(), draw_size, |_, _| {
192        editor.clone().into_any_element()
193    });
194    let (snapshot, mut lines, blocks) = editor.update_in(cx, |editor, window, cx| {
195        let snapshot = editor.snapshot(window, cx);
196        let text = editor.display_text(cx);
197        let lines = text.lines().map(|s| s.to_string()).collect::<Vec<String>>();
198        let blocks = snapshot
199            .blocks_in_range(DisplayRow(0)..snapshot.max_point().row())
200            .map(|(row, block)| (row, block.clone()))
201            .collect::<Vec<_>>();
202        (snapshot, lines, blocks)
203    });
204    for (row, block) in blocks {
205        match block {
206            Block::Custom(custom_block) => {
207                let content = block_content_for_tests(editor, custom_block.id, cx)
208                    .expect("block content not found");
209                // 2: "related info 1 for diagnostic 0"
210                if let Some(height) = custom_block.height {
211                    if height == 0 {
212                        lines[row.0 as usize - 1].push_str(" § ");
213                        lines[row.0 as usize - 1].push_str(&content);
214                    } else {
215                        let block_lines = content.lines().collect::<Vec<_>>();
216                        assert_eq!(block_lines.len(), height as usize);
217                        lines[row.0 as usize].push_str("§ ");
218                        lines[row.0 as usize].push_str(block_lines[0].trim_end());
219                        for i in 1..height as usize {
220                            if row.0 as usize + i >= lines.len() {
221                                lines.push("".to_string());
222                            };
223                            lines[row.0 as usize + i].push_str("§ ");
224                            lines[row.0 as usize + i].push_str(block_lines[i].trim_end());
225                        }
226                    }
227                }
228            }
229            Block::FoldedBuffer {
230                first_excerpt,
231                height,
232            } => {
233                while lines.len() <= row.0 as usize {
234                    lines.push(String::new());
235                }
236                lines[row.0 as usize].push_str(&cx.update(|_, cx| {
237                    format!(
238                        "§ {}",
239                        first_excerpt
240                            .buffer(snapshot.buffer_snapshot())
241                            .file()
242                            .map(|file| file.file_name(cx))
243                            .unwrap_or("<no file>")
244                    )
245                }));
246                for row in row.0 + 1..row.0 + height {
247                    while lines.len() <= row as usize {
248                        lines.push(String::new());
249                    }
250                    lines[row as usize].push_str("§ -----");
251                }
252            }
253            Block::ExcerptBoundary { height, .. } => {
254                for row in row.0..row.0 + height {
255                    while lines.len() <= row as usize {
256                        lines.push(String::new());
257                    }
258                    lines[row as usize].push_str("§ -----");
259                }
260            }
261            Block::BufferHeader { excerpt, height } => {
262                while lines.len() <= row.0 as usize {
263                    lines.push(String::new());
264                }
265                lines[row.0 as usize].push_str(&cx.update(|_, cx| {
266                    format!(
267                        "§ {}",
268                        excerpt
269                            .buffer(snapshot.buffer_snapshot())
270                            .file()
271                            .map(|file| file.file_name(cx))
272                            .unwrap_or("<no file>")
273                    )
274                }));
275                for row in row.0 + 1..row.0 + height {
276                    while lines.len() <= row as usize {
277                        lines.push(String::new());
278                    }
279                    lines[row as usize].push_str("§ -----");
280                }
281            }
282            Block::Spacer { height, .. } => {
283                for row in row.0..row.0 + height {
284                    while lines.len() <= row as usize {
285                        lines.push(String::new());
286                    }
287                    lines[row as usize].push_str("§ spacer");
288                }
289            }
290        }
291    }
292    lines.join("\n")
293}
294
Served at tenant.openagents/omega Member data and write actions are omitted.