nixos/tests: init Kaidan (#469539)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
'';
|
||||
}
|
||||
@@ -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" ];
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user