There’s a Phantom in the machine (but how do I take control of it?)

When it comes to fixing a problem with my computer, or debugging code I am writing, I can sit for hours trying to figure out why I am not getting the results I desire. When I finally have my solution, sometimes I’ll want to hit myself, realizing it was a simple mistake that I probably should have caught earlier (and now won’t ever repeat again), while in other cases where the solution is more complex, rather than feeling like I “wasted”time, I feel like I actually learned something

The latter happened this past week as I shifted some of my attention to learning JavaScript (no, I didn’t skip over Rails, I’ll get back to that in upcoming posts). I’d previously worked with JS a little, but now I was getting ready to learn it from the ground up, using test-driven-development (TDD) as my guide for both understanding the JS concepts I was learning, as well as to allow to validate my progress. In Ruby and Rails, I utilized RSpec as the tool for TDD, while in JS, I was being introduced to Jasmine as our testing library. One of the nice things about Jasmine is that it can display the test results within an interactive browser window, allowing you to to step through each test and re-run the test after you update the code in your IDE. To work with Jasmine tests from within the command line, another program called phantomJS is required. phantomJS can be used for “Headless Testing”, relying on Jasmine to evaluate the tests, but to display the results within the CLI window. And I had a lot of difficulty getting phantomJS to work.

First, I tried to determine if I had phantomJS installed in my local environment and it appeared I did. Through, whenever I tried to invoke it through learn’s CLI command, I received the following error message:

Installing missing dependency phantomjs...
Error: An unsatisfied requirement failed this build.

Not a lot of information to go on. Though, when I googled this error message, I learned that I wasn’t the only one to see this issue with phantomJS. Many others (including myself) had tried installing phantomJS via Homebrew, typically a very effective package manager tool capable of downloading the program desired and any required dependencies. However in this case, following the introduction of OS X 10.11 El Capitan (the latest version of OS X), Homebrew couldn’t download phantomJS:

phantomjs: OS X Yosemite or older is required.
Error: An unsatisfied requirement failed this build.

Users who later appeared to be successful installing phantomJS did so through npm, also referred to as the Node Package Manager, and more focused on maintaining JavaScript-related packages. So I tried installing installing phantomJS via the command:

npm install -g phantomjs

I did this a few times (below is one of the runs). Adding to the confusion was that the package name was changed to “phantomjs-prebuilt” though the program was still called “phantomjs”:

npm WARN deprecated phantomjs@2.1.7: Package renamed to phantomjs-prebuilt. Please update 'phantomjs' package references to 'phantomjs-prebuilt'
PhantomJS not found on PATH
Download already available at /var/folders/h8/bsq9_lfn5s1778jztg3wclv00000gp/T/phantomjs/
Verified checksum of previously downloaded file
Extracting zip contents
Copying extracted folder /var/folders/h8/bsq9_lfn5s1778jztg3wclv00000gp/T/phantomjs/ -> /usr/local/Cellar/node/5.2.0/libexec/npm/lib/node_modules/phantomjs
Writing location.js file
Done. Phantomjs binary available at /usr/local/Cellar/node/5.2.0/libexec/npm/lib/node_modules/phantomjs
├── progress@1.1.8
├── kew@0.7.0
├── request-progress@2.0.1 (throttleit@1.0.0)
├── which@1.2.10 (isexe@1.1.2)
├── hasha@2.2.0 (is-stream@1.1.0, pinkie-promise@2.0.1)
├── extract-zip@1.5.0 (debug@0.7.4, yauzl@2.4.1, mkdirp@0.5.0, concat-stream@1.5.0)
├── fs-extra@0.26.7 (path-is-absolute@1.0.0, klaw@1.3.0, graceful-fs@4.1.4, jsonfile@2.3.1, rimraf@2.5.3)
└── request@2.67.0 (tunnel-agent@0.4.3, aws-sign2@0.6.0, oauth-sign@0.8.2, forever-agent@0.6.1, is-typedarray@1.0.0, caseless@0.11.0, stringstream@0.0.5, isstream@0.1.2, json-stringify-safe@5.0.1, extend@3.0.0, tough-cookie@2.2.2, node-uuid@1.4.7, qs@5.2.0, combined-stream@1.0.5, mime-types@2.1.11, form-data@1.0.0-rc4, bl@1.0.3, hawk@3.1.3, http-signature@1.1.1, har-validator@2.0.6)

Yet, subsequently I would still get the same error message I initially got when trying to run my Jasmine tests. I also tried to install phantomJS within a given project folder (not globally via -g) but no luck there either.

I had noticed the message  PhantomJS not found on PATH was displayed in the output whenever I tried to install the application and decided to focus on that. I knew about the concept of PATH variables as global system variables referenced by programs from working on Windows, but was not entirely familiar with them on macOS, or how to set them in bash. I learned that you can set a PATH variable within a bash session using the export PATH command, or make it persistent by modifying the .bash_profile file that resides in every User’s home directory. As I learned and refreshed my memory, the .bash_profile file gets called whenever you load Terminal or another bash application (I use iTerm2) containing a user’s settings, preferences, AND PATH variable configurations for reference when executing commands from a command line. Given that from the npm install output log, I knew that phantomJS was installed in /usr/local/Cellar/node/5.2.0/libexec/npm/lib/node_modules/phantomjs (which somewhat ironically is the directory where applications installed via Homebrew also reside), I tried adding the following line in my .bash_profile:

export PATH=/usr/local/Cellar/node/5.2.0/libexec/npm/lib/node_modules/phantomjs/bin:$PATH

Following saving the .bash_profile file, and restarting iTerm2, I navigated to my project folder where Jasmine tests were present, and invoked them to run in the command line via phantomJS. AND IT WORKED! presenting the results of the tests with no error messages. I also invoked it to run in the browser as well and this too was successful with no error messages.

Up until this point in my studies, I really hadn’t had any local Environment configuration issues. Researching and figuring out this solution probably took about 4-5 hours over the course of 2-3 evenings. While time consuming, troubleshooting this ultimately taught me more about:

  • how Jasmine and phantomJS work together as a testing suite for Javascript,
  • the npm package manager, which I anticipate I will be using more in my JS work (and that Homebrew isn’t the be all solution),
  • bash configuration and customization

…and reminding me of the continued importance of patience and persistence.

About the author

Leave a Reply

Your email address will not be published. Required fields are marked *

About This Blog

This blog will serve as my outlet to share my thoughts and learnings as I dedicate myself to becoming a full-stack web developer...something too long in the making.

What I’ve Been Learning

+ Ruby
+ Ruby on Rails
+ JavaScript
+ jQuery
+ AngularJS