AppTester¶
API¶
-
class
AppTester
(app, opts)¶ Machinery for testing a sandbox application.
Provides setup, interaction and checking tasks. Whenever a task method is called, its task is scheduled to run next time
AppTester.run()
is called.Arguments: - app (App) – the sandbox app to be tested.
- opts.api (object) – options to initialise the tester’s
DummyApi()
with each reset.
-
static
reset
()¶ Clears scheduled tasks and data, and uses a new api and interaction machine, clearing things for the next tester run.
-
static
run
()¶ Runs the tester’s scheduled tasks in the order they were scheduled, then resets the tester. Returns a promise which will be fulfilled once the scheduled tasks have run and the tester has reset itself.
Setup Tasks¶
Setup tasks are used to configure the sandbox app’s config and store data before any interaction and checking is done.
-
AppTester.
setup
(fn)¶ Allows custom setting up of the sandbox application’s config and data.
Arguments: - fn (function) – function to be used to set up the sandbox application. Takes the
form
func(api)
, whereapi
is the tester’s api instance andthis
is theAppTester()
instance. May return a promise.
tester.setup(function(api) { api.config.store.foo = 'bar'; });
- fn (function) – function to be used to set up the sandbox application. Takes the
form
-
AppTester.setup.
char_limit
(n)¶ Sets the character limit checked during the checking phase of the tester run. The default character limit is 160.
Arguments: - n (object) – the new character limit to set.
tester.setup.char_limit(20);
-
AppTester.setup.
config
(obj)¶ Updates the sandbox config with the properties given in
obj
.Arguments: - obj (object) – the properties to update the current app config with.
- opts.json (object) – whether these config options should be serialized to JSON.
tester.setup.config({foo: 'bar'});
-
AppTester.setup.
config
(obj) Updates the sandbox’s app config (the
'config'
field in the sandbox config) with the properties given inobj
.Arguments: - obj (object) – the properties to update the current app config with.
tester.setup.config.app({name: 'some_amazing_app'});
-
AppTester.setup.
endpoint
(endpoint, delivery_class)¶ Updates the sandbox’s app config (the
'config'
field in the sandbox config) with the given outbound endpoints.Arguments: - str (opts.delivery_class) – the name of the endpoint to configure
- str – the name of the delivery class. See
ContactStore.get()
for a list of the supported delivery classes.
tester.setup.config.endpoint('sms_endpoint', { delivery_class: 'sms', });
-
AppTester.setup.
kv
(obj)¶ Updates the app’s kv store with the properties given in
obj
.Arguments: - obj (object) – the properties to update the current kv store with.
tester.setup.kv({foo: 'bar'});
-
AppTester.setup.
user
(obj)¶ Updates the currently stored data about the user with the properties given in
obj
.Arguments: - obj (object) – the properties to update the currently stored user data with
tester.setup.user({ addr: '+81', lang: 'jp' });
If any properties other than
addr
are given,AppTester assumes that this is an existing user. This effects whether a :class:`UserNewEvent()
orUserLoadEvent()
will be fired during the sandbox run.
-
AppTester.setup.
user
(fn) Passes the currently stored user data to the function
fn
, then set the stored user data to the function’s result.Arguments: - fn (function) – function of the form
func(user)
, whereuser
is the currently stored user data object andthis
is theAppTester()
instance. The stored user data is set withfn
‘s result. May return its result via a promise.
tester.setup.user(function(user) { user.addr = '+81'; user.lang = 'jp'; return user; })
If any properties other than
addr
are given,AppTester assumes that this is an existing user. This effects whether a :class:`UserNewEvent()
orUserLoadEvent()
will be fired during the sandbox run.- fn (function) – function of the form
-
AppTester.setup.user.
addr
(addr)¶ Sets the from address of the user sending a message received by the sandbox app.
Arguments: - addr (string) – the user’s new from address
tester.setup.user.addr('+27987654321');
-
AppTester.setup.user.
answer
(state_name, answer)¶ Sets the user’s answer to a state already encountered.
Arguments: - state_name (string) – the name of the state to set an answer for.
- answer (string) – the answer given by the user for the state
tester.setup.user.answer('initial_state', 'coffee');
-
AppTester.setup.user.
answers
(answers)¶ Sets the user’s answers to states already encountered by the user.
Arguments: - answers (object) – (state name, answer) pairs for each state the user has encountered and answered
tester.setup.user.answers({ initial_state: 'coffee', coffee_state: 'yes' });
-
AppTester.setup.user.
lang
(lang)¶ Sets the user’s language code.
Arguments: - lang (string) – the user’s new language code (eg, ‘en’ or ‘af’)
tester.setup.user.lang('af');
-
AppTester.setup.user.
metadata
(metadata)¶ Updates the user’s metadata. Any properties in the current metadata with the same names as properties in the new metadata will overwritten.
Arguments: - metadata (object) – The new metadata to update the current user metadata with.
tester.setup.user.metadata({foo: 'bar'});
-
AppTester.setup.user.
state
(state_name[, opts])¶ Sets the state most recently visited by the user using a state name.
Arguments: - name (string) – The name of the state.
- opts.metadata (object) – metadata associated with the state. Optional.
- opts.creator_opts (object) – options to be given to the creator associated with the given state name. Optional.
tester.setup.user.state('initial_state', { metadata: {foo: 'bar'}, creator_opts: {baz: 'qux'} });
-
AppTester.setup.user.
state
(opts) Sets the state most recently visited by the user using options.
Arguments: - opts.name (string) – The name of the state.
- opts.metadata (object) – Optional state metadata.
- opts.creator_opts (object) – options to be given to the creator associated with the given state name. Optional.
tester.setup.user.state({ name: 'initial_state', metadata: {foo: 'bar'}, creator_opts: {baz: 'qux'} });
-
AppTester.setup.user.state.
creator_opts
(opts)¶ Updates the options passed to the state creator of the state most recently visited by the user.
Arguments: - opts (object) – The new options to update the current creator options with. Any properties in the current creator options with the same names as properties in the new options will overwritten.
States are created typically created twice (on the first sandbox run when we switch to the state, and on the next sandbox run when we give the state the user’s input). This makes this setup method useful for setting up the options for the second sandbox run.
tester.setup.user.state.creator_opts({foo: 'bar'});
- opts (object) –
-
AppTester.setup.user.state.
metadata
(metadata)¶ Updates the metadata of the state most recently visited by the user.
Arguments: - metadata (object) – The new metadata to update the current state metadata with. Any properties in the current metadata with the same names as properties in the new metadata will overwritten.
tester.setup.user.state.metadata({foo: 'bar'});
Interaction Tasks¶
Interaction tasks are used to simulate interaction with the sandbox. Input interactions are the most common, where the sandbox receives a message sent in by a user.
-
AppTester.
input
(content)¶ Updates the content of the message to be sent from the user into the sandbox. If the content is
null
orundefined
, defaults the message’s session event to'new', or otherwise to ``'resume'
.Arguments: - content (string or null) – the new content of the message to be sent
tester.input('coffee');
-
AppTester.
input
() Updates the content of the message to be sent from the user into the sandbox to be
null
and defaults the message’s session event type to ‘new’. Typically used to test starting up a session with the user.tester.input();
-
AppTester.
input
(obj) Updates the message to be sent from the user into the sandbox with the properties given in
obj
.Arguments: - obj (object) – the properties to update on the message to be sent
tester.input({ content: 'coffee', session_event: 'resume' });
-
AppTester.
input
(fn) Passes the current message data to be sent from the user into the sandbox into the function
fn
, then sets it with the function’s result.Arguments: - fn (function) – function of the form
func(msg)
, wheremsg
is the current message data andthis
is theAppTester()
instance. The current message is updated withfn
‘s result. May return its result via a promise.
tester.input(function(msg) { msg.content = 'coffee'; return msg; })
- fn (function) – function of the form
-
AppTester.input.
content
(content)¶ Updates the content of the message to be sent from the user into the sandbox.
Arguments: - content (string) – the new content of the message to be sent
tester.input.content('coffee');
-
AppTester.input.
session_event
(session_event)¶ Updates the session event of the message to be sent from the user into the sandbox.
Arguments: - session_event (string) – the session event of the message to be sent.
The following session event values are recognised:
'new'
: used to signal the start of the session, where the session has been initiated by the user. The content of the message is irrelevant.'resume'
: a common message sent in from the user during a session'close'
: used to signal the end of the session, where the session has been terminated by the user. The content of the message is irrelevant.
tester.input.session_event('resume');
-
AppTester.
inputs
(input1[, input2[, ...]])¶ Sets a collection of messages to be sent from the user into the sandbox. Each input corresponds to a new message in a new interaction.
AppTester()
setup methods will count for the first interaction, subsequent interactions will rely on api state from the previous interaction, and check methods will only happen after the last interaction.Arguments: - input1, input2, ... (arguments) – The messages to be given as input in each interaction. If an object
is given for an input, the object’s properties are used as the
actual message properties.
null
or string inputs will be taken as the message content for that particular message.
tester.inputs(null, 'coffee', '1', {content: '2'});
- input1, input2, ... (arguments) – The messages to be given as input in each interaction. If an object
is given for an input, the object’s properties are used as the
actual message properties.
-
AppTester.
inputs
(fn) Passes the current messages to be sent from the user into the sandbox into the function
fn
, then sets it with the function’s result.Arguments: - fn (function) – function of the form
func(msgs)
, wheremsgs
is the current messages andthis
is theAppTester()
instance. The current messages are updated withfn
‘s result. May return its result via a promise.
tester.inputs(function(msgs) { return msgs.concat('coffee'); })
- fn (function) – function of the form
-
AppTester.
start
()¶ Updates the content of the message to be sent from the user into the sandbox to be null and defaults the message’s session event type to ‘new’. Typically used to test starting up a session with the user.
tester.start();
Checking Tasks¶
Checking tasks are used to check the state of the sandbox application and its currently associated user (the user which sent in a message to the sandbox application). The check tasks are where the test assertions happen.
-
AppTester.
check
(fn)¶ Allows custom assertions to be done after a sandbox run.
Arguments: - fn (function) – function that will be performing the assertions. Takes the form
func(api, im, app)
, whereapi
is the tester’s api instance (by default an instance ofDummyApi()
),im
is the tester’sInteractionMachine()
instance,app
is the sandbox app being tested andthis
is theAppTester()
instance. May return a promise.
tester.check(function(api, im, app) { assert.notDeepEqual(api.logs, []); });
-
static
interaction
(opts)¶ Performs the checks typically done after a user has interacted with a sandbox app.
Arguments: - opts.state (string) – the expected name of user’s state at the end of the sandbox run.
- opts.reply (string) – the expected content of the reply message sent back to the user after the sandbox run. Optional.
- opts.char_limit (integer) – Checks that the content of the reply sent back to the user does not exceed the given character count. Optional.
tester.check.interaction({ state: 'initial_state', reply: 'Tea or coffee?' });
- fn (function) – function that will be performing the assertions. Takes the form
-
AppTester.check.
ends_session
()¶ Checks if the reply message sent to the user was set to end the session. This happens, for example, when the user reaches an
EndState()
.tester.check.reply.ends_session();
-
AppTester.check.
reply
(content)¶ Checks that the content of the reply sent back to the user during the sandbox run equals the expected
content
. Alias toAppTester.check.reply.content()
.Arguments: - content (string) – the expected content of the sent out reply.
tester.check.reply('Tea or coffee?');
-
AppTester.check.
reply
(re) Checks that the content of the reply sent back to the user during the sandbox run matches the regex.
Arguments: - re (RegExp) – Regular expression to match the content of the sent out reply against.
tester.check.reply.content(/Tea or coffee?/);
-
AppTester.check.
reply
(obj) Checks that the reply sent back to the user during the sandbox run deep equals
obj
.Arguments: - obj (object) – the properties to check the reply against
tester.check.reply({ content: 'Tea or coffee?' });
-
AppTester.check.
reply
(fn) Passes the reply sent back to the user during the sandbox run to the function
fn
, allowing custom assertions to be done on the reply.Arguments: - fn (function) – function of the form
func(reply)
, wherereply
is the sent out reply andthis
is theAppTester()
instance.
tester.check.reply(function(reply) { assert.equal(reply.content, 'Tea or coffee?'); })
- fn (function) – function of the form
-
AppTester.check.reply.
char_limit
(n)¶ Checks that the content of the reply sent back to the user does not exceed the character count given by
n
.Arguments: - n (integer) – the character count that the sent out reply’s content is expected to not exceed.
tester.check.reply.char_limit(10);
-
AppTester.check.reply.
content
(content)¶ Checks that the content of the reply sent back to the user during the sandbox run equals the expected
content
. Alias toAppTester.check.reply.content()
.Arguments: - content (string) – the expected content of the sent out reply.
tester.check.reply.content('Tea or coffee?');
-
AppTester.check.reply.
content
(re) Checks that the content of the reply sent back to the user during the sandbox run matches the regex. Alias to
AppTester.check.reply.content()
.Arguments: - re (RegExp) – Regular expression to match the content of the sent out reply against.
tester.check.reply.content(/Tea or coffee?/);
-
AppTester.check.reply.
content
(content) Checks that no reply was sent back to the user.
tester.check.no_reply();
-
AppTester.check.reply.
properties
(obj)¶ Checks that the expected properties given in
obj
are equal to the corresponding properties of the reply sent back to the user during the sandbox run.Arguments: - obj (object) – the properties to check the reply against
tester.check.reply.properties({ content: 'Tea or coffee?' });
-
AppTester.check.
user
(obj)¶ Checks that once serialized, the user deep equals
obj
.Arguments: - obj (object) – the properties to check the user against
tester.check.user({ state: {name: 'coffee_state'}, answers: {initial_state: 'coffee'} });
-
AppTester.check.
user
(fn) Passes the current user instance to the function
fn
, allowing custom assertions to be done on the user. May return a promise.Arguments: - fn (function) – function of the form
func(user)
, whereuser
is the current user instance andthis
is theAppTester()
instance.
tester.check.user(function(user) { assert.equal(user.state.name, 'coffee_state'); assert.equal(user.get_answer('initial_state', 'coffee'); })
- fn (function) – function of the form
-
AppTester.check.user.
answer
(state_name, answer)¶ Checks that the user’s answer to a state already encountered matches the expected
answer
.Arguments: - state_name (string) – the name of the state to check the answer of.
- answer (string) – the expected answer by the user for the state
tester.check.user.answer('initial_state', 'coffee');
-
AppTester.check.user.
answers
(answers)¶ Checks that the user’s answers to states already encountered by the user match the expected
answers
.Arguments: - answers (object) – (
state_name
,answer
) pairs for each state the user has encountered and answered
tester.check.user.answers({ initial_state: 'coffee', coffee_state: 'yes' });
- answers (object) – (
-
AppTester.check.user.
lang
(lang)¶ Checks that the user’s language matches the expected language code.
Arguments: - lang (string) – the language code (e.g. ‘sw’, ‘en’, ‘en_ZA’) or
null
to check that no language code is set.
tester.check.user.lang('sw'); tester.check.user.lang(null);
- lang (string) – the language code (e.g. ‘sw’, ‘en’, ‘en_ZA’) or
-
AppTester.check.user.
metadata
(metadata)¶ Checks that the user’s metadata after a sandbox run deep equals the expected
metadata
.Arguments: - metadata (object) – the expected metadata of the user
tester.check.user.metadata({foo: 'bar'});
-
AppTester.check.user.
properties
(obj)¶ Checks that the expected properties given in
obj
are equal to the corresponding properties of the user after a sandbox run.Arguments: - obj (object) – the properties to check the user against
tester.check.user.properties({ lang: 'en', state: {name: 'coffee_state'}, answers: {initial_state: 'coffee'} });
-
AppTester.check.user.
state
(name)¶ Checks that the name of the user’s state after a sandbox run equals the expected
name
.Arguments: - name (string) – the expected name of the current state
tester.check.user.state('coffee_state');
-
AppTester.check.user.
state
(obj) Checks that the user’s state after a sandbox run deep equals
obj
.Arguments: - obj.name (string) – the expected name for the state
- obj.metadata (object) – the expected metadata for the state.
- obj.creator_opts (object) – the expected creator options for the state.
tester.check.user.state({ name: 'coffee_state', metadata: {foo: 'bar'}, creator_opts: {baz: 'qux'} });
-
AppTester.check.user.
state
(fn) Passes the user’s state data after a sandbox run to the function
fn
, allowing custom assertions to be done on the state.Arguments: - fn (function) – function of the form
func(state)
, wherestate
is the current state instance andthis
is theAppTester()
instance.
tester.check.user.state(function(state) { assert.equal(state.name, 'coffee_state'); })
- fn (function) – function of the form
-
AppTester.check.user.state.
creator_opts
(creator_opts)¶ Checks that the creator options of the interaction machine’s current state after a sandbox run deep equals the expected options.
Arguments: - creator_opts (object) – the expected creator_opts of the current state
tester.check.user.state.creator_opts({foo: 'bar'});
-
AppTester.check.user.state.
metadata
(metadata)¶ Checks that the metadata of the interaction machine’s current state after a sandbox run deep equals the expected
metadata
.Arguments: - metadata (object) – the expected metadata of the current state
tester.check.user.state.metadata({foo: 'bar'});
Under the Hood¶
If need be, one can always add custom task types. AppTester’s setup,
interaction and check tasks all extend the same class,
AppTesterTasks()
.
-
class
AppTesterTaskSet
()¶ Manages a set of
AppTesterTasks()
. Used byAppTester()
to control all its task collections (setup, interaction and check tasks) without needing to interact with each collection individually.-
static
add
(name, tasks)¶ Adds a task collection to this set of task collections.
Arguments: - name (string) – the name to be used to identify this collection of tasks.
- tasks (AppTesterTasks) – the collection of tasks to be added.
-
static
attach
()¶ Attaches each of the collections’ task methods to their tester. See
AppTesterTasks.attach()
.
-
static
get
(name)¶ Retrieves the task collection associated with the specified name.
Arguments: - name (string) – the name to be used to look up the collection of tasks.
-
static
invoke
(method_name[, args])¶ Invokes a method on each task collection in the set, returning the results as an array.
Arguments: - method_name (string) – the name of the method to invoke on each task collection.
- args (array) – the arguments to invoke the method with.
-
static
length
¶ The total number of currently scheduled tasks in this set.
-
static
reset
()¶ Resets all of its collections. See
AppTesterTasks.reset()
.
-
static
run
()¶ Runs the set’s task collections’ tasks in the order the collections were added in.
-
static
yoink
()¶ Attaches the tester’s
api
,im
andapp
to directly to each of its tasks. SeeAppTesterTasks.yoink()
.
-
static
-
class
AppTesterTasks
(tester)¶ A collection of tasks to be run one after the other.
Arguments: - tester (AppTester) – the tester that this collection of tasks will be scheduled for.
-
static
after
()¶ Hook invoked after all of the scheduled tasks have been run. May return a promise.
-
static
attach
()¶ Attaches the task collection’s methods to the collection’s associated tester. Any method defined on the testers
self.methods
attribute will be attached as a method on the tester.The method attached to the tester is constructed to simply schedule the actual task method. For example, if the task collection has a method
self.methods.foo()
, a corresponding methodtester.foo()
will be constructed. Whentester.foo()
is called, a call toself.methods.foo()
will be scheduled next time this task collection is run.
-
static
before
()¶ Hook invoked before any of the scheduled tasks are run. May return a promise.
-
static
length
¶ The number of currently scheduled tasks in this collection.
-
static
reset
()¶ Attaches the tester’s
api
,im
andapp
to directly this collection of tasks.
-
static
reset
() Clears the task collection’s currently scheduled tasks and stored data.
-
static
run
()¶ Runs the collections’s scheduled tasks in the order they were scheduled, then performs a reset. Returns a promise which will be fulfilled once the scheduled tasks have run and the collection has reset itself.
-
static
schedule
(name, fn, args)¶ Schedules a task method to be invoked on the next
AppTesterTasks.run()
call.Arguments: - name (string) – the name of the task method to be scheduled
- fn (function) – the actual task method
- args (array) – the args that the task method will be scheduled to invoke.
-
static
validate
(name[, args])¶ Optional validator invoked each time a task is scheduled.
Arguments: - name (string) – the name of the task method to be scheduled
- args (array) – the args that the task method will be scheduled to invoke.
-
AppTesterTasks.after.
each
()¶ Hook invoked after each scheduled task has been run. May return a promise.
-
AppTesterTasks.before.
each
()¶ Hook invoked before each scheduled task is run. May return a promise.
-
class
TaskError
(message)¶ Thrown when an error occurs while trying to schedule or run a task.
Arguments: - message (string) – the error message.
-
class
TaskMethodError
(message)¶ Thrown when an error occurs while trying to invoke a task method.
Arguments: - method_name (string) – the name of the task method associated to the error.
- message (string) – the error message.