diff --git a/Gruntfile.coffee b/Gruntfile.coffee index ab95146..ca6f7f0 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -74,4 +74,4 @@ module.exports = (grunt) -> grunt.registerTask "dist", ["coffee", "browserify", "uglify"] grunt.registerTask "server", ["dist", "connect:server"] grunt.registerTask "lint", ["coffeelint"] - grunt.registerTask "test", ["nodeunit"] + grunt.registerTask "test", ["coffee", "nodeunit"] diff --git a/README.md b/README.md index f09c624..b5a51c0 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,13 @@ scripting language for chatterbots, making it easy to write trigger/response pairs for building up a bot's intelligence. This library can be used both in a web browser or as a Node module. -See the `eg/` folder for a web browser example. There's a `node/` folder with -an example Node TCP server. +See the `eg/` folder for examples. + +## DOCUMENTATION + +[Documentation](https://github.com/aichaos/rivescript-js/tree/master/docs) for +the module's API is available in the `docs/` directory and is browseable in +Markdown and HTML format. ## INSTALLATION diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..ef0fd2b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,17 @@ +# RiveScript.js Documentation + +This provides documentation for the RiveScript JS module. + +You probably want the public facing API: [RiveScript](./rivescript.md) + +The rest of the documentation covers internal modules and functions which aren't +necessarily available over the public API. + +* [rivescript.RiveScript](./rivescript.md) +* [rivescript.Brain](./brain.md) +* [rivescript.inheritance](./inheritance.md) +* [rivescript.lang.coffee](./lang.coffee.md) +* [rivescript.lang.javascript](./lang.javascript.md) +* [rivescript.Parser](./parser.md) +* [rivescript.sorting](./sorting.md) +* [rivescript.utils](./utils.md) diff --git a/docs/html/rivescript.html b/docs/html/rivescript.html index bba0e30..afb9bf9 100644 --- a/docs/html/rivescript.html +++ b/docs/html/rivescript.html @@ -15,6 +15,7 @@

RiveScript (hash options)

  • bool strict: Strict mode (default true)
  • bool utf8: Enable UTF-8 mode (default false)
  • func onDebug: Set a custom handler to catch debug log messages (default null)
  • +
  • obj errors: Customize certain error messages (see below)
  • UTF-8 Mode

    In UTF-8 mode, most characters in a user's message are left intact, except for @@ -27,6 +28,51 @@

    UTF-8 Mode

    bot.unicodePunctuation = new RegExp(/[.,!?;:]/g); +

    Custom Error Messages

    +

    You can provide any or all of the following properties in the errors +argument to the constructor to override certain internal error messages:

    + +

    The default is "ERR: No Reply Matched"

    +

    Note: the recommended way to handle this case is to provide a trigger of + simply *, which serves as the catch-all trigger and is the default one + that will match if nothing else matches the user's message. Example:

    +

    + * + - I don't know what to say to that! + replyNotFound: This message is returned when the user did* in fact match + a trigger, but no response was found for the user. For example, if a trigger + only checks a set of conditions that are all false and provides no "normal" + reply, this error message is given to the user instead.

    +

    The default is "ERR: No Reply Found"

    +

    Note: the recommended way to handle this case is to provide at least one + normal reply (with the - command) to every trigger to cover the cases + where none of the conditions are true. Example:

    +

    + hello + * <get name> != undefined => Hello there, <get name>. + - Hi there. +* objectNotFound: This message is inserted into the bot's reply in-line when + it attempts to call an object macro which does not exist (for example, its + name was invalid or it was written in a programming language that the bot + couldn't parse, or that it had compile errors).

    +

    The default is "[ERR: Object Not Found]" +* deepRecursion: This message is inserted when the bot encounters a deep + recursion situation, for example when a reply redirects to a trigger which + redirects back to the first trigger, creating an infinite loop.

    +

    The default is "ERR: Deep Recursion Detected"

    +

    These custom error messages can be provided during the construction of the +RiveScript object, or set afterwards on the object's errors property.

    +

    Examples:

    +
    var bot = new RiveScript({
    +   errors: {
    +       replyNotFound: "I don't know how to reply to that."
    +   }
    +});
    +
    +bot.errors.objectNotFound = "Something went terribly wrong.";
    + +

    Constructor and Debug Methods

    string version ()

    Returns the version number of the RiveScript.js library.

    @@ -68,7 +114,7 @@

    int loadFile (string path || array path[, onSuccess[, onError]])

    onSuccess receives: int batchNumber onError receives: string errorMessage[, int batchNumber]

    void loadDirectory (string path[, func onSuccess[, func onError]])

    -

    Load RiveScript documents from a directory.

    +

    Load RiveScript documents from a directory recursively.

    This function is not supported in a web environment.

    bool stream (string code[, func onError])

    Stream in RiveScript code dynamically. code should be the raw RiveScript diff --git a/docs/rivescript.md b/docs/rivescript.md index ee3d27e..be04163 100644 --- a/docs/rivescript.md +++ b/docs/rivescript.md @@ -8,6 +8,7 @@ following keys: * bool strict: Strict mode (default true) * bool utf8: Enable UTF-8 mode (default false) * func onDebug: Set a custom handler to catch debug log messages (default null) +* obj errors: Customize certain error messages (see below) ## UTF-8 Mode @@ -24,6 +25,67 @@ var bot = new RiveScript({utf8: true}); bot.unicodePunctuation = new RegExp(/[.,!?;:]/g); ``` +## Custom Error Messages + +You can provide any or all of the following properties in the `errors` +argument to the constructor to override certain internal error messages: + +* `replyNotMatched`: The message returned when the user's message does not + match any triggers in your RiveScript code. + + The default is "ERR: No Reply Matched" + + **Note:** the recommended way to handle this case is to provide a trigger of + simply `*`, which serves as the catch-all trigger and is the default one + that will match if nothing else matches the user's message. Example: + + ``` + + * + - I don't know what to say to that! + ``` +* `replyNotFound`: This message is returned when the user *did* in fact match + a trigger, but no response was found for the user. For example, if a trigger + only checks a set of conditions that are all false and provides no "normal" + reply, this error message is given to the user instead. + + The default is "ERR: No Reply Found" + + **Note:** the recommended way to handle this case is to provide at least one + normal reply (with the `-` command) to every trigger to cover the cases + where none of the conditions are true. Example: + + ``` + + hello + * != undefined => Hello there, . + - Hi there. + ``` +* `objectNotFound`: This message is inserted into the bot's reply in-line when + it attempts to call an object macro which does not exist (for example, its + name was invalid or it was written in a programming language that the bot + couldn't parse, or that it had compile errors). + + The default is "[ERR: Object Not Found]" +* `deepRecursion`: This message is inserted when the bot encounters a deep + recursion situation, for example when a reply redirects to a trigger which + redirects back to the first trigger, creating an infinite loop. + + The default is "ERR: Deep Recursion Detected" + +These custom error messages can be provided during the construction of the +RiveScript object, or set afterwards on the object's `errors` property. + +Examples: + +```javascript +var bot = new RiveScript({ + errors: { + replyNotFound: "I don't know how to reply to that." + } +}); + +bot.errors.objectNotFound = "Something went terribly wrong."; +``` + # Constructor and Debug Methods ## string version () @@ -85,7 +147,7 @@ argument, in case you want to correlate it with your call to `loadFile()`. ## void loadDirectory (string path[, func onSuccess[, func onError]]) -Load RiveScript documents from a directory. +Load RiveScript documents from a directory recursively. This function is not supported in a web environment. diff --git a/src/brain.coffee b/src/brain.coffee index ee8bf70..fa94708 100644 --- a/src/brain.coffee +++ b/src/brain.coffee @@ -110,7 +110,7 @@ class Brain break text = utils.strip(match[1]) - + # get subroutine name subroutineNameMatch = (/(\S+)/ig).exec(text) subroutineName = subroutineNameMatch[0] @@ -142,7 +142,7 @@ class Brain else output = "[ERR: No Object Handler]" else - output = "[ERR: Object Not Found]" + output = @master.errors.objectNotFound # if we get a promise back and we are not in the async mode, # leave an error message to suggest using an async version of rs @@ -185,7 +185,7 @@ class Brain doubleQuoteRe = /"/ig flushBuffer = () -> - if buff.length isnt 0 + if buff.length isnt 0 result.push(buff) buff = "" @@ -208,7 +208,7 @@ class Brain # wrap arguments inside in {__call_arg__}{/__call_arg__} callRegEx = /\s*(.*?)\s*<\/call>/ig callArgsRegEx = /\s*[^\s]+ (.*)<\/call>/ig - + callSignatures = [] while true @@ -224,7 +224,7 @@ class Brain argsMatch = callArgsRegEx.exec(originalCallSignature) if not argsMatch break - + originalArgs = argsMatch[1] args = @_parseCallArgsString(originalArgs) wrappedArgs = [] @@ -232,12 +232,12 @@ class Brain for a in args wrappedArgs.push "{__call_arg__}#{a}{/__call_arg__}" - wrappedCallSignature = wrappedCallSignature.replace(originalArgs, + wrappedCallSignature = wrappedCallSignature.replace(originalArgs, wrappedArgs.join(' ')) callSignatures.push original: originalCallSignature - wrapped: wrappedCallSignature + wrapped: wrappedCallSignature for cs in callSignatures reply = reply.replace cs.original, cs.wrapped @@ -277,7 +277,7 @@ class Brain # Avoid deep recursion. if step > @master._depth - return "ERR: Deep Recursion Detected" + return @master.errors.deepRecursion # Are we in the BEGIN block? if context is "begin" @@ -506,9 +506,9 @@ class Brain # Still no reply? if not foundMatch - reply = "ERR: No Reply Matched" + reply = @master.errors.replyNotMatched else if reply is undefined or reply.length is 0 - reply = "ERR: No Reply Found" + reply = @master.errors.replyNotFound @say "Reply: #{reply}" diff --git a/src/lang/coffee.coffee b/src/lang/coffee.coffee index a41a6f5..ef7b036 100644 --- a/src/lang/coffee.coffee +++ b/src/lang/coffee.coffee @@ -48,7 +48,7 @@ class CoffeeObjectHandler call: (rs, name, fields, scope) -> # We have it? if not @_objects[name] - return "[ERR: Object Not Found]" + return @_master.errors.objectNotFound # Call the dynamic method. func = @_objects[name] diff --git a/src/lang/javascript.coffee b/src/lang/javascript.coffee index a6b2c1e..29bc52e 100644 --- a/src/lang/javascript.coffee +++ b/src/lang/javascript.coffee @@ -50,7 +50,7 @@ class JSObjectHandler call: (rs, name, fields, scope) -> # We have it? if not @_objects[name] - return "[ERR: Object Not Found]" + return @_master.errors.objectNotFound # Call the dynamic method. func = @_objects[name] diff --git a/src/rivescript.coffee b/src/rivescript.coffee index 2b3fdd7..dfded21 100644 --- a/src/rivescript.coffee +++ b/src/rivescript.coffee @@ -30,6 +30,7 @@ readDir = require("fs-readdir-recursive") # * bool strict: Strict mode (default true) # * bool utf8: Enable UTF-8 mode (default false) # * func onDebug: Set a custom handler to catch debug log messages (default null) +# * obj errors: Customize certain error messages (see below) # # ## UTF-8 Mode # @@ -45,6 +46,68 @@ readDir = require("fs-readdir-recursive") # var bot = new RiveScript({utf8: true}); # bot.unicodePunctuation = new RegExp(/[.,!?;:]/g); # ``` +# +# ## Custom Error Messages +# +# You can provide any or all of the following properties in the `errors` +# argument to the constructor to override certain internal error messages: +# +# * `replyNotMatched`: The message returned when the user's message does not +# match any triggers in your RiveScript code. +# +# The default is "ERR: No Reply Matched" +# +# **Note:** the recommended way to handle this case is to provide a trigger of +# simply `*`, which serves as the catch-all trigger and is the default one +# that will match if nothing else matches the user's message. Example: +# +# ``` +# + * +# - I don't know what to say to that! +# ``` +# * `replyNotFound`: This message is returned when the user *did* in fact match +# a trigger, but no response was found for the user. For example, if a trigger +# only checks a set of conditions that are all false and provides no "normal" +# reply, this error message is given to the user instead. +# +# The default is "ERR: No Reply Found" +# +# **Note:** the recommended way to handle this case is to provide at least one +# normal reply (with the `-` command) to every trigger to cover the cases +# where none of the conditions are true. Example: +# +# ``` +# + hello +# * != undefined => Hello there, . +# - Hi there. +# ``` +# * `objectNotFound`: This message is inserted into the bot's reply in-line when +# it attempts to call an object macro which does not exist (for example, its +# name was invalid or it was written in a programming language that the bot +# couldn't parse, or that it had compile errors). +# +# The default is "[ERR: Object Not Found]" +# * `deepRecursion`: This message is inserted when the bot encounters a deep +# recursion situation, for example when a reply redirects to a trigger which +# redirects back to the first trigger, creating an infinite loop. +# +# The default is "ERR: Deep Recursion Detected" +# +# These custom error messages can be provided during the construction of the +# RiveScript object, or set afterwards on the object's `errors` property. +# +# Examples: +# +# ```javascript +# var bot = new RiveScript({ +# errors: { +# replyNotFound: "I don't know how to reply to that." +# } +# }); +# +# bot.errors.objectNotFound = "Something went terribly wrong."; +# ``` +# ## class RiveScript @@ -66,6 +129,17 @@ class RiveScript # UTF-8 punctuation, overridable by the user. @unicodePunctuation = new RegExp(/[.,!?;:]/g) + # Customized error messages. + @errors = + replyNotMatched: "ERR: No Reply Matched" + replyNotFound: "ERR: No Reply Found" + objectNotFound: "[ERR: Object Not Found]" + deepRecursion: "ERR: Deep Recursion Detected" + if typeof(opts.errors) is "object" + for key, value of opts.errors + if opts.errors.hasOwnProperty(key) + @errors[key] = value + # Identify our runtime environment. Web, or node? @_node = {} # NodeJS objects @_runtime = @runtime() diff --git a/test/test-begin.coffee b/test/test-begin.coffee new file mode 100644 index 0000000..7e694ac --- /dev/null +++ b/test/test-begin.coffee @@ -0,0 +1,62 @@ +TestCase = require("./test-base") + +################################################################################ +# BEGIN Block Tests +################################################################################ + +exports.test_no_begin_block = (test) -> + bot = new TestCase(test, """ + + hello bot + - Hello human. + """) + bot.reply("Hello bot", "Hello human.") + test.done() + +exports.test_simple_begin_block = (test) -> + bot = new TestCase(test, """ + > begin + + request + - {ok} + < begin + + + hello bot + - Hello human. + """) + bot.reply("Hello bot.", "Hello human.") + test.done() + +exports.test_blocked_begin_block = (test) -> + bot = new TestCase(test, """ + > begin + + request + - Nope. + < begin + + + hello bot + - Hello human. + """) + bot.reply("Hello bot.", "Nope.") + test.done() + +exports.test_conditional_begin_block = (test) -> + bot = new TestCase(test, """ + > begin + + request + * == undefined => {ok} + * != undefined => : {ok} + - {ok} + < begin + + + hello bot + - Hello human. + + + my name is * + - >Hello, . + """) + bot.reply("Hello bot.", "Hello human.") + bot.uservar("met", "true") + bot.uservar("name", "undefined") + bot.reply("My name is bob", "Hello, Bob.") + bot.uservar("name", "Bob") + bot.reply("Hello Bot", "Bob: Hello human.") + test.done() diff --git a/test/test-bot-variables.coffee b/test/test-bot-variables.coffee new file mode 100644 index 0000000..bcd7b98 --- /dev/null +++ b/test/test-bot-variables.coffee @@ -0,0 +1,44 @@ +TestCase = require("./test-base") + +################################################################################ +# Bot Variable Tests +################################################################################ + +exports.test_bot_variables = (test) -> + bot = new TestCase(test, """ + ! var name = Aiden + ! var age = 5 + + + what is your name + - My name is . + + + how old are you + - I am . + + + what are you + - I'm . + + + happy birthday + - Thanks! + """) + bot.reply("What is your name?", "My name is Aiden.") + bot.reply("How old are you?", "I am 5.") + bot.reply("What are you?", "I'm undefined.") + bot.reply("Happy birthday!", "Thanks!") + bot.reply("How old are you?", "I am 6.") + test.done() + +exports.test_global_variables = (test) -> + bot = new TestCase(test, """ + ! global debug = false + + + debug mode + - Debug mode is: + + + set debug mode * + - >Switched to . + """) + bot.reply("Debug mode.", "Debug mode is: false") + bot.reply("Set debug mode true", "Switched to true.") + bot.reply("Debug mode?", "Debug mode is: true") + test.done() diff --git a/test/test-math.coffee b/test/test-math.coffee new file mode 100644 index 0000000..ee21ff8 --- /dev/null +++ b/test/test-math.coffee @@ -0,0 +1,44 @@ +TestCase = require("./test-base") + +################################################################################ +# calculation (add,sub) tests +################################################################################ + +exports.test_addition = (test) -> + bot = new TestCase(test, """ + + test counter + - counter set + + + show + - counter = + + + add + - adding + + + sub + - subbing + + + div + - + ^

    + ^ divving + + + mult + - + ^ + ^ multing + """) + bot.reply("test counter", "counter set") + bot.reply("show", "counter = 0") + bot.reply("add", "adding") + bot.reply("show", "counter = 1") + bot.reply("sub", "subbing") + bot.reply("show", "counter = 0") + + bot.reply("div", "divving") + bot.reply("show", "counter = 5") + + bot.reply("mult", "multing") + bot.reply("show", "counter = 20") + + test.done() diff --git a/test/test-objects.coffee b/test/test-objects.coffee new file mode 100644 index 0000000..2db315a --- /dev/null +++ b/test/test-objects.coffee @@ -0,0 +1,317 @@ +TestCase = require("./test-base") + +################################################################################ +# Object Macro Tests +################################################################################ + +exports.test_js_objects = (test) -> + bot = new TestCase(test, """ + > object nolang + return "Test w/o language." + < object + + > object wlang javascript + return "Test w/ language." + < object + + > object reverse javascript + var msg = args.join(" "); + console.log(msg); + return msg.split("").reverse().join(""); + < object + + > object broken javascript + return "syntax error + < object + + > object foreign perl + return "Perl checking in!" + < object + + + test nolang + - Nolang: nolang + + + test wlang + - Wlang: wlang + + + reverse * + - reverse + + + test broken + - Broken: broken + + + test fake + - Fake: fake + + + test perl + - Perl: foreign + """) + bot.reply("Test nolang", "Nolang: Test w/o language.") + bot.reply("Test wlang", "Wlang: Test w/ language.") + bot.reply("Reverse hello world.", "dlrow olleh") + bot.reply("Test broken", "Broken: [ERR: Object Not Found]") + bot.reply("Test fake", "Fake: [ERR: Object Not Found]") + bot.reply("Test perl", "Perl: [ERR: Object Not Found]") + test.done() + +exports.test_disabled_js_language = (test) -> + bot = new TestCase(test, """ + > object test javascript + return 'JavaScript here!' + < object + + + test + - Result: test + """) + bot.reply("test", "Result: JavaScript here!") + bot.rs.setHandler("javascript", undefined) + bot.reply("test", "Result: [ERR: No Object Handler]") + test.done() + +exports.test_get_variable = (test) -> + bot = new TestCase(test, """ + ! var test_var = test + + > object test_get_var javascript + var uid = rs.currentUser(); + var name = "test_var"; + return rs.getVariable(uid, name); + < object + + + show me var + - test_get_var + """) + bot.reply("show me var", "test") + test.done() + +exports.test_js_string_in_setSubroutine = (test) -> + bot = new TestCase(test, """ + + hello + - hello helper + """) + + input = "hello there" + + bot.rs.setSubroutine("helper", ["return 'person';"]) + bot.reply("hello", "hello person") + test.done() + +exports.test_function_in_setSubroutine = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello personhelper + """) + + input = "my name is Rive" + + bot.rs.setSubroutine("helper", (rs, args) -> + test.equal(rs, bot.rs) + test.equal(args.length, 1) + test.equal(args[0], "rive") + test.done() + ) + + bot.reply(input, "hello person") + +exports.test_function_in_setSubroutine_return_value = (test) -> + bot = new TestCase(test, """ + + hello + - hello helper + """) + + bot.rs.setSubroutine("helper", (rs, args) -> + "person" + ) + + bot.reply("hello", "hello person") + test.done() + +exports.test_arguments_in_setSubroutine = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello helper 12 + """) + + bot.rs.setSubroutine("helper", (rs, args) -> + test.equal(args.length, 2) + test.equal(args[0], "thomas edison") + test.equal(args[1], "12") + args[0] + ) + + bot.reply("my name is thomas edison", "hello thomas edison") + test.done() + +exports.test_quoted_strings_arguments_in_setSubroutine = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello helper 12 "another param" + """) + + bot.rs.setSubroutine("helper", (rs, args) -> + test.equal(args.length, 3) + test.equal(args[0], "thomas edison") + test.equal(args[1], "12") + test.equal(args[2], "another param") + args[0] + ) + + bot.reply("my name is thomas edison", "hello thomas edison") + test.done() + +exports.test_arguments_with_funky_spacing_in_setSubroutine = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello helper 12 "another param" + """) + + bot.rs.setSubroutine("helper", (rs, args) -> + test.equal(args.length, 3) + test.equal(args[0], "thomas edison") + test.equal(args[1], "12") + test.equal(args[2], "another param") + args[0] + ) + + bot.reply("my name is thomas edison", "hello thomas edison") + test.done() + +exports.test_promises_in_objects = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello there helperWithPromise with a anotherHelperWithPromise + """) + + input = "my name is Rive" + + bot.rs.setSubroutine("helperWithPromise", (rs, args) -> + return new rs.Promise((resolve, reject) -> + resolve("stranger") + ) + ) + + bot.rs.setSubroutine("anotherHelperWithPromise", (rs) -> + return new rs.Promise((resolve, reject) -> + setTimeout () -> + resolve("delay") + , 1000 + ) + ) + + bot.rs.replyAsync(bot.username, input).then (reply) -> + test.equal(reply, "hello there stranger with a delay") + test.done() + +exports.test_replyAsync_supports_callbacks = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello there asyncHelper + """) + + input = "my name is Rive" + + bot.rs.setSubroutine("asyncHelper", (rs, args) -> + return new rs.Promise((resolve, reject) -> + resolve("stranger") + ) + ) + + bot.rs.replyAsync(bot.username, input, null, (error, reply) -> + test.ok(!error) + test.equal(reply, "hello there stranger") + test.done() + ) + +exports.test_use_reply_with_async_subroutines = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello there asyncHelper + """) + + bot.rs.setSubroutine("asyncHelper", (rs, args) -> + return new rs.Promise((resolve, reject) -> + resolve("stranger") + ) + ) + + bot.reply("my name is Rive", "hello there [ERR: Using async routine with reply: use replyAsync instead]") + test.done() + +exports.test_errors_in_async_subroutines_with_callbacks = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello there asyncHelper + """) + + errorMessage = "Something went terribly wrong" + + bot.rs.setSubroutine("asyncHelper", (rs, args) -> + return new rs.Promise((resolve, reject) -> + reject(new Error(errorMessage)) + ) + ) + + bot.rs.replyAsync(bot.username, "my name is Rive", null, (error, reply) -> + test.ok(error) + test.equal(error.message, errorMessage) + test.ok(!reply) + test.done() + ) + +exports.test_errors_in_async_subroutines_with_promises = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello there asyncHelper + """) + + errorMessage = "Something went terribly wrong" + + bot.rs.setSubroutine("asyncHelper", (rs, args) -> + return new rs.Promise((resolve, reject) -> + reject(new Error(errorMessage)) + ) + ) + + bot.rs.replyAsync(bot.username, "my name is Rive").catch (error) -> + test.ok(error) + test.equal(error.message, errorMessage) + test.done() + +exports.test_async_and_sync_subroutines_together = (test) -> + bot = new TestCase(test, """ + + my name is * + - hello there asyncHelperexclaim + """) + + + bot.rs.setSubroutine("exclaim", (rs, args) -> + return "!" + ) + + bot.rs.setSubroutine("asyncHelper", (rs, args) -> + return new rs.Promise((resolve, reject) -> + resolve("stranger") + ) + ) + + bot.rs.replyAsync(bot.username, "my name is Rive").then (reply) -> + test.equal(reply, "hello there stranger!") + test.done() + +exports.test_stringify_with_objects = (test) -> + bot = new TestCase(test, """ + > object hello javascript + return \"Hello\"; + < object + + my name is * + - hello thereexclaim + """) + + bot.rs.setSubroutine("exclaim", (rs) -> + return "!" + ) + + src = bot.rs.stringify() + expect = '! version = 2.0\n! local concat = none\n\n> object hello javascript\n\treturn "Hello";\n< object\n\n> object exclaim javascript\n\treturn "!";\n< object\n\n+ my name is *\n- hello thereexclaim\n' + test.equal(src, expect) + test.done() diff --git a/test/test-options.coffee b/test/test-options.coffee new file mode 100644 index 0000000..92d68d4 --- /dev/null +++ b/test/test-options.coffee @@ -0,0 +1,120 @@ +TestCase = require("./test-base") + +################################################################################ +# Parser option tests +################################################################################ + +exports.test_concat = (test) -> + bot = new TestCase(test, """ + // Default concat mode = none + + test concat default + - Hello + ^ world! + + ! local concat = space + + test concat space + - Hello + ^ world! + + ! local concat = none + + test concat none + - Hello + ^ world! + + ! local concat = newline + + test concat newline + - Hello + ^ world! + + // invalid concat setting is equivalent to 'none' + ! local concat = foobar + + test concat foobar + - Hello + ^ world! + + // the option is file scoped so it can be left at + // any setting and won't affect subsequent parses + ! local concat = newline + """) + bot.extend(""" + // concat mode should be restored to the default in a + // separate file/stream parse + + test concat second file + - Hello + ^ world! + """) + + bot.reply("test concat default", "Helloworld!") + bot.reply("test concat space", "Hello world!") + bot.reply("test concat none", "Helloworld!") + bot.reply("test concat newline", "Hello\nworld!") + bot.reply("test concat foobar", "Helloworld!") + bot.reply("test concat second file", "Helloworld!") + + test.done() + +exports.test_concat_with_conditionals = (test) -> + # Newline + bot = new TestCase(test, """ + ! local concat = newline + + + test * + * == a => First A line + ^ Second A line + ^ Third A line + - First B line + ^ Second B line + ^ Third B line + """) + + bot.reply("test a", "First A line\nSecond A line\nThird A line") + bot.reply("test b", "First B line\nSecond B line\nThird B line") + + # Space + bot = new TestCase(test, """ + ! local concat = space + + + test * + * == a => First A line + ^ Second A line + ^ Third A line + - First B line + ^ Second B line + ^ Third B line + """) + + bot.reply("test a", "First A line Second A line Third A line") + bot.reply("test b", "First B line Second B line Third B line") + + # No concat + bot = new TestCase(test, """ + + test * + * == a => First A line + ^ Second A line + ^ Third A line + - First B line + ^ Second B line + ^ Third B line + """) + + bot.reply("test a", "First A lineSecond A lineThird A line") + bot.reply("test b", "First B lineSecond B lineThird B line") + + test.done() + +exports.test_concat_space_with_conditionals = (test) -> + bot = new TestCase(test, """ + ! local concat = newline + + + test * + * == a => First A line + ^ Second A line + ^ Third A line + - First B line + ^ Second B line + ^ Third B line + """) + + bot.reply("test a", "First A line\nSecond A line\nThird A line") + bot.reply("test b", "First B line\nSecond B line\nThird B line") + test.done() diff --git a/test/test-replies.coffee b/test/test-replies.coffee new file mode 100644 index 0000000..02f1ed0 --- /dev/null +++ b/test/test-replies.coffee @@ -0,0 +1,207 @@ +TestCase = require("./test-base") + +################################################################################ +# Reply Tests +################################################################################ + +exports.test_previous = (test) -> + bot = new TestCase(test, """ + ! sub who's = who is + ! sub it's = it is + ! sub didn't = did not + + + knock knock + - Who's there? + + + * + % who is there + - who? + + + * + % * who + - Haha! ! + + + * + - I don't know. + """) + bot.reply("knock knock", "Who's there?") + bot.reply("Canoe", "Canoe who?") + bot.reply("Canoe help me with my homework?", "Haha! Canoe help me with my homework!") + bot.reply("hello", "I don't know.") + test.done() + +exports.test_random = (test) -> + bot = new TestCase(test, """ + + test random response + - One. + - Two. + + + test random tag + - This sentence has a random {random}word|bit{/random}. + """) + bot.replyRandom("test random response", ["One.", "Two."]) + bot.replyRandom("test random tag", [ + "This sentence has a random word.", + "This sentence has a random bit.", + ]) + test.done() + +exports.test_continuations = (test) -> + bot = new TestCase(test, """ + + tell me a poem + - There once was a man named Tim,\\s + ^ who never quite learned how to swim.\\s + ^ He fell off a dock, and sank like a rock,\\s + ^ and that was the end of him. + """) + bot.reply("Tell me a poem.", "There once was a man named Tim, + who never quite learned how to swim. + He fell off a dock, and sank like a rock, + and that was the end of him.") + test.done() + +exports.test_redirects = (test) -> + bot = new TestCase(test, """ + + hello + - Hi there! + + + hey + @ hello + + + hi there + - {@hello} + """) + bot.reply("hello", "Hi there!") + bot.reply("hey", "Hi there!") + bot.reply("hi there", "Hi there!") + test.done() + +exports.test_conditionals = (test) -> + bot = new TestCase(test, """ + + i am # years old + - >OK. + + + what can i do + * == undefined => I don't know. + * > 25 => Anything you want. + * == 25 => Rent a car for cheap. + * >= 21 => Drink. + * >= 18 => Vote. + * < 18 => Not much of anything. + + + am i your master + * == true => Yes. + - No. + """) + age_q = "What can I do?" + bot.reply(age_q, "I don't know.") + + ages = + '16' : "Not much of anything." + '18' : "Vote." + '20' : "Vote." + '22' : "Drink." + '24' : "Drink." + '25' : "Rent a car for cheap." + '27' : "Anything you want." + for age of ages + if (!ages.hasOwnProperty(age)) + continue + bot.reply("I am " + age + " years old.", "OK.") + bot.reply(age_q, ages[age]) + + bot.reply("Am I your master?", "No.") + bot.rs.setUservar(bot.username, "master", "true") + bot.reply("Am I your master?", "Yes.") + test.done() + +exports.test_embedded_tags = (test) -> + bot = new TestCase(test, """ + + my name is * + * != undefined => >I thought\\s + ^ your name was ? + ^ > + - >OK. + + + what is my name + - Your name is , right? + + + html test + - Name>This has some non-RS tags in it. + """) + bot.reply("What is my name?", "Your name is undefined, right?") + bot.reply("My name is Alice.", "OK.") + bot.reply("My name is Bob.", "I thought your name was Alice?") + bot.reply("What is my name?", "Your name is Bob, right?") + bot.reply("HTML Test", "This has some non-RS tags in it.") + test.done() + +exports.test_set_uservars = (test) -> + bot = new TestCase(test, """ + + what is my name + - Your name is . + + + how old am i + - You are . + """) + bot.rs.setUservars(bot.username, { + "name": "Aiden", + "age": 5, + }) + bot.reply("What is my name?", "Your name is Aiden.") + bot.reply("How old am I?", "You are 5.") + test.done() + +exports.test_questionmark = (test) -> + bot = new TestCase(test, """ + + google * + - Results are here + """) + bot.reply("google coffeescript", + 'Results are here' + ) + test.done() + +exports.test_reply_arrays = (test) -> + bot = new TestCase(test, """ + ! array greek = alpha beta gamma + ! array test = testing trying + ! array format = ||| + + + test random array + - Testing (@greek) array. + + + test two random arrays + - {formal}(@test){/formal} another (@greek) array. + + + test nonexistant array + - This (@array) does not exist. + + + test more arrays + - I'm (@test) more (@greek) (@arrays). + + + test weird syntax + - This (@ greek) shouldn't work, and neither should this @test. + + + random format * + - (@format) + """) + bot.replyRandom("test random array", [ + "Testing alpha array.", "Testing beta array.", "Testing gamma array.", + ]) + bot.replyRandom("test two random arrays", [ + "Testing another alpha array.", "Testing another beta array.", + "Testing another gamma array.", "Trying another alpha array.", + "Trying another beta array.", "Trying another gamma array.", + ]) + bot.reply("test nonexistant array", "This (@array) does not exist.") + bot.replyRandom("test more arrays", [ + "I'm testing more alpha (@arrays).", "I'm testing more beta (@arrays).", + "I'm testing more gamma (@arrays).", "I'm trying more alpha (@arrays).", + "I'm trying more beta (@arrays).", "I'm trying more gamma (@arrays)." + ]) + bot.reply("test weird syntax", "This (@ greek) shouldn't work, and neither should this @test.") + bot.replyRandom("random format hello world", [ + "HELLO WORLD", "hello world", "Hello World", "Hello world", + ]) + test.done() diff --git a/test/test-rivescript.coffee b/test/test-rivescript.coffee index 7202519..12659b0 100644 --- a/test/test-rivescript.coffee +++ b/test/test-rivescript.coffee @@ -1,1093 +1,10 @@ TestCase = require("./test-base") ################################################################################ -# BEGIN Block Tests +# RiveScript API Tests ################################################################################ -exports.test_no_begin_block = (test) -> - bot = new TestCase(test, """ - + hello bot - - Hello human. - """) - bot.reply("Hello bot", "Hello human.") - test.done() - -exports.test_simple_begin_block = (test) -> - bot = new TestCase(test, """ - > begin - + request - - {ok} - < begin - - + hello bot - - Hello human. - """) - bot.reply("Hello bot.", "Hello human.") - test.done() - -exports.test_blocked_begin_block = (test) -> - bot = new TestCase(test, """ - > begin - + request - - Nope. - < begin - - + hello bot - - Hello human. - """) - bot.reply("Hello bot.", "Nope.") - test.done() - -exports.test_conditional_begin_block = (test) -> - bot = new TestCase(test, """ - > begin - + request - * == undefined => {ok} - * != undefined => : {ok} - - {ok} - < begin - - + hello bot - - Hello human. - - + my name is * - - >Hello, . - """) - bot.reply("Hello bot.", "Hello human.") - bot.uservar("met", "true") - bot.uservar("name", "undefined") - bot.reply("My name is bob", "Hello, Bob.") - bot.uservar("name", "Bob") - bot.reply("Hello Bot", "Bob: Hello human.") - test.done() - -################################################################################ -# Bot Variable Tests -################################################################################ - -exports.test_bot_variables = (test) -> - bot = new TestCase(test, """ - ! var name = Aiden - ! var age = 5 - - + what is your name - - My name is . - - + how old are you - - I am . - - + what are you - - I'm . - - + happy birthday - - Thanks! - """) - bot.reply("What is your name?", "My name is Aiden.") - bot.reply("How old are you?", "I am 5.") - bot.reply("What are you?", "I'm undefined.") - bot.reply("Happy birthday!", "Thanks!") - bot.reply("How old are you?", "I am 6.") - test.done() - -exports.test_global_variables = (test) -> - bot = new TestCase(test, """ - ! global debug = false - - + debug mode - - Debug mode is: - - + set debug mode * - - >Switched to . - """) - bot.reply("Debug mode.", "Debug mode is: false") - bot.reply("Set debug mode true", "Switched to true.") - bot.reply("Debug mode?", "Debug mode is: true") - test.done() - -################################################################################ -# Substitution Tests -################################################################################ - -exports.test_substitutions = (test) -> - bot = new TestCase(test, """ - + whats up - - nm. - - + what is up - - Not much. - """) - bot.reply("whats up", "nm.") - bot.reply("what's up?", "nm.") - bot.reply("what is up?", "Not much.") - - bot.extend(""" - ! sub whats = what is - ! sub what's = what is - """) - bot.reply("whats up", "Not much.") - bot.reply("what's up?", "Not much.") - bot.reply("What is up?", "Not much.") - test.done() - -exports.test_person_substitutions = (test) -> - bot = new TestCase(test, """ - + say * - - - """) - bot.reply("say I am cool", "i am cool") - bot.reply("say You are dumb", "you are dumb") - - bot.extend(""" - ! person i am = you are - ! person you are = I am - """) - bot.reply("say I am cool", "you are cool") - bot.reply("say You are dumb", "I am dumb") - test.done() - -################################################################################ -# Trigger Tests -################################################################################ - -exports.test_atomic_triggers = (test) -> - bot = new TestCase(test, """ - + hello bot - - Hello human. - - + what are you - - I am a RiveScript bot. - """) - bot.reply("Hello bot", "Hello human.") - bot.reply("What are you?", "I am a RiveScript bot.") - test.done() - -exports.test_wildcard_triggers = (test) -> - bot = new TestCase(test, """ - + my name is * - - Nice to meet you, . - - + * told me to say * - - Why did tell you to say ? - - + i am # years old - - A lot of people are . - - + i am _ years old - - Say that with numbers. - - + i am * years old - - Say that with fewer words. - """) - bot.reply("my name is Bob", "Nice to meet you, bob.") - bot.reply("bob told me to say hi", "Why did bob tell you to say hi?") - bot.reply("i am 5 years old", "A lot of people are 5.") - bot.reply("i am five years old", "Say that with numbers.") - bot.reply("i am twenty five years old", "Say that with fewer words.") - test.done() - -exports.test_alternatives_and_optionals = (test) -> - bot = new TestCase(test, """ - + what (are|is) you - - I am a robot. - - + what is your (home|office|cell) [phone] number - - It is 555-1234. - - + [please|can you] ask me a question - - Why is the sky blue? - - + (aa|bb|cc) [bogus] - - Matched. - - + (yo|hi) [computer|bot] * - - Matched. - """) - bot.reply("What are you?", "I am a robot.") - bot.reply("What is you?", "I am a robot.") - - bot.reply("What is your home phone number?", "It is 555-1234.") - bot.reply("What is your home number?", "It is 555-1234.") - bot.reply("What is your cell phone number?", "It is 555-1234.") - bot.reply("What is your office number?", "It is 555-1234.") - - bot.reply("Can you ask me a question?", "Why is the sky blue?") - bot.reply("Please ask me a question?", "Why is the sky blue?") - bot.reply("Ask me a question.", "Why is the sky blue?") - - bot.reply("aa", "Matched.") - bot.reply("bb", "Matched.") - bot.reply("aa bogus", "Matched.") - bot.reply("aabogus", "ERR: No Reply Matched") - bot.reply("bogus", "ERR: No Reply Matched") - - bot.reply("hi Aiden", "Matched.") - bot.reply("hi bot how are you?", "Matched.") - bot.reply("yo computer what time is it?", "Matched.") - bot.reply("yoghurt is yummy", "ERR: No Reply Matched") - bot.reply("hide and seek is fun", "ERR: No Reply Matched") - bot.reply("hip hip hurrah", "ERR: No Reply Matched") - test.done() - -exports.test_trigger_arrays = (test) -> - bot = new TestCase(test, """ - ! array colors = red blue green yellow white - ^ dark blue|light blue - - + what color is my (@colors) * - - Your is . - - + what color was * (@colors) * - - It was . - - + i have a @colors * - - Tell me more about your . - """) - bot.reply("What color is my red shirt?", "Your shirt is red.") - bot.reply("What color is my blue car?", "Your car is blue.") - bot.reply("What color is my pink house?", "ERR: No Reply Matched") - bot.reply("What color is my dark blue jacket?", "Your jacket is dark blue.") - bot.reply("What color was Napoleoan's white horse?", "It was white.") - bot.reply("What color was my red shirt?", "It was red.") - bot.reply("I have a blue car.", "Tell me more about your car.") - bot.reply("I have a cyan car.", "ERR: No Reply Matched") - test.done() - -exports.test_weighted_triggers = (test) -> - bot = new TestCase(test, """ - + * or something{weight=10} - - Or something. <@> - - + can you run a google search for * - - Sure! - - + hello *{weight=20} - - Hi there! - """) - bot.reply("Hello robot.", "Hi there!") - bot.reply("Hello or something.", "Hi there!") - bot.reply("Can you run a Google search for Node", "Sure!") - bot.reply("Can you run a Google search for Node or something", "Or something. Sure!") - test.done() - -################################################################################ -# Reply Tests -################################################################################ - -exports.test_previous = (test) -> - bot = new TestCase(test, """ - ! sub who's = who is - ! sub it's = it is - ! sub didn't = did not - - + knock knock - - Who's there? - - + * - % who is there - - who? - - + * - % * who - - Haha! ! - - + * - - I don't know. - """) - bot.reply("knock knock", "Who's there?") - bot.reply("Canoe", "Canoe who?") - bot.reply("Canoe help me with my homework?", "Haha! Canoe help me with my homework!") - bot.reply("hello", "I don't know.") - test.done() - -exports.test_random = (test) -> - bot = new TestCase(test, """ - + test random response - - One. - - Two. - - + test random tag - - This sentence has a random {random}word|bit{/random}. - """) - bot.replyRandom("test random response", ["One.", "Two."]) - bot.replyRandom("test random tag", [ - "This sentence has a random word.", - "This sentence has a random bit.", - ]) - test.done() - -exports.test_continuations = (test) -> - bot = new TestCase(test, """ - + tell me a poem - - There once was a man named Tim,\\s - ^ who never quite learned how to swim.\\s - ^ He fell off a dock, and sank like a rock,\\s - ^ and that was the end of him. - """) - bot.reply("Tell me a poem.", "There once was a man named Tim, - who never quite learned how to swim. - He fell off a dock, and sank like a rock, - and that was the end of him.") - test.done() - -exports.test_redirects = (test) -> - bot = new TestCase(test, """ - + hello - - Hi there! - - + hey - @ hello - - + hi there - - {@hello} - """) - bot.reply("hello", "Hi there!") - bot.reply("hey", "Hi there!") - bot.reply("hi there", "Hi there!") - test.done() - -exports.test_conditionals = (test) -> - bot = new TestCase(test, """ - + i am # years old - - >OK. - - + what can i do - * == undefined => I don't know. - * > 25 => Anything you want. - * == 25 => Rent a car for cheap. - * >= 21 => Drink. - * >= 18 => Vote. - * < 18 => Not much of anything. - - + am i your master - * == true => Yes. - - No. - """) - age_q = "What can I do?" - bot.reply(age_q, "I don't know.") - - ages = - '16' : "Not much of anything." - '18' : "Vote." - '20' : "Vote." - '22' : "Drink." - '24' : "Drink." - '25' : "Rent a car for cheap." - '27' : "Anything you want." - for age of ages - if (!ages.hasOwnProperty(age)) - continue - bot.reply("I am " + age + " years old.", "OK.") - bot.reply(age_q, ages[age]) - - bot.reply("Am I your master?", "No.") - bot.rs.setUservar(bot.username, "master", "true") - bot.reply("Am I your master?", "Yes.") - test.done() - -exports.test_embedded_tags = (test) -> - bot = new TestCase(test, """ - + my name is * - * != undefined => >I thought\\s - ^ your name was ? - ^ > - - >OK. - - + what is my name - - Your name is , right? - - + html test - - Name>This has some non-RS tags in it. - """) - bot.reply("What is my name?", "Your name is undefined, right?") - bot.reply("My name is Alice.", "OK.") - bot.reply("My name is Bob.", "I thought your name was Alice?") - bot.reply("What is my name?", "Your name is Bob, right?") - bot.reply("HTML Test", "This has some non-RS tags in it.") - test.done() - -exports.test_set_uservars = (test) -> - bot = new TestCase(test, """ - + what is my name - - Your name is . - - + how old am i - - You are . - """) - bot.rs.setUservars(bot.username, { - "name": "Aiden", - "age": 5, - }) - bot.reply("What is my name?", "Your name is Aiden.") - bot.reply("How old am I?", "You are 5.") - test.done() - -exports.test_questionmark = (test) -> - bot = new TestCase(test, """ - + google * - - Results are here - """) - bot.reply("google coffeescript", - 'Results are here' - ) - test.done() - -exports.test_reply_arrays = (test) -> - bot = new TestCase(test, """ - ! array greek = alpha beta gamma - ! array test = testing trying - ! array format = ||| - - + test random array - - Testing (@greek) array. - - + test two random arrays - - {formal}(@test){/formal} another (@greek) array. - - + test nonexistant array - - This (@array) does not exist. - - + test more arrays - - I'm (@test) more (@greek) (@arrays). - - + test weird syntax - - This (@ greek) shouldn't work, and neither should this @test. - - + random format * - - (@format) - """) - bot.replyRandom("test random array", [ - "Testing alpha array.", "Testing beta array.", "Testing gamma array.", - ]) - bot.replyRandom("test two random arrays", [ - "Testing another alpha array.", "Testing another beta array.", - "Testing another gamma array.", "Trying another alpha array.", - "Trying another beta array.", "Trying another gamma array.", - ]) - bot.reply("test nonexistant array", "This (@array) does not exist.") - bot.replyRandom("test more arrays", [ - "I'm testing more alpha (@arrays).", "I'm testing more beta (@arrays).", - "I'm testing more gamma (@arrays).", "I'm trying more alpha (@arrays).", - "I'm trying more beta (@arrays).", "I'm trying more gamma (@arrays)." - ]) - bot.reply("test weird syntax", "This (@ greek) shouldn't work, and neither should this @test.") - bot.replyRandom("random format hello world", [ - "HELLO WORLD", "hello world", "Hello World", "Hello world", - ]) - test.done() - -################################################################################ -# Object Macro Tests -################################################################################ - -exports.test_js_objects = (test) -> - bot = new TestCase(test, """ - > object nolang - return "Test w/o language." - < object - - > object wlang javascript - return "Test w/ language." - < object - - > object reverse javascript - var msg = args.join(" "); - console.log(msg); - return msg.split("").reverse().join(""); - < object - - > object broken javascript - return "syntax error - < object - - > object foreign perl - return "Perl checking in!" - < object - - + test nolang - - Nolang: nolang - - + test wlang - - Wlang: wlang - - + reverse * - - reverse - - + test broken - - Broken: broken - - + test fake - - Fake: fake - - + test perl - - Perl: foreign - """) - bot.reply("Test nolang", "Nolang: Test w/o language.") - bot.reply("Test wlang", "Wlang: Test w/ language.") - bot.reply("Reverse hello world.", "dlrow olleh") - bot.reply("Test broken", "Broken: [ERR: Object Not Found]") - bot.reply("Test fake", "Fake: [ERR: Object Not Found]") - bot.reply("Test perl", "Perl: [ERR: Object Not Found]") - test.done() - -exports.test_disabled_js_language = (test) -> - bot = new TestCase(test, """ - > object test javascript - return 'JavaScript here!' - < object - - + test - - Result: test - """) - bot.reply("test", "Result: JavaScript here!") - bot.rs.setHandler("javascript", undefined) - bot.reply("test", "Result: [ERR: No Object Handler]") - test.done() - -exports.test_get_variable = (test) -> - bot = new TestCase(test, """ - ! var test_var = test - - > object test_get_var javascript - var uid = rs.currentUser(); - var name = "test_var"; - return rs.getVariable(uid, name); - < object - - + show me var - - test_get_var - """) - bot.reply("show me var", "test") - test.done() - - -################################################################################ -# Topic Tests -################################################################################ - -exports.test_punishment_topic = (test) -> - bot = new TestCase(test, """ - + hello - - Hi there! - - + swear word - - How rude! Apologize or I won't talk to you again.{topic=sorry} - - + * - - Catch-all. - - > topic sorry - + sorry - - It's ok!{topic=random} - - + * - - Say you're sorry! - < topic - """) - bot.reply("hello", "Hi there!") - bot.reply("How are you?", "Catch-all.") - bot.reply("Swear word!", "How rude! Apologize or I won't talk to you again.") - bot.reply("hello", "Say you're sorry!") - bot.reply("How are you?", "Say you're sorry!") - bot.reply("Sorry!", "It's ok!") - bot.reply("hello", "Hi there!") - bot.reply("How are you?", "Catch-all.") - test.done() - -exports.test_topic_inheritance = (test) -> - RS_ERR_MATCH = "ERR: No Reply Matched" - bot = new TestCase(test, """ - > topic colors - + what color is the sky - - Blue. - - + what color is the sun - - Yellow. - < topic - - > topic linux - + name a red hat distro - - Fedora. - - + name a debian distro - - Ubuntu. - < topic - - > topic stuff includes colors linux - + say stuff - - \"Stuff.\" - < topic - - > topic override inherits colors - + what color is the sun - - Purple. - < topic - - > topic morecolors includes colors - + what color is grass - - Green. - < topic - - > topic evenmore inherits morecolors - + what color is grass - - Blue, sometimes. - < topic - """) - bot.rs.setUservar(bot.username, "topic", "colors") - bot.reply("What color is the sky?", "Blue.") - bot.reply("What color is the sun?", "Yellow.") - bot.reply("What color is grass?", RS_ERR_MATCH) - bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) - bot.reply("Name a Debian distro.", RS_ERR_MATCH) - bot.reply("Say stuff.", RS_ERR_MATCH) - - bot.rs.setUservar(bot.username, "topic", "linux") - bot.reply("What color is the sky?", RS_ERR_MATCH) - bot.reply("What color is the sun?", RS_ERR_MATCH) - bot.reply("What color is grass?", RS_ERR_MATCH) - bot.reply("Name a Red Hat distro.", "Fedora.") - bot.reply("Name a Debian distro.", "Ubuntu.") - bot.reply("Say stuff.", RS_ERR_MATCH) - - bot.rs.setUservar(bot.username, "topic", "stuff") - bot.reply("What color is the sky?", "Blue.") - bot.reply("What color is the sun?", "Yellow.") - bot.reply("What color is grass?", RS_ERR_MATCH) - bot.reply("Name a Red Hat distro.", "Fedora.") - bot.reply("Name a Debian distro.", "Ubuntu.") - bot.reply("Say stuff.", '"Stuff."') - - bot.rs.setUservar(bot.username, "topic", "override") - bot.reply("What color is the sky?", "Blue.") - bot.reply("What color is the sun?", "Purple.") - bot.reply("What color is grass?", RS_ERR_MATCH) - bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) - bot.reply("Name a Debian distro.", RS_ERR_MATCH) - bot.reply("Say stuff.", RS_ERR_MATCH) - - bot.rs.setUservar(bot.username, "topic", "morecolors") - bot.reply("What color is the sky?", "Blue.") - bot.reply("What color is the sun?", "Yellow.") - bot.reply("What color is grass?", "Green.") - bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) - bot.reply("Name a Debian distro.", RS_ERR_MATCH) - bot.reply("Say stuff.", RS_ERR_MATCH) - - bot.rs.setUservar(bot.username, "topic", "evenmore") - bot.reply("What color is the sky?", "Blue.") - bot.reply("What color is the sun?", "Yellow.") - bot.reply("What color is grass?", "Blue, sometimes.") - bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) - bot.reply("Name a Debian distro.", RS_ERR_MATCH) - bot.reply("Say stuff.", RS_ERR_MATCH) - - test.done() - - -################################################################################ -# calculation (add,sub) tests -################################################################################ - -exports.test_addition = (test) -> - bot = new TestCase(test, """ - + test counter - - counter set - - + show - - counter = - - + add - - adding - - + sub - - subbing - - + div - - - ^
    - ^ divving - - + mult - - - ^ - ^ multing - """) - bot.reply("test counter", "counter set") - bot.reply("show", "counter = 0") - bot.reply("add", "adding") - bot.reply("show", "counter = 1") - bot.reply("sub", "subbing") - bot.reply("show", "counter = 0") - - bot.reply("div", "divving") - bot.reply("show", "counter = 5") - - bot.reply("mult", "multing") - bot.reply("show", "counter = 20") - - test.done() - -################################################################################ -# Parser option tests -################################################################################ - -exports.test_concat = (test) -> - bot = new TestCase(test, """ - // Default concat mode = none - + test concat default - - Hello - ^ world! - - ! local concat = space - + test concat space - - Hello - ^ world! - - ! local concat = none - + test concat none - - Hello - ^ world! - - ! local concat = newline - + test concat newline - - Hello - ^ world! - - // invalid concat setting is equivalent to 'none' - ! local concat = foobar - + test concat foobar - - Hello - ^ world! - - // the option is file scoped so it can be left at - // any setting and won't affect subsequent parses - ! local concat = newline - """) - bot.extend(""" - // concat mode should be restored to the default in a - // separate file/stream parse - + test concat second file - - Hello - ^ world! - """) - - bot.reply("test concat default", "Helloworld!") - bot.reply("test concat space", "Hello world!") - bot.reply("test concat none", "Helloworld!") - bot.reply("test concat newline", "Hello\nworld!") - bot.reply("test concat foobar", "Helloworld!") - bot.reply("test concat second file", "Helloworld!") - - test.done() - -################################################################################ -# Unicode Tests -################################################################################ - -exports.test_unicode = (test) -> - bot = new TestCase(test, """ - ! sub who's = who is - - + äh - - What's the matter? - - + ブラッキー - - エーフィ - - // Make sure %Previous continues working in UTF-8 mode. - + knock knock - - Who's there? - - + * - % who is there - - who? - - + * - % * who - - Haha! ! - - // And with UTF-8. - + tëll më ä pöëm - - Thërë öncë wäs ä män nämëd Tïm - - + more - % thërë öncë wäs ä män nämëd tïm - - Whö nëvër qüïtë lëärnëd höw tö swïm - - + more - % whö nëvër qüïtë lëärnëd höw tö swïm - - Hë fëll öff ä döck, änd sänk lïkë ä röck - - + more - % hë fëll öff ä döck änd sänk lïkë ä röck - - Änd thät wäs thë ënd öf hïm. - """, {"utf8": true}) - - bot.reply("äh", "What's the matter?") - bot.reply("ブラッキー", "エーフィ") - bot.reply("knock knock", "Who's there?") - bot.reply("Orange", "Orange who?") - bot.reply("banana", "Haha! Banana!") - bot.reply("tëll më ä pöëm", "Thërë öncë wäs ä män nämëd Tïm") - bot.reply("more", "Whö nëvër qüïtë lëärnëd höw tö swïm") - bot.reply("more", "Hë fëll öff ä döck, änd sänk lïkë ä röck") - bot.reply("more", "Änd thät wäs thë ënd öf hïm.") - test.done() - -exports.test_punctuation = (test) -> - bot = new TestCase(test, """ - + hello bot - - Hello human! - """, {"utf8": true}) - - bot.reply("Hello bot", "Hello human!") - bot.reply("Hello, bot!", "Hello human!") - bot.reply("Hello: Bot", "Hello human!") - bot.reply("Hello... bot?", "Hello human!") - - bot.rs.unicodePunctuation = new RegExp(/xxx/g) - bot.reply("Hello bot", "Hello human!") - bot.reply("Hello, bot!", "ERR: No Reply Matched") - test.done() - -################################################################################ -# Promise Tests -################################################################################ - -exports.test_js_string_in_setSubroutine = (test) -> - bot = new TestCase(test, """ - + hello - - hello helper - """) - - input = "hello there" - - bot.rs.setSubroutine("helper", ["return 'person';"]) - bot.reply("hello", "hello person") - test.done() - -exports.test_function_in_setSubroutine = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello personhelper - """) - - input = "my name is Rive" - - bot.rs.setSubroutine("helper", (rs, args) -> - test.equal(rs, bot.rs) - test.equal(args.length, 1) - test.equal(args[0], "rive") - test.done() - ) - - bot.reply(input, "hello person") - -exports.test_function_in_setSubroutine_return_value = (test) -> - bot = new TestCase(test, """ - + hello - - hello helper - """) - - bot.rs.setSubroutine("helper", (rs, args) -> - "person" - ) - - bot.reply("hello", "hello person") - test.done() - -exports.test_arguments_in_setSubroutine = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello helper 12 - """) - - bot.rs.setSubroutine("helper", (rs, args) -> - test.equal(args.length, 2) - test.equal(args[0], "thomas edison") - test.equal(args[1], "12") - args[0] - ) - - bot.reply("my name is thomas edison", "hello thomas edison") - test.done() - -exports.test_quoted_strings_arguments_in_setSubroutine = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello helper 12 "another param" - """) - - bot.rs.setSubroutine("helper", (rs, args) -> - test.equal(args.length, 3) - test.equal(args[0], "thomas edison") - test.equal(args[1], "12") - test.equal(args[2], "another param") - args[0] - ) - - bot.reply("my name is thomas edison", "hello thomas edison") - test.done() - -exports.test_arguments_with_funky_spacing_in_setSubroutine = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello helper 12 "another param" - """) - - bot.rs.setSubroutine("helper", (rs, args) -> - test.equal(args.length, 3) - test.equal(args[0], "thomas edison") - test.equal(args[1], "12") - test.equal(args[2], "another param") - args[0] - ) - - bot.reply("my name is thomas edison", "hello thomas edison") - test.done() - -exports.test_promises_in_objects = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello there helperWithPromise with a anotherHelperWithPromise - """) - - input = "my name is Rive" - - bot.rs.setSubroutine("helperWithPromise", (rs, args) -> - return new rs.Promise((resolve, reject) -> - resolve("stranger") - ) - ) - - bot.rs.setSubroutine("anotherHelperWithPromise", (rs) -> - return new rs.Promise((resolve, reject) -> - setTimeout () -> - resolve("delay") - , 1000 - ) - ) - - bot.rs.replyAsync(bot.username, input).then (reply) -> - test.equal(reply, "hello there stranger with a delay") - test.done() - -exports.test_replyAsync_supports_callbacks = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello there asyncHelper - """) - - input = "my name is Rive" - - bot.rs.setSubroutine("asyncHelper", (rs, args) -> - return new rs.Promise((resolve, reject) -> - resolve("stranger") - ) - ) - - bot.rs.replyAsync(bot.username, input, null, (error, reply) -> - test.ok(!error) - test.equal(reply, "hello there stranger") - test.done() - ) - -exports.test_use_reply_with_async_subroutines = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello there asyncHelper - """) - - bot.rs.setSubroutine("asyncHelper", (rs, args) -> - return new rs.Promise((resolve, reject) -> - resolve("stranger") - ) - ) - - bot.reply("my name is Rive", "hello there [ERR: Using async routine with reply: use replyAsync instead]") - test.done() - -exports.test_errors_in_async_subroutines_with_callbacks = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello there asyncHelper - """) - - errorMessage = "Something went terribly wrong" - - bot.rs.setSubroutine("asyncHelper", (rs, args) -> - return new rs.Promise((resolve, reject) -> - reject(new Error(errorMessage)) - ) - ) - - bot.rs.replyAsync(bot.username, "my name is Rive", null, (error, reply) -> - test.ok(error) - test.equal(error.message, errorMessage) - test.ok(!reply) - test.done() - ) - -exports.test_errors_in_async_subroutines_with_promises = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello there asyncHelper - """) - - errorMessage = "Something went terribly wrong" - - bot.rs.setSubroutine("asyncHelper", (rs, args) -> - return new rs.Promise((resolve, reject) -> - reject(new Error(errorMessage)) - ) - ) - - bot.rs.replyAsync(bot.username, "my name is Rive").catch (error) -> - test.ok(error) - test.equal(error.message, errorMessage) - test.done() - -exports.test_async_and_sync_subroutines_together = (test) -> - bot = new TestCase(test, """ - + my name is * - - hello there asyncHelperexclaim - """) - - - bot.rs.setSubroutine("exclaim", (rs, args) -> - return "!" - ) - - bot.rs.setSubroutine("asyncHelper", (rs, args) -> - return new rs.Promise((resolve, reject) -> - resolve("stranger") - ) - ) - - bot.rs.replyAsync(bot.username, "my name is Rive").then (reply) -> - test.equal(reply, "hello there stranger!") - test.done() - - -exports.test_stringify_with_objects = (test) -> - bot = new TestCase(test, """ - > object hello javascript - return \"Hello\"; - < object - + my name is * - - hello thereexclaim - """) - - bot.rs.setSubroutine("exclaim", (rs) -> - return "!" - ) - - src = bot.rs.stringify() - expect = '! version = 2.0\n! local concat = none\n\n> object hello javascript\n\treturn "Hello";\n< object\n\n> object exclaim javascript\n\treturn "!";\n< object\n\n+ my name is *\n- hello thereexclaim\n' - test.equal(src, expect) - test.done() - - -exports.load_directory_recursively = (test) -> +exports.test_load_directory_recursively = (test) -> bot = new TestCase(test, """ + * - No, this failed. @@ -1102,69 +19,84 @@ exports.load_directory_recursively = (test) -> test.equal(true, false) # Throw error ) -exports.test_concat_with_conditionals = (test) -> - # Newline +exports.test_default_error_messages = (test) -> bot = new TestCase(test, """ - ! local concat = newline + + condition only + * == Aiden => Your name is Aiden! + + + recursion + - {@recursion} + + + impossible object + - Here we go: unhandled - + test * - * == a => First A line - ^ Second A line - ^ Third A line - - First B line - ^ Second B line - ^ Third B line + > object unhandled rust + return "Hello world" + < object """) - bot.reply("test a", "First A line\nSecond A line\nThird A line") - bot.reply("test b", "First B line\nSecond B line\nThird B line") + DEF_NOT_FOUND = "ERR: No Reply Found" + DEF_NOT_MATCH = "ERR: No Reply Matched" + DEF_NO_OBJECT = "[ERR: Object Not Found]" + DEF_RECURSION = "ERR: Deep Recursion Detected" - # Space - bot = new TestCase(test, """ - ! local concat = space + bot.reply("condition only", DEF_NOT_FOUND) + bot.reply("hello bot", DEF_NOT_MATCH) + bot.reply("impossible object", "Here we go: #{DEF_NO_OBJECT}") + bot.reply("recursion", DEF_RECURSION) - + test * - * == a => First A line - ^ Second A line - ^ Third A line - - First B line - ^ Second B line - ^ Third B line - """) + # Set some error handlers manually, one at a time. + bot.rs.errors.replyNotFound = "I didn't find a reply!" + bot.reply("condition only", "I didn't find a reply!") + bot.reply("hello bot", DEF_NOT_MATCH) + bot.reply("impossible object", "Here we go: #{DEF_NO_OBJECT}") + bot.reply("recursion", DEF_RECURSION) - bot.reply("test a", "First A line Second A line Third A line") - bot.reply("test b", "First B line Second B line Third B line") + bot.rs.errors.replyNotMatched = "I don't even know what to say to that!" + bot.reply("condition only", "I didn't find a reply!") + bot.reply("hello bot", "I don't even know what to say to that!") + bot.reply("impossible object", "Here we go: #{DEF_NO_OBJECT}") + bot.reply("recursion", DEF_RECURSION) - # No concat - bot = new TestCase(test, """ - + test * - * == a => First A line - ^ Second A line - ^ Third A line - - First B line - ^ Second B line - ^ Third B line - """) + bot.rs.errors.objectNotFound = "I can't handle this object!" + bot.reply("condition only", "I didn't find a reply!") + bot.reply("hello bot", "I don't even know what to say to that!") + bot.reply("impossible object", "Here we go: I can't handle this object!") + bot.reply("recursion", DEF_RECURSION) - bot.reply("test a", "First A lineSecond A lineThird A line") - bot.reply("test b", "First B lineSecond B lineThird B line") + bot.rs.errors.deepRecursion = "I'm going too far down the rabbit hole." + bot.reply("condition only", "I didn't find a reply!") + bot.reply("hello bot", "I don't even know what to say to that!") + bot.reply("impossible object", "Here we go: I can't handle this object!") + bot.reply("recursion", "I'm going too far down the rabbit hole.") test.done() - -exports.test_concat_space_with_conditionals = (test) -> +exports.test_error_constructor_configuration = (test) -> bot = new TestCase(test, """ - ! local concat = newline + + condition only + * == Aiden => Your name is Aiden! - + test * - * == a => First A line - ^ Second A line - ^ Third A line - - First B line - ^ Second B line - ^ Third B line - """) + + recursion + - {@recursion} + + + impossible object + - Here we go: unhandled + + > object unhandled rust + return "Hello world" + < object + """, { + errors: + replyNotFound: "I didn't find a reply!" + replyNotMatched: "I don't even know what to say to that!" + objectNotFound: "I can't handle this object!" + deepRecursion: "I'm going too far down the rabbit hole." + }) + + bot.reply("condition only", "I didn't find a reply!") + bot.reply("hello bot", "I don't even know what to say to that!") + bot.reply("impossible object", "Here we go: I can't handle this object!") + bot.reply("recursion", "I'm going too far down the rabbit hole.") - bot.reply("test a", "First A line\nSecond A line\nThird A line") - bot.reply("test b", "First B line\nSecond B line\nThird B line") test.done() diff --git a/test/test-substitutions.coffee b/test/test-substitutions.coffee new file mode 100644 index 0000000..bc6d207 --- /dev/null +++ b/test/test-substitutions.coffee @@ -0,0 +1,42 @@ +TestCase = require("./test-base") + +################################################################################ +# Substitution Tests +################################################################################ + +exports.test_substitutions = (test) -> + bot = new TestCase(test, """ + + whats up + - nm. + + + what is up + - Not much. + """) + bot.reply("whats up", "nm.") + bot.reply("what's up?", "nm.") + bot.reply("what is up?", "Not much.") + + bot.extend(""" + ! sub whats = what is + ! sub what's = what is + """) + bot.reply("whats up", "Not much.") + bot.reply("what's up?", "Not much.") + bot.reply("What is up?", "Not much.") + test.done() + +exports.test_person_substitutions = (test) -> + bot = new TestCase(test, """ + + say * + - + """) + bot.reply("say I am cool", "i am cool") + bot.reply("say You are dumb", "you are dumb") + + bot.extend(""" + ! person i am = you are + ! person you are = I am + """) + bot.reply("say I am cool", "you are cool") + bot.reply("say You are dumb", "I am dumb") + test.done() diff --git a/test/test-topics.coffee b/test/test-topics.coffee new file mode 100644 index 0000000..efc2475 --- /dev/null +++ b/test/test-topics.coffee @@ -0,0 +1,123 @@ +TestCase = require("./test-base") + +################################################################################ +# Topic Tests +################################################################################ + +exports.test_punishment_topic = (test) -> + bot = new TestCase(test, """ + + hello + - Hi there! + + + swear word + - How rude! Apologize or I won't talk to you again.{topic=sorry} + + + * + - Catch-all. + + > topic sorry + + sorry + - It's ok!{topic=random} + + + * + - Say you're sorry! + < topic + """) + bot.reply("hello", "Hi there!") + bot.reply("How are you?", "Catch-all.") + bot.reply("Swear word!", "How rude! Apologize or I won't talk to you again.") + bot.reply("hello", "Say you're sorry!") + bot.reply("How are you?", "Say you're sorry!") + bot.reply("Sorry!", "It's ok!") + bot.reply("hello", "Hi there!") + bot.reply("How are you?", "Catch-all.") + test.done() + +exports.test_topic_inheritance = (test) -> + RS_ERR_MATCH = "ERR: No Reply Matched" + bot = new TestCase(test, """ + > topic colors + + what color is the sky + - Blue. + + + what color is the sun + - Yellow. + < topic + + > topic linux + + name a red hat distro + - Fedora. + + + name a debian distro + - Ubuntu. + < topic + + > topic stuff includes colors linux + + say stuff + - \"Stuff.\" + < topic + + > topic override inherits colors + + what color is the sun + - Purple. + < topic + + > topic morecolors includes colors + + what color is grass + - Green. + < topic + + > topic evenmore inherits morecolors + + what color is grass + - Blue, sometimes. + < topic + """) + bot.rs.setUservar(bot.username, "topic", "colors") + bot.reply("What color is the sky?", "Blue.") + bot.reply("What color is the sun?", "Yellow.") + bot.reply("What color is grass?", RS_ERR_MATCH) + bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) + bot.reply("Name a Debian distro.", RS_ERR_MATCH) + bot.reply("Say stuff.", RS_ERR_MATCH) + + bot.rs.setUservar(bot.username, "topic", "linux") + bot.reply("What color is the sky?", RS_ERR_MATCH) + bot.reply("What color is the sun?", RS_ERR_MATCH) + bot.reply("What color is grass?", RS_ERR_MATCH) + bot.reply("Name a Red Hat distro.", "Fedora.") + bot.reply("Name a Debian distro.", "Ubuntu.") + bot.reply("Say stuff.", RS_ERR_MATCH) + + bot.rs.setUservar(bot.username, "topic", "stuff") + bot.reply("What color is the sky?", "Blue.") + bot.reply("What color is the sun?", "Yellow.") + bot.reply("What color is grass?", RS_ERR_MATCH) + bot.reply("Name a Red Hat distro.", "Fedora.") + bot.reply("Name a Debian distro.", "Ubuntu.") + bot.reply("Say stuff.", '"Stuff."') + + bot.rs.setUservar(bot.username, "topic", "override") + bot.reply("What color is the sky?", "Blue.") + bot.reply("What color is the sun?", "Purple.") + bot.reply("What color is grass?", RS_ERR_MATCH) + bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) + bot.reply("Name a Debian distro.", RS_ERR_MATCH) + bot.reply("Say stuff.", RS_ERR_MATCH) + + bot.rs.setUservar(bot.username, "topic", "morecolors") + bot.reply("What color is the sky?", "Blue.") + bot.reply("What color is the sun?", "Yellow.") + bot.reply("What color is grass?", "Green.") + bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) + bot.reply("Name a Debian distro.", RS_ERR_MATCH) + bot.reply("Say stuff.", RS_ERR_MATCH) + + bot.rs.setUservar(bot.username, "topic", "evenmore") + bot.reply("What color is the sky?", "Blue.") + bot.reply("What color is the sun?", "Yellow.") + bot.reply("What color is grass?", "Blue, sometimes.") + bot.reply("Name a Red Hat distro.", RS_ERR_MATCH) + bot.reply("Name a Debian distro.", RS_ERR_MATCH) + bot.reply("Say stuff.", RS_ERR_MATCH) + + test.done() diff --git a/test/test-triggers.coffee b/test/test-triggers.coffee new file mode 100644 index 0000000..0fb13b3 --- /dev/null +++ b/test/test-triggers.coffee @@ -0,0 +1,125 @@ +TestCase = require("./test-base") + +################################################################################ +# Trigger Tests +################################################################################ + +exports.test_atomic_triggers = (test) -> + bot = new TestCase(test, """ + + hello bot + - Hello human. + + + what are you + - I am a RiveScript bot. + """) + bot.reply("Hello bot", "Hello human.") + bot.reply("What are you?", "I am a RiveScript bot.") + test.done() + +exports.test_wildcard_triggers = (test) -> + bot = new TestCase(test, """ + + my name is * + - Nice to meet you, . + + + * told me to say * + - Why did tell you to say ? + + + i am # years old + - A lot of people are . + + + i am _ years old + - Say that with numbers. + + + i am * years old + - Say that with fewer words. + """) + bot.reply("my name is Bob", "Nice to meet you, bob.") + bot.reply("bob told me to say hi", "Why did bob tell you to say hi?") + bot.reply("i am 5 years old", "A lot of people are 5.") + bot.reply("i am five years old", "Say that with numbers.") + bot.reply("i am twenty five years old", "Say that with fewer words.") + test.done() + +exports.test_alternatives_and_optionals = (test) -> + bot = new TestCase(test, """ + + what (are|is) you + - I am a robot. + + + what is your (home|office|cell) [phone] number + - It is 555-1234. + + + [please|can you] ask me a question + - Why is the sky blue? + + + (aa|bb|cc) [bogus] + - Matched. + + + (yo|hi) [computer|bot] * + - Matched. + """) + bot.reply("What are you?", "I am a robot.") + bot.reply("What is you?", "I am a robot.") + + bot.reply("What is your home phone number?", "It is 555-1234.") + bot.reply("What is your home number?", "It is 555-1234.") + bot.reply("What is your cell phone number?", "It is 555-1234.") + bot.reply("What is your office number?", "It is 555-1234.") + + bot.reply("Can you ask me a question?", "Why is the sky blue?") + bot.reply("Please ask me a question?", "Why is the sky blue?") + bot.reply("Ask me a question.", "Why is the sky blue?") + + bot.reply("aa", "Matched.") + bot.reply("bb", "Matched.") + bot.reply("aa bogus", "Matched.") + bot.reply("aabogus", "ERR: No Reply Matched") + bot.reply("bogus", "ERR: No Reply Matched") + + bot.reply("hi Aiden", "Matched.") + bot.reply("hi bot how are you?", "Matched.") + bot.reply("yo computer what time is it?", "Matched.") + bot.reply("yoghurt is yummy", "ERR: No Reply Matched") + bot.reply("hide and seek is fun", "ERR: No Reply Matched") + bot.reply("hip hip hurrah", "ERR: No Reply Matched") + test.done() + +exports.test_trigger_arrays = (test) -> + bot = new TestCase(test, """ + ! array colors = red blue green yellow white + ^ dark blue|light blue + + + what color is my (@colors) * + - Your is . + + + what color was * (@colors) * + - It was . + + + i have a @colors * + - Tell me more about your . + """) + bot.reply("What color is my red shirt?", "Your shirt is red.") + bot.reply("What color is my blue car?", "Your car is blue.") + bot.reply("What color is my pink house?", "ERR: No Reply Matched") + bot.reply("What color is my dark blue jacket?", "Your jacket is dark blue.") + bot.reply("What color was Napoleoan's white horse?", "It was white.") + bot.reply("What color was my red shirt?", "It was red.") + bot.reply("I have a blue car.", "Tell me more about your car.") + bot.reply("I have a cyan car.", "ERR: No Reply Matched") + test.done() + +exports.test_weighted_triggers = (test) -> + bot = new TestCase(test, """ + + * or something{weight=10} + - Or something. <@> + + + can you run a google search for * + - Sure! + + + hello *{weight=20} + - Hi there! + """) + bot.reply("Hello robot.", "Hi there!") + bot.reply("Hello or something.", "Hi there!") + bot.reply("Can you run a Google search for Node", "Sure!") + bot.reply("Can you run a Google search for Node or something", "Or something. Sure!") + test.done() diff --git a/test/test-unicode.coffee b/test/test-unicode.coffee new file mode 100644 index 0000000..cf00595 --- /dev/null +++ b/test/test-unicode.coffee @@ -0,0 +1,71 @@ +TestCase = require("./test-base") + +################################################################################ +# Unicode Tests +################################################################################ + +exports.test_unicode = (test) -> + bot = new TestCase(test, """ + ! sub who's = who is + + + äh + - What's the matter? + + + ブラッキー + - エーフィ + + // Make sure %Previous continues working in UTF-8 mode. + + knock knock + - Who's there? + + + * + % who is there + - who? + + + * + % * who + - Haha! ! + + // And with UTF-8. + + tëll më ä pöëm + - Thërë öncë wäs ä män nämëd Tïm + + + more + % thërë öncë wäs ä män nämëd tïm + - Whö nëvër qüïtë lëärnëd höw tö swïm + + + more + % whö nëvër qüïtë lëärnëd höw tö swïm + - Hë fëll öff ä döck, änd sänk lïkë ä röck + + + more + % hë fëll öff ä döck änd sänk lïkë ä röck + - Änd thät wäs thë ënd öf hïm. + """, {"utf8": true}) + + bot.reply("äh", "What's the matter?") + bot.reply("ブラッキー", "エーフィ") + bot.reply("knock knock", "Who's there?") + bot.reply("Orange", "Orange who?") + bot.reply("banana", "Haha! Banana!") + bot.reply("tëll më ä pöëm", "Thërë öncë wäs ä män nämëd Tïm") + bot.reply("more", "Whö nëvër qüïtë lëärnëd höw tö swïm") + bot.reply("more", "Hë fëll öff ä döck, änd sänk lïkë ä röck") + bot.reply("more", "Änd thät wäs thë ënd öf hïm.") + test.done() + +exports.test_punctuation = (test) -> + bot = new TestCase(test, """ + + hello bot + - Hello human! + """, {"utf8": true}) + + bot.reply("Hello bot", "Hello human!") + bot.reply("Hello, bot!", "Hello human!") + bot.reply("Hello: Bot", "Hello human!") + bot.reply("Hello... bot?", "Hello human!") + + bot.rs.unicodePunctuation = new RegExp(/xxx/g) + bot.reply("Hello bot", "Hello human!") + bot.reply("Hello, bot!", "ERR: No Reply Matched") + test.done()