1let
2 makeTest = import ./make-test-python.nix;
3 # Just to make sure everything is the same, need it for OCR & navigating greeter
4 user = "alice";
5 description = "Alice Foobar";
6 password = "foobar";
7
8 wallpaperName = "wallpaper.jpg";
9 # In case it ever shows up in the VM, we could OCR for it instead
10 wallpaperText = "Lorem ipsum";
11
12 # tmpfiles setup to make OCRing on terminal output more reliable
13 terminalOcrTmpfilesSetup =
14 {
15 pkgs,
16 lib,
17 config,
18 }:
19 let
20 white = "255, 255, 255";
21 black = "0, 0, 0";
22 colorSection = color: {
23 Color = color;
24 Bold = true;
25 Transparency = false;
26 };
27 terminalColors = pkgs.writeText "customized.colorscheme" (
28 lib.generators.toINI { } {
29 Background = colorSection white;
30 Foreground = colorSection black;
31 Color2 = colorSection black;
32 Color2Intense = colorSection black;
33 }
34 );
35 terminalConfig = pkgs.writeText "terminal.ubports.conf" (
36 lib.generators.toINI { } {
37 General = {
38 colorScheme = "customized";
39 fontSize = "16";
40 fontStyle = "Inconsolata";
41 };
42 }
43 );
44 confBase = "${config.users.users.${user}.home}/.config";
45 userDirArgs = {
46 mode = "0700";
47 user = user;
48 group = "users";
49 };
50 in
51 {
52 "${confBase}".d = userDirArgs;
53 "${confBase}/terminal.ubports".d = userDirArgs;
54 "${confBase}/terminal.ubports/customized.colorscheme".L.argument = "${terminalColors}";
55 "${confBase}/terminal.ubports/terminal.ubports.conf".L.argument = "${terminalConfig}";
56 };
57
58 wallpaperFile =
59 pkgs:
60 pkgs.runCommand wallpaperName
61 {
62 nativeBuildInputs = with pkgs; [
63 (imagemagick.override { ghostscriptSupport = true; }) # produce OCR-able image
64 ];
65 }
66 ''
67 magick -size 640x480 canvas:white -pointsize 30 -fill black -annotate +100+100 '${wallpaperText}' $out
68 '';
69 # gsettings tool with access to wallpaper schema
70 lomiri-gsettings =
71 pkgs:
72 pkgs.stdenv.mkDerivation {
73 name = "lomiri-gsettings";
74 dontUnpack = true;
75 nativeBuildInputs = with pkgs; [
76 glib
77 wrapGAppsHook3
78 ];
79 buildInputs = with pkgs; [
80 # Not using the Lomiri-namespaced setting yet
81 # lomiri.lomiri-schemas
82 gsettings-desktop-schemas
83 ];
84 installPhase = ''
85 runHook preInstall
86 mkdir -p $out/bin
87 ln -s ${pkgs.lib.getExe' pkgs.glib "gsettings"} $out/bin/lomiri-gsettings
88 runHook postInstall
89 '';
90 };
91 setLomiriWallpaperService =
92 pkgs:
93 let
94 lomiriServices = [
95 "lomiri.service"
96 "lomiri-full-greeter.service"
97 "lomiri-full-shell.service"
98 "lomiri-greeter.service"
99 "lomiri-shell.service"
100 ];
101 in
102 rec {
103 description = "Set Lomiri wallpaper to something OCR-able";
104 wantedBy = lomiriServices;
105 before = lomiriServices;
106 serviceConfig = {
107 Type = "oneshot";
108 # Not using the Lomiri-namespaed settings yet
109 # ExecStart = "${lomiri-gsettings pkgs}/bin/lomiri-gsettings set com.lomiri.Shell background-picture-uri file://${wallpaperFile pkgs}";
110 ExecStart = "${lomiri-gsettings pkgs}/bin/lomiri-gsettings set org.gnome.desktop.background picture-uri file://${wallpaperFile pkgs}";
111 };
112 };
113
114 sharedTestFunctions = ''
115 def wait_for_text(text):
116 """
117 Wait for on-screen text, and try to optimise retry count for slow hardware.
118 """
119
120 machine.sleep(30)
121 machine.wait_for_text(text)
122
123 def toggle_maximise():
124 """
125 Maximise the current window.
126 """
127
128 machine.send_key("ctrl-meta_l-up")
129
130 # For some reason, Lomiri in these VM tests very frequently opens the starter menu a few seconds after sending the above.
131 # Because this isn't 100% reproducible all the time, and there is no command to await when OCR doesn't pick up some text,
132 # the best we can do is send some Escape input after waiting some arbitrary time and hope that it works out fine.
133 machine.sleep(5)
134 machine.send_key("esc")
135 machine.sleep(5)
136
137 def mouse_click(xpos, ypos):
138 """
139 Move the mouse to a screen location and hit left-click.
140 """
141
142 # Need to reset to top-left, --absolute doesn't work?
143 machine.execute("ydotool mousemove -- -10000 -10000")
144 machine.sleep(2)
145
146 # Move
147 machine.execute(f"ydotool mousemove -- {xpos} {ypos}")
148 machine.sleep(2)
149
150 # Click (C0 - left button: down & up)
151 machine.execute("ydotool click 0xC0")
152 machine.sleep(2)
153
154 def open_starter():
155 """
156 Open the starter, and ensure it's opened.
157 """
158
159 # Using the keybind has a chance of instantly closing the menu again? Just click the button
160 mouse_click(20, 30)
161
162 '';
163
164 makeIndicatorTest =
165 {
166 name,
167 left,
168 ocr,
169 extraCheck ? null,
170
171 titleOcr,
172 }:
173
174 makeTest (
175 { pkgs, lib, ... }:
176 {
177 name = "lomiri-desktop-ayatana-indicator-${name}";
178
179 meta = {
180 maintainers = lib.teams.lomiri.members;
181 };
182
183 nodes.machine =
184 { config, ... }:
185 {
186 imports = [
187 ./common/auto.nix
188 ./common/user-account.nix
189 ];
190
191 virtualisation.memorySize = 2047;
192
193 users.users.${user} = {
194 inherit description password;
195 };
196
197 test-support.displayManager.auto = {
198 enable = true;
199 inherit user;
200 };
201
202 # To control mouse via scripting
203 programs.ydotool.enable = true;
204
205 services.desktopManager.lomiri.enable = lib.mkForce true;
206 services.displayManager.defaultSession = lib.mkForce "lomiri";
207
208 # Not setting wallpaper, as it breaks indicator OCR(?)
209 };
210
211 enableOCR = true;
212
213 testScript =
214 { nodes, ... }:
215 sharedTestFunctions
216 + ''
217 start_all()
218 machine.wait_for_unit("multi-user.target")
219
220 # The session should start, and not be stuck in i.e. a crash loop
221 with subtest("lomiri starts"):
222 machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'")
223 # Output rendering from Lomiri has started when it starts printing performance diagnostics
224 machine.wait_for_console_text("Last frame took")
225 # Look for datetime's clock, one of the last elements to load
226 wait_for_text(r"(AM|PM)")
227 machine.screenshot("lomiri_launched")
228
229 # The ayatana indicators are an important part of the experience, and they hold the only graphical way of exiting the session.
230 # There's a test app we could use that also displays their contents, but it's abit inconsistent.
231 mouse_click(735, 0) # the cog in the top-right, for the session indicator
232 wait_for_text(${titleOcr})
233 machine.screenshot("indicators_open")
234
235 # Indicator order within the menus *should* be fixed based on per-indicator order setting
236 # Session is the one we clicked, but it might not be the one we want to test right now.
237 # Go as far left as necessary.
238 ${lib.strings.replicate left "machine.send_key(\"left\")\n"}
239
240 with subtest("ayatana indicator session works"):
241 wait_for_text(r"(${lib.strings.concatStringsSep "|" ocr})")
242 machine.screenshot("indicator_${name}")
243 ''
244 + lib.optionalString (extraCheck != null) extraCheck;
245 }
246 );
247
248 makeIndicatorTests =
249 {
250 titles,
251 details,
252 }:
253 let
254 titleOcr = "r\"(${builtins.concatStringsSep "|" titles})\"";
255 in
256 builtins.listToAttrs (
257 builtins.map (
258 {
259 name,
260 left,
261 ocr,
262 extraCheck ? null,
263 }:
264 {
265 name = "desktop-ayatana-indicator-${name}";
266 value = makeIndicatorTest {
267 inherit
268 name
269 left
270 ocr
271 extraCheck
272 titleOcr
273 ;
274 };
275 }
276 ) details
277 );
278in
279{
280 greeter = makeTest (
281 { pkgs, lib, ... }:
282 {
283 name = "lomiri-greeter";
284
285 meta = {
286 maintainers = lib.teams.lomiri.members;
287 };
288
289 nodes.machine =
290 { config, ... }:
291 {
292 imports = [ ./common/user-account.nix ];
293
294 virtualisation.memorySize = 2047;
295
296 users.users.${user} = {
297 inherit description password;
298 };
299
300 services.xserver.enable = true;
301 services.xserver.windowManager.icewm.enable = true;
302 services.xserver.displayManager.lightdm = {
303 enable = true;
304 greeters.lomiri.enable = true;
305 };
306 services.displayManager.defaultSession = lib.mkForce "none+icewm";
307 };
308
309 enableOCR = true;
310
311 testScript =
312 { nodes, ... }:
313 sharedTestFunctions
314 + ''
315 start_all()
316 machine.wait_for_unit("multi-user.target")
317
318 # Lomiri in greeter mode should work & be able to start a session
319 with subtest("lomiri greeter works"):
320 machine.wait_for_unit("display-manager.service")
321 machine.wait_until_succeeds("pgrep -u lightdm -f 'lomiri --mode=greeter'")
322
323 # Start page shows current time
324 wait_for_text(r"(AM|PM)")
325 machine.screenshot("lomiri_greeter_launched")
326
327 # Advance to login part
328 machine.send_key("ret")
329 wait_for_text("${description}")
330 machine.screenshot("lomiri_greeter_login")
331
332 # Login
333 machine.send_chars("${password}\n")
334 machine.wait_for_x()
335 machine.screenshot("session_launched")
336 '';
337 }
338 );
339
340 desktop-basics = makeTest (
341 { pkgs, lib, ... }:
342 {
343 name = "lomiri-desktop-basics";
344
345 meta = {
346 maintainers = lib.teams.lomiri.members;
347 };
348
349 nodes.machine =
350 { config, ... }:
351 {
352 imports = [
353 ./common/auto.nix
354 ./common/user-account.nix
355 ];
356
357 virtualisation.memorySize = 2047;
358
359 users.users.${user} = {
360 inherit description password;
361 };
362
363 test-support.displayManager.auto = {
364 enable = true;
365 inherit user;
366 };
367
368 # To control mouse via scripting
369 programs.ydotool.enable = true;
370
371 services.desktopManager.lomiri.enable = lib.mkForce true;
372 services.displayManager.defaultSession = lib.mkForce "lomiri";
373
374 # Help with OCR
375 fonts.packages = [ pkgs.inconsolata ];
376
377 environment = {
378 # Help with OCR
379 etc."xdg/alacritty/alacritty.toml".source = (pkgs.formats.toml { }).generate "alacritty.toml" {
380 font = rec {
381 normal.family = "Inconsolata";
382 bold.family = normal.family;
383 italic.family = normal.family;
384 bold_italic.family = normal.family;
385 size = 16;
386 };
387 colors = rec {
388 primary = {
389 foreground = "0x000000";
390 background = "0xffffff";
391 };
392 normal = {
393 green = primary.foreground;
394 };
395 };
396 };
397
398 etc."${wallpaperName}".source = wallpaperFile pkgs;
399
400 systemPackages = with pkgs; [
401 # Forcing alacritty to run as an X11 app when opened from the starter menu
402 (symlinkJoin {
403 name = "x11-${alacritty.name}";
404
405 paths = [ alacritty ];
406
407 nativeBuildInputs = [ makeWrapper ];
408
409 postBuild = ''
410 wrapProgram $out/bin/alacritty \
411 --set WINIT_UNIX_BACKEND x11 \
412 --set WAYLAND_DISPLAY ""
413 '';
414
415 inherit (alacritty) meta;
416 })
417 ];
418 };
419
420 # Help with OCR
421 systemd.tmpfiles.settings = {
422 "10-lomiri-test-setup" = terminalOcrTmpfilesSetup { inherit pkgs lib config; };
423 };
424
425 systemd.user.services.set-lomiri-wallpaper = setLomiriWallpaperService pkgs;
426 };
427
428 enableOCR = true;
429
430 testScript =
431 { nodes, ... }:
432 sharedTestFunctions
433 + ''
434 start_all()
435 machine.wait_for_unit("multi-user.target")
436
437 # The session should start, and not be stuck in i.e. a crash loop
438 with subtest("lomiri starts"):
439 machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'")
440 # Output rendering from Lomiri has started when it starts printing performance diagnostics
441 machine.wait_for_console_text("Last frame took")
442 # Look for datetime's clock, one of the last elements to load
443 wait_for_text(r"(AM|PM)")
444 machine.screenshot("lomiri_launched")
445
446 # Working terminal keybind is good
447 with subtest("terminal keybind works"):
448 machine.send_key("ctrl-alt-t")
449 wait_for_text(r"(${user}|machine)")
450 machine.screenshot("terminal_opens")
451 machine.send_key("alt-f4")
452
453 # We want the ability to launch applications
454 with subtest("starter menu works"):
455 open_starter()
456 machine.screenshot("starter_opens")
457
458 # Just try the terminal again, we know that it should work
459 machine.send_chars("Terminal\n")
460 wait_for_text(r"(${user}|machine)")
461 machine.send_key("alt-f4")
462
463 # We want support for X11 apps
464 with subtest("xwayland support works"):
465 open_starter()
466 machine.send_chars("Alacritty\n")
467 wait_for_text(r"(${user}|machine)")
468 machine.screenshot("alacritty_opens")
469 machine.send_key("alt-f4")
470
471 # Morph is how we go online
472 with subtest("morph browser works"):
473 open_starter()
474 machine.send_chars("Morph\n")
475 wait_for_text(r"(Bookmarks|address|site|visited any)")
476 machine.screenshot("morph_open")
477
478 # morph-browser has a separate VM test to test its basic functionalities
479
480 machine.send_key("alt-f4")
481
482 # LSS provides DE settings
483 with subtest("system settings open"):
484 open_starter()
485 machine.send_chars("System Settings\n")
486 wait_for_text("Rotation Lock")
487 machine.screenshot("settings_open")
488
489 # lomiri-system-settings has a separate VM test to test its basic functionalities
490
491 machine.send_key("alt-f4")
492 '';
493 }
494 );
495
496 desktop-appinteractions = makeTest (
497 { pkgs, lib, ... }:
498 {
499 name = "lomiri-desktop-appinteractions";
500
501 meta = {
502 maintainers = lib.teams.lomiri.members;
503 };
504
505 nodes.machine =
506 { config, ... }:
507 {
508 imports = [
509 ./common/auto.nix
510 ./common/user-account.nix
511 ];
512
513 virtualisation.memorySize = 2047;
514
515 users.users.${user} = {
516 inherit description password;
517 # polkit agent test
518 extraGroups = [ "wheel" ];
519 };
520
521 test-support.displayManager.auto = {
522 enable = true;
523 inherit user;
524 };
525
526 # To control mouse via scripting
527 programs.ydotool.enable = true;
528
529 services.desktopManager.lomiri.enable = lib.mkForce true;
530 services.displayManager.defaultSession = lib.mkForce "lomiri";
531
532 # Help with OCR
533 fonts.packages = [ pkgs.inconsolata ];
534
535 environment = {
536 # Help with OCR
537 etc."xdg/alacritty/alacritty.yml".text = lib.generators.toYAML { } {
538 font = rec {
539 normal.family = "Inconsolata";
540 bold.family = normal.family;
541 italic.family = normal.family;
542 bold_italic.family = normal.family;
543 size = 16;
544 };
545 colors = rec {
546 primary = {
547 foreground = "0x000000";
548 background = "0xffffff";
549 };
550 normal = {
551 green = primary.foreground;
552 };
553 };
554 };
555
556 etc."${wallpaperName}".source = wallpaperFile pkgs;
557
558 variables = {
559 # So we can test what lomiri-content-hub is working behind the scenes
560 LOMIRI_CONTENT_HUB_LOGGING_LEVEL = "2";
561 };
562
563 systemPackages = with pkgs; [
564 # For a convenient way of kicking off lomiri-content-hub peer collection
565 lomiri.lomiri-content-hub.examples
566 ];
567 };
568
569 # Help with OCR
570 systemd.tmpfiles.settings = {
571 "10-lomiri-test-setup" = terminalOcrTmpfilesSetup { inherit pkgs lib config; };
572 };
573
574 systemd.user.services.set-lomiri-wallpaper = setLomiriWallpaperService pkgs;
575 };
576
577 enableOCR = true;
578
579 testScript =
580 { nodes, ... }:
581 sharedTestFunctions
582 + ''
583 start_all()
584 machine.wait_for_unit("multi-user.target")
585
586 # The session should start, and not be stuck in i.e. a crash loop
587 with subtest("lomiri starts"):
588 machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'")
589 # Output rendering from Lomiri has started when it starts printing performance diagnostics
590 machine.wait_for_console_text("Last frame took")
591 # Look for datetime's clock, one of the last elements to load
592 wait_for_text(r"(AM|PM)")
593 machine.screenshot("lomiri_launched")
594
595 # Working terminal keybind is good
596 with subtest("terminal keybind works"):
597 machine.send_key("ctrl-alt-t")
598 wait_for_text(r"(${user}|machine)")
599 machine.screenshot("terminal_opens")
600
601 # for the LSS lomiri-content-hub test to work reliably, we need to kick off peer collecting
602 machine.send_chars("lomiri-content-hub-test-importer\n")
603 wait_for_text(r"(/build/source|hub.cpp|handler.cpp|void|virtual|const)") # awaiting log messages from lomiri-content-hub
604 machine.send_key("ctrl-c")
605
606 # Doing this here, since we need an in-session shell & separately starting a terminal again wastes time
607 with subtest("polkit agent works"):
608 machine.send_chars("pkexec touch /tmp/polkit-test\n")
609 # There's an authentication notification here that gains focus, but we struggle with OCRing it
610 # Just hope that it's up after a short wait
611 machine.sleep(10)
612 machine.screenshot("polkit_agent")
613 machine.send_chars("${password}")
614 machine.sleep(2) # Hopefully enough delay to make sure all the password characters have been registered? Maybe just placebo
615 machine.send_chars("\n")
616 machine.wait_for_file("/tmp/polkit-test", 10)
617
618 machine.send_key("alt-f4")
619
620 # LSS provides DE settings
621 with subtest("system settings open"):
622 open_starter()
623 machine.send_chars("System Settings\n")
624 wait_for_text("Rotation Lock")
625 machine.screenshot("settings_open")
626
627 # lomiri-system-settings has a separate VM test, only test Lomiri-specific lomiri-content-hub functionalities here
628
629 # Make fullscreen, can't navigate to Background plugin via keyboard unless window has non-phone-like aspect ratio
630 toggle_maximise()
631
632 # Load Background plugin
633 machine.send_key("tab")
634 machine.send_key("tab")
635 machine.send_key("tab")
636 machine.send_key("tab")
637 machine.send_key("tab")
638 machine.send_key("tab")
639 machine.send_key("ret")
640 wait_for_text("Background image")
641
642 # Try to load custom background
643 machine.send_key("shift-tab")
644 machine.send_key("shift-tab")
645 machine.send_key("shift-tab")
646 machine.send_key("shift-tab")
647 machine.send_key("shift-tab")
648 machine.send_key("shift-tab")
649 machine.send_key("ret")
650
651 # Peers should be loaded
652 wait_for_text("Morph") # or Gallery, but Morph is already packaged
653 machine.screenshot("settings_lomiri-content-hub_peers")
654
655 # Select Morph as content source
656 mouse_click(370, 100)
657
658 # Expect Morph to be brought into the foreground, with its Downloads page open
659 wait_for_text("No downloads")
660
661 # If lomiri-content-hub encounters a problem, it may have crashed the original application issuing the request.
662 # Check that it's still alive
663 machine.succeed("pgrep -u ${user} -f lomiri-system-settings")
664
665 machine.screenshot("lomiri-content-hub_exchange")
666
667 # Testing any more would require more applications & setup, the fact that it's already being attempted is a good sign
668 machine.send_key("esc")
669
670 machine.sleep(2) # sleep a tiny bit so morph can close & the focus can return to LSS
671 machine.send_key("alt-f4")
672 '';
673 }
674 );
675
676 keymap =
677 let
678 pwInput = "qwerty";
679 pwOutput = "qwertz";
680 in
681 makeTest (
682 { pkgs, lib, ... }:
683 {
684 name = "lomiri-keymap";
685
686 meta = {
687 maintainers = lib.teams.lomiri.members;
688 };
689
690 nodes.machine =
691 { config, ... }:
692 {
693 imports = [ ./common/user-account.nix ];
694
695 virtualisation.memorySize = 2047;
696
697 users.users.${user} = {
698 inherit description;
699 password = lib.mkForce pwOutput;
700 };
701
702 services.desktopManager.lomiri.enable = lib.mkForce true;
703 services.displayManager.defaultSession = lib.mkForce "lomiri";
704
705 # Help with OCR
706 fonts.packages = [ pkgs.inconsolata ];
707
708 services.xserver.xkb.layout = lib.strings.concatStringsSep "," [
709 # Start with a non-QWERTY keymap to test keymap patch
710 "de"
711 # Then a QWERTY one to test switching
712 "us"
713 ];
714
715 environment.etc."${wallpaperName}".source = wallpaperFile pkgs;
716
717 systemd.user.services.set-lomiri-wallpaper = setLomiriWallpaperService pkgs;
718
719 # Help with OCR
720 systemd.tmpfiles.settings = {
721 "10-lomiri-test-setup" = terminalOcrTmpfilesSetup { inherit pkgs lib config; };
722 };
723 };
724
725 enableOCR = true;
726
727 testScript =
728 { nodes, ... }:
729 sharedTestFunctions
730 + ''
731 start_all()
732 machine.wait_for_unit("multi-user.target")
733
734 # Lomiri in greeter mode should use the correct keymap
735 with subtest("lomiri greeter keymap works"):
736 machine.wait_for_unit("display-manager.service")
737 machine.wait_until_succeeds("pgrep -u lightdm -f 'lomiri --mode=greeter'")
738
739 # Start page shows current time
740 wait_for_text(r"(AM|PM)")
741 machine.screenshot("lomiri_greeter_launched")
742
743 # Advance to login part
744 machine.send_key("ret")
745 wait_for_text("${description}")
746 machine.screenshot("lomiri_greeter_login")
747
748 # Login
749 machine.send_chars("${pwInput}\n")
750 machine.wait_until_succeeds("pgrep -u ${user} -f 'lomiri --mode=full-shell'")
751
752 # Output rendering from Lomiri has started when it starts printing performance diagnostics
753 machine.wait_for_console_text("Last frame took")
754 # Look for datetime's clock, one of the last elements to load
755 wait_for_text(r"(AM|PM)")
756 machine.screenshot("lomiri_launched")
757
758 # Lomiri in desktop mode should use the correct keymap
759 with subtest("lomiri session keymap works"):
760 machine.send_key("ctrl-alt-t")
761 wait_for_text(r"(${user}|machine)")
762 machine.screenshot("terminal_opens")
763
764 machine.send_chars("touch ${pwInput}\n")
765 machine.wait_for_file("/home/alice/${pwOutput}", 90)
766
767 # Issues with this keybind: input leaks to focused surface, may open launcher
768 # Don't have the keyboard indicator to handle this better
769 machine.send_key("meta_l-spc")
770 machine.wait_for_console_text('SET KEYMAP "us"')
771
772 # Handle keybind fallout
773 machine.sleep(10) # wait for everything to settle
774 machine.send_key("esc") # close launcher in case it was opened
775 machine.sleep(2) # wait for animation to finish
776 # Make sure input leaks are gone
777 machine.send_key("backspace")
778 machine.send_key("backspace")
779 machine.send_key("backspace")
780 machine.send_key("backspace")
781 machine.send_key("backspace")
782 machine.send_key("backspace")
783 machine.send_key("backspace")
784 machine.send_key("backspace")
785 machine.send_key("backspace")
786 machine.send_key("backspace")
787
788 machine.send_chars("touch ${pwInput}\n")
789 machine.wait_for_file("/home/alice/${pwInput}", 90)
790
791 machine.send_key("alt-f4")
792 '';
793 }
794 );
795}
796// makeIndicatorTests {
797 titles = [
798 "Notifications" # messages
799 "Rotation" # display
800 "Battery" # power
801 "Sound" # sound
802 "Time" # datetime
803 "Date" # datetime
804 "System" # session
805 ];
806 details = [
807 # messages normally has no contents
808 ({
809 name = "display";
810 left = 6;
811 ocr = [ "Lock" ];
812 })
813 ({
814 name = "bluetooth";
815 left = 5;
816 ocr = [ "Bluetooth" ];
817 })
818 ({
819 name = "network";
820 left = 4;
821 ocr = [
822 "Flight"
823 "Wi-Fi"
824 ];
825 })
826 ({
827 name = "sound";
828 left = 3;
829 ocr = [
830 "Silent"
831 "Volume"
832 ];
833 })
834 ({
835 name = "power";
836 left = 2;
837 ocr = [
838 "Charge"
839 "Battery"
840 ];
841 })
842 ({
843 name = "datetime";
844 left = 1;
845 ocr = [
846 "Time"
847 "Date"
848 ];
849 })
850 ({
851 name = "session";
852 left = 0;
853 ocr = [ "Log Out" ];
854 extraCheck = ''
855 # We should be able to log out and return to the greeter
856 mouse_click(720, 280) # "Log Out"
857 mouse_click(400, 240) # confirm logout
858 machine.wait_until_fails("pgrep -u ${user} -f 'lomiri --mode=full-shell'")
859 '';
860 })
861 ];
862}