Fail when the last film stock cannot be reached
The film list bug gave no failure anywhere: the data was right, the markup compiled, and the list rendered. Two guards now check that the list can be walked to its end, both by driving input rather than by reading markup. tests/film_list_reaches_every_stock.rs runs in CI and needs no display. It builds the real AppWindow on Slint's testing backend and gives it 28 stocks. It dispatches window events through the same routing a window uses: popup, Flickables, arbitration. It then checks that the last stock is on screen, that is, not clipped away: - after Down past the end, and that Enter chooses it; - after drags on the list; - after a run of wheel events with a still pointer; - after dragging the scrollbar thumb. Element queries need the Slint compiler's debug tables, which build.rs emitted only for the `automation` feature. It now emits them for every debug build too. Release builds, the ones that ship, are unchanged. The testing backend is a dev-dependency at the same pinned version the automation feature already uses, so no new crate enters the lockfile. The test is compiled out of release test runs. film_reach in tools/manual/scenes.py is the same check on the recording rig: a real X pointer from xdotool, the release build, and the demo library. It makes no picture, so it adds nothing to the manual. It runs with every recording, or alone with `record.sh LIBRARY film_reach`, and fails the run if the last stock (Ilford HP5 Plus) is out of reach by the wheel, a drag, the scrollbar or the keys. Both have to add the popup's position back. The testing backend reports anything inside a popup relative to the popup, and so does the automation hook built on it. They take the popup's position from the Film row and Slint's clamp into the window.
This commit is contained in:
@@ -979,6 +979,90 @@ def film():
|
||||
undo_all()
|
||||
|
||||
|
||||
FILM_LAST = 'Ilford HP5 Plus' # the last stock `DevelopSession::film_choices` lists
|
||||
FILM_ROWS = 28 # None and the 27 camera stocks
|
||||
FILM_ROW, FILM_LIST_MAX = 32, 320
|
||||
|
||||
|
||||
def film_list_open():
|
||||
"""The film list, open, at its top: closed first if it was open. Not
|
||||
by pressing the Film row again: a press outside an open list closes it
|
||||
and goes no further, so that press would only close it."""
|
||||
if film_list_is_open():
|
||||
key('Escape')
|
||||
pause(0.6)
|
||||
dr.click(*in_column('Film@Button'))
|
||||
dr.wait_for('Fujifilm C200@Text', 5)
|
||||
pause(0.6)
|
||||
|
||||
|
||||
def film_list_is_open():
|
||||
"""Any stock's row on screen. The Film row names the chosen stock too,
|
||||
so this is only true of an open list while the choice is None."""
|
||||
return any(e['role'] == 'Text' for maker in ('Fujifilm', 'Kodak', 'Ilford')
|
||||
for e in dr.ask(f'labels {maker}'))
|
||||
|
||||
|
||||
def film_list_origin():
|
||||
"""Where the open list's popup is in the window. The hook reports what
|
||||
is inside a popup relative to the popup, so a scene adds this back. The
|
||||
popup asks to sit `gap-sm` (6px) under the Film row, as wide as it, and Slint moves it
|
||||
up into the window when it would run off the bottom — the same clamp."""
|
||||
x0, _, x1, y1 = dr.rect('Film@Button')
|
||||
W, H = dr.window_size()
|
||||
h = min(FILM_ROWS * FILM_ROW, FILM_LIST_MAX)
|
||||
return min(max(0, x0), W - (x1 - x0)), min(max(0, y1 + 6), H - h), x1 - x0, h
|
||||
|
||||
|
||||
def film_reached(how):
|
||||
if not dr.present(f'{FILM_LAST}@Text'):
|
||||
raise AssertionError(f'the film list: {FILM_LAST} cannot be reached by {how}')
|
||||
print(f' {FILM_LAST} reached by {how}', flush=True)
|
||||
|
||||
|
||||
@scene(media=[], sources=DEVELOP_SRC + ['core/dr-film/src/**'])
|
||||
def film_reach():
|
||||
"""Not a picture — a check, run with every recording: the last stock in
|
||||
the film list can be reached by each way there is to scroll it. It was
|
||||
once a scroller inside the develop column's, and the column took the
|
||||
drag and, under a still pointer, the wheel: eighteen stocks, every
|
||||
black-and-white one, were on the list and out of reach."""
|
||||
at_develop()
|
||||
|
||||
# The wheel, in one run with the pointer still: the column used to take
|
||||
# a run like this whenever it had scrolled under that pointer last.
|
||||
film_list_open()
|
||||
px, py, pw, ph = film_list_origin()
|
||||
wheel(12, px + pw // 2, py + ph // 2)
|
||||
pause(0.8)
|
||||
film_reached('the wheel')
|
||||
|
||||
# A drag on the rows, which is what a flick is to a mouse.
|
||||
film_list_open()
|
||||
for _ in range(3):
|
||||
dr.drag(px + pw // 3, py + ph - 20, px + pw // 3, py + 10, 25)
|
||||
pause(0.8)
|
||||
film_reached('a drag')
|
||||
|
||||
# The scrollbar's thumb, dragged to the bottom of its track.
|
||||
film_list_open()
|
||||
dr.drag(px + pw - 5, py + 6, px + pw - 5, py + ph + 40, 25)
|
||||
pause(0.6)
|
||||
film_reached('the scrollbar')
|
||||
|
||||
# The keys, chosen with Enter: the summary names what was chosen.
|
||||
film_list_open()
|
||||
for _ in range(FILM_ROWS + 2):
|
||||
dr.x('key', 'Down')
|
||||
key('Return')
|
||||
pause(1.5)
|
||||
if dr.present('Fujifilm C200@Text') or not dr.present(f'{FILM_LAST}@Text'):
|
||||
# Closed, and the Film row now names the last stock.
|
||||
raise AssertionError(f'the film list: Down and Enter did not choose {FILM_LAST}')
|
||||
print(f' {FILM_LAST} chosen by the keys', flush=True)
|
||||
undo_all()
|
||||
|
||||
|
||||
@scene(media=['presets.png'], sources=DEVELOP_SRC + ['ui/dr-ui/ui/presets.slint', 'ui/dr-ui/src/presets.rs'])
|
||||
def presets():
|
||||
at_develop()
|
||||
|
||||
Reference in New Issue
Block a user