Compare commits
No commits in common. "c66ffcb3033f3637ce7f7ba489052180db74e5a8" and "20f267d5f7dce2060dc851d1c79ed47901bd4c01" have entirely different histories.
c66ffcb303
...
20f267d5f7
7 changed files with 172 additions and 1232 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,139 @@
|
||||||
//! Desktop entry point for the PDF widget test host.
|
//! Test host for the PDF page widget.
|
||||||
//!
|
//!
|
||||||
//! The app itself lives in [`nigig_pdf_makepad::test_host`] so the Android
|
//! This binary exists so `makepad_test` can drive the widget through real
|
||||||
//! build (which packages the crate's `--lib` target as a cdylib) compiles the
|
//! Makepad event delivery. Until now `handle_event` was only exercised
|
||||||
//! `app_main!` entry point too. On desktop this thin main just hands off.
|
//! indirectly: the interaction logic behind it was unit-tested, but nothing
|
||||||
|
//! proved that a click actually reaches it through `event.hits()`.
|
||||||
|
//!
|
||||||
|
//! It loads the corpus AcroForm fixture, so the widget under test has a real
|
||||||
|
//! parsed document with a link, a text field and a checkbox on it.
|
||||||
|
|
||||||
fn main() {
|
pub use makepad_widgets;
|
||||||
nigig_pdf_makepad::test_host::app_main();
|
|
||||||
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
use nigig_pdf_document::PdfDocument;
|
||||||
|
use nigig_pdf_graphics::content::parse_content_stream;
|
||||||
|
use nigig_pdf_graphics::recording::RecordingDevice;
|
||||||
|
use nigig_pdf_graphics::text::PageText;
|
||||||
|
// The accessor trait generated by `#[derive(Widget)]` must be in scope for
|
||||||
|
// `WidgetRef::pdf_page_widget()`.
|
||||||
|
use nigig_pdf_makepad::page_view::{PageContent, PdfPageAction, PdfPageWidgetWidgetRefExt};
|
||||||
|
use nigig_pdf_makepad::PdfAction;
|
||||||
|
|
||||||
|
/// The two-page AcroForm fixture. Everything interactive is on page index 1.
|
||||||
|
const FIXTURE: &[u8] = include_bytes!("../../../pdf-document/tests/acroform.pdf");
|
||||||
|
|
||||||
|
/// Which page of the fixture carries the interactive content.
|
||||||
|
const PAGE_INDEX: usize = 1;
|
||||||
|
|
||||||
|
app_main!(App);
|
||||||
|
|
||||||
|
script_mod! {
|
||||||
|
use mod.prelude.widgets.*
|
||||||
|
|
||||||
|
startup() do #(App::script_component(vm)){
|
||||||
|
ui: Root{
|
||||||
|
main_window := Window{
|
||||||
|
window.inner_size: vec2(800, 1000)
|
||||||
|
body +: {
|
||||||
|
main_view := View{
|
||||||
|
width: Fill, height: Fill
|
||||||
|
flow: Down
|
||||||
|
// The label is how a test observes what the widget
|
||||||
|
// emitted, since actions themselves are not visible
|
||||||
|
// to the Studio protocol.
|
||||||
|
action_label := Label{
|
||||||
|
text: "no action"
|
||||||
|
}
|
||||||
|
pdf_page := mod.widgets.PdfPageWidget{
|
||||||
|
width: Fill, height: Fill
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Script, ScriptHook)]
|
||||||
|
pub struct App {
|
||||||
|
#[live]
|
||||||
|
ui: WidgetRef,
|
||||||
|
#[rust]
|
||||||
|
loaded: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
/// Parse the fixture and hand the page to the widget.
|
||||||
|
fn load_fixture(&mut self, cx: &mut Cx) {
|
||||||
|
let Ok(mut doc) = PdfDocument::parse(FIXTURE) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(page) = doc.page(PAGE_INDEX) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let commands = parse_content_stream(&page.content_data)
|
||||||
|
.map(|ops| RecordingDevice::from_ops(&ops))
|
||||||
|
.unwrap_or_default();
|
||||||
|
let text = PageText::from_commands(&commands);
|
||||||
|
let annotations = doc.page_annotations(PAGE_INDEX).unwrap_or_default();
|
||||||
|
let form = doc.acroform().ok().flatten();
|
||||||
|
|
||||||
|
let widget = self.ui.pdf_page_widget(cx, ids!(pdf_page));
|
||||||
|
widget.begin_document(cx, Default::default());
|
||||||
|
widget.set_content(
|
||||||
|
cx,
|
||||||
|
PageContent {
|
||||||
|
commands,
|
||||||
|
annotations,
|
||||||
|
form,
|
||||||
|
text,
|
||||||
|
page_height: page.height(),
|
||||||
|
generation: Default::default(),
|
||||||
|
page_index: PAGE_INDEX,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mirror an emitted action into the label so a test can assert on it.
|
||||||
|
fn show_action(&mut self, cx: &mut Cx, action: &PdfAction) {
|
||||||
|
let text = match action {
|
||||||
|
PdfAction::OpenUri(uri) => format!("OpenUri: {uri}"),
|
||||||
|
PdfAction::GoToPage { page_index } => format!("GoToPage: {page_index}"),
|
||||||
|
PdfAction::GoToNamed(name) => format!("GoToNamed: {name}"),
|
||||||
|
PdfAction::FieldChanged { .. } => "FieldChanged".to_string(),
|
||||||
|
PdfAction::CopyText(t) => format!("CopyText: {t}"),
|
||||||
|
};
|
||||||
|
self.ui.label(cx, ids!(action_label)).set_text(cx, &text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppMain for App {
|
||||||
|
fn script_mod(vm: &mut ScriptVm) -> ScriptValue {
|
||||||
|
crate::makepad_widgets::script_mod(vm);
|
||||||
|
nigig_pdf_makepad::script_mod(vm);
|
||||||
|
self::script_mod(vm)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
||||||
|
// Load once, after the widget tree exists.
|
||||||
|
if !self.loaded && matches!(event, Event::Draw(_)) {
|
||||||
|
self.loaded = true;
|
||||||
|
self.load_fixture(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actions are collected from the child, not returned by
|
||||||
|
// handle_event, so they have to be captured around the call.
|
||||||
|
let actions = cx.capture_actions(|cx| {
|
||||||
|
self.ui.handle_event(cx, event, &mut Scope::empty());
|
||||||
|
});
|
||||||
|
|
||||||
|
let widget = self.ui.pdf_page_widget(cx, ids!(pdf_page));
|
||||||
|
if let Some(item) = actions.find_widget_action(widget.widget_uid()) {
|
||||||
|
if let PdfPageAction::Action(action) = item.cast::<PdfPageAction>() {
|
||||||
|
self.show_action(cx, &action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -935,30 +935,6 @@ mod tests {
|
||||||
assert!(!state.focus.is_focused());
|
assert!(!state.focus.is_focused());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hit_testing_is_keyed_by_the_page_index() {
|
|
||||||
let (mut form, _) = text_field();
|
|
||||||
// The fixture field lives on page 0 (its /P resolves to page 0). A
|
|
||||||
// state pointing at page 1 must not see it, which is the regression
|
|
||||||
// behind `set_content` syncing `interaction.page_index`.
|
|
||||||
let mut other_page = InteractionState::new(1, Viewport::default());
|
|
||||||
let (sx, sy) = other_page.viewport.to_screen(150.0, 610.0);
|
|
||||||
other_page.click(sx, sy, &[], Some(&mut form));
|
|
||||||
assert!(
|
|
||||||
!other_page.focus.is_focused(),
|
|
||||||
"a field on another page must not take focus"
|
|
||||||
);
|
|
||||||
assert_eq!(other_page.focus.field, None);
|
|
||||||
|
|
||||||
let mut same_page = InteractionState::new(0, Viewport::default());
|
|
||||||
let (sx, sy) = same_page.viewport.to_screen(150.0, 610.0);
|
|
||||||
same_page.click(sx, sy, &[], Some(&mut form));
|
|
||||||
assert!(
|
|
||||||
same_page.focus.is_focused(),
|
|
||||||
"the field on this page must take focus"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn caret_movement_inserts_at_the_right_place() {
|
fn caret_movement_inserts_at_the_right_place() {
|
||||||
let (mut form, _) = text_field();
|
let (mut form, _) = text_field();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ pub mod device;
|
||||||
pub mod interaction;
|
pub mod interaction;
|
||||||
pub mod page_view;
|
pub mod page_view;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
pub mod test_host;
|
|
||||||
|
|
||||||
pub use device::MakepadPdfDevice;
|
pub use device::MakepadPdfDevice;
|
||||||
pub use interaction::{
|
pub use interaction::{
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,6 @@ pub struct PdfPageWidget {
|
||||||
#[layout]
|
#[layout]
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
#[rust]
|
#[rust]
|
||||||
#[area]
|
|
||||||
area: Area,
|
area: Area,
|
||||||
|
|
||||||
#[redraw]
|
#[redraw]
|
||||||
|
|
@ -214,11 +213,6 @@ impl PdfPageWidget {
|
||||||
// A new page invalidates any focus or selection held on the old one.
|
// A new page invalidates any focus or selection held on the old one.
|
||||||
self.interaction.focus = Default::default();
|
self.interaction.focus = Default::default();
|
||||||
self.interaction.selection = Default::default();
|
self.interaction.selection = Default::default();
|
||||||
// Hit testing keys off the page the content belongs to, so the
|
|
||||||
// interaction viewport must track the content rather than whatever
|
|
||||||
// page was loaded before. Without this, page-1 content on a
|
|
||||||
// multi-page document hit-tests against page 0 and nothing responds.
|
|
||||||
self.interaction.page_index = self.content.page_index;
|
|
||||||
self.redraw(cx);
|
self.redraw(cx);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
@ -352,8 +346,7 @@ impl Widget for PdfPageWidget {
|
||||||
let rect = self.area.rect(cx);
|
let rect = self.area.rect(cx);
|
||||||
self.sync_viewport(rect);
|
self.sync_viewport(rect);
|
||||||
|
|
||||||
let hit = event.hits(cx, self.area);
|
match event.hits(cx, self.area) {
|
||||||
match hit {
|
|
||||||
// Cursor feedback (step 4.2).
|
// Cursor feedback (step 4.2).
|
||||||
Hit::FingerHoverIn(e) | Hit::FingerHoverOver(e) => {
|
Hit::FingerHoverIn(e) | Hit::FingerHoverOver(e) => {
|
||||||
let target = self.interaction.hover_at(
|
let target = self.interaction.hover_at(
|
||||||
|
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
//! Test host for the PDF page widget.
|
|
||||||
//!
|
|
||||||
//! Lives in the lib so the Android APK build (which packages the crate's
|
|
||||||
//! `--lib` target as a cdylib) gets the `app_main!` entry point too. The
|
|
||||||
//! desktop test binary delegates to [`app_main`] instead of duplicating the
|
|
||||||
//! app.
|
|
||||||
//!
|
|
||||||
//! It loads the corpus AcroForm fixture, so the widget under test has a real
|
|
||||||
//! parsed document with a link, a text field and a checkbox on it.
|
|
||||||
|
|
||||||
use makepad_widgets::*;
|
|
||||||
|
|
||||||
use nigig_pdf_document::PdfDocument;
|
|
||||||
use nigig_pdf_graphics::content::parse_content_stream;
|
|
||||||
use nigig_pdf_graphics::recording::RecordingDevice;
|
|
||||||
use nigig_pdf_graphics::text::PageText;
|
|
||||||
// The accessor trait generated by `#[derive(Widget)]` must be in scope for
|
|
||||||
// `WidgetRef::pdf_page_widget()`.
|
|
||||||
use crate::page_view::{PageContent, PdfPageAction, PdfPageWidgetWidgetRefExt};
|
|
||||||
use crate::PdfAction;
|
|
||||||
|
|
||||||
/// The two-page AcroForm fixture. Everything interactive is on page index 1.
|
|
||||||
const FIXTURE: &[u8] = include_bytes!("../../pdf-document/tests/acroform.pdf");
|
|
||||||
|
|
||||||
/// Which page of the fixture carries the interactive content.
|
|
||||||
const PAGE_INDEX: usize = 1;
|
|
||||||
|
|
||||||
app_main!(App);
|
|
||||||
|
|
||||||
script_mod! {
|
|
||||||
use mod.prelude.widgets.*
|
|
||||||
|
|
||||||
startup() do #(App::script_component(vm)){
|
|
||||||
ui: Root{
|
|
||||||
main_window := Window{
|
|
||||||
window.inner_size: vec2(800, 1000)
|
|
||||||
body +: {
|
|
||||||
main_view := View{
|
|
||||||
width: Fill, height: Fill
|
|
||||||
flow: Down
|
|
||||||
// The label is how a test observes what the widget
|
|
||||||
// emitted, since actions themselves are not visible
|
|
||||||
// to the Studio protocol.
|
|
||||||
action_label := Label{
|
|
||||||
text: "no action"
|
|
||||||
}
|
|
||||||
pdf_page := mod.widgets.PdfPageWidget{
|
|
||||||
width: Fill, height: Fill
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Script, ScriptHook)]
|
|
||||||
pub struct App {
|
|
||||||
#[live]
|
|
||||||
ui: WidgetRef,
|
|
||||||
#[rust]
|
|
||||||
loaded: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl App {
|
|
||||||
/// Parse the fixture and hand the page to the widget.
|
|
||||||
fn load_fixture(&mut self, cx: &mut Cx) {
|
|
||||||
let Ok(mut doc) = PdfDocument::parse(FIXTURE) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Ok(page) = doc.page(PAGE_INDEX) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let commands = parse_content_stream(&page.content_data)
|
|
||||||
.map(|ops| RecordingDevice::from_ops(&ops))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let text = PageText::from_commands(&commands);
|
|
||||||
let annotations = doc.page_annotations(PAGE_INDEX).unwrap_or_default();
|
|
||||||
let form = doc.acroform().ok().flatten();
|
|
||||||
|
|
||||||
let widget = self.ui.pdf_page_widget(cx, ids!(pdf_page));
|
|
||||||
widget.begin_document(cx, Default::default());
|
|
||||||
widget.set_content(
|
|
||||||
cx,
|
|
||||||
PageContent {
|
|
||||||
commands,
|
|
||||||
annotations,
|
|
||||||
form,
|
|
||||||
text,
|
|
||||||
page_height: page.height(),
|
|
||||||
generation: Default::default(),
|
|
||||||
page_index: PAGE_INDEX,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mirror an emitted action into the label so a test can assert on it.
|
|
||||||
fn show_action(&mut self, cx: &mut Cx, action: &PdfAction) {
|
|
||||||
let text = match action {
|
|
||||||
PdfAction::OpenUri(uri) => format!("OpenUri: {uri}"),
|
|
||||||
PdfAction::GoToPage { page_index } => format!("GoToPage: {page_index}"),
|
|
||||||
PdfAction::GoToNamed(name) => format!("GoToNamed: {name}"),
|
|
||||||
PdfAction::FieldChanged { .. } => "FieldChanged".to_string(),
|
|
||||||
PdfAction::CopyText(t) => format!("CopyText: {t}"),
|
|
||||||
};
|
|
||||||
self.ui.label(cx, ids!(action_label)).set_text(cx, &text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AppMain for App {
|
|
||||||
fn script_mod(vm: &mut ScriptVm) -> ScriptValue {
|
|
||||||
makepad_widgets::script_mod(vm);
|
|
||||||
crate::script_mod(vm);
|
|
||||||
self::script_mod(vm)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
|
||||||
// Load once, after the widget tree exists.
|
|
||||||
if !self.loaded && matches!(event, Event::Draw(_)) {
|
|
||||||
self.loaded = true;
|
|
||||||
self.load_fixture(cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions are collected from the child, not returned by
|
|
||||||
// handle_event, so they have to be captured around the call.
|
|
||||||
let actions = cx.capture_actions(|cx| {
|
|
||||||
self.ui.handle_event(cx, event, &mut Scope::empty());
|
|
||||||
});
|
|
||||||
|
|
||||||
let widget = self.ui.pdf_page_widget(cx, ids!(pdf_page));
|
|
||||||
if let Some(item) = actions.find_widget_action(widget.widget_uid()) {
|
|
||||||
if let PdfPageAction::Action(action) = item.cast::<PdfPageAction>() {
|
|
||||||
self.show_action(cx, &action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,22 +2,37 @@
|
||||||
//!
|
//!
|
||||||
//! This closes the gap carried since Phase 4: the interaction logic behind
|
//! This closes the gap carried since Phase 4: the interaction logic behind
|
||||||
//! `handle_event` was unit-tested, but nothing proved a click actually
|
//! `handle_event` was unit-tested, but nothing proved a click actually
|
||||||
//! reaches it through `event.hits()`. These tests go through the headless
|
//! reaches it through `event.hits()`. These tests go through the Studio
|
||||||
//! `makepad_test` runtime against the test host in `src/bin/nigig-pdf-makepad.rs`,
|
//! protocol against the test host in `src/bin/nigig-pdf-makepad.rs`, so the
|
||||||
//! so the whole path — event delivery, hit testing, action emission — is
|
//! whole path — event delivery, hit testing, action emission — is exercised.
|
||||||
//! exercised without a Studio hub.
|
//!
|
||||||
|
//! Headless by default. `MAKEPAD_TEST_VISIBLE=1` runs against a visible
|
||||||
|
//! Studio for debugging.
|
||||||
//!
|
//!
|
||||||
//! Run with `--test-threads=1`: each test starts its own app instance, and
|
//! Run with `--test-threads=1`: each test starts its own app instance, and
|
||||||
//! several competing for the same port produces spurious failures rather
|
//! several competing for the same port produces spurious failures rather
|
||||||
//! than real ones.
|
//! than real ones.
|
||||||
//!
|
//!
|
||||||
|
//! # Why these are `#[ignore]`
|
||||||
|
//!
|
||||||
|
//! They are ignored by default because the Studio hub cannot start an app in
|
||||||
|
//! this sandbox: the harness launches the binary with `--stdin-loop`, which
|
||||||
|
//! Makepad refuses without a Studio websocket, and the build exits 101
|
||||||
|
//! before startup. This is not specific to the PDF widget — upstream's own
|
||||||
|
//! `spreadsheet-ui` and `map` UI suites fail identically here with the same
|
||||||
|
//! error, so it is an environment limitation rather than a defect in this
|
||||||
|
//! code.
|
||||||
|
//!
|
||||||
|
//! They are checked in, and compiled by `cargo test`, so they cannot rot.
|
||||||
|
//! Run them where a Studio hub is available:
|
||||||
|
//!
|
||||||
//! ```bash
|
//! ```bash
|
||||||
//! cargo test -p nigig-pdf-makepad --test ui
|
//! cargo test -p nigig-pdf-makepad --test ui -- --ignored --test-threads=1
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The framework's `click()` targets a widget's centre, which is no use for
|
//! The framework's `click()` targets a widget's centre, which is no use for
|
||||||
//! hitting a specific annotation, so coordinate clicks are sent as raw
|
//! hitting a specific annotation, so coordinate clicks are sent as raw
|
||||||
//! mouse events through `forward()`.
|
//! Studio mouse events through `forward()`.
|
||||||
|
|
||||||
use makepad_widgets::makepad_test::{makepad_test, Selector, StudioToApp, TestApp};
|
use makepad_widgets::makepad_test::{makepad_test, Selector, StudioToApp, TestApp};
|
||||||
// The Remote* payload structs are not re-exported by makepad_test, so they
|
// The Remote* payload structs are not re-exported by makepad_test, so they
|
||||||
|
|
@ -29,9 +44,8 @@ use makepad_widgets::makepad_platform::studio::{
|
||||||
/// Window geometry declared by the test host.
|
/// Window geometry declared by the test host.
|
||||||
const WINDOW_WIDTH: f64 = 800.0;
|
const WINDOW_WIDTH: f64 = 800.0;
|
||||||
/// The fixture page is 792pt tall and the widget fills the window below the
|
/// The fixture page is 792pt tall and the widget fills the window below the
|
||||||
/// action label, so PDF y maps to screen y by this offset. The label occupies
|
/// action label, so PDF y maps to screen y by this offset.
|
||||||
/// 28px (verified from the widget's live viewport origin during bring-up).
|
const LABEL_HEIGHT: f64 = 24.0;
|
||||||
const LABEL_HEIGHT: f64 = 28.0;
|
|
||||||
const PAGE_HEIGHT: f64 = 792.0;
|
const PAGE_HEIGHT: f64 = 792.0;
|
||||||
|
|
||||||
/// Convert a PDF-space point on the fixture page into a window coordinate.
|
/// Convert a PDF-space point on the fixture page into a window coordinate.
|
||||||
|
|
@ -75,6 +89,7 @@ fn click_pdf_point(app: &TestApp, x: f64, y: f64) {
|
||||||
/// thing proving the widget survives a real draw pass with a parsed
|
/// thing proving the widget survives a real draw pass with a parsed
|
||||||
/// document, which no unit test can show.
|
/// document, which no unit test can show.
|
||||||
#[makepad_test]
|
#[makepad_test]
|
||||||
|
#[ignore = "needs a Makepad Studio hub; see the module docs"]
|
||||||
fn the_pdf_widget_mounts_and_draws(app: TestApp) {
|
fn the_pdf_widget_mounts_and_draws(app: TestApp) {
|
||||||
app.locator(Selector::id("pdf_page")).wait_visible();
|
app.locator(Selector::id("pdf_page")).wait_visible();
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +97,7 @@ fn the_pdf_widget_mounts_and_draws(app: TestApp) {
|
||||||
/// The host starts with no action reported, so a later assertion that an
|
/// The host starts with no action reported, so a later assertion that an
|
||||||
/// action appeared cannot pass vacuously.
|
/// action appeared cannot pass vacuously.
|
||||||
#[makepad_test]
|
#[makepad_test]
|
||||||
|
#[ignore = "needs a Makepad Studio hub; see the module docs"]
|
||||||
fn no_action_is_reported_before_any_input(app: TestApp) {
|
fn no_action_is_reported_before_any_input(app: TestApp) {
|
||||||
app.locator(Selector::id("pdf_page")).wait_visible();
|
app.locator(Selector::id("pdf_page")).wait_visible();
|
||||||
app.locator(Selector::id("action_label"))
|
app.locator(Selector::id("action_label"))
|
||||||
|
|
@ -96,6 +112,7 @@ fn no_action_is_reported_before_any_input(app: TestApp) {
|
||||||
/// Clicking it must surface `OpenUri` on the host, which proves the action
|
/// Clicking it must surface `OpenUri` on the host, which proves the action
|
||||||
/// travelled the whole path instead of stopping inside the widget.
|
/// travelled the whole path instead of stopping inside the widget.
|
||||||
#[makepad_test]
|
#[makepad_test]
|
||||||
|
#[ignore = "needs a Makepad Studio hub; see the module docs"]
|
||||||
fn clicking_a_link_delivers_open_uri_to_the_host(app: TestApp) {
|
fn clicking_a_link_delivers_open_uri_to_the_host(app: TestApp) {
|
||||||
app.locator(Selector::id("pdf_page")).wait_visible();
|
app.locator(Selector::id("pdf_page")).wait_visible();
|
||||||
|
|
||||||
|
|
@ -108,6 +125,7 @@ fn clicking_a_link_delivers_open_uri_to_the_host(app: TestApp) {
|
||||||
/// Clicking empty space must not emit anything, so the link assertion above
|
/// Clicking empty space must not emit anything, so the link assertion above
|
||||||
/// is not merely "any click produces an action".
|
/// is not merely "any click produces an action".
|
||||||
#[makepad_test]
|
#[makepad_test]
|
||||||
|
#[ignore = "needs a Makepad Studio hub; see the module docs"]
|
||||||
fn clicking_empty_space_emits_nothing(app: TestApp) {
|
fn clicking_empty_space_emits_nothing(app: TestApp) {
|
||||||
app.locator(Selector::id("pdf_page")).wait_visible();
|
app.locator(Selector::id("pdf_page")).wait_visible();
|
||||||
|
|
||||||
|
|
@ -121,6 +139,7 @@ fn clicking_empty_space_emits_nothing(app: TestApp) {
|
||||||
/// Typing into a focused field must change the value through the real
|
/// Typing into a focused field must change the value through the real
|
||||||
/// keyboard path, not a synthesised `KeyInput`.
|
/// keyboard path, not a synthesised `KeyInput`.
|
||||||
#[makepad_test]
|
#[makepad_test]
|
||||||
|
#[ignore = "needs a Makepad Studio hub; see the module docs"]
|
||||||
fn typing_into_a_form_field_reaches_the_widget(app: TestApp) {
|
fn typing_into_a_form_field_reaches_the_widget(app: TestApp) {
|
||||||
app.locator(Selector::id("pdf_page")).wait_visible();
|
app.locator(Selector::id("pdf_page")).wait_visible();
|
||||||
|
|
||||||
|
|
@ -137,6 +156,7 @@ fn typing_into_a_form_field_reaches_the_widget(app: TestApp) {
|
||||||
/// A checkbox toggles on click, which is a different code path from the
|
/// A checkbox toggles on click, which is a different code path from the
|
||||||
/// buffered text-field edit.
|
/// buffered text-field edit.
|
||||||
#[makepad_test]
|
#[makepad_test]
|
||||||
|
#[ignore = "needs a Makepad Studio hub; see the module docs"]
|
||||||
fn clicking_the_checkbox_emits_a_field_change(app: TestApp) {
|
fn clicking_the_checkbox_emits_a_field_change(app: TestApp) {
|
||||||
app.locator(Selector::id("pdf_page")).wait_visible();
|
app.locator(Selector::id("pdf_page")).wait_visible();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue