navit alternatives and similar modules
Based on the "Testing" category.
Alternatively, view navit alternatives based on common mentions on social networks and blogs.
-
Playwright
Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API. -
Nightwatch
Integrated end-to-end testing framework written in Node.js and using W3C Webdriver API. Developed at @browserstack -
volkswagen
:see_no_evil: Volkswagen detects when your tests are being run in a CI server, and makes them pass. -
istanbul
Yet another JS code coverage tool that computes statement, line, function and branch coverage with module loader hooks to transparently add coverage when running tests. Supports all JS coverage use cases including unit tests, server side functional tests and browser tests. Built for scale. -
loadtest
Runs a load test on the selected URL. Fast and easy to use. Can be integrated in your own workflow using the API. -
power-assert
Power Assert in JavaScript. Provides descriptive assertion messages through standard assert interface. No API is the best API. -
testcontainers-node
Testcontainers is a NodeJS library that supports tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
SaaSHub - Software Alternatives and Reviews
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of navit or a related project?
Popular Comparisons
README
navit
Wrapper for Electron to simplify browser tests scripting.
Install
Note, you need to install electron
with this package, it is not included as
a dependency.
npm install navit electron --save
Examples
const browser = require('./')({ timeout: 30000, engine: 'electron' });
const stack = []; // You can use lazy functions to pass data between stages,
// but arrays have more compact notation.
browser
.open('https://dev.nodeca.com')
.wait(() => {
try { return window.NodecaLoader.booted; } catch (__) { return false; }
})
.get.url(stack)
.click('forum-category__content:first forum-section__title-link')
.wait(data => location.url !== data[data.length - 1], stack)
.test.exists('.forum-topiclines')
.close()
.then(() => console.log('Succeeded'), err => console.log(err));
// Or with callback (old way)
browser
.open('https://dev.nodeca.com')
.wait(() => {
try { return window.NodecaLoader.booted; } catch (__) { return false; }
})
.get.url(stack)
.click('forum-category__content:first forum-section__title-link')
.wait(data => location.url !== data[data.length - 1], stack)
.test.exists('.forum-topiclines')
// first param `true` is equivalent to `.close()` call
.run(true, function (err) {
console.log(err || 'Succeeded');
});
Also look files in test folder.
Those are real examples how to use navit
with mocha
.
API
- All methods are chainable.
- Methods, marked with
+
have direct aliases without namespace. - Chain should be finished with terminator
.run([teardown,] callback)
call. - Almost everywhere
String
&Number
params can be defined as functions for lazy evaluation.
Known limitations:
Some methods like .get.evaluate()
allow to pass params to evaluated functions.
navit
uses function's .length
property, to properly detect params count,
because tailing callbacks are optional. That means, such functions must have
explicit parameters list in definition, and you must pass exactly the same
params count as defined. We decided, it's not a big price for nice API.
Electron is NOT headless. To run your script in headless environment, you should xvfb.
new Navit(options, engineOpts)
options (not mandatory):
inject
: Array of scripts (file paths) to inject after every page load ([ require.resolve('jquery/dist/jquery') ]
).timeout
: Page load and.wait()
timeout, default5000ms
.prefix
: url prefix for.open()
and.post()
, default empty string.engine
: optional, engine driver to use. Onlyelectron
is available for now.enginePath
: optional, direct path to browser engine. Don't use without need, it should be autodetected viaelectron
package.
engineOpts (not mandatory, camelCase):
See https://www.electronjs.org/docs/api/command-line-switches. You can pass any options, supported by browser engine. Option names should be in camelCase.
Actions: .do.*()
Navigation:
- +
.do.open(url [, options])
- options:
method
- get(default)|post|put|delete|headdata
headers
- +
.do.post(url, data[, options])
- shortcut to.open
, for convenience;method
is set topost
, anddata
is forwarded tooptions.data
. - +
.do.back()
- +
.do.forward()
- +
.do.reload()
DOM:
- +
.do.click(selector)
- click on an element matchingselector
- +
.do.type(selector, text)
- typetext
into input or contenteditable - +
.do.clear(selector)
- clear input value (supports contenteditable) - +
.do.check(selector)
- toggles checkbox or radio - +
.do.select(selector, option)
- selects anoption
in dropdown - +
.do.upload(selector, path)
- selects a file ininput[type="file"]
- +
.do.fill(selector, obj [, submit])
- fill out a form (same as fill in CasperJS) - +
.do.scrollTo(top, left)
- executeswindow.scrollTo(top, left)
- +
.do.inject([type, ] file)
- appends a script or stylesheets from externalfile
to page,type
can be one ofjs
orcss
(default type isjs
).
Waiting:
- +
.do.wait()
- wait until page ready; can be useful afterclick
,back
andforward
actions (open
andreload
track progress for html pages automatically) - +
.do.wait(delay)
- pause fordelay
milliseconds - +
.do.wait(selector [, timeout])
- wait until selector available - +
.do.wait(fn [, params..., timeout])
- evaluate function in cycle, until returnstrue
.
Get data/params: .get.*()
All functions, passed to .get.*
, can be sync (with 1 param) or async (with 2
params). If function returns not falsy type of result (usually a Error
) or
throws exception, chain will be terminated. That can be used to create complex
test conditions.
- +
.get.title(fn)
- +
.get.url(fn)
- +
.get.count(selector, fn)
- +
.get.text(selector, fn)
- +
.get.html([selector,] fn)
- when no selector given, returns full page html. - +
.get.attribute(selector, attribute, fn)
- +
.get.value(selector, fn)
- for input/selector fields, returns field value. .get.evaluate(fnToEval [, params, fn])
- evaluate function on client with optional params. Returned result can be processed on server, if handler set..get.status(fn)
.get.body(fn)
.get.headers(fn)
- return server reply headers. Note, testing method is not "symmetric" - use.test.header(name, ...)
..get.cookies(fn)
(no pair in.test.*
)
Sugar:
- If you pass
Array
instead ofFunction
, data will be pushed into it. - If
fn
returnsError
object (or anything else not falsy), chain will be stopped with that value. - If last param (
callback
) exists, chain will be finished as with.run
method.
Set data/params: .set.*()
- +
.set.headers(obj)
- +
.set.useragent(string)
- +
.set.authentication(user, pass)
- +
.set.viewport(width, height)
- +
.set.zoom(scale)
- +
.set.cookie(obj)
- +
.set.cookie(name, value)
*If value not passed, cookie will be deleted.
Assertions: .test.*()
& test()
Tests available for the most of get.*
methods:
.test.method_name(params..., value [, message)
- If value to compare is
RegExp
, then data is converted toString
, and tested to match provided regexp. - Negative condition
.not
can be added to almost any test, before or after method name.
Additional:
- +
.test[.not].exists(selector [, message])
- +
.test[.not].visible(selector [, message])
- +
.test.evaluate(fn [params..., message])
- evaluate & die on any result buttrue
.
Special sugar:
.test(status_number [, message])
.test(body_rexexp [, message])
.test(header_name, string_or_regexp [, message])
Tabs: .tab.*()
.tab.open([url [, options]])
- create and switch to new tab. Run.do.open(url, options)
ifurl
specified.tab.count(fn)
- get tabs count (if you passArray
, value will be pushed into).tab.switch(index)
- switch to tab byindex
.tab.close([index])
- close tab byindex
or close current tab ifindex
not specified- negative
index
address tab from the tail - after all tabs closed, new one will be created automatically
- negative
Other
.fn(function, params)
- local function execute. Function can be with callback or sync or async or return Promise. Params count should match function signature for sync functions (and be 1 less for function with callback)..exit()
- tear down browser process. Note, browser will NOT be closed until you do it explicit via this method or.run(true, ...)
..close()
- similar to.exit()
but stackable (will be executed in order with other chained commends)..run([teardown,] done)
- terminate sequence of commands (execute and do callback).- If
teardown
istrue
, then close the browser after the sequence finishes. - If callback not passed, return result as
Promise
.
- If
.then(onSuccess, onFail)
- executes.run(false)
under the hood..screenshot([ selector|bounding_rect, type,] path)
- do screenshot.registerMethod(names, fn)
- add new method with given name(s) (names
can be string or array)..use(plugin [, params...])
- apply plugin.
Batches
navit
allows record sequence or commands to run it later with one call as
many times as you wish.
// create
.batch.create('init_page', function() {
this.
.wait(function () {
try {
return window.NodecaLoader.booted;
} catch (__) {}
return false;
});
.viewport(1600, 1200)
.inject(require.resolve('jquery/dist/jquery'))
.fn(function () {
console.log('Batch done.');
})
})
// run
.batch('init_page')
.afterOpen
If you assign function to this property, it will be called after any .open
and .reload
definition to stack additional commands. This is experimental
feature, that can be changed.
Sometime you may wish to do global setup for all opened pages. For example:
- wait full page init, when it has dynamic scripts loader.
- inject testing scripts from remote host (when you don't like to use global option).
You can record your sequence to batch and automate it's injection after every
open
/ reload
. See example how we setup navit
in nodeca
:
// Wait for nodeca scripts load and check status
//
navit.batch.create('waitNodecaBooted', function () {
this
.wait(function () {
try {
return window.NodecaLoader.booted;
} catch (__) {}
return false;
})
.test.status(200);
});
navit.afterOpen = function () {
this.batch('waitNodecaBooted');
};
Note. .afterOpen
is called on chain definition phase, not on execution
phase. It's ~ equivalent of typing content manually in test body. That's why it
doesn't have callback to wait async operations - it's not needed.
Debug
If you assign environment variable DEBUG
to navit
, you will see debug message
for every action.
Output example for DEBUG=navit mocha
:
...
navit do.open('http://localhost:17345/test/fixtures/do/type.html') +25ms
navit do.type('#type-test') +20ms
navit test.evaluate() +9ms
navit do.type('#contenteditable-test') +2ms
navit test.evaluate() +9ms
โ type (64ms)
...
Other scripting projects
Here are links to other similar libraries and comments why we did this one. Note that comments are given according to our requirements. Your ones can be different. May be you need more to scrape data from real sites instead of interface testing and so on. Select the best package for you needs:
- CasperJS
- Runs standalone. You will not be able to control server and browser from single script (load fixtures to db, prior to open page).
- Tests could be more compact, if CasperJS allows curried style.
- Zombie.js
- Uses jsdom. Nice idea, but jsdom emulation is a bit limited for complex things. We prefer real browser engines like PhantomJS and SlimerJS.
- Nightmare
- That was the nearest to our needs, and we used it before.
- It has poor errors control if error happpens in the middle of batch. For example, if you wait for selector, it's difficult to check do you finished with succes or by timeout.
- Too few built-in assertions.
- Not actively developped (see tracker - some problems caused by buggy bridge to PhantomJS are not fixed for a long time).
- Horseman
- Has sync api, that can be convenient for scraping.
- Sync api limits you with getting multiple data from browser to server - getter should be the single, always the last. You can workaround this limitation, but that will increase amount of code to write.
Authors
License
*Note that all licence references and agreements mentioned in the navit README section above
are relevant to that project's source code only.