Make the Rust client the sole app
This commit is contained in:
1 parent
a8602c1626
commit
d8bb1699a8
230 files changed
+762
-27300
No files matched your search
@@ -0,0 +1,166 @@
|
||||
use ai_app::ui::fixture::{PHONE_FRAME_MS, PHONE_SCALE, phone_size};
|
||||
use iris::harness::{Harness, TouchAction, TouchScript};
|
||||
use iris::prelude::*;
|
||||
use iris::sense::DRAG_SLOP;
|
||||
|
||||
fn opened() -> (Harness, ai_app::ui::TranscriptScreen) {
|
||||
let mut h = Harness::new(phone_size(), PHONE_SCALE);
|
||||
let opened = ai_app::ui::fixture::open(&mut h.rsc, &mut h.state).expect("the fixture folds");
|
||||
h.frame(0);
|
||||
h.frame(PHONE_FRAME_MS);
|
||||
(h, opened.screen)
|
||||
}
|
||||
|
||||
fn tracked_row(h: &mut Harness, screen: &ai_app::ui::TranscriptScreen) -> (RowKey, f32) {
|
||||
let middle = phone_size().y / 2.0;
|
||||
let list = (screen.list)(&mut h.rsc);
|
||||
let key = list.key_at(middle).expect("a row under the viewport");
|
||||
let (top, _) = list.extent(key).expect("that row has an extent");
|
||||
(key, top)
|
||||
}
|
||||
|
||||
fn row_top(h: &mut Harness, screen: &ai_app::ui::TranscriptScreen, key: RowKey) -> f32 {
|
||||
(screen.list)(&mut h.rsc)
|
||||
.extent(key)
|
||||
.expect("the tracked row is still loaded")
|
||||
.0
|
||||
}
|
||||
|
||||
const STEP: f32 = 2.0;
|
||||
const SAMPLES: usize = 3;
|
||||
const CATCH_X: f32 = 540.0;
|
||||
|
||||
fn drag_from(
|
||||
h: &mut Harness,
|
||||
screen: &ai_app::ui::TranscriptScreen,
|
||||
key: RowKey,
|
||||
y0: f32,
|
||||
t0: u64,
|
||||
expect_tracking: bool,
|
||||
) -> u64 {
|
||||
let before = row_top(h, screen, key);
|
||||
h.touch(TouchAction::Down, Vec2::new(CATCH_X, y0), t0);
|
||||
assert_eq!(
|
||||
row_top(h, screen, key),
|
||||
before,
|
||||
"the down itself must not move the content, only stop it"
|
||||
);
|
||||
let mut t = t0;
|
||||
for i in 1..=SAMPLES {
|
||||
let moved = STEP * i as f32;
|
||||
t = t0 + 8 * i as u64;
|
||||
h.touch(TouchAction::Move, Vec2::new(CATCH_X, y0 + moved), t);
|
||||
let travelled = row_top(h, screen, key) - before;
|
||||
if expect_tracking {
|
||||
assert!(
|
||||
(travelled - moved).abs() < 0.5,
|
||||
"sample {i}: the finger has moved {moved}px since the down and the content \
|
||||
{travelled:.1}px -- it is not pinned to the finger"
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
travelled.abs() < 0.5,
|
||||
"sample {i}: a {moved}px drag is inside DRAG_SLOP ({DRAG_SLOP}px) and must move \
|
||||
nothing, but the content moved {travelled:.1}px"
|
||||
);
|
||||
}
|
||||
}
|
||||
t += 8;
|
||||
h.touch(
|
||||
TouchAction::Up,
|
||||
Vec2::new(CATCH_X, y0 + STEP * SAMPLES as f32),
|
||||
t,
|
||||
);
|
||||
t
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_press_on_a_flinging_list_pins_the_content_to_the_finger() {
|
||||
let (mut h, screen) = opened();
|
||||
|
||||
let flick = TouchScript::parse(include_str!("../touch/flick-120hz.touch"))
|
||||
.unwrap_or_else(|e| panic!("flick-120hz.touch: {e}"));
|
||||
h.replay(&flick);
|
||||
|
||||
let catch_at = flick.end_ms() + 150;
|
||||
h.frames_until(
|
||||
flick.end_ms() + PHONE_FRAME_MS,
|
||||
catch_at - PHONE_FRAME_MS,
|
||||
PHONE_FRAME_MS,
|
||||
);
|
||||
assert!(
|
||||
(screen.list)(&mut h.rsc).is_scrolling(),
|
||||
"the fling must still be running 150ms in, or this test catches nothing"
|
||||
);
|
||||
|
||||
let (key, _) = tracked_row(&mut h, &screen);
|
||||
drag_from(&mut h, &screen, key, 1200.0, catch_at, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_catch_that_never_moved_is_not_a_tap_and_does_not_fling() {
|
||||
let (mut h, screen) = opened();
|
||||
|
||||
let flick = TouchScript::parse(include_str!("../touch/flick-120hz.touch"))
|
||||
.unwrap_or_else(|e| panic!("flick-120hz.touch: {e}"));
|
||||
h.replay(&flick);
|
||||
let catch_at = flick.end_ms() + 150;
|
||||
h.frames_until(
|
||||
flick.end_ms() + PHONE_FRAME_MS,
|
||||
catch_at - PHONE_FRAME_MS,
|
||||
PHONE_FRAME_MS,
|
||||
);
|
||||
assert!(
|
||||
(screen.list)(&mut h.rsc).is_scrolling(),
|
||||
"the fling must still be running 150ms in, or this test catches nothing"
|
||||
);
|
||||
|
||||
let (key, _) = tracked_row(&mut h, &screen);
|
||||
h.touch(TouchAction::Down, Vec2::new(CATCH_X, 1200.0), catch_at);
|
||||
let stopped_at = row_top(&mut h, &screen, key);
|
||||
h.touch(TouchAction::Up, Vec2::new(CATCH_X, 1200.0), catch_at + 8);
|
||||
|
||||
assert_eq!(
|
||||
(screen.list)(&mut h.rsc).fling_velocity(),
|
||||
None,
|
||||
"a press that stopped a fling and moved nothing must not start another"
|
||||
);
|
||||
h.frames_until(catch_at + 16, catch_at + 500, PHONE_FRAME_MS);
|
||||
assert!(
|
||||
(row_top(&mut h, &screen, key) - stopped_at).abs() < 0.5,
|
||||
"the content moved after a catch was released without moving"
|
||||
);
|
||||
assert_eq!(
|
||||
h.state.opened_urls,
|
||||
Vec::<String>::new(),
|
||||
"a catch is not a tap: nothing under it may be followed"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_same_small_drag_on_a_settled_list_moves_nothing() {
|
||||
let (mut h, screen) = opened();
|
||||
|
||||
let flick = TouchScript::parse(include_str!("../touch/flick-120hz.touch"))
|
||||
.unwrap_or_else(|e| panic!("flick-120hz.touch: {e}"));
|
||||
h.replay(&flick);
|
||||
let settled = h.frames_until(
|
||||
flick.end_ms() + PHONE_FRAME_MS,
|
||||
flick.end_ms() + 4000,
|
||||
PHONE_FRAME_MS,
|
||||
);
|
||||
assert!(
|
||||
!(screen.list)(&mut h.rsc).is_scrolling(),
|
||||
"the fling must have stopped, or this is the same case as the test above"
|
||||
);
|
||||
|
||||
let (key, _) = tracked_row(&mut h, &screen);
|
||||
drag_from(
|
||||
&mut h,
|
||||
&screen,
|
||||
key,
|
||||
1200.0,
|
||||
settled + PHONE_FRAME_MS,
|
||||
false,
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user