1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
{
lib,
...
}:
{
name = "Kaidan XMPP Chat App";
nodes = {
machine =
{
pkgs,
...
}:
{
imports = [
# enable graphical session + users (alice, bob)
../common/x11.nix
../common/user-account.nix
# XMPP server for Kaidan
./prosody.nix
];
test-support.displayManager.auto.user = "alice";
environment.systemPackages = with pkgs; [
kaidan
xdotool # automated mouse clicks
];
# Kaidan requires a keyring for storing user passwords
services.gnome.gnome-keyring.enable = true;
};
};
enableOCR = true;
interactive.sshBackdoor.enable = true;
testScript =
{ nodes, ... }:
let
users.john = {
email = "john@example.com";
password = "foobar";
message = "Hello, I'm John!";
};
users.alice = {
email = "alice@example.com";
password = "foobar";
message = "Hello, I'm Alice!";
};
in
# py
''
import json
users = json.loads("""${lib.strings.toJSON users}""")
def wait_main_screen():
machine.wait_for_text(r"(Kaidan|free|communication|every|device)")
def click_position(x: int, y: int):
machine.succeed(f"su - alice -c 'DISPLAY=:0 xdotool mousemove --sync {x} {y} click 1'")
machine.sleep(1)
def login_user(user: str):
machine.send_chars(f"{users[user]["email"]}\n", 0.1)
machine.sleep(1)
machine.send_chars(f"{users[user]["password"]}\n", 0.1)
# add user account
def add_user_account(user: str):
click_position(19, 52) # burger menu
click_position(70, 150) # add account
wait_main_screen()
click_position(366, 598) # chat address
login_user(user)
machine.sleep(1)
# add user to the contact list
# NOTE: currently, we're hardcoding this to add to john's contact list,
# since it's simpler than somehow reading the screen, determining where
# each user is positioned and choosing them.
def add_contact(user):
click_position(19, 52) # burger menu
machine.sleep(10)
click_position(225, 344) # Add contact by chat address
click_position(404, 359) # Add contact to john
machine.send_chars(f"{users[user]["email"]}\n",0.1);
machine.sleep(1)
click_position(511, 500) # Add
# send a message
def send_message(message):
click_position(602, 742) # message box
machine.send_chars(f"{message}\n", 0.2)
machine.sleep(1)
## START ##
start_all()
machine.wait_for_x()
# Setup prosody so we can connect
machine.wait_for_unit("prosody.service")
machine.succeed("create-prosody-users")
machine.systemctl("start network-online.target")
machine.wait_for_unit("network-online.target")
# Start Kaidan and scale it to full screen
machine.execute("env DISPLAY=:0 sudo -u alice kaidan >&2 &")
wait_main_screen()
machine.send_key("alt-f10")
machine.sleep(1)
with subtest("Set up users"):
login_user("john")
# set up keyring for storing user passwords
machine.wait_for_text(r"(Choose|keyring|Default|Confirm|Continue)")
machine.send_chars("foobar", 0.1)
machine.send_key("tab")
machine.send_chars("foobar\n", 0.1)
machine.wait_for_console_text(r"(RosterPage|EmptyChatPage)")
machine.sleep(10)
# we add a second account, which will be communicating with the first one
add_user_account("alice")
machine.wait_for_console_text(r"(RosterPage|EmptyChatPage)")
machine.sleep(10)
# NOTE: OCR doesn't work well here. We assume both messages are received
# and just take a screenshot.
# TODO: verify messages exist in the screenshot.
with subtest("Chat between 2 users"):
# add alice to john's contacts with an initial message
add_contact("alice")
machine.sleep(10)
# john sends alice a message
click_position(151, 110) # alice in john's contacts
send_message(users["john"]["message"])
# alice receives john's message and replies
click_position(151, 183) # john in alice's contacts
send_message(users["alice"]["message"])
# john receives alice's message
click_position(151, 110) # alice in john's contacts
machine.screenshot("kaidan_chat_log") # both messages should be here
'';
}
|