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), where api is the tester’s api instance and this is the AppTester() instance. May return a promise.
tester.setup(function(api) {
    api.config.store.foo = 'bar';
});
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 in obj.

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() or UserLoadEvent() 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), where user is the currently stored user data object and this is the AppTester() instance. The stored user data is set with fn‘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() or UserLoadEvent() will be fired during the sandbox run.

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'});
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 or undefined, 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), where msg is the current message data and this is the AppTester() instance. The current message is updated with fn‘s result. May return its result via a promise.
tester.input(function(msg) {
    msg.content = 'coffee';
    return msg;
})
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'});
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), where msgs is the current messages and this is the AppTester() instance. The current messages are updated with fn‘s result. May return its result via a promise.
tester.inputs(function(msgs) {
    return msgs.concat('coffee');
})
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), where api is the tester’s api instance (by default an instance of DummyApi()), im is the tester’s InteractionMachine() instance, app is the sandbox app being tested and this is the AppTester() 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?'
});
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 to AppTester.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), where reply is the sent out reply and this is the AppTester() instance.
tester.check.reply(function(reply) {
    assert.equal(reply.content, 'Tea or coffee?');
})
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 to AppTester.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), where user is the current user instance and this is the AppTester() instance.
tester.check.user(function(user) {
    assert.equal(user.state.name, 'coffee_state');
    assert.equal(user.get_answer('initial_state', 'coffee');
})
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'
});
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);
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), where state is the current state instance and this is the AppTester() instance.
tester.check.user.state(function(state) {
    assert.equal(state.name, 'coffee_state');
})
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 by AppTester() 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 and app to directly to each of its tasks. See AppTesterTasks.yoink().

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 method tester.foo() will be constructed. When tester.foo() is called, a call to self.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 and app 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.