tartare-util
v1.2.2
Published
A set of utils to make acceptance tests
Downloads
7
Maintainers
Readme
tartare-util
The Tartare family: tartare | tartare-chai | tartare-mock | tartare-collections | tartare-logs | protractor-tartare
This module offers a set of utils that can help you when making acceptance tests.
Install
$ npm install tartare-util
Import
JavaScript:
var tartareUtil = require('tartare-util');
TypeScript:
import * as tartareUtil from 'tartare-util';
API
tartare-util exports both functions and constants that are very handy when making acceptance tests. Some of that functions are grouped in submodules:
- http: functions related to the HTTP protocol.
- sut: functions that help you to start and stop the SUT (Subject Under Test).
Some of the functions below use OS commands (such as lsof
, pkill
, etc.) so they need to be installed for the
functions to work. Those functions have been tested with the following OSs: RHEL 6, RHEL 7, Ubuntu and OSX.
NONASCII_STRING
A string constant that contains characters outside of the ASCII-7 set. Useful to test whether a SUT accepts non-english characters.
INJECTION_STRING
A string constant that contains characters typically used for performing injection attacks.
getOS()
Guesses the type of operating system. It is based on the node.js os.platform()
function but distinguishes among
several Linux distributions.
It returns a string with some of the following values: 'redhat'
, 'ubuntu'
or 'osx'
. It returns null
when the OS
cannot be guessed.
http.getReason(statusCode)
Returns the HTTP reason related to the given status code. It gets the reason messages from the node.js
http.STATUS_CODES
array but this function does not fail when it receives a wrong status code, returning the
'Unknown status code' string.
tartareUtil.http.getReason(200);
'OK'
http.lowerCaseHeaders(headers)
headers
Object containing HTTP headers.
Returns the same object with all its properties lower-cased. This is useful to compare HTTP headers since they are case-insensitive.
tartareUtil.http.lowerCaseHeaders({
'Content-Type': 'text/html',
Date: 'Wed, 20 Jul 2016 08:12:31 GMT'
});
{
'content-type': 'text/html',
date: 'Tue, 15 Nov 1994 08:12:31 GMT'
}
http.getCharsetFromContentType(value)
value
String containing a typical value for a 'Content-Type' HTTP header, including a charset specification.
Extract the charset from a typical 'Content-Type' HTTP header.
tartareUtil.http.getCharsetFromContentType('text/html; charset=utf-8');
'utf-8'
sut.renderConfigFile(templateConfigFile, outputConfigFile, baseConfig, [additionalConfig])
templateConfigFile
(String) Configuration template filename containing mustache placeholders.outputConfigFile
(String) Resulting file after having applied the configurations over thetemplateConfigFile
.baseConfig
(Object) Configuration object to be applied overtemplateConfigFile
's mustache placeholders.additionalConfig
(Object) The same that the former parameter. Properties in this object will overwrite the ones inbaseConfig
with the same name. This allows using a basic configuration inbaseConfig
and some more specific configuration inadditionalConfig
.
Reads a configuration file containing mustache placeholders,
replaces them with the values from baseConfig
and additionalConfig
, and write the resulting configuration file.
This is useful when testing a SUT against different configurations, to generate different configuration files from
a template and specific values for each test.
Example:
Given that there is a template file named config.mustache
with the following content:
{
"serverPort": {{server.port}},
"database": {
"uri": "mongodb://localhost:{{mongoDb.port}}/{{{mongoDb.databaseName}}}"
}
}
When you apply renderConfigFile
:
var config = {
server: {
port: 8008
},
mongoDb: {
port: 5000,
databaseName: 'test'
}
}
tartareUtil.sut.renderConfigFile('config.mustache', 'config.json', config);
You get a file named config.json
with the following content:
{
"serverPort": 8008,
"database": {
"uri": "mongodb://localhost:5000/test"
}
}
sut.startServer(serverOpts, [timeout], cb)
serverOpts
Object with the following information about the server:command
(String) The server executable command.args
(String[]) Array of arguments to be passed to the server.env
(Object) Environment key-value pairs.cwd
(String) Current working directory of the child process.startupMessages
(String|String[]) Messages to be searched in stdout or stderr to consider that the served has started.
timeout
(Number) Max time (in ms) to wait for the server to start (Defaults to 5000).cb
The callback function will be called with the error and an object with some of the following parameters:pid
(Number) The process' PID (only if it has been started).stdout
(Stream) A Readable Stream that represents the process' stdout (only if it has been started).stderr
(Stream) A Readable Stream that represents the process' stderr (only if it has been started).stdin
(Stream) A Writable Stream that represents the child process' stdin (only if it has been started).readStdout
(String) What the process has already written to stdout at the time the callback is called.readStderr
(String) What the process has already written to stderr at the time the callback is called.exitCode
(Number) Exit code returned by the process, in case it has exited.signal
(String) Signal that terminated the process, in case it has exited.
Runs an instance of a generic server and optionally wait for something to be written in stdout or stderr to consider that the server has correctly started.
Depending on how your server behaves, you can use this function in different ways:
- If the server writes something to the stdout/stderr to signal that it has started
(e.g.: "Listening on port 8008") you can pass the string in the
startupMessages
property and the function will wait until the server has writen such a message. Then the callback will be called with different arguments depending on the server behaviour:- If everything goes well and the sever writes the message, the callback will be called without error and the second
parameter will include
pid
,stdout
,stderr
,stdin
,readStdout
andreadStderr
. - If the server exits before writing the message (before the
timeout
expires), the callback will be called with an error. - If the server does not write the message before the
timeout
expires (and it keeps running), it will be killed and the callback will be called with an error.
- If everything goes well and the sever writes the message, the callback will be called without error and the second
parameter will include
- If the server does not write anything to signal that it has started, call the function without
startupMessages
and it will wait fortimeout
ms, and then the callback will be called withpid
,stdout
,stderr
,stdin
,readStdout
andreadStderr
in the second argument. - If you expect the server to exit (for instance, because you are testing a wrong configuration), call the function
without
startupMessages
, and the callback will be called withreadStdout
,readStderr
,exitCode
andsignal
in the second argument when the server exits.
In any other case, the callback will be called with an error if the server cannot be executed or it unexpectedly exits.
Such an error will have the stdout
and stderr
properties with the output written by the server.
Note that you can put an array of strings on startupMessages
if the server writes several messages to signal
that it has started (e.g.: listening on several ports, listening on a port and connected to the database, etc.).
Example: Start a server and wait for it to write "Listening on port 8008" on the stdout:
var serverOpts = {
command: './bin/myserver',
args: ['--config', 'config.json'],
startupMessages: 'Listening on port 8008'
};
tartareUtil.sut.startServer(serverOpts, 3000, function(err, server) {
// As soon as the server writes the message
if (err) {
err.message += '\n\nstderr:' + err.stderr + '\n\nstdout:' + err.stdout;
return cb(err);
}
cb(null, server.pid);
});
Example: Start a server that does not write anything to the stdout or stderr and wait 3 seconds:
var serverOpts = {
command: './bin/myserver',
args: ['--config', 'config.json']
};
tartareUtil.sut.startServer(serverOpts, 3000, function(err, server) {
// After 3 seconds
if (err) {
err.message += '\n\nstderr:' + err.stderr + '\n\nstdout:' + err.stdout;
return cb(err);
}
cb(null, server.pid);
});
With TypeScript you can use the tartareUtil.sut.Server
type for the server
parameter of the callback.
sut.stopServer(pid, [signal])
pid
(Number) The PID of the process to stop.signal
(String|Number) The signal sent to the process (defaults to SIGTERM).
Stops a server (or any process) by its PID. The difference with process.kill()
is that this function
does not fail if the process does not exist.
sut.killServersByTcpPorts(ports, [signal], cb)
ports
(Number|Number[]) Ports whose processes are going to be killed.signal
(String|Number) The signal sent to the processes (defaults to SIGTERM).cb
Function called when the processes have been killed.err
Error.
Finds all the processes that are listening on the given list of ports and kill them using the given signal.
This function uses the lsof
or netstat
commands to find the process that listen on a port, so some of
them needs to be installed (lsof
is more compatible and should be enough if it is available for you OS).
It does not fail if no processes are found.
sut.killProcesses(opts, [signal], cb)
opts
Object with options used to match the processes to be killed:name
(String) The name of the process to be killed.args
(String) Args passed to the process through the command line.exact
(Boolean) Whether the matching is done exactly or not (Defaults totrue
).invert
(Boolean) Negates the matching (Defaults tofalse
).children
(Boolean) Also kills children processes (Defaults tofalse
).
signal
(String|Number) The signal sent to the processes (defaults to SIGTERM).cb
Function called when the processes have been killed.err
Error.
Kills processes that match the options using the given signal. This function uses the pgrep
, pkill
and kill
commands, so they need to be installed. It does not fail if there are no processes matching the options.