The Gilbert Arenas Dagger
The Gilbert Arenas Dagger

Reputation: 12741

Run Selenium tests against an Angular application in headless Chrome

I'm attempting to create Selenium tests against an Angular application. I want these tests to run in my continuous integration builds, which necessitates running them in headless mode. I'm attempting to use headless Chrome.

I've created two simple Selenium tests. One test accesses my local Angular application, the other accesses Google. They both run perfectly when I run them using the Chrome GUI, but the Angular test fails when I switch to Chrome headless.

I print out the page source in the Angular test and all HTML is rendered correctly when using the Chrome GUI, but when I switch to headless the page source shows only empty head and body tags.

Why is this happening and how can I fix it?

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExampleSeleniumTest {

    @LocalServerPort
    private int port;

    @Autowired
    private WebDriver driver;

    @Test // Always works
    public void testGoogle() {
        driver.get("http://www.google.com");
        WebElement element = driver.findElement(By.name("q"));
        element.sendKeys("Cheese!");
        element.submit();

        List<WebElement> findElements = driver.findElements(By.xpath("//*[@id='rso']//h3/a"));

        for (WebElement webElement : findElements) {
            System.out.println(webElement.getAttribute("href"));
        }
        Assert.assertTrue(findElements.size > 0);
    }


    @Test // Breaks in headless mode
    public void testLocalAngular() {
        driver.get("localhost:" + port);
        String pageSource = driver.getPageSource();
        // Page source empty in headless mode
        System.out.println(pageSource);
        String title = driver.findElement(By.className("mat-card-title")).getText();
        Assert.assertEquals("My Starter", title);
    }
} 

These tests depend on the following configuration

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
@ComponentScan(basePackageClasses = MyStarterApplication.class)
public class SeleniumConfig {

    @Value("${selenium.headless:#{true}}")
    private boolean headless;   

    @EventListener(classes = ApplicationReadyEvent.class)
    public void prepareDriver() {
        // Using https://github.com/bonigarcia/webdrivermanager
        ChromeDriverManager.getInstance().setup();
    }

    @Bean(destroyMethod = "quit")
    public WebDriver webDriver() {
        ChromeOptions options = new ChromeOptions();
        if (headless) {
            options.addArguments("headless");
            options.addArguments("window-size=1200x600");
        }
        WebDriver driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        return driver;
    }

}

Upvotes: 2

Views: 836

Answers (1)

The Gilbert Arenas Dagger
The Gilbert Arenas Dagger

Reputation: 12741

The problem was caused by:

driver.get("localhost:" + port);

I needed to specify the protocol. My test case works if I use:

driver.get("http://localhost:" + port);

Upvotes: 1

Related Questions