wrike / callisto

Callisto is an open-source Kubernetes-native implementation of Selenium Grid.
MIT License
110 stars 15 forks source link

Problem with check that file is downloaded #13

Open klesarev opened 1 month ago

klesarev commented 1 month ago

Hi!

I am using Selenide + Callisto. Some tests needs to check that value is copied to clipboard and file is downloaded (with file extension format). Cases with clipboard i realized with JavaScript, but I am stuck with file download tests.

If I understand correctly, Callisto don't provide full access to CDP. I've tried various methods from Selenide to check file uploads - none of them works, but with Moon or Selenoid everything works fine.

I don’t want to solve the problem again using JavaScript. Maybe there are some other ways? Or do you have plans to implement such a check (access to the downloads folder)?

Thanks!

shilko2013 commented 1 month ago

@klesarev Thank you for contacting us. Unfortunaly we currently do not plan to support this functionality in Callisto. We use the next flow for checking file downloading:

  1. Open chrome://downloads/ page
  2. Execute script to get URL and name of the downloaded file
  3. Download this file using URL and check its content

I'll provide you with the Java + Selenium code example

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.hamcrest.core.IsNull.notNullValue;

public class DownloadFileTest {

    private static final String GET_LAST_DOWNLOAD_URL = "try { return document" +
            ".querySelector(\"downloads-manager\").shadowRoot.querySelector(\"iron-list\")" +
            ".querySelector(\"downloads-item\").shadowRoot.getElementById(\"url\").getAttribute(\"href\") }" +
            "catch (e) { return null }";
    private static final String GET_LAST_DOWNLOAD_NAME = "try { return document" +
            ".querySelector(\"downloads-manager\").shadowRoot.querySelector(\"iron-list\")" +
            ".querySelector(\"downloads-item\").shadowRoot.getElementById(\"file-link\").innerText}" +
            "catch (e) { return null }";

    private RemoteWebDriver driver;

    @BeforeEach
    void setUp() {
        driver = new ChromeDriver();
    }

    @Test
    void testFileDownloading() throws IOException {
        //todo: download file
        checkDownloadedFile("File", "Content");
    }

    @AfterEach
    void tearDown() {
        driver.quit();
    }

    private void checkDownloadedFile(final String expectedName, final String expectedContent) throws IOException {
        driver.get("chrome://downloads/");
        String downloadedFileUrl = executeScriptUntilSuccess(GET_LAST_DOWNLOAD_URL);
        String downloadedFileName = executeScriptUntilSuccess(GET_LAST_DOWNLOAD_NAME);
        assertThat(downloadedFileName)
                .isEqualTo(expectedName);
        Path path = downloadFileFromUrl(downloadedFileUrl, downloadedFileName);
        assertThat(path)
                .hasContent(expectedContent);
    }

    private String executeScriptUntilSuccess(final String script) {
        return await("Downloaded file is present on <downloads> page")
                .atMost(3, SECONDS)
                .pollInterval(250, MILLISECONDS)
                .until(() -> (String) driver.executeScript(script), notNullValue());
    }

    private Path downloadFileFromUrl(final String fileUrl, final String fileName) throws IOException {
        Path tempDirectory = Files.createTempDirectory("tmp");
        Path downloadedFile = tempDirectory.resolve(fileName);

        try (InputStream in = new URL(fileUrl).openStream()) {
            Files.copy(in, downloadedFile, StandardCopyOption.REPLACE_EXISTING);
        }
        return downloadedFile;
    }

}

and maven dependencies for this example

<dependencies>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.25.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.11.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.assertj</groupId>
        <artifactId>assertj-core</artifactId>
        <version>3.26.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.awaitility</groupId>
        <artifactId>awaitility</artifactId>
        <version>4.2.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>
klesarev commented 1 month ago

Thanks alot! I'll try your method, and I’ll write about this in the comments below)

P.S. Callisto is a powerful thing! it has better performance(with less resource consumption) and test speed than Selenoid or Moon)