Files
Ely-GPUI-Components/src/git/tests.rs
T

176 lines
5.6 KiB
Rust

use gpui::{
Context, IntoElement, KeyBinding, KeyUpEvent, Keystroke, ParentElement, Render, Styled,
TestAppContext, VisualTestContext, Window, div, px,
};
use super::DiffViewer;
use crate::{forms, primitives::FocusNext, theme::Theme};
/// A diff whose first stretch folds, and the folds asked open.
struct Folded {
opened: Vec<usize>,
}
impl Render for Folded {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let view = cx.entity();
let old: String = (0..20).map(|ix| format!("line {ix}\n")).collect();
let new = old.replace("line 18", "line eighteen");
div().w(px(480.0)).h(px(320.0)).child(
DiffViewer::new("diff", "a.rs", &old, &new)
.headless()
.on_open(move |ix, _, cx| view.update(cx, |folded, _| folded.opened.push(ix))),
)
}
}
fn settle(cx: &mut VisualTestContext) {
cx.run_until_parked();
cx.update(|window, _| window.refresh());
cx.run_until_parked();
}
#[gpui::test]
fn a_fold_opens_from_the_keyboard(cx: &mut TestAppContext) {
cx.update(|cx| {
Theme::init(cx);
forms::bind_keys(cx);
cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]);
});
let (view, cx) = cx.add_window_view(|_, _| Folded { opened: Vec::new() });
cx.update(|window, _| window.activate_window());
settle(cx);
cx.update(|window, cx| window.focus_next(cx));
settle(cx);
cx.simulate_keystrokes("enter");
settle(cx);
cx.simulate_event(KeyUpEvent {
keystroke: Keystroke::parse("enter").expect("a key"),
});
settle(cx);
assert_eq!(view.read_with(cx, |folded, _| folded.opened.clone()), [0]);
}
/// A blame from before the file changed: an owner too few, and one past the blames.
struct Behind;
impl Render for Behind {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
let blame = super::Blame {
commit: "a1".into(),
author: "Ann".into(),
when: "today".into(),
subject: "first".into(),
age: 0.0,
};
div().w(px(600.0)).child(
super::BlameView::new("blame", "one\ntwo\nthree\nfour", [0, 3, 0], [blame]).current(3),
)
}
}
#[gpui::test]
fn a_blame_that_lags_its_code_draws_every_line(cx: &mut TestAppContext) {
cx.update(Theme::init);
let (_, cx) = cx.add_window_view(|_, _| Behind);
cx.run_until_parked();
}
/// Every section of a changes list, each with one file.
struct Sorted;
impl Render for Sorted {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
use crate::lists::GitStatus;
let file = |path: &str, status| super::Changed {
path: path.to_string().into(),
status,
lines: Some((1, 0)),
};
div().w(px(420.0)).child(
super::ChangesList::new(
"changes",
[file("a.rs", GitStatus::Modified)],
[file("b.rs", GitStatus::Modified)],
)
.conflicted([file("c.rs", GitStatus::Conflicted)])
.untracked([file("d.rs", GitStatus::Untracked)])
.ignored([super::Changed {
lines: None,
..file("target/", GitStatus::Untracked)
}]),
)
}
}
#[gpui::test]
fn every_section_draws_with_its_own_words(cx: &mut TestAppContext) {
cx.update(Theme::init);
let (_, cx) = cx.add_window_view(|_, _| Sorted);
settle(cx);
}
/// Lines and hunks pressed, from stretches made elsewhere.
#[derive(Default)]
struct Picking {
lines: Vec<((usize, usize), bool)>,
hunks: Vec<usize>,
}
impl Render for Picking {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let (lines, hunks) = (cx.entity(), cx.entity());
let stretches = std::rc::Rc::new(super::diff("a\nb\n", "a\nc\n", 1));
div().w(px(480.0)).h(px(320.0)).child(
DiffViewer::from_stretches("picking", "a.txt", stretches)
.selected([(0, 2)])
.on_line(move |place, shift, _, cx| {
lines.update(cx, |picking, _| picking.lines.push((place, shift)))
})
.hunk_action("Stage", move |hunk, _, cx| {
hunks.update(cx, |picking, _| picking.hunks.push(hunk))
}),
)
}
}
#[gpui::test]
fn changed_lines_and_hunks_answer_presses(cx: &mut TestAppContext) {
cx.update(|cx| {
Theme::init(cx);
forms::bind_keys(cx);
cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]);
});
let (view, cx) = cx.add_window_view(|_, _| Picking::default());
cx.update(|window, _| window.activate_window());
settle(cx);
let press = |cx: &mut VisualTestContext, key: &str| {
cx.simulate_keystrokes(key);
settle(cx);
cx.simulate_event(KeyUpEvent {
keystroke: Keystroke::parse(key).expect("a key"),
});
settle(cx);
};
// Past the two layout segments: the hunk's button, then its lines.
let next = |cx: &mut VisualTestContext| {
cx.update(|window, cx| window.focus_next(cx));
settle(cx);
};
(0..3).for_each(|_| next(cx));
press(cx, "enter");
next(cx);
press(cx, "enter");
next(cx);
press(cx, "enter");
let (lines, hunks) = view.read_with(cx, |picking, _| {
(picking.lines.clone(), picking.hunks.clone())
});
assert_eq!(hunks, [0], "the hunk's button");
assert_eq!(
lines,
[((0, 1), false), ((0, 2), false)],
"removed, then added"
);
}