concept TestScript { S scriptName, comments; bool active; long lastRun; bool testedOK; S botLinePattern1, userLine1; S botLinePattern2, userLine2; S botLinePattern3, userLine3; S botLinePattern4, userLine4; S botLinePattern5, userLine5; S botLinePattern6, userLine6; S botLinePattern7, userLine7; S botLinePattern8, userLine8; int highestIndex() { ret 8; } S botLinePattern(int i) { ret trim(getString(this, "botLinePattern" + i)); } S userLine(int i) { ret trim(getString(this, "userLine" + i)); } } sclass TestScripting { sO html(S uri, SS params, AuthedDialogID auth) null { S uri2 = appendSlash(uri); bool requestAuthed = auth != null; if (startsWith(uri2, "/testscripts/")) { if (!requestAuthed) ret serveAuthForm(params.get('uri)); ret serveTestScriptingAdmin(uri, params); } } sO serveTestScriptingAdmin(S uri, SS params) { S nav = p(ahref(rawBotLink(dbBotID), "Main admin") + " | " + ahref(baseLink + "/testscripts", "Test scripts admin")); if (ewic(uri, "/run-test")) { long id = parseLong(params.get("id")); TestScript script = getConcept TestScript(id); if (script == null) ret "Script " + id + " not found"; S output = hijackPrint_tee_pcall(() -> runTestScript(script)); S title = "Test results for script: " + script.scriptName; ret hhtml(hhead_title(title) + hbody( hsansserif() + nav + h1(title) + hsourcecode(output))); } HCRUD_Concepts data = new HCRUD_Concepts<>(TestScript); HCRUD crud = new(rawLink("testscripts"), data) { S frame(S title, S contents) { ret hhtml(hhead_title_htmldecode(title) + hbody( hsansserif() + hcss_responstable() /*+ loadJQuery() + hscript_reloadOnHistoryNav()*/ + nav + h1(title) + contents)); } S renderValue(S field, O value) { if (eq(field, "lastRun")) ret renderHowLongAgo(toLong(value)); ret super.renderValue(field, value); } }; crud.renderCmds = item -> crud.renderCmds_base(item) + " | " + ahref(rawLink("testscripts/run-test" + hquery(id := item.get("id"))), "run test"); crud.cmdsLeft = true; crud.tableClass = "responstable"; crud.uneditableFields = litset("lastRun", "testedOK"); ret subBot_serveHTMLNoCache(crud.renderPage(params)); } svoid runTestScript(TestScript script) { try { temp WebBotTester tester = new(programID()); tester.params.put("testMode", "1"); tester.start(); int i = 0; for (int idx = 1; idx <= script.highestIndex(); idx++) { S pat = script.botLinePattern(idx); if (nempty(pat)) { print("Bot line pattern: " + pat); tester.waitForMessages(i+1); WebChatBotMsg msg = get(tester.msgs, i); try { assertTrueVerbose(i + ": " + pat + "/" + msg.msgText, mmo2_match(pat, msg.msgText)); assertTrue("fromBot", !msg.fromUser); } on fail { print(msgs := tester.msgs); } ++i; } S userLine = script.userLine(idx); if (nempty(userLine)) { print("Sending line: " + userLine); tester.sendMsg(userLine); ++i; } } print("Script OK: " + script.scriptName); cset(script, testedOK := true); } catch print e { cset(script, testedOK := false); } cset(script, lastRun := now()); } }