forked from Fediversity/simple-nixos-fediverse
interactive test is working
This commit is contained in:
parent
693e21b1a8
commit
dab12bc2b8
33
garage.nix
33
garage.nix
|
@ -38,7 +38,8 @@ let
|
|||
|
||||
${optionalString corsRules.enable ''
|
||||
garage bucket allow --read --write --owner ${bucketArg} --key tmp
|
||||
aws --endpoint http://s3.garage.localhost:3900 s3api put-bucket-cors --bucket ${bucketArg} --cors-configuration ${corsRulesJSON}
|
||||
# TODO: endpoin-url should not be hard-coded
|
||||
aws --region ${cfg.settings.s3_api.s3_region} --endpoint-url http://s3.garage.localhost:3900 s3api put-bucket-cors --bucket ${bucketArg} --cors-configuration ${corsRulesJSON}
|
||||
garage bucket deny --read --write --owner ${bucketArg} --key tmp
|
||||
''}
|
||||
'';
|
||||
|
@ -124,21 +125,23 @@ in {
|
|||
};
|
||||
|
||||
config = {
|
||||
virtualisation.diskSize = 2048;
|
||||
virtualisation.forwardPorts = [
|
||||
{
|
||||
from = "host";
|
||||
host.port = 3901;
|
||||
guest.port = 3901;
|
||||
}
|
||||
{
|
||||
from = "host";
|
||||
host.port = 3902;
|
||||
guest.port = 3902;
|
||||
}
|
||||
];
|
||||
virtualisation.vmVariant = { config, ... }: {
|
||||
virtualisation.diskSize = 2048;
|
||||
virtualisation.forwardPorts = [
|
||||
{
|
||||
from = "host";
|
||||
host.port = 3901;
|
||||
guest.port = 3901;
|
||||
}
|
||||
{
|
||||
from = "host";
|
||||
host.port = 3902;
|
||||
guest.port = 3902;
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.minio-client pkgs.awscli ];
|
||||
environment.systemPackages = [ pkgs.minio-client pkgs.awscli ];
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 3901 3902 ];
|
||||
services.garage = {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.5 KiB |
BIN
tests/green.png
Normal file
BIN
tests/green.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 692 B |
|
@ -1,7 +1,37 @@
|
|||
{ pkgs, self }:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
# python = pkgs.python310.withPackages (ps: with ps; [ requests aiokafka ]);
|
||||
rebuildableTest = import ./rebuildableTest.nix pkgs;
|
||||
seleniumScript = pkgs.writers.writePython3Bin "selenium-script"
|
||||
{
|
||||
libraries = with pkgs.python3Packages; [ selenium ];
|
||||
} ''
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.firefox.options import Options
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
print(1)
|
||||
|
||||
options = Options()
|
||||
options.add_argument("--headless")
|
||||
# devtools don't show up in headless screenshots
|
||||
# options.add_argument("-devtools")
|
||||
service = webdriver.FirefoxService(executable_path="${lib.getExe pkgs.geckodriver}") # noqa: E501
|
||||
|
||||
driver = webdriver.Firefox(options=options, service=service)
|
||||
driver.get("http://mastodon.localhost:55001/public/local")
|
||||
|
||||
# wait until the statuses load
|
||||
WebDriverWait(driver, 90).until(
|
||||
lambda x: x.find_element(By.CLASS_NAME, "status"))
|
||||
|
||||
# XXX: how do I save this to the derivation output?
|
||||
driver.save_screenshot("/mastodon-screenshot.png")
|
||||
|
||||
driver.close()
|
||||
'';
|
||||
in
|
||||
rebuildableTest {
|
||||
name = "test-mastodon-garage";
|
||||
|
@ -10,13 +40,29 @@ rebuildableTest {
|
|||
# skipTypeCheck = true;
|
||||
|
||||
nodes = {
|
||||
server = {
|
||||
server = {config, ...}: {
|
||||
virtualisation.memorySize = lib.mkVMOverride 4096;
|
||||
imports = [ self.nixosModules.garage self.nixosModules.mastodon ];
|
||||
environment.systemPackages = with pkgs; [ toot ];
|
||||
# TODO: pair down
|
||||
environment.systemPackages = with pkgs; [
|
||||
python3
|
||||
firefox-unwrapped
|
||||
geckodriver
|
||||
toot
|
||||
xh
|
||||
seleniumScript
|
||||
helix
|
||||
imagemagick
|
||||
];
|
||||
environment.variables = {
|
||||
POST_MEDIA = ./green.png;
|
||||
AWS_ACCESS_KEY_ID = config.services.garage.ensureKeys.mastodon.id;
|
||||
AWS_SECRET_ACCESS_KEY = config.services.garage.ensureKeys.mastodon.secret;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
testScript = {nodes, ...}: ''
|
||||
import re
|
||||
import time
|
||||
|
||||
|
@ -26,33 +72,59 @@ rebuildableTest {
|
|||
server.wait_for_unit("mastodon-web.service")
|
||||
|
||||
# make sure mastodon is fully up and running before we interact with it
|
||||
# TODO: is there a way to test for this?
|
||||
time.sleep(180)
|
||||
|
||||
with subtest("Account creation"):
|
||||
account_creation_output = server.succeed("mastodon-tootctl accounts create test --email test@test.com --confirmed --approve")
|
||||
password_re = re.compile('New password: (.*)')
|
||||
password_match = password_re.match(account_creation_output)
|
||||
password_match = re.match('.*New password: ([^\n]*).*', account_creation_output, re.S)
|
||||
assert password_match is not None
|
||||
password = password_match.groups()[0]
|
||||
password = password_match.group(1)
|
||||
|
||||
with subtest("TTY Login"):
|
||||
server.wait_until_tty_matches("1", "login: ")
|
||||
server.send_chars("root\n");
|
||||
|
||||
with subtest("Log in with toot"):
|
||||
# toot doesn't provide a way to just specify our login details as arguments, so we have to pretend we're typing them in at the prompt
|
||||
server.send_chars("toot login_ctl\n")
|
||||
time.sleep(0.2)
|
||||
# Enter instance URL
|
||||
server.send_chars("http://mastodon.localhost:55001\n")
|
||||
time.sleep(0.2)
|
||||
# Email
|
||||
server.send_chars("test@test.com\n")
|
||||
time.sleep(0.2)
|
||||
# Password
|
||||
server.send_chars("toot login_cli --instance http://mastodon.localhost:55001 --email test@test.com\n")
|
||||
server.wait_until_tty_matches("1", "Password: ")
|
||||
server.send_chars(password + "\n")
|
||||
server.wait_until_tty_matches("1", "Successfully logged in.")
|
||||
|
||||
with subtest("Post an image"):
|
||||
server.succeed("toot post --media ${./fediversity.png}")
|
||||
with subtest("post text"):
|
||||
server.succeed("echo 'hello mastodon' | toot post")
|
||||
|
||||
# TODO: I don't think there's a good way to test for whether the image visually shows up.
|
||||
# we can test for CORS headers using curl / xh
|
||||
# or **maybe** somehow read the javascript console?
|
||||
with subtest("post image"):
|
||||
server.succeed("toot post --media $POST_MEDIA")
|
||||
|
||||
with subtest("access garage"):
|
||||
server.succeed("mc alias set garage http://s3.garage.localhost:3900 --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY")
|
||||
server.succeed("mc ls garage/mastodon")
|
||||
|
||||
with subtest("access image in garage"):
|
||||
image = server.succeed("mc find garage --regex original")
|
||||
image = image.rstrip()
|
||||
assert image != ""
|
||||
server.succeed(f"mc cat {image} >/garage-image.webp")
|
||||
garage_image_hash = server.succeed("identify -quiet -format '%#' /garage-image.webp")
|
||||
image_hash = server.succeed("identify -quiet -format '%#' $POST_MEDIA")
|
||||
assert garage_image_hash == image_hash
|
||||
|
||||
with subtest("Content security policy allows garage images"):
|
||||
headers = server.succeed("xh -h http://masstodon.localhost:55001/public/local")
|
||||
csp_match = re.match('^Content-Security-Policy: (.*)$', headers, re.M)
|
||||
assert csp_match is not None
|
||||
csp = csp_match.group(1)
|
||||
# the content security policy should include the garage server
|
||||
garage_csp = re.match(".*web\.garage\.localhost:3902.*", csp)
|
||||
assert garage_csp is not None
|
||||
|
||||
with subtest("image displays"):
|
||||
server.succeed("selenium-script")
|
||||
server.copy_from_vm("/mastodon-screenshot.png", "")
|
||||
displayed_colors = server.succeed("convert /mastodon-screenshot.png -define histogram:unique-colors=true -format %c histogram:info:")
|
||||
# check that the green image displayed somewhere
|
||||
re.match(".*#00FF00.*", displayed_colors, re.S)
|
||||
'';
|
||||
}
|
||||
|
|
Reference in a new issue