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 ''
|
${optionalString corsRules.enable ''
|
||||||
garage bucket allow --read --write --owner ${bucketArg} --key tmp
|
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
|
garage bucket deny --read --write --owner ${bucketArg} --key tmp
|
||||||
''}
|
''}
|
||||||
'';
|
'';
|
||||||
|
@ -124,21 +125,23 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
virtualisation.diskSize = 2048;
|
virtualisation.vmVariant = { config, ... }: {
|
||||||
virtualisation.forwardPorts = [
|
virtualisation.diskSize = 2048;
|
||||||
{
|
virtualisation.forwardPorts = [
|
||||||
from = "host";
|
{
|
||||||
host.port = 3901;
|
from = "host";
|
||||||
guest.port = 3901;
|
host.port = 3901;
|
||||||
}
|
guest.port = 3901;
|
||||||
{
|
}
|
||||||
from = "host";
|
{
|
||||||
host.port = 3902;
|
from = "host";
|
||||||
guest.port = 3902;
|
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 ];
|
networking.firewall.allowedTCPPorts = [ 3901 3902 ];
|
||||||
services.garage = {
|
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 }:
|
{ pkgs, self }:
|
||||||
let
|
let
|
||||||
|
lib = pkgs.lib;
|
||||||
# python = pkgs.python310.withPackages (ps: with ps; [ requests aiokafka ]);
|
# python = pkgs.python310.withPackages (ps: with ps; [ requests aiokafka ]);
|
||||||
rebuildableTest = import ./rebuildableTest.nix pkgs;
|
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
|
in
|
||||||
rebuildableTest {
|
rebuildableTest {
|
||||||
name = "test-mastodon-garage";
|
name = "test-mastodon-garage";
|
||||||
|
@ -10,13 +40,29 @@ rebuildableTest {
|
||||||
# skipTypeCheck = true;
|
# skipTypeCheck = true;
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
server = {
|
server = {config, ...}: {
|
||||||
|
virtualisation.memorySize = lib.mkVMOverride 4096;
|
||||||
imports = [ self.nixosModules.garage self.nixosModules.mastodon ];
|
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 re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -26,33 +72,59 @@ rebuildableTest {
|
||||||
server.wait_for_unit("mastodon-web.service")
|
server.wait_for_unit("mastodon-web.service")
|
||||||
|
|
||||||
# make sure mastodon is fully up and running before we interact with it
|
# 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)
|
time.sleep(180)
|
||||||
|
|
||||||
with subtest("Account creation"):
|
with subtest("Account creation"):
|
||||||
account_creation_output = server.succeed("mastodon-tootctl accounts create test --email test@test.com --confirmed --approve")
|
account_creation_output = server.succeed("mastodon-tootctl accounts create test --email test@test.com --confirmed --approve")
|
||||||
password_re = re.compile('New password: (.*)')
|
password_match = re.match('.*New password: ([^\n]*).*', account_creation_output, re.S)
|
||||||
password_match = password_re.match(account_creation_output)
|
|
||||||
assert password_match is not None
|
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"):
|
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
|
# 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")
|
server.send_chars("toot login_cli --instance http://mastodon.localhost:55001 --email test@test.com\n")
|
||||||
time.sleep(0.2)
|
server.wait_until_tty_matches("1", "Password: ")
|
||||||
# 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(password + "\n")
|
server.send_chars(password + "\n")
|
||||||
|
server.wait_until_tty_matches("1", "Successfully logged in.")
|
||||||
|
|
||||||
with subtest("Post an image"):
|
with subtest("post text"):
|
||||||
server.succeed("toot post --media ${./fediversity.png}")
|
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.
|
with subtest("post image"):
|
||||||
# we can test for CORS headers using curl / xh
|
server.succeed("toot post --media $POST_MEDIA")
|
||||||
# or **maybe** somehow read the javascript console?
|
|
||||||
|
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