1{ runTest, lib }:
2let
3 textInput = "This works.";
4 inputBoxText = "Enter input";
5 inputBox =
6 pkgs:
7 pkgs.writeShellScript "zenity-input" ''
8 ${lib.getExe pkgs.zenity} --entry --text '${inputBoxText}:' > /tmp/output &
9 '';
10 asUser = ''
11 def as_user(cmd: str):
12 """
13 Return a shell command for running a shell command as a specific user.
14 """
15 return f"sudo -u alice -i {cmd}"
16 '';
17in
18{
19 headless = runTest (
20 { lib, ... }:
21 {
22 name = "headless";
23
24 enableOCR = true;
25
26 nodes.machine = {
27 imports = [ ./common/user-account.nix ];
28
29 users.users.alice.extraGroups = [ "ydotool" ];
30
31 programs.ydotool.enable = true;
32
33 services.getty.autologinUser = "alice";
34 };
35
36 testScript = asUser + ''
37 start_all()
38
39 machine.wait_for_unit("multi-user.target")
40 machine.wait_for_text("alice")
41 machine.succeed(as_user("ydotool type 'echo ${textInput} > /tmp/output'")) # text input
42 machine.succeed(as_user("ydotool key 28:1 28:0")) # text input
43 machine.screenshot("headless_input")
44 machine.wait_for_file("/tmp/output")
45 machine.wait_until_succeeds("grep '${textInput}' /tmp/output") # text input
46 '';
47
48 meta.maintainers = with lib.maintainers; [
49 OPNA2608
50 quantenzitrone
51 ];
52 }
53 );
54
55 x11 = runTest (
56 { config, lib, ... }:
57 {
58 name = "x11";
59
60 enableOCR = true;
61
62 nodes.machine =
63 { lib, ... }:
64 {
65 imports = [
66 ./common/user-account.nix
67 ./common/auto.nix
68 ./common/x11.nix
69 ];
70
71 users.users.alice.extraGroups = [ "ydotool" ];
72
73 programs.ydotool.enable = true;
74
75 test-support.displayManager.auto = {
76 enable = true;
77 user = "alice";
78 };
79
80 services.xserver.windowManager.dwm.enable = true;
81 services.displayManager.defaultSession = lib.mkForce "none+dwm";
82 };
83
84 testScript = asUser + ''
85 start_all()
86
87 machine.wait_for_x()
88 machine.execute(as_user("${inputBox config.node.pkgs}"))
89 machine.wait_for_text("${inputBoxText}")
90 machine.succeed(as_user("ydotool type '${textInput}'")) # text input
91 machine.screenshot("x11_input")
92 machine.succeed(as_user("ydotool mousemove -a 400 110")) # mouse input
93 machine.succeed(as_user("ydotool click 0xC0")) # mouse input
94 machine.wait_for_file("/tmp/output")
95 machine.wait_until_succeeds("grep '${textInput}' /tmp/output") # text input
96 '';
97
98 meta.maintainers = with lib.maintainers; [
99 OPNA2608
100 quantenzitrone
101 ];
102 }
103 );
104
105 wayland = runTest (
106 { lib, ... }:
107 {
108 name = "wayland";
109
110 enableOCR = true;
111
112 nodes.machine =
113 { pkgs, ... }:
114 {
115 imports = [ ./common/user-account.nix ];
116
117 services.cage = {
118 enable = true;
119 user = "alice";
120 };
121
122 programs.ydotool.enable = true;
123
124 services.cage.program = inputBox pkgs;
125 };
126
127 testScript = ''
128 start_all()
129
130 machine.wait_for_unit("graphical.target")
131 machine.wait_for_text("${inputBoxText}")
132 machine.succeed("ydotool type '${textInput}'") # text input
133 machine.screenshot("wayland_input")
134 machine.succeed("ydotool mousemove -a 100 100") # mouse input
135 machine.succeed("ydotool click 0xC0") # mouse input
136 machine.wait_for_file("/tmp/output")
137 machine.wait_until_succeeds("grep '${textInput}' /tmp/output") # text input
138 '';
139
140 meta.maintainers = with lib.maintainers; [
141 OPNA2608
142 quantenzitrone
143 ];
144 }
145 );
146
147 customGroup =
148 let
149 name = "customGroup";
150 nodeName = "${name}Node";
151 insideGroupUsername = "ydotool-user";
152 outsideGroupUsername = "other-user";
153 groupName = "custom-group";
154 in
155 runTest (
156 { lib, ... }:
157 {
158 inherit name;
159
160 nodes."${nodeName}" = {
161 programs.ydotool = {
162 enable = true;
163 group = groupName;
164 };
165
166 users.users = {
167 "${insideGroupUsername}" = {
168 isNormalUser = true;
169 extraGroups = [ groupName ];
170 };
171 "${outsideGroupUsername}".isNormalUser = true;
172 };
173 };
174
175 testScript = ''
176 start_all()
177
178 # Wait for service to start
179 ${nodeName}.wait_for_unit("multi-user.target")
180 ${nodeName}.wait_for_unit("ydotoold.service")
181
182 # Verify that user with the configured group can use the service
183 ${nodeName}.succeed("sudo --login --user=${insideGroupUsername} ydotool type 'Hello, World!'")
184
185 # Verify that user without the configured group can't use the service
186 ${nodeName}.fail("sudo --login --user=${outsideGroupUsername} ydotool type 'Hello, World!'")
187 '';
188
189 meta.maintainers = with lib.maintainers; [ l0b0 ];
190 }
191 );
192}