Phantomjs not showing text

TL;DR if Phantomjs doesn’t show any text/fonts, give it a Truetype web font.

phantomjs-logo

Despite Phantomjs‘ [1] development slowing down [2] it still brings most of the features I need for regression testing web applications. And, thanks to Docker, it should be possible to operate it for a long time to come. Installing and operating Phantomjs is disarmingly simple: it is a single binary with no dependencies and installing it is as simple as copying it into a folder. There are also ways to get it with a package manager [3].

In constrained, headless environments, Phantomjs will sometimes not render text. If folklore [4] is to be trusted, the reason is mostly fonts not being available in those environments. Version 2.1.10 and above seems to be able to load and render Truetype web fonts, which is the basic escape plan:

  1. install a fallback Truetype font with the web application
  2. declare a CSS rule which loads the fallback font only for Phantomjs
  3. activate the rule in tests

Implementing the escape plan

Downloading a (preferably Unicode) TTF and deploying it with the web application should be straight forward.

Next, declare a Phantomjs-only rule in the web application’s CSS. I found that Phantomjs will not render fonts that have been inlined [5], it has to be a regular URL:

@font-face {
 font-family: phantomjsfont;
 src: url(/static/fonts/arial.ttf);
}

.phantomjs *{
 font-family: phantomjsfont;
}

Make sure your web server delivers fonts with a proper MIME type [6].

Last, activate the rule in integration tests. E.g. in a JUnit test with Webdriver, adding the “phantomjs” class to the root document element:

((JavascriptExecutor) webDriver).executeScript(
"document.getElementsByTagName('body')[0].setAttribute('class','phantomjs');"
);

One more thing…

A web UI which uses “strange” characters (U+00FF and above) may suddenly run into test failures with elements not being visible and/or clickable. I found that as long as Phantomjs had no  font to render, it would render text with empty spaces which, however, do take up some space. Once Phantomjs has a font it can use for rendering, but cannot find a character in that font, it will not show anything. So make sure you use fonts that have glyphs for all characters that are important in tests.

Resources

[1] Phantomjs website
http://phantomjs.org/

[2] Announcement: main Phantomjs developer stepping down
https://groups.google.com/forum/#!topic/phantomjs/9aI5d-LDuNE

[3] phantomjs for npm
https://www.npmjs.com/package/phantomjs

phantomjs for maven
https://mvnrepository.com/artifact/org.webjars.npm/phantomjs-prebuilt

[4] Embedded fonts not rendered
https://github.com/ariya/phantomjs/issues/10247

Web Fonts do not render, use fallback fonts instead.
https://github.com/ariya/phantomjs/issues/10592

Linux fonts not rendering correctly
https://github.com/ariya/phantomjs/issues/14013

[5] base-64-font-loader
https://www.npmjs.com/package/base64-font-loader

[6] TTF MIME type
https://stackoverflow.com/questions/5128069/what-is-the-mime-type-for-ttf-files

 

 

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.