use std::time::Duration;
use crate::event::{Event, KeyEvent, KeyKind};
use crate::geometry::{Rect, Size};
use crate::runtime::{App, Command, Harness};
use crate::widget::{EventCx, MeasureCx, PaintCx, View, Widget};
use crate::widgets::{Button, TextArea, TextInput};
#[derive(Default)]
struct NewWorkspace {
name: String,
created: Vec<String>,
}
#[derive(Clone)]
enum Msg {
Name(String),
Create,
}
impl App for NewWorkspace {
type Msg = Msg;
fn update(&mut self, msg: Msg) -> Command<Msg> {
match msg {
Msg::Name(name) => self.name = name,
Msg::Create => self.created.push(std::mem::take(&mut self.name)),
}
Command::none()
}
fn view(&self, ui: &mut View<'_, Msg>) {
ui.add(
TextInput::new(&self.name).placeholder("Workspace name").on_change(Msg::Name).on_submit(|_| Msg::Create),
)
.fill_width()
.id("name");
ui.add(Button::new("Create").on_press(Msg::Create));
}
}
fn burst(text: &str) -> Vec<Event> {
text.chars()
.map(|c| match c {
'\n' => "enter".to_owned(),
' ' => "space".to_owned(),
c => c.to_string(),
})
.map(|chord| Event::Key(KeyEvent::press(&chord)))
.collect()
}
fn form() -> Harness<NewWorkspace> {
let mut h = Harness::new(NewWorkspace::default(), 40, 4);
let (x, y) = h.find("Workspace name").expect("the field shows its placeholder");
h.click(x, y);
h
}
#[test]
fn every_key_of_a_burst_reaches_a_controlled_field() {
let mut h = form();
h.events(&burst("demo"));
assert_eq!(h.app().name, "demo");
assert!(h.screen().contains("demo"), "{}", h.screen());
h.events(&burst("-api"));
assert_eq!(h.app().name, "demo-api", "a second burst continues where the first ended");
}
#[test]
fn enter_in_the_same_burst_submits_everything_typed_before_it() {
let mut h = form();
h.events(&burst("demo\n"));
assert_eq!(h.app().created, ["demo"]);
}
#[test]
fn spaces_of_a_burst_reach_a_text_field() {
let mut h = form();
h.events(&burst("a b c"));
assert_eq!(h.app().name, "a b c");
h.events(&burst(" d"));
assert_eq!(h.app().name, "a b c d", "two spaces in a row are two spaces");
}
#[test]
fn a_space_the_terminal_repeats_types_into_a_text_field() {
let mut h = form();
h.type_text("a").press("space");
h.key(KeyEvent { kind: KeyKind::Repeat, ..KeyEvent::press("space") });
assert_eq!(h.app().name, "a ");
}
#[derive(Default)]
struct Notes {
text: String,
}
impl App for Notes {
type Msg = String;
fn update(&mut self, text: String) -> Command<String> {
self.text = text;
Command::none()
}
fn view(&self, ui: &mut View<'_, String>) {
ui.add(TextArea::new(&self.text).on_change(|text| text)).fill();
}
}
#[test]
fn both_enters_of_a_burst_reach_a_text_area() {
let mut h = Harness::new(Notes::default(), 30, 6);
h.press("tab");
h.events(&burst("one\n\ntwo"));
assert_eq!(h.app().text, "one\n\ntwo");
}
struct Recorder;
impl Widget<char> for Recorder {
fn measure(&self, _cx: &mut MeasureCx<'_>, available: Size) -> Size {
available
}
fn paint(&self, cx: &mut PaintCx<'_>, area: Rect) {
cx.register_hit(area);
}
fn event(&self, cx: &mut EventCx<'_, char>, event: &Event) -> bool {
match event {
Event::Key(key) if key.text.is_some() => {
cx.emit(key.text.unwrap_or_default());
true
}
_ => false,
}
}
fn focusable(&self) -> bool {
true
}
}
#[derive(Default)]
struct Recorded(String);
impl App for Recorded {
type Msg = char;
fn update(&mut self, c: char) -> Command<char> {
self.0.push(c);
Command::none()
}
fn view(&self, ui: &mut View<'_, char>) {
ui.add(Recorder).fill();
}
}
#[test]
fn a_key_between_two_spaces_shows_neither_is_held() {
let mut h = Harness::new(Recorded::default(), 10, 1);
h.press("tab");
h.events(&burst("a b c"));
assert_eq!(h.app().0, "a b c");
}
#[derive(Default)]
struct Counter(u32);
impl App for Counter {
type Msg = ();
fn update(&mut self, (): ()) -> Command<()> {
self.0 += 1;
Command::none()
}
fn view(&self, ui: &mut View<'_, ()>) {
ui.add(Button::new("Save").on_press(()));
}
}
#[test]
fn an_enter_the_terminal_reports_as_a_repeat_does_not_press_a_button_again() {
let mut h = Harness::new(Counter::default(), 20, 1);
h.press("tab").press("enter");
assert_eq!(h.app().0, 1);
h.advance(Duration::from_secs(1));
h.key(KeyEvent { kind: KeyKind::Repeat, ..KeyEvent::press("enter") });
assert_eq!(h.app().0, 1, "a held Enter presses once");
h.press("enter");
assert_eq!(h.app().0, 2, "a new press still presses");
}