#include "ui_core/overlay_lifetime.h" #include "test_harness.h" using pp::foundation::StatusCode; using pp::ui::NodeLifetimeTree; using pp::ui::UiCaptureKind; using pp::ui::UiOverlayLifetime; namespace { void opens_root_and_child_popups_with_capture_restore(pp::tests::Harness& h) { NodeLifetimeTree tree; const auto root = tree.create_root(); PP_EXPECT(h, root); if (!root) { return; } UiOverlayLifetime overlays(tree, root.value()); const auto popup = overlays.open_popup(); PP_EXPECT(h, popup); if (!popup) { return; } const auto child = overlays.open_child_popup(popup.value()); PP_EXPECT(h, child); if (!child) { return; } PP_EXPECT(h, overlays.overlay_count() == 2U); const auto captured_child = tree.captured_node(UiCaptureKind::pointer); PP_EXPECT(h, captured_child); if (captured_child) { PP_EXPECT(h, captured_child.value() == child.value()); } PP_EXPECT(h, overlays.close(child.value()).ok()); PP_EXPECT(h, overlays.overlay_count() == 1U); PP_EXPECT(h, !tree.contains(child.value())); PP_EXPECT(h, tree.contains(popup.value())); const auto captured_parent = tree.captured_node(UiCaptureKind::pointer); PP_EXPECT(h, captured_parent); if (captured_parent) { PP_EXPECT(h, captured_parent.value() == popup.value()); } } void closing_parent_popup_closes_child_branch(pp::tests::Harness& h) { NodeLifetimeTree tree; const auto root = tree.create_root(); PP_EXPECT(h, root); if (!root) { return; } UiOverlayLifetime overlays(tree, root.value()); const auto popup = overlays.open_popup(); PP_EXPECT(h, popup); if (!popup) { return; } const auto child = overlays.open_child_popup(popup.value()); PP_EXPECT(h, child); if (!child) { return; } PP_EXPECT(h, overlays.close(popup.value()).ok()); PP_EXPECT(h, overlays.overlay_count() == 0U); PP_EXPECT(h, !tree.contains(popup.value())); PP_EXPECT(h, !tree.contains(child.value())); PP_EXPECT(h, !tree.captured_node(UiCaptureKind::pointer).ok()); } void modal_dialog_captures_pointer_and_keyboard(pp::tests::Harness& h) { NodeLifetimeTree tree; const auto root = tree.create_root(); PP_EXPECT(h, root); if (!root) { return; } UiOverlayLifetime overlays(tree, root.value()); const auto popup = overlays.open_popup(); PP_EXPECT(h, popup); if (!popup) { return; } const auto dialog = overlays.open_dialog(true); PP_EXPECT(h, dialog); if (!dialog) { return; } const auto pointer = tree.captured_node(UiCaptureKind::pointer); const auto keyboard = tree.captured_node(UiCaptureKind::keyboard); PP_EXPECT(h, pointer); PP_EXPECT(h, keyboard); if (pointer) { PP_EXPECT(h, pointer.value() == dialog.value()); } if (keyboard) { PP_EXPECT(h, keyboard.value() == dialog.value()); } PP_EXPECT(h, overlays.close(dialog.value()).ok()); const auto restored_pointer = tree.captured_node(UiCaptureKind::pointer); PP_EXPECT(h, restored_pointer); if (restored_pointer) { PP_EXPECT(h, restored_pointer.value() == popup.value()); } PP_EXPECT(h, !tree.captured_node(UiCaptureKind::keyboard).ok()); } void modeless_dialog_does_not_steal_capture(pp::tests::Harness& h) { NodeLifetimeTree tree; const auto root = tree.create_root(); PP_EXPECT(h, root); if (!root) { return; } UiOverlayLifetime overlays(tree, root.value()); const auto popup = overlays.open_popup(); PP_EXPECT(h, popup); if (!popup) { return; } const auto dialog = overlays.open_dialog(false); PP_EXPECT(h, dialog); if (!dialog) { return; } const auto pointer = tree.captured_node(UiCaptureKind::pointer); PP_EXPECT(h, pointer); if (pointer) { PP_EXPECT(h, pointer.value() == popup.value()); } PP_EXPECT(h, !tree.captured_node(UiCaptureKind::keyboard).ok()); PP_EXPECT(h, overlays.top_overlay()); if (const auto top = overlays.top_overlay()) { PP_EXPECT(h, top.value() == dialog.value()); } } void rejects_untracked_or_dead_overlay_closes(pp::tests::Harness& h) { NodeLifetimeTree tree; const auto root = tree.create_root(); PP_EXPECT(h, root); if (!root) { return; } const auto raw_child = tree.create_child(root.value()); PP_EXPECT(h, raw_child); if (!raw_child) { return; } UiOverlayLifetime overlays(tree, root.value()); const auto close_raw = overlays.close(raw_child.value()); const auto child_popup = overlays.open_child_popup(raw_child.value()); PP_EXPECT(h, !close_raw.ok()); PP_EXPECT(h, close_raw.code == StatusCode::invalid_argument); PP_EXPECT(h, !child_popup.ok()); PP_EXPECT(h, child_popup.status().code == StatusCode::invalid_argument); } void clear_for_layout_reload_invalidates_overlays(pp::tests::Harness& h) { NodeLifetimeTree tree; const auto root = tree.create_root(); PP_EXPECT(h, root); if (!root) { return; } UiOverlayLifetime overlays(tree, root.value()); const auto popup = overlays.open_popup(); PP_EXPECT(h, popup); if (!popup) { return; } const auto dialog = overlays.open_dialog(true); PP_EXPECT(h, dialog); if (!dialog) { return; } overlays.clear_for_layout_reload(); PP_EXPECT(h, overlays.overlay_count() == 0U); PP_EXPECT(h, !overlays.top_overlay().ok()); PP_EXPECT(h, !tree.contains(root.value())); PP_EXPECT(h, !tree.contains(popup.value())); PP_EXPECT(h, !tree.contains(dialog.value())); PP_EXPECT(h, !tree.captured_node(UiCaptureKind::pointer).ok()); PP_EXPECT(h, !tree.captured_node(UiCaptureKind::keyboard).ok()); } } int main() { pp::tests::Harness harness; harness.run( "opens_root_and_child_popups_with_capture_restore", opens_root_and_child_popups_with_capture_restore); harness.run("closing_parent_popup_closes_child_branch", closing_parent_popup_closes_child_branch); harness.run("modal_dialog_captures_pointer_and_keyboard", modal_dialog_captures_pointer_and_keyboard); harness.run("modeless_dialog_does_not_steal_capture", modeless_dialog_does_not_steal_capture); harness.run("rejects_untracked_or_dead_overlay_closes", rejects_untracked_or_dead_overlay_closes); harness.run("clear_for_layout_reload_invalidates_overlays", clear_for_layout_reload_invalidates_overlays); return harness.finish(); }