from app import ( build_archinstall_config, build_archinstall_creds, validate_step1, ) def test_validate_step1_accepts_good_input(): errors, values = validate_step1( { "hostname": "furtka", "username": "daniel", "password": "topsecretpw", "password2": "topsecretpw", "language": "de", } ) assert errors == [] assert values == { "hostname": "furtka", "username": "daniel", "password": "topsecretpw", "language": "de", } def test_validate_step1_collects_all_errors(): errors, _ = validate_step1( { "hostname": "BAD!", "username": "1bad", "password": "short", "password2": "mismatch", "language": "xx", } ) assert len(errors) == 5 def test_build_archinstall_config_uses_selected_locale(monkeypatch): # build_disk_config imports archinstall lazily; archinstall isn't # installed in CI (only runs on the live ISO), so stub it out. import app as app_module monkeypatch.setattr(app_module, "build_disk_config", lambda d: {"stubbed_device": d}) cfg = build_archinstall_config( { "hostname": "h", "username": "u", "password": "pw12345678", "language": "pl", "boot_drive": "/dev/sda", } ) assert cfg["disk_config"] == {"stubbed_device": "/dev/sda"} assert cfg["hostname"] == "h" assert cfg["locale_config"]["locale"] == "pl_PL.UTF-8" # Users moved out of config into creds once we adopted archinstall 4.x's # `!password` sentinel; config only carries a gpasswd in custom_commands # so the user lands in the docker group after docker is pacstrapped. assert "users" not in cfg assert cfg["custom_commands"][0] == "gpasswd -a u docker" def test_build_archinstall_config_includes_post_install_bootstrap(monkeypatch): # The installed system should come up with a Furtka landing page at # http://.local. That means caddy + avahi pacstrapped, the # matching services enabled, a Caddyfile + index.html written into the # target rootfs, and nss-mdns spliced into nsswitch.conf. import app as app_module monkeypatch.setattr(app_module, "build_disk_config", lambda d: {"stubbed_device": d}) cfg = build_archinstall_config( { "hostname": "heimserver", "username": "u", "password": "pw12345678", "language": "en", "boot_drive": "/dev/sda", } ) for pkg in ("caddy", "avahi", "nss-mdns"): assert pkg in cfg["packages"] # Packaged units go in `services` (enabled before custom_commands runs); # our own units don't exist at that point, so they must be enabled from # within custom_commands after the unit files land on disk. for svc in ("caddy", "avahi-daemon"): assert svc in cfg["services"] assert "furtka-welcome" not in cfg["services"] assert "furtka-status.timer" not in cfg["services"] joined = "\n".join(cfg["custom_commands"]) assert "systemctl enable furtka-welcome.service furtka-status.timer" in joined for path in ( "/etc/caddy/Caddyfile", "/srv/furtka/www/index.html", "/srv/furtka/www/style.css", "/srv/furtka/www/status.json", "/usr/local/bin/furtka-status", "/usr/local/bin/furtka-welcome", "/etc/systemd/system/furtka-status.service", "/etc/systemd/system/furtka-status.timer", "/etc/systemd/system/furtka-welcome.service", ): assert path in joined, f"expected {path} to be written by custom_commands" assert "mdns_minimal" in joined assert "nsswitch.conf" in joined # The chosen hostname is pinned into the static HTML at install-time. assert "s/__HOSTNAME__/heimserver/g" in joined def test_build_archinstall_creds_uses_archinstall_sentinel_keys(): creds = build_archinstall_creds({"username": "u", "password": "pw12345678"}) assert creds["!root-password"] == "pw12345678" assert creds["users"] == [ { "username": "u", "!password": "pw12345678", "sudo": True, "groups": [], } ]