nixos/tests: init Kaidan (#469539)

This commit is contained in:
Ivan Mincik
2025-12-11 08:52:00 +00:00
committed by GitHub
4 changed files with 220 additions and 0 deletions
+1
View File
@@ -802,6 +802,7 @@ in
jotta-cli = runTest ./jotta-cli.nix;
k3s = handleTest ./k3s { };
kafka = handleTest ./kafka { };
kaidan = runTest ./kaidan;
kanboard = runTest ./web-apps/kanboard.nix;
kanidm = runTest ./kanidm.nix;
kanidm-provisioning = runTest ./kanidm-provisioning.nix;
+158
View File
@@ -0,0 +1,158 @@
{
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; # ssh -o User=root vsock/3
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(26, 48) # burger menu
click_position(179, 144) # 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, message=""):
click_position(26, 48) # burger menu
machine.wait_for_text(r"(Add|contact|chat|QR|code|address)")
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)
machine.send_key("tab")
machine.send_key("tab")
machine.sleep(1)
machine.send_chars(f"{message if message != "" else users[user]["message"]}\n",0.1);
machine.sleep(1)
click_position(511, 524) # 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_text(r"(Search|Select|chat|start)")
# we add a second account, which will be communicating with the first one
add_user_account("alice")
machine.wait_for_text(r"(Search|Select|chat|start)")
# 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", users["john"]["message"])
machine.sleep(5)
# 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
'';
}
+59
View File
@@ -0,0 +1,59 @@
{
config,
pkgs,
lib,
...
}:
# NOTE: most of this is taken from the prosody test
let
cert = pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -days 365 \
-subj '/C=GB/CN=example.com/CN=uploads.example.com/CN=conference.example.com' -addext "subjectAltName = DNS:example.com,DNS:uploads.example.com,DNS:conference.example.com"
mkdir -p $out
cp key.pem cert.pem $out
'';
# Creates and set password for the 2 xmpp test users.
#
# Doing that in a bash script instead of doing that in the test
# script allow us to easily provision the users when running that
# test interactively.
createUsers = pkgs.writeShellScriptBin "create-prosody-users" ''
set -e
prosodyctl register alice example.com foobar
prosodyctl register john example.com foobar
'';
in
{
# Make the self-signed certificates work
security.pki.certificateFiles = [ "${cert}/cert.pem" ];
networking.extraHosts = ''
${config.networking.primaryIPAddress} example.com
${config.networking.primaryIPAddress} conference.example.com
${config.networking.primaryIPAddress} uploads.example.com
'';
environment.systemPackages = [
createUsers
];
# Configure Prosody with self-signed certificates
services.prosody = {
enable = true;
ssl.cert = "${cert}/cert.pem";
ssl.key = "${cert}/key.pem";
virtualHosts.example = {
enabled = true;
domain = "example.com";
ssl.cert = "${cert}/cert.pem";
ssl.key = "${cert}/key.pem";
};
muc = [ { domain = "conference.example.com"; } ];
httpFileShare = {
domain = "uploads.example.com";
};
};
networking.hosts."127.0.0.1" = [ "example.com" ];
}
+2
View File
@@ -3,6 +3,7 @@
stdenv,
fetchFromGitLab,
nix-update-script,
nixosTests,
# build
cmake,
@@ -74,6 +75,7 @@ stdenv.mkDerivation (finalAttrs: {
'';
passthru.updateScript = nix-update-script { extraArgs = [ "--version=branch" ]; };
passthru.tests.kaidan = nixosTests.kaidan;
meta = {
description = "User-friendly and modern chat app, using XMPP";