Typical integration test frameworks are a nightmare of callbacks and arbitrary chaining syntax. Ghostjs uses standardized ES7 async functions in order to create a syntax that's extremely easy to reason about and work with. Take a look at our API and an example test case below. Ghostjs currently runs on both Chrome, Firefox (through SlimerJS), and Phantom.
npm install ghostjs
ghost.injectScripts(path)
- Injects scripts into the webpage.ghost.setDriverOpts(opts)
- Sets driver options. You can find a list of supported options here.await ghost.open(url, options={headers={}, settings:{}, viewportSize:{}})
- Instantiates ghostjs and opens a webpageawait ghost.findElement(selector)
- Returns an element instance of this selector.await ghost.findElements(selector)
- Returns an array of element instances that match the given selector.ghost.goBack()
- Navigates back in history one page.ghost.goForward()
- Navigates forward in history one page.await ghost.screenshot(filename?, folder?)
- Saves a screenshot to the screenshots/ folder.await ghost.script(func, [args]?)
- Executes a script within a page and returns the result of that function.await ghost.usePage(string)
- Uses a page as a context to script. E.g., a url from window.open. Pass null to switch back to the main page.await ghost.wait(ms)
- Waits for an arbitrary amount of time. It's typicall better to wait for elements or dom state instead.await ghost.wait(func)
- Waits until the return condition of the passed in function is met. Polls continuously until a return condition is true.await ghost.waitForElement(selector)
- Waits for an element to exist in the page, and returns it.await ghost.waitForElementNotVisible(selector)
- Waits for an element to be hidden or inexistent in the dom.await ghost.waitForElementVisible(selector)
- Waits for an element to exist and be visible on the page.await ghost.waitForPage(string)
- Waits for the a page to be opened opened with the given url (or string search), via window.open.await ghost.waitForPageTitle(string|RegExp)
- Waits for the page title to match the expected value.await ghost.click(selector)
- Clicks on an element specified by the selector, by default in the center of the element.await ghost.fill(selector, text)
- Fills a form field with the provided value. Tries to set the right value for non-text inputs.await element.click(x?, y?)
- Clicks the element, by default in the center of the element.await element.getAttribute(attribute)
- Returns the value of an attribute for this elementawait element.html()
- Returns the innerHTML of an element.await element.file(path)
- Sets a file input to a file on disk.await element.fill(text)
- Sets a form field to the provided value. Tries setting the right value for non-text inputs.await element.isVisible()
- Checks whether or not the element is visible.await element.mouse(type, x?, y?)
- Dispatches a mouse of event of the given type to the element.await element.rect()
- Returns the current coordinates and sizing information of the element.await element.text()
- Returns the textContent of an element.await element.script(func, [args]?)
- Executes a function on the page which receives the DOM element as the first argument.
import ghost from 'ghostjs'
import assert from 'assert'
describe('Google', () => {
it('has some content', async () => {
await ghost.open('http://google.com')
let pageTitle = await ghost.pageTitle()
assert.equal(pageTitle, 'Google')
// Get the content of the body
let body = await ghost.findElement('body')
assert.ok(await body.isVisible())
console.log('got body content', await body.html())
// Wait for the first link and click it
let firstLink = await ghost.waitForElement('a')
firstLink.click()
})
})
await ghost.open(myUrl)
var hasMoved = await ghost.waitFor(async () => {
var el = await ghost.findElement('.someSelector')
var rect = await el.rect()
return rect.left > 100
})
assert.equal(hasMoved, true)
// The recommended way to get element text:
let el = await ghost.waitForElement(selector)
let text = await el.text()
console.log(text)
// If you're looking for something slightly less verbose, you can also chain with .then():
let text = await ghost.waitForElement(selector).then( async el => el.text() )
console.log(text)
By default ghostjs will use Chrome as a test runner, or when you pass --browser chrome
as a command line argument. You will need to have chrome installed on your machine, but ghostjs will try to automatically locate the binary. You can specify a CHROME_BIN env var to override this location.
You can also set flags that you'd like to specify to the chrome binary by setting the CHROME_FLAGS env variable, separated by commas:
CHROME_FLAGS=--disable-gpu,--force-text-direction=RTL ghostjs --browser chrome test/*.js
You can choose to test on PhantomJS as a test runner by passing the --browser phantom
option to the ghostjs
command. PhantomJS is installed as a dependency of the ghostjs
package. E.g., you may have the following in your package.json:
"scripts": {
"test": "ghostjs --browser phantom test/*.js"
}
You can choose to test on Firefox (through SlimerJS) as a test runner by passing the --browser firefox
option to the ghostjs
command. Firefox must be installed on your computer to run tests against Firefox. E.g., you may have the following in your package.json:
"scripts": {
"test": "ghostjs --browser firefox test/*.js"
}
Note: SlimerJS is not headless and requires a windowing environment to run. If you are trying to run SlimerJS on travis, you can modify your travis.yml to have the following:
before_script:
- export DISPLAY=:99.0
- "sh -e /etc/init.d/xvfb start"
You can see how we run both Chrome, Firefox and PhantomJS tests in our example package.json and our .travis.yml
Since we're using bleeding edge javascript /w async functions we currently recommend that you use babel to run your tests. At a minimum you should install these packages:
npm install babel-preset-es2015 --save-dev
npm install babel-preset-stage-0 --save-dev
In a file named .babelrc
:
{
"presets": ["es2015", "stage-0"]
}
You can output verbose website information like console.log statements and errors by using the --verbose
flag. E.g, ghostjs ./test/mytest.js --verbose
.
The Slimer JSConsole can be very useful when debugging tests. There are two ways to open the console, one inside a test with:
ghost.setDriverOpts({parameters: ['-jsconsole']})
You can also pass an environment variable to enable the console:
GHOST_CONSOLE=1 ./node_modules/.bin/ghostjs
onResourceRequested - Pass a custom function to execute whenever a resource is requested.
networkOptions: ghost.networkTypes['offline'|'gprs'|'regular2g'|'good2g'|'regular3g'|'good3g'|'regular4g|'dsl'|'wifi']
As of v1.11.0, Ghost supports network throttling for loading pages. This feature is only available when run with the --browser=chrome
flag.
With network throttling, you can simulate running your tests with a variety of connections. These connections are exposed in Ghost under ghost.networkTypes
, and represent the latency, download, and upload speeds that are found in the Chrome devtools.
Please see: CONTRIBUTING.md