mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 07:18:09 +00:00
feat(core): enable UI tests for redesigned UI
[no changelog]
This commit is contained in:
parent
2f987c3c5e
commit
1f612580f7
@ -101,10 +101,10 @@ test_emu_click: ## run click tests
|
||||
$(EMU_TEST) $(PYTEST) $(TESTPATH)/click_tests $(TESTOPTS)
|
||||
|
||||
test_emu_ui: ## run ui integration tests
|
||||
$(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests --ui=test --ui-check-missing $(TESTOPTS)
|
||||
UI2="$(UI2)" $(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests --ui=test --ui-check-missing $(TESTOPTS)
|
||||
|
||||
test_emu_ui_record: ## record and hash screens for ui integration tests
|
||||
$(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests --ui=record --ui-check-missing $(TESTOPTS)
|
||||
UI2="$(UI2)" $(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests --ui=record --ui-check-missing $(TESTOPTS)
|
||||
|
||||
pylint: ## run pylint on application sources and tests
|
||||
pylint -E $(shell find src tests -name *.py)
|
||||
|
@ -15,6 +15,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_Layout;
|
||||
MP_QSTR_CONFIRMED;
|
||||
MP_QSTR_CANCELLED;
|
||||
MP_QSTR_INFO;
|
||||
MP_QSTR_confirm_action;
|
||||
MP_QSTR_confirm_text;
|
||||
MP_QSTR_request_pin;
|
||||
|
@ -220,24 +220,30 @@ impl LayoutObj {
|
||||
|
||||
fn symbol(&mut self, name: &str) {
|
||||
self.0
|
||||
.call_with_n_args(&[name.try_into().unwrap()])
|
||||
.call_with_n_args(&[
|
||||
"<".try_into().unwrap(),
|
||||
name.try_into().unwrap(),
|
||||
">".try_into().unwrap(),
|
||||
])
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn open(&mut self, name: &str) {
|
||||
self.0
|
||||
.call_with_n_args(&[name.try_into().unwrap()])
|
||||
.call_with_n_args(&["<".try_into().unwrap(), name.try_into().unwrap()])
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn field(&mut self, name: &str, value: &dyn Trace) {
|
||||
self.0
|
||||
.call_with_n_args(&[name.try_into().unwrap()])
|
||||
.call_with_n_args(&[name.try_into().unwrap(), ": ".try_into().unwrap()])
|
||||
.unwrap();
|
||||
value.trace(self);
|
||||
}
|
||||
|
||||
fn close(&mut self) {}
|
||||
fn close(&mut self) {
|
||||
self.0.call_with_n_args(&[">".try_into().unwrap()]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
self.inner
|
||||
|
@ -25,6 +25,7 @@ unsafe impl Sync for ResultObj {}
|
||||
|
||||
static CONFIRMED_TYPE: Type = obj_type! { name: Qstr::MP_QSTR_CONFIRMED, };
|
||||
static CANCELLED_TYPE: Type = obj_type! { name: Qstr::MP_QSTR_CANCELLED, };
|
||||
static INFO_TYPE: Type = obj_type! { name: Qstr::MP_QSTR_INFO, };
|
||||
|
||||
pub static CONFIRMED: ResultObj = ResultObj {
|
||||
base: CONFIRMED_TYPE.as_base(),
|
||||
@ -32,3 +33,6 @@ pub static CONFIRMED: ResultObj = ResultObj {
|
||||
pub static CANCELLED: ResultObj = ResultObj {
|
||||
base: CANCELLED_TYPE.as_base(),
|
||||
};
|
||||
pub static INFO: ResultObj = ResultObj {
|
||||
base: INFO_TYPE.as_base(),
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
},
|
||||
layout::{
|
||||
obj::{ComponentMsgObj, LayoutObj},
|
||||
result::{CANCELLED, CONFIRMED},
|
||||
result::{CANCELLED, CONFIRMED, INFO},
|
||||
},
|
||||
},
|
||||
util,
|
||||
@ -212,6 +212,9 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// CANCELLED: object
|
||||
Qstr::MP_QSTR_CANCELLED => CANCELLED.as_obj(),
|
||||
|
||||
/// INFO: object
|
||||
Qstr::MP_QSTR_INFO => INFO.as_obj(),
|
||||
|
||||
/// def confirm_action(
|
||||
/// *,
|
||||
/// title: str,
|
||||
|
@ -27,6 +27,7 @@ def confirm_text(
|
||||
"""Confirm text."""
|
||||
CONFIRMED: object
|
||||
CANCELLED: object
|
||||
INFO: object
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
|
@ -50,6 +50,13 @@ if __debug__:
|
||||
LAYOUT_WATCHER_STATE = 1
|
||||
LAYOUT_WATCHER_LAYOUT = 2
|
||||
|
||||
try:
|
||||
import trezorui2
|
||||
|
||||
UI2 = True
|
||||
except ImportError:
|
||||
UI2 = False
|
||||
|
||||
def screenshot() -> bool:
|
||||
if storage.save_screen:
|
||||
display.save(storage.save_screen_directory + "/refresh-")
|
||||
@ -62,10 +69,20 @@ if __debug__:
|
||||
layout_change_chan.publish(storage.current_content)
|
||||
|
||||
async def dispatch_debuglink_decision(msg: DebugLinkDecision) -> None:
|
||||
from trezor.enums import DebugButton
|
||||
from trezor.enums import DebugSwipeDirection
|
||||
from trezor.enums import DebugButton, DebugSwipeDirection
|
||||
from trezor.ui import Result
|
||||
from trezor.ui.components.tt import confirm, swipe
|
||||
|
||||
if UI2:
|
||||
confirm = trezorui2
|
||||
|
||||
class swipe:
|
||||
SWIPE_UP = 0x01
|
||||
SWIPE_DOWN = 0x02
|
||||
SWIPE_LEFT = 0x04
|
||||
SWIPE_RIGHT = 0x08
|
||||
|
||||
else:
|
||||
from trezor.ui.components.tt import confirm, swipe
|
||||
|
||||
if msg.button is not None:
|
||||
if msg.button == DebugButton.NO:
|
||||
|
@ -24,11 +24,47 @@ class _RustLayout(ui.Layout):
|
||||
def set_timer(self, token: int, deadline: int) -> None:
|
||||
self.timer.schedule(deadline, token)
|
||||
|
||||
def create_tasks(self) -> tuple[loop.Task, ...]:
|
||||
return self.handle_input_and_rendering(), self.handle_timers()
|
||||
if __debug__:
|
||||
|
||||
def create_tasks(self) -> tuple[loop.AwaitableTask, ...]:
|
||||
from apps.debug import confirm_signal, input_signal
|
||||
|
||||
return (
|
||||
self.handle_input_and_rendering(),
|
||||
self.handle_timers(),
|
||||
confirm_signal(),
|
||||
input_signal(),
|
||||
)
|
||||
|
||||
def read_content(self) -> list[str]:
|
||||
result = []
|
||||
|
||||
def callback(*args):
|
||||
for arg in args:
|
||||
result.append(str(arg))
|
||||
|
||||
self.layout.trace(callback)
|
||||
result = " ".join(result).split("\n")
|
||||
return result
|
||||
|
||||
else:
|
||||
|
||||
def create_tasks(self) -> tuple[loop.AwaitableTask, ...]:
|
||||
return self.handle_input_and_rendering(), self.handle_timers()
|
||||
|
||||
def _before_render(self) -> None:
|
||||
if __debug__ and self.should_notify_layout_change:
|
||||
from apps.debug import notify_layout_change
|
||||
|
||||
# notify about change and do not notify again until next await.
|
||||
# (handle_rendering might be called multiple times in a single await,
|
||||
# because of the endless loop in __iter__)
|
||||
self.should_notify_layout_change = False
|
||||
notify_layout_change(self)
|
||||
|
||||
def handle_input_and_rendering(self) -> loop.Task: # type: ignore [awaitable-is-generator]
|
||||
touch = loop.wait(io.TOUCH)
|
||||
self._before_render()
|
||||
ui.display.clear()
|
||||
self.layout.paint()
|
||||
# self.layout.bounds()
|
||||
|
@ -1,5 +1,6 @@
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
from contextlib import contextmanager
|
||||
@ -112,6 +113,9 @@ def screen_recording(
|
||||
# Making the model global for other functions
|
||||
global MODEL
|
||||
MODEL = f"T{client.features.model}"
|
||||
if os.getenv("UI2") == "1":
|
||||
MODEL += "ui2"
|
||||
|
||||
test_name = f"{MODEL}_{test_name}"
|
||||
|
||||
screens_test_path = SCREENS_DIR / test_name
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user