Misc · Codes and checks: a QR code scanner and a captcha

misc::QrCodeScanner reads QR codes with rqrr 0.11 from the frames the
host hands in, one at a time off the main thread, and hands each code
to the owner once. misc::Captcha shows the owner's picture over an
answer field that empties and keeps focus with each answer; the owner
says how it stood. BarcodeDisplay, Signature and Rating Widget point
to their homes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-09-28 01:40:15 -04:00
1 parent 854f44ed6c
commit 621c8406bb
14 files changed
+785 -10

No files matched your search

+135
View File
@@ -0,0 +1,135 @@
use std::{
cell::{Cell, RefCell},
sync::Arc,
};
use gpui::{AnyElement, IntoElement, RenderImage, TestAppContext, VisualTestContext};
use super::{at_root, press, settle, shown, stage};
use crate::misc::{Captcha, CaptchaState, QrCodeScanner, scanner::frame_of};
thread_local! {
static FRAME: RefCell<Option<Arc<RenderImage>>> = const { RefCell::new(None) };
static SAID: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };
static STATE: Cell<CaptchaState> = const { Cell::new(CaptchaState::Asking) };
}
fn said() -> Vec<String> {
SAID.with(|said| said.borrow().clone())
}
fn say(text: &str) {
SAID.with(|said| said.borrow_mut().push(text.to_string()));
}
/// Hands the stage a new frame, or state, and lets it draw and read.
fn show(cx: &mut VisualTestContext) {
cx.update(|window, _| window.refresh());
settle(cx);
}
fn scanner() -> AnyElement {
let scanner = QrCodeScanner::new("scanner", 1.0).on_scan(|text, _, _| say(text));
match FRAME.with(|frame| frame.borrow().clone()) {
Some(frame) => scanner.frame(frame),
None => scanner,
}
.into_any_element()
}
/// Frames read off the main thread; a code goes to the owner once, and a new one after it.
#[gpui::test]
fn a_scanner_reads_each_code_once(cx: &mut TestAppContext) {
FRAME.with(|frame| frame.replace(Some(frame_of("first"))));
let (_, cx) = stage(scanner, cx);
assert_eq!(said(), ["first"]);
assert!(shown("scanned-first", cx));
FRAME.with(|frame| frame.replace(Some(frame_of("first"))));
show(cx);
assert_eq!(
said(),
["first"],
"a new frame of the same code says nothing"
);
FRAME.with(|frame| frame.replace(Some(frame_of("second"))));
show(cx);
assert_eq!(said(), ["first", "second"]);
}
/// A frame that comes while one is read waits: the read's end redraws, and the newest frame is read next.
#[gpui::test]
fn a_frame_that_comes_mid_read_is_read_next(cx: &mut TestAppContext) {
let (_, cx) = stage(scanner, cx);
for text in ["first", "second"] {
FRAME.with(|frame| frame.replace(Some(frame_of(text))));
cx.update(|window, _| window.refresh());
}
assert!(said().is_empty(), "both frames drew before any read ended");
cx.run_until_parked();
assert_eq!(said(), ["first", "second"], "only the read's end redrew");
}
fn captcha() -> AnyElement {
Captcha::new("captcha", frame_of("W7XK"), 1.0)
.state(STATE.get())
.on_answer(|text, _, _| say(text))
.into_any_element()
}
/// Enter hands the answer over and empties the field, which keeps focus through the owner's verdict.
#[gpui::test]
fn a_captcha_hands_over_answers_and_keeps_focus(cx: &mut TestAppContext) {
let (_, cx) = stage(captcha, cx);
press("tab", cx);
press("enter", cx);
assert!(said().is_empty(), "nothing typed, nothing handed over");
cx.simulate_input(" w7xk ");
press("enter", cx);
assert_eq!(said(), ["w7xk"]);
STATE.set(CaptchaState::Wrong);
show(cx);
assert!(shown("captcha-wrong", cx));
cx.simulate_input("W7XK");
press("enter", cx);
assert_eq!(
said(),
["w7xk", "W7XK"],
"the field emptied for the next try"
);
STATE.set(CaptchaState::Passed);
show(cx);
assert!(
shown("captcha-verified", cx) && !at_root(cx),
"the field kept focus"
);
cx.simulate_input("again");
press("enter", cx);
assert_eq!(said().len(), 2, "a passed captcha takes no more answers");
}
/// Enter on Verify hands the answer over and focus to the emptied field, as Verify rests.
#[gpui::test]
fn verify_hands_focus_to_the_field(cx: &mut TestAppContext) {
let (_, cx) = stage(captcha, cx);
press("tab", cx);
cx.simulate_input("W7XK");
press("tab", cx);
press("enter", cx);
assert_eq!(said(), ["W7XK"]);
assert!(!at_root(cx), "focus went to the field, not the root");
}
/// Verify spins while the owner checks, and its mark keeps its focus once passed.
#[gpui::test]
fn verify_keeps_its_focus_through_the_check(cx: &mut TestAppContext) {
let (_, cx) = stage(captcha, cx);
press("tab", cx);
cx.simulate_input("W7XK");
press("tab", cx);
STATE.set(CaptchaState::Checking);
show(cx);
assert!(!at_root(cx), "a spinning Verify stays a stop");
STATE.set(CaptchaState::Passed);
show(cx);
assert!(!at_root(cx), "the Verified mark took Verify's focus");
}