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