forked from fediversity/fediversity
		
	Reviewed-on: Fediversity/Fediversity#458 Co-authored-by: Kiara Grouwstra <kiara@procolix.eu> Co-committed-by: Kiara Grouwstra <kiara@procolix.eu>
		
			
				
	
	
		
			230 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ pkgs, ... }:
 | 
						|
 | 
						|
let
 | 
						|
  lib = pkgs.lib;
 | 
						|
 | 
						|
  ## FIXME: this binding was not used but maybe we want a side effect or something?
 | 
						|
  # rebuildableTest = import ./rebuildableTest.nix pkgs;
 | 
						|
 | 
						|
  email = "test@test.com";
 | 
						|
  password = "testtest";
 | 
						|
 | 
						|
  # FIXME: Replace all the By.XPATH by By.CSS_SELECTOR.
 | 
						|
 | 
						|
  seleniumImports = ''
 | 
						|
    import sys
 | 
						|
    from selenium import webdriver
 | 
						|
    from selenium.webdriver.common.by import By
 | 
						|
    from selenium.webdriver.chrome.options import Options
 | 
						|
  '';
 | 
						|
 | 
						|
  seleniumSetup = ''
 | 
						|
    print("Create and configure driver...", file=sys.stderr)
 | 
						|
    options = Options()
 | 
						|
    # options.add_argument("--headless=new")
 | 
						|
    service = webdriver.ChromeService(executable_path="${lib.getExe pkgs.chromedriver}")  # noqa: E501
 | 
						|
    driver = webdriver.Chrome(options=options, service=service)
 | 
						|
    driver.implicitly_wait(30)
 | 
						|
    driver.set_window_size(1280, 960)
 | 
						|
  '';
 | 
						|
 | 
						|
  seleniumPixelfedLogin = ''
 | 
						|
    print("Open login page...", file=sys.stderr)
 | 
						|
    driver.get("http://pixelfed.localhost/login")
 | 
						|
    print("Enter email...", file=sys.stderr)
 | 
						|
    driver.find_element(By.ID, "email").send_keys("${email}")
 | 
						|
    print("Enter password...", file=sys.stderr)
 | 
						|
    driver.find_element(By.ID, "password").send_keys("${password}")
 | 
						|
    # FIXME: This is disgusting. Find instead the input type submit in the form
 | 
						|
    # with action ending in "/login".
 | 
						|
    print("Click “Login” button...", file=sys.stderr)
 | 
						|
    driver.find_element(By.XPATH, "//button[normalize-space()='Login']").click()
 | 
						|
  '';
 | 
						|
 | 
						|
  ## NOTE: `path` must be a valid python string, either a variable or _quoted_.
 | 
						|
  seleniumTakeScreenshot = path: ''
 | 
						|
    print("Take screenshot...", file=sys.stderr)
 | 
						|
    if not driver.save_screenshot(${path}):
 | 
						|
        raise Exception("selenium could not save screenshot")
 | 
						|
  '';
 | 
						|
 | 
						|
  seleniumQuit = ''
 | 
						|
    print("Quitting...", file=sys.stderr)
 | 
						|
    driver.quit()
 | 
						|
  '';
 | 
						|
 | 
						|
  seleniumScriptPostPicture =
 | 
						|
    pkgs.writers.writePython3Bin "selenium-script-post-picture"
 | 
						|
      { libraries = with pkgs.python3Packages; [ selenium ]; }
 | 
						|
      ''
 | 
						|
        import os
 | 
						|
        import time
 | 
						|
        ${seleniumImports}
 | 
						|
        from selenium.webdriver.support.wait import WebDriverWait
 | 
						|
 | 
						|
        ${seleniumSetup}
 | 
						|
        ${seleniumPixelfedLogin}
 | 
						|
        time.sleep(3)
 | 
						|
 | 
						|
        media_path = os.environ['POST_MEDIA']
 | 
						|
 | 
						|
        # Find the new post form, fill it in with our pictureand a caption.
 | 
						|
        print("Click on “Create New Post”...", file=sys.stderr)
 | 
						|
        driver.find_element(By.LINK_TEXT, "Create New Post").click()
 | 
						|
        print("Add file to input element...", file=sys.stderr)
 | 
						|
        driver.find_element(By.XPATH, "//input[@type='file']").send_keys(media_path)
 | 
						|
        print("Add a caption", file=sys.stderr)
 | 
						|
        driver.find_element(By.CSS_SELECTOR, ".media-body textarea").send_keys(
 | 
						|
            "Fediversity test of image upload to pixelfed with garage storage."
 | 
						|
        )
 | 
						|
        time.sleep(3)
 | 
						|
        print("Click on “Post” button...", file=sys.stderr)
 | 
						|
        driver.find_element(By.LINK_TEXT, "Post").click()
 | 
						|
 | 
						|
        # Wait until the post loads, and in particular its picture, then take a
 | 
						|
        # screenshot of the whole page.
 | 
						|
        print("Wait for post and image to be loaded...", file=sys.stderr)
 | 
						|
        img = driver.find_element(
 | 
						|
            By.XPATH,
 | 
						|
            "//div[@class='timeline-status-component-content']//img"
 | 
						|
        )
 | 
						|
        WebDriverWait(driver, timeout=10).until(
 | 
						|
            lambda d: d.execute_script("return arguments[0].complete", img)
 | 
						|
        )
 | 
						|
        time.sleep(3)
 | 
						|
 | 
						|
        ${seleniumTakeScreenshot "\"/home/selenium/screenshot.png\""}
 | 
						|
        ${seleniumQuit}'';
 | 
						|
 | 
						|
  seleniumScriptGetSrc =
 | 
						|
    pkgs.writers.writePython3Bin "selenium-script-get-src"
 | 
						|
      { libraries = with pkgs.python3Packages; [ selenium ]; }
 | 
						|
      ''
 | 
						|
        ${seleniumImports}
 | 
						|
        ${seleniumSetup}
 | 
						|
        ${seleniumPixelfedLogin}
 | 
						|
 | 
						|
        img = driver.find_element(
 | 
						|
            By.XPATH,
 | 
						|
            "//div[@class='timeline-status-component-content']//img"
 | 
						|
        )
 | 
						|
        # REVIEW: Need to wait for it to be loaded?
 | 
						|
        print(img.get_attribute('src'))
 | 
						|
 | 
						|
        ${seleniumQuit}'';
 | 
						|
 | 
						|
  dummyFile = pkgs.writeText "dummy" "dummy";
 | 
						|
in
 | 
						|
{
 | 
						|
  name = "test-pixelfed-garage";
 | 
						|
 | 
						|
  nodes = {
 | 
						|
    server =
 | 
						|
      { config, ... }:
 | 
						|
      {
 | 
						|
 | 
						|
        services = {
 | 
						|
          xserver = {
 | 
						|
            enable = true;
 | 
						|
            displayManager.lightdm.enable = true;
 | 
						|
            desktopManager.lxqt.enable = true;
 | 
						|
          };
 | 
						|
 | 
						|
          displayManager.autoLogin = {
 | 
						|
            enable = true;
 | 
						|
            user = "selenium";
 | 
						|
          };
 | 
						|
        };
 | 
						|
        virtualisation.resolution = {
 | 
						|
          x = 1680;
 | 
						|
          y = 1050;
 | 
						|
        };
 | 
						|
 | 
						|
        virtualisation = {
 | 
						|
          memorySize = lib.mkVMOverride 8192;
 | 
						|
          cores = 8;
 | 
						|
        };
 | 
						|
        imports = [
 | 
						|
          ../fediversity
 | 
						|
          ../vm/garage-vm.nix
 | 
						|
          ../vm/pixelfed-vm.nix
 | 
						|
        ];
 | 
						|
        # TODO: pair down
 | 
						|
        environment.systemPackages = with pkgs; [
 | 
						|
          python3
 | 
						|
          chromium
 | 
						|
          chromedriver
 | 
						|
          xh
 | 
						|
          seleniumScriptPostPicture
 | 
						|
          seleniumScriptGetSrc
 | 
						|
          helix
 | 
						|
          imagemagick
 | 
						|
        ];
 | 
						|
        environment.variables = {
 | 
						|
          POST_MEDIA = ./fediversity.png;
 | 
						|
          AWS_ACCESS_KEY_ID = "$(cat ${config.fediversity.pixelfed.s3AccessKeyFile})";
 | 
						|
          AWS_SECRET_ACCESS_KEY = "$(cat ${config.fediversity.pixelfed.s3SecretKeyFile})";
 | 
						|
          ## without this we get frivolous errors in the logs
 | 
						|
          MC_REGION = "garage";
 | 
						|
        };
 | 
						|
        # chrome does not like being run as root
 | 
						|
        users.users.selenium = {
 | 
						|
          isNormalUser = true;
 | 
						|
        };
 | 
						|
        fediversity.temp.initialUser = {
 | 
						|
          username = "dummy";
 | 
						|
          displayName = "dummy";
 | 
						|
          email = "dummy";
 | 
						|
          passwordFile = dummyFile;
 | 
						|
        };
 | 
						|
      };
 | 
						|
  };
 | 
						|
 | 
						|
  testScript =
 | 
						|
    { nodes, ... }:
 | 
						|
    ''
 | 
						|
      import re
 | 
						|
 | 
						|
      server.start()
 | 
						|
 | 
						|
      with subtest("Pixelfed starts"):
 | 
						|
        server.wait_for_unit("phpfpm-pixelfed.service")
 | 
						|
 | 
						|
      with subtest("Account creation"):
 | 
						|
        server.succeed("pixelfed-manage user:create --name=test --username=test --email=${email} --password=${password} --confirm_email=1")
 | 
						|
 | 
						|
      # NOTE: This could in theory give a false positive if pixelfed changes it's
 | 
						|
      # colorscheme to include pure green. (see same problem in mastodon-garage.nix).
 | 
						|
      # TODO: For instance: post a red image and check that the green pixel IS NOT
 | 
						|
      # there, then post a green image and check that the green pixel IS there.
 | 
						|
 | 
						|
      with subtest("Image displays"):
 | 
						|
        server.succeed("su - selenium -c 'selenium-script-post-picture ${email} ${password}'")
 | 
						|
        server.copy_from_vm("/home/selenium/screenshot.png", "")
 | 
						|
        displayed_colors = server.succeed("magick /home/selenium/screenshot.png -define histogram:unique-colors=true -format %c histogram:info:")
 | 
						|
        # check that the green image displayed somewhere
 | 
						|
        image_check = re.match(".*#FF0500.*", displayed_colors, re.S)
 | 
						|
        if image_check is None:
 | 
						|
          raise Exception("cannot detect the uploaded image on pixelfed page.")
 | 
						|
 | 
						|
      with subtest("access garage"):
 | 
						|
        server.succeed("mc alias set garage ${nodes.server.fediversity.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY")
 | 
						|
        server.succeed("mc ls garage/pixelfed")
 | 
						|
 | 
						|
      with subtest("access image in garage"):
 | 
						|
        image = server.succeed("mc find garage --regex '\\.png' --ignore '*_thumb.png'")
 | 
						|
        image = image.rstrip()
 | 
						|
        if image == "":
 | 
						|
          raise Exception("image posted to Pixelfed did not get stored in garage")
 | 
						|
        server.succeed(f"mc cat {image} >/garage-image.png")
 | 
						|
        garage_image_hash = server.succeed("identify -quiet -format '%#' /garage-image.png")
 | 
						|
        image_hash = server.succeed("identify -quiet -format '%#' $POST_MEDIA")
 | 
						|
        if garage_image_hash != image_hash:
 | 
						|
          raise Exception("image stored in garage did not match image uploaded")
 | 
						|
 | 
						|
      with subtest("Check that image comes from garage"):
 | 
						|
        src = server.succeed("su - selenium -c 'selenium-script-get-src ${email} ${password}'")
 | 
						|
        if not src.startswith("${nodes.server.fediversity.garage.web.urlForBucket "pixelfed"}"):
 | 
						|
          raise Exception("image does not come from garage")
 | 
						|
    '';
 | 
						|
}
 |