/* MonkeyTalk - a cross-platform functional testing tool Copyright (C) 2012 Gorilla Logic, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.gorillalogic.monkeytalk.processor.tests; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.containsString; import java.io.File; import java.io.IOException; import java.util.Map; import org.json.JSONObject; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import com.gorillalogic.monkeytalk.api.js.tools.JSHelper; import com.gorillalogic.monkeytalk.processor.PlaybackListener; import com.gorillalogic.monkeytalk.processor.PlaybackResult; import com.gorillalogic.monkeytalk.processor.PlaybackStatus; import com.gorillalogic.monkeytalk.processor.Scope; import com.gorillalogic.monkeytalk.processor.ScriptProcessor; import com.gorillalogic.monkeytalk.sender.Response; import com.gorillalogic.monkeytalk.utils.FileUtils; import com.gorillalogic.monkeytalk.utils.TestHelper; public class RunIfTest extends TestHelper { private static final String HOST = "localhost"; private static final int PORT = 18027; private static String output; private static final PlaybackListener LISTENER_WITH_OUTPUT = new PlaybackListener() { @Override public void onStart(Scope scope) { output += scope.getCurrentCommand(); } @Override public void onScriptStart(Scope scope) { output += (output.length() > 0 ? "\n" : "") + "START\n"; } @Override public void onScriptComplete(Scope scope, PlaybackResult r) { output += "COMPLETE : " + r; } @Override public void onComplete(Scope scope, Response resp) { output += " -> " + resp + "\n"; } @Override public void onPrint(String message) { output += message; } }; @AfterClass public static void afterClass() throws IOException { cleanup(); } @Before public void before() { output = ""; } @Test public void testRunIfVerify() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); tempScript("foo.mt", "Script bar.mt RunIf Device * Verify iOS os", dir); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.mt"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.OK)); server.assertCommands("Device * Verify iOS os", "Button BAR Tap"); assertThat(output, containsString("START")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify iOS os -> OK : running bar.mt...\n")); assertThat(output, containsString("Script bar.mt Run\n")); assertThat(output, containsString("Button BAR Tap -> OK\n")); assertThat(output, containsString("COMPLETE : OK")); } @Test public void testRunIfVerifyAndModifiers() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); tempScript("foo.mt", "Script bar.mt RunIf Device * Verify iOS os %thinktime=5000 %timeout=5000", dir); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.mt"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.OK)); server.assertCommands("Device * Verify iOS os %thinktime=5000 %timeout=5000", "Button BAR Tap"); assertThat(output, containsString("START")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify iOS os %thinktime=5000 %timeout=5000 -> OK : running bar.mt...\n")); assertThat(output, containsString("Script bar.mt Run %thinktime=5000 %timeout=5000\n")); assertThat(output, containsString("Button BAR Tap -> OK\n")); assertThat(output, containsString("COMPLETE : OK")); } @Test public void testRunIfVerifyWithError() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); tempScript("foo.mt", "Script bar.mt RunIf Device * Verify Joe", dir); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.mt"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR)); server.assertCommands("Device * Verify Joe"); assertThat(output, containsString("START")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify Joe -> ERROR : verify error - error on Joe\n")); assertThat(output, not(containsString("Button BAR Tap"))); assertThat(output, containsString("COMPLETE : ERROR")); } @Test public void testRunIfVerifyWithFailure() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); tempScript("foo.mt", "Script bar.mt RunIf Device * Verify Fred", dir); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.mt"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.OK)); server.assertCommands("Device * Verify Fred"); assertThat(output, containsString("START")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify Fred -> OK : not running bar.mt - fail on Fred\n")); assertThat(output, not(containsString("Button BAR Tap"))); assertThat(output, containsString("COMPLETE : OK")); } @Test public void testRunIfWithMissingVerify() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); tempScript("foo.mt", "Script bar.mt RunIf", dir); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.mt"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR)); assertThat( result.getMessage(), is("command 'Script bar.mt RunIf' must have a valid verify command as its arguments")); assertThat( output, containsString("START\nScript bar.mt RunIf -> ERROR : command 'Script bar.mt RunIf' must have a valid verify command as its arguments\n")); assertThat( output, containsString("COMPLETE : ERROR : command 'Script bar.mt RunIf' must have a valid verify command as its arguments")); } @Test public void testRunIfWithInvalidVerify() throws IOException { File dir = tempDir(); tempScript("foo.mt", "Button FOO Tap\nScript bar.mt RunIf FOOBAR", dir); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.mt"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR)); assertThat(result.getMessage(), is("command 'Script bar.mt RunIf FOOBAR' has invalid verify command 'FOOBAR'")); server.assertCommands("Button FOO Tap"); assertThat(output, containsString("START\n")); assertThat(output, containsString("Button FOO Tap -> OK\n")); assertThat( output, containsString("Script bar.mt RunIf FOOBAR -> ERROR : command 'Script bar.mt RunIf FOOBAR' has invalid verify command 'FOOBAR'\n")); assertThat( output, containsString("COMPLETE : ERROR : command 'Script bar.mt RunIf FOOBAR' has invalid verify command 'FOOBAR'")); } @Test public void testRunIfWithMissingScript() throws IOException { File dir = tempDir(); tempScript("foo.mt", "Script missing.mt RunIf Device * Verify iOS os", dir); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.mt"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR)); assertThat(result.getMessage(), is("script 'missing.mt' not found")); assertThat(output, containsString("START")); assertThat( output, containsString("Script missing.mt RunIf Device * Verify iOS os -> OK : running missing.mt...\n")); assertThat(output, containsString("Script missing.mt Run -> OK")); assertThat(output, containsString("COMPLETE : ERROR : script 'missing.mt' not found")); } @Test public void testRunIfJavascript() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); File foo = tempScript("foo.mt", "Button FOO1 Tap\nScript bar.mt RunIf Device * Verify iOS os\nButton FOO2 Tap", dir); File fooJS = new File(dir, "foo.js"); JSHelper.genAPIAndLib(dir); JSHelper.genJS(foo); String js = FileUtils.readFile(fooJS); assertThat(js, containsString("load(\"libs/MyProj.js\");\n")); assertThat(js, containsString("MyProj.foo.prototype.run = function() {\n")); assertThat(js, containsString("app.button(\"FOO1\").tap();\n")); assertThat( js, containsString("app.bar().runIf(\"Device\", \"*\", \"Verify\", \"iOS\", \"os\");\n")); assertThat(js, containsString("app.button(\"FOO2\").tap();\n")); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.js"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.OK)); server.assertCommands("Button FOO1 tap", "Device * Verify iOS os", "Button BAR Tap", "Button FOO2 tap"); assertThat(output, containsString("Button FOO1 tap -> OK\n")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify iOS os -> OK : running bar.mt...\n")); assertThat( output, containsString("Script bar.mt Run\nSTART\nButton BAR Tap -> OK\nCOMPLETE : OK -> OK\n")); assertThat(output, containsString("Button FOO2 tap -> OK\n")); } @Test public void testRunIfJavascriptAndModifiers() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); File foo = tempScript( "foo.mt", "Button FOO1 Tap\nScript bar.mt RunIf Device * Verify iOS os %thinktime=5000 %timeout=5000\nButton FOO2 Tap", dir); File fooJS = new File(dir, "foo.js"); JSHelper.genAPIAndLib(dir); JSHelper.genJS(foo); String js = FileUtils.readFile(fooJS); assertThat(js, containsString("load(\"libs/MyProj.js\");\n")); assertThat(js, containsString("MyProj.foo.prototype.run = function() {\n")); assertThat(js, containsString("app.button(\"FOO1\").tap();\n")); assertThat( js, containsString("app.bar().runIf(\"Device\", \"*\", \"Verify\", \"iOS\", \"os\", {thinktime:\"5000\", timeout:\"5000\"});\n")); assertThat(js, containsString("app.button(\"FOO2\").tap();\n")); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.js"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.OK)); server.assertCommands("Button FOO1 tap", "Device * Verify iOS os %thinktime=5000 %timeout=5000", "Button BAR Tap", "Button FOO2 tap"); assertThat(output, containsString("Button FOO1 tap -> OK\n")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify iOS os %thinktime=5000 %timeout=5000 -> OK : running bar.mt...\n")); assertThat( output, containsString("Script bar.mt Run %thinktime=5000 %timeout=5000\nSTART\nButton BAR Tap -> OK\nCOMPLETE : OK -> OK\n")); assertThat(output, containsString("Button FOO2 tap -> OK\n")); } @Test public void testRunIfJavascriptWithError() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); File foo = tempScript("foo.mt", "Button FOO1 Tap\nScript bar.mt RunIf Device * Verify Joe\nButton FOO2 Tap", dir); File fooJS = new File(dir, "foo.js"); JSHelper.genAPIAndLib(dir); JSHelper.genJS(foo); String js = FileUtils.readFile(fooJS); assertThat(js, containsString("load(\"libs/MyProj.js\");\n")); assertThat(js, containsString("MyProj.foo.prototype.run = function() {\n")); assertThat(js, containsString("app.button(\"FOO1\").tap();\n")); assertThat(js, containsString("app.bar().runIf(\"Device\", \"*\", \"Verify\", \"Joe\");\n")); assertThat(js, containsString("app.button(\"FOO2\").tap();\n")); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.js"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.ERROR)); assertThat(result.getMessage(), is("verify error - error on Joe")); server.assertCommands("Button FOO1 tap", "Device * Verify Joe"); assertThat(output, containsString("Button FOO1 tap -> OK\n")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify Joe -> ERROR : verify error - error on Joe\n")); } @Test public void testRunIfJavascriptWithFailure() throws IOException { File dir = tempDir(); tempScript("bar.mt", "Button BAR Tap", dir); File foo = tempScript("foo.mt", "Button FOO1 Tap\nScript bar.mt RunIf Device * Verify Fred\nButton FOO2 Tap", dir); File fooJS = new File(dir, "foo.js"); JSHelper.genAPIAndLib(dir); JSHelper.genJS(foo); String js = FileUtils.readFile(fooJS); assertThat(js, containsString("load(\"libs/MyProj.js\");\n")); assertThat(js, containsString("MyProj.foo.prototype.run = function() {\n")); assertThat(js, containsString("app.button(\"FOO1\").tap();\n")); assertThat(js, containsString("app.bar().runIf(\"Device\", \"*\", \"Verify\", \"Fred\");\n")); assertThat(js, containsString("app.button(\"FOO2\").tap();\n")); ScriptProcessor processor = new ScriptProcessor(HOST, PORT, dir); CommandServer server = new ErrorOnJoeAndFailOnFredServer(PORT); processor.setPlaybackListener(LISTENER_WITH_OUTPUT); PlaybackResult result = processor.runScript("foo.js"); server.stop(); assertThat("FAIL: " + result, result.getStatus(), is(PlaybackStatus.OK)); server.assertCommands("Button FOO1 tap", "Device * Verify Fred", "Button FOO2 tap"); assertThat(output, containsString("Button FOO1 tap -> OK\n")); assertThat( output, containsString("Script bar.mt RunIf Device * Verify Fred -> OK : not running bar.mt - fail on Fred\n")); assertThat(output, containsString("Button FOO2 tap -> OK\n")); } private class ErrorOnJoeAndFailOnFredServer extends CommandServer { public ErrorOnJoeAndFailOnFredServer(int port) throws IOException { super(port); } @Override public Response serve(String uri, String method, Map<String, String> headers, JSONObject json) { Response resp = super.serve(uri, method, headers, json); if (json.toString().toLowerCase().contains("joe")) { return new Response(HttpStatus.OK, "{result:\"ERROR\",message:\"error on Joe\"}"); } else if (json.toString().toLowerCase().contains("fred")) { return new Response(HttpStatus.OK, "{result:\"FAILURE\",message:\"fail on Fred\"}"); } else if (json.optString("action", "").equalsIgnoreCase("verify")) { return new Response(HttpStatus.OK, "{result:\"OK\",message:\"msg\"}"); } return resp; } } private class CommandServer extends com.gorillalogic.monkeytalk.utils.TestHelper.CommandServer { public CommandServer(int port) throws IOException { super(port); } public void assertCommands(String... cmds) { assertCommands(false, cmds); } public void assertCommands(boolean showDefaultTimings, String... cmds) { assertThat(getCommands(), notNullValue()); assertThat(getCommands().size(), is(cmds.length)); for (int i = 0; i < cmds.length; i++) { assertThat(getCommands().get(i).getCommand(showDefaultTimings), is(cmds[i])); } } } }