Files
Ely-GPUI-Components/src/documents/document/tests/cells.rs
T
ZacharyZhang-NYandClaude Opus 5.5 f1771b3880
CI / platforms (windows-latest) (push) Failing after 10s
CI / site (push) Successful in 22s
CI / crate (push) Failing after 11m22s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s
Documents: cells keep their row's pipes; long reads finish cell moves
An emptied bare edge cell writes a pipe so its column stays. The caret
reads the escaped write-back. A right press beside an edited cell keeps
its place. A move that waits on a long read opens once the read lands.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 02:09:43 -04:00

303 lines
11 KiB
Rust

//! A press in a table opens only its cell (R6.1).
use gpui::{Entity, Modifiers, MouseButton, TestAppContext, VisualTestContext, point, px};
use super::{open, opened, point::heard, text};
use crate::documents::{MarkdownDocument, MarkdownMode};
const TABLE: &str = "| a | **bold** |\n| --- | --- |\n| c | |\n";
/// Presses cell `row`, `column` of the first table.
fn press_cell(row: usize, column: usize, cx: &mut VisualTestContext) {
press_cell_with(row, column, MouseButton::Left, cx);
}
fn press_cell_with(row: usize, column: usize, button: MouseButton, cx: &mut VisualTestContext) {
let name = format!("markdown-cell-0-{row}-{column}");
let bounds = cx
.debug_bounds(Box::leak(name.into_boxed_str()))
.expect("the cell is drawn");
let at = point(bounds.left() + px(2.0), bounds.top() + px(2.0));
cx.simulate_mouse_down(at, button, Modifiers::none());
cx.simulate_mouse_up(at, button, Modifiers::none());
cx.run_until_parked();
}
/// Presses the open cell's field `x` past its left.
fn press_field(x: f32, button: MouseButton, cx: &mut VisualTestContext) {
let field = cx
.debug_bounds("markdown-open-cell")
.expect("a cell is open");
let at = point(field.left() + px(x), field.top() + px(10.0));
cx.simulate_mouse_down(at, button, Modifiers::none());
cx.simulate_mouse_up(at, button, Modifiers::none());
cx.run_until_parked();
}
fn caret(document: &Entity<MarkdownDocument>, cx: &mut VisualTestContext) -> usize {
document.read_with(cx, |document, cx| {
document
.open
.as_ref()
.expect("open")
.input
.read(cx)
.cursor()
})
}
/// Where byte `k` of the open cell lies.
fn x_of(document: &Entity<MarkdownDocument>, k: usize, cx: &mut VisualTestContext) -> f32 {
(0..400)
.map(|step| step as f32)
.find(|&x| {
press_field(x, MouseButton::Left, cx);
caret(document, cx) == k
})
.expect("the byte is drawn")
}
#[gpui::test]
fn a_press_opens_its_cell_and_writes_one_undo_step(cx: &mut TestAppContext) {
let (document, cx) = open(TABLE, MarkdownMode::Visual, cx);
press_cell(0, 1, cx);
assert_eq!(opened(&document, cx), "**bold**");
assert!(
cx.debug_bounds("markdown-cell-0-0-0").is_some(),
"the rest stays drawn"
);
press_cell(1, 1, cx);
assert_eq!(opened(&document, cx), "");
cx.simulate_input("x|y");
assert_eq!(
text(&document, cx),
"| a | **bold** |\n| --- | --- |\n| c | x\\|y |\n"
);
cx.simulate_keystrokes("escape");
let editor = document.read_with(cx, |document, _| document.editor().clone());
editor.update(cx, |editor, cx| editor.undo(cx));
assert_eq!(text(&document, cx), TABLE);
}
#[gpui::test]
fn tab_and_arrows_walk_the_cells(cx: &mut TestAppContext) {
let (document, cx) = open(TABLE, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
assert_eq!(opened(&document, cx), "a");
cx.simulate_keystrokes("tab");
assert_eq!(opened(&document, cx), "**bold**");
cx.simulate_keystrokes("shift-tab");
assert_eq!(opened(&document, cx), "a");
cx.simulate_keystrokes("down");
assert_eq!(opened(&document, cx), "c");
cx.simulate_keystrokes("enter");
assert!(document.read_with(cx, |document, _| document.open.is_none()));
assert_eq!(text(&document, cx), TABLE);
}
const WORDS: &str = "| alpha | beta |\n| --- | --- |\n| c | d |\n";
#[gpui::test]
fn a_press_in_the_open_cell_moves_its_caret_and_keeps_one_step(cx: &mut TestAppContext) {
let (document, cx) = open(WORDS, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
assert_eq!(caret(&document, cx), 5);
cx.simulate_input("X");
let x = x_of(&document, 1, cx);
press_field(x, MouseButton::Left, cx);
assert_eq!(caret(&document, cx), 1, "the cell stays open");
cx.simulate_input("Y");
cx.simulate_keystrokes("escape");
assert_eq!(
text(&document, cx),
"| aYlphaX | beta |\n| --- | --- |\n| c | d |\n"
);
let editor = document.read_with(cx, |document, _| document.editor().clone());
editor.update(cx, |editor, cx| editor.undo(cx));
assert_eq!(text(&document, cx), WORDS);
}
#[gpui::test]
fn a_match_in_a_table_opens_its_cell_selected(cx: &mut TestAppContext) {
let table = "| needle | B |\n| --- | --- |\n| C | tail |\n";
let (document, cx) = open(table, MarkdownMode::Visual, cx);
let at = table.find("needle").expect("the word");
document.update_in(cx, |document, window, cx| {
document.show_match(at..at + 6, window, cx)
});
assert_eq!(opened(&document, cx), "needle");
let picked = document.read_with(cx, |document, cx| {
document
.open
.as_ref()
.expect("open")
.input
.read(cx)
.selection()
});
assert_eq!(picked, 0..6);
}
#[gpui::test]
fn a_closing_backslash_keeps_the_table(cx: &mut TestAppContext) {
let table = "|a|b|\n|---|---|\n|c|d|\n";
let (document, cx) = open(table, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
cx.simulate_input("\\");
cx.simulate_keystrokes("escape");
assert_eq!(text(&document, cx), "|a\\\\|b|\n|---|---|\n|c|d|\n");
press_cell(0, 1, cx);
assert_eq!(opened(&document, cx), "b", "still its own cell");
}
#[gpui::test]
fn a_right_press_after_typed_pipes_finds_the_link(cx: &mut TestAppContext) {
let (document, cx) = open(WORDS, MarkdownMode::Visual, cx);
let heard = heard(&document, cx);
press_cell(1, 1, cx);
cx.simulate_keystrokes("backspace");
cx.simulate_input("||[go](https://ely.dev)");
let x = x_of(&document, 3, cx);
press_field(x, MouseButton::Right, cx);
let target = heard.borrow().last().cloned().expect("heard");
assert_eq!(target.link.as_deref(), Some("https://ely.dev"));
}
#[gpui::test]
fn a_right_press_on_a_cell_points_at_it(cx: &mut TestAppContext) {
let (document, cx) = open(WORDS, MarkdownMode::Visual, cx);
let heard = heard(&document, cx);
press_cell_with(1, 1, MouseButton::Right, cx);
let at = heard.borrow().last().expect("heard").at;
assert_eq!(at, WORDS.rfind(" d").expect("the cell") + 2);
}
#[gpui::test]
fn an_untouched_backslash_cell_keeps_its_bytes(cx: &mut TestAppContext) {
let table = "| a\\ | b |\n| --- | --- |\n| c | d |\n";
let (document, cx) = open(table, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
assert_eq!(opened(&document, cx), "a\\");
document.update_in(cx, |document, window, cx| {
document.set_mode(MarkdownMode::Source, window, cx)
});
assert_eq!(text(&document, cx), table);
}
const BARE: &str = "alpha | beta\n--- | ---\nc | d\n";
#[gpui::test]
fn tab_leaves_an_edited_first_cell_without_outer_pipes(cx: &mut TestAppContext) {
let (document, cx) = open(BARE, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
cx.simulate_input("X");
cx.simulate_keystrokes("tab");
assert_eq!(opened(&document, cx), "beta");
assert_eq!(text(&document, cx), "alphaX | beta\n--- | ---\nc | d\n");
}
#[gpui::test]
fn a_neighbour_press_leaves_an_edited_first_cell(cx: &mut TestAppContext) {
let (document, cx) = open(BARE, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
cx.simulate_input("X");
press_cell(0, 1, cx);
assert_eq!(opened(&document, cx), "beta");
}
#[gpui::test]
fn the_open_cells_padding_lands_at_its_end_in_one_step(cx: &mut TestAppContext) {
let (document, cx) = open(WORDS, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
cx.simulate_input("X");
let x = x_of(&document, 1, cx);
press_field(x, MouseButton::Left, cx);
assert_eq!(caret(&document, cx), 1);
press_cell(0, 0, cx);
assert_eq!(caret(&document, cx), 6, "the padding lands at the end");
cx.simulate_input("Y");
cx.simulate_keystrokes("escape");
assert_eq!(
text(&document, cx),
"| alphaXY | beta |\n| --- | --- |\n| c | d |\n"
);
let editor = document.read_with(cx, |document, _| document.editor().clone());
editor.update(cx, |editor, cx| editor.undo(cx));
assert_eq!(text(&document, cx), WORDS);
}
#[gpui::test]
fn a_right_press_on_the_open_cells_padding_points_at_its_end(cx: &mut TestAppContext) {
let (document, cx) = open(WORDS, MarkdownMode::Visual, cx);
let heard = heard(&document, cx);
press_cell(0, 0, cx);
cx.simulate_input("||");
press_cell_with(0, 0, MouseButton::Right, cx);
let target = heard.borrow().last().cloned().expect("heard");
assert!(target.in_table);
assert_eq!(
target.at,
WORDS.find("alpha").expect("the cell") + "alpha\\|\\|".len()
);
assert_eq!(opened(&document, cx), "alpha||", "the cell stays open");
}
#[gpui::test]
fn the_caret_after_a_typed_pipe_reads_the_escaped_cell(cx: &mut TestAppContext) {
for (typed, column) in [("|中", 5), ("|x", 5)] {
let (document, cx) = open(WORDS, MarkdownMode::Visual, cx);
press_cell(0, 0, cx);
cx.simulate_keystrokes("backspace backspace backspace backspace backspace");
cx.simulate_input(typed);
let caret = document.read_with(cx, |document, cx| document.caret(cx));
assert_eq!(caret, (0, column), "{typed}");
}
}
#[gpui::test]
fn emptied_bare_edge_cells_keep_the_table(cx: &mut TestAppContext) {
let cases = [
(0, 0, 5, "| | beta\n--- | ---\nc | d\n"),
(0, 1, 4, "alpha | |\n--- | ---\nc | d\n"),
(1, 0, 1, "alpha | beta\n--- | ---\n| | d\n"),
];
for (row, column, chars, written) in cases {
let (document, cx) = open(BARE, MarkdownMode::Visual, cx);
press_cell(row, column, cx);
for _ in 0..chars {
cx.simulate_keystrokes("backspace");
}
cx.simulate_keystrokes("escape");
assert_eq!(text(&document, cx), written);
press_cell(1, 1, cx);
assert_eq!(opened(&document, cx), "d", "{written:?} is still a table");
}
}
#[gpui::test]
fn a_right_press_beside_an_edited_cell_points(cx: &mut TestAppContext) {
let (document, cx) = open(WORDS, MarkdownMode::Visual, cx);
let heard = heard(&document, cx);
press_cell(0, 0, cx);
cx.simulate_input("X");
press_cell_with(0, 1, MouseButton::Right, cx);
let at = heard.borrow().last().expect("heard").at;
let written = "| alphaX | beta |\n| --- | --- |\n| c | d |\n";
assert_eq!(text(&document, cx), written);
assert_eq!(at, written.find("beta").expect("the cell") + 4);
}
#[gpui::test]
fn tab_in_a_long_document_opens_the_next_cell_once_read(cx: &mut TestAppContext) {
let long = format!("{WORDS}\n```\n{}\n```\n", "x".repeat(super::super::AT_ONCE));
let (document, cx) = open(&long, MarkdownMode::Visual, cx);
document.update_in(cx, |document, window, cx| document.reveal(0, window, cx));
super::frames(cx);
press_cell(0, 0, cx);
cx.simulate_input("X");
cx.simulate_keystrokes("tab");
cx.run_until_parked();
assert_eq!(opened(&document, cx), "beta");
assert!(text(&document, cx).starts_with("| alphaX | beta |"));
}