{"id":17981377,"url":"https://github.com/rohitghatol/cucumber-sikuli-selenium-framework","last_synced_at":"2025-04-04T01:22:42.845Z","repository":{"id":32022616,"uuid":"35593847","full_name":"rohitghatol/cucumber-sikuli-selenium-framework","owner":"rohitghatol","description":"Cucumber Sikuli Selenium Framework which uses configurable Actions defined in JSON flow files","archived":false,"fork":false,"pushed_at":"2015-05-14T08:03:14.000Z","size":198,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-09T13:11:09.228Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rohitghatol.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-14T06:01:43.000Z","updated_at":"2015-05-14T07:57:42.000Z","dependencies_parsed_at":"2022-09-12T17:50:24.229Z","dependency_job_id":null,"html_url":"https://github.com/rohitghatol/cucumber-sikuli-selenium-framework","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohitghatol%2Fcucumber-sikuli-selenium-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohitghatol%2Fcucumber-sikuli-selenium-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohitghatol%2Fcucumber-sikuli-selenium-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohitghatol%2Fcucumber-sikuli-selenium-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rohitghatol","download_url":"https://codeload.github.com/rohitghatol/cucumber-sikuli-selenium-framework/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247104217,"owners_count":20884189,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-29T18:09:43.237Z","updated_at":"2025-04-04T01:22:42.821Z","avatar_url":"https://github.com/rohitghatol.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cucumber-sikuli-selenium-framework \nSikuli Cucumber Gradle Test Framework Showcase\n\n## Setup\n* Java SDK 7\n* Eclipse Luna\n* Eclipse Plugins\n  * Gradle Integration for Eclipse http://dist.springsource.com/milestone/TOOLS/gradle\n \nEclipse Setup\n* Open Eclipse Luna \n* Install Plugin - Gradle Integration for Eclipse http://dist.springsource.com/milestone/TOOLS/gradle\n* Restart Eclipse\n* click on File -\u003e Import -\u003e Gradle Project\n* Choose the checkout directory\n* Click on \"Build Model\" then you will see the project in the list below, select that and click \"Finish\"\n\n## Steps\n\n* Checkout the project\n* Close all Browser Windows\n* On Linux/Mac run $\u003e./gradlew cucumber\n* on Windows run cmd\u003egradlew.bat cucumber\n\nThis should start a new Browser window, shows Google Text Search and Image Search for keyword \"facebook\".\nThe Text Search uses Selenium and the Image Search uses Sikuli.\n\n## Architecture\n\nThe way this framework works is Feature file are run by cucumber which calls the Step Definition classes, which in turn call FlowRunner.java class, which in turn runs step.json file. In step.json file we have Actions (Selenium and Sikuli actions for verifying element/image is present, clicking them, typing in them). See BaseAction and its derived classes.\n\nFlow Diagram \n```\nFeature File ==\u003e Step Definitions ==\u003e Flow.json ==\u003e Actions\n```\n\nFeature File\n```\nFeature: Google Text Search\n\n\nScenario: Doing Google Text Search\n    Given Google in Open in Browser    \n    When I search for \"Facebook\"\n    Then I can see \"Welcome to Facebook - Log In, Sign Up or Learn More\" link in search result\n\nScenario: Doing Google Text Search\n    Given Google in Open in Browser    \n    When I search for \"Facebook\" image\n    Then I can see facebook image in search result\n    \n```\n\nStep Definition File\n```\n\npublic class GoogleImageSearchStepDefinitions {\n\t@Autowired\n\tprivate Context context;\n\t\n\t@Autowired\n\tprivate FlowRunner flowRunner;\n\t\n\t@When(\"^I search for \\\"(.*?)\\\" image$\")\n\tpublic void i_search_for_image(String searchKeyword) throws Throwable {\n\t\tcontext.setFeature(\"google/image\");\n\t\tMap\u003cString,String\u003e dictionary = new HashMap\u003cString,String\u003e();\n\t\tdictionary.put(\"text\", searchKeyword);\n\t    flowRunner.run(context, \"when-1.json\",dictionary);\n\t}\n\n\t@Then(\"^I can see facebook image in search result$\")\n\tpublic void i_can_see_facebook_image_in_search_result() throws Throwable {\n\t\tcontext.setFeature(\"google/image\");\n\t    flowRunner.run(context, \"then-1.json\");\n\t}\n\n}\n\n```\n\nStep.json\n```\n[{\n    \"name\": \"Type in Google Search Text Box\",\n    \"type\": \"TypeInWebElementAction\",\n\n    \"selector\": \"id:lst-ib\",\n    \"text\": \"{{text}}\",\n    \"errorMessage\": \"Could not search for keyword in Google Search\",\n    \"waitPeriodInMillis\": 10000\n\n},\n{\n    \"name\": \"Click on Search Button\",\n    \"type\": \"ClickWebElementAction\",\n\n    \"selector\": \"name:btnG\",\n    \"text\": \"{{text}}\",\n    \"errorMessage\": \"Could not find Search Button\",\n    \"waitPeriodInMillis\": 10000\n\n}]\n```\n\nBase Action class\n```\n\npublic abstract class BaseAction {\n\n\t/** The test driver. */\n\tprotected TestDriver testDriver;\n\n\t/** The content mgr. */\n\tprotected ContentManager contentMgr;\n\n\t/** The context. */\n\tprotected Context context;\n\n\t/** The name. */\n\tprotected String name;\n\n\t/** The type. */\n\tprotected String type;\n\n\t/**\n\t * Gets the name.\n\t *\n\t * @return the name\n\t */\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t/**\n\t * Sets the name.\n\t *\n\t * @param name\n\t *            the new name\n\t */\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\n\t/**\n\t * Gets the type.\n\t *\n\t * @return the type\n\t */\n\tpublic String getType() {\n\t\treturn type;\n\t}\n\n\t/**\n\t * Sets the type.\n\t *\n\t * @param type\n\t *            the new type\n\t */\n\tpublic void setType(String type) {\n\t\tthis.type = type;\n\t}\n\n\t/**\n\t * Gets the test driver.\n\t *\n\t * @return the test driver\n\t */\n\tpublic TestDriver getTestDriver() {\n\t\treturn testDriver;\n\t}\n\n\t/**\n\t * Sets the test driver.\n\t *\n\t * @param testDriver\n\t *            the new test driver\n\t */\n\tpublic void setTestDriver(TestDriver testDriver) {\n\t\tthis.testDriver = testDriver;\n\t}\n\n\t/**\n\t * Gets the content mgr.\n\t *\n\t * @return the content mgr\n\t */\n\tpublic ContentManager getContentMgr() {\n\t\treturn contentMgr;\n\t}\n\n\t/**\n\t * Sets the content mgr.\n\t *\n\t * @param contentMgr\n\t *            the new content mgr\n\t */\n\tpublic void setContentMgr(ContentManager contentMgr) {\n\t\tthis.contentMgr = contentMgr;\n\t}\n\n\t/**\n\t * Gets the context.\n\t *\n\t * @return the context\n\t */\n\tpublic Context getContext() {\n\t\treturn context;\n\t}\n\n\t/**\n\t * Sets the context.\n\t *\n\t * @param context\n\t *            the new context\n\t */\n\tpublic void setContext(Context context) {\n\t\tthis.context = context;\n\t}\n\n\t/**\n\t * Execute.\n\t *\n\t * @throws ActionFailedException\n\t *             the action failed exception\n\t */\n\tpublic abstract void execute() throws ActionFailedException;\n\n\tpublic abstract void resolvePlaceHolders(Map\u003cString, String\u003e dictionary);\n\n\t/*\n\t * (non-Javadoc)\n\t * \n\t * @see java.lang.Object#toString()\n\t */\n\tpublic abstract String toString();\n\n}\n```\n\n\nTypeInImageAction (sikuli)\n```\n\npublic class TypeInImageAction extends BaseAction {\n\n\t/** The image. */\n\tprivate String image;\n\n\t/** The text. */\n\tprivate String text;\n\n\t/** The error message. */\n\tprivate String errorMessage;\n\n\t/** The wait period in millis. */\n\tprivate int waitPeriodInMillis;\n\n\t/**\n\t * Gets the image.\n\t *\n\t * @return the image\n\t */\n\tpublic String getImage() {\n\t\treturn image;\n\t}\n\n\t/**\n\t * Sets the image.\n\t *\n\t * @param image\n\t *            the new image\n\t */\n\tpublic void setImage(String image) {\n\t\tthis.image = image;\n\t}\n\n\t/**\n\t * Gets the error message.\n\t *\n\t * @return the error message\n\t */\n\tpublic String getErrorMessage() {\n\t\treturn errorMessage;\n\t}\n\n\t/**\n\t * Sets the error message.\n\t *\n\t * @param errorMessage\n\t *            the new error message\n\t */\n\tpublic void setErrorMessage(String errorMessage) {\n\t\tthis.errorMessage = errorMessage;\n\t}\n\n\t/**\n\t * Gets the wait period in millis.\n\t *\n\t * @return the wait period in millis\n\t */\n\tpublic int getWaitPeriodInMillis() {\n\t\treturn waitPeriodInMillis;\n\t}\n\n\t/**\n\t * Sets the wait period in millis.\n\t *\n\t * @param waitPeriodInMillis\n\t *            the new wait period in millis\n\t */\n\tpublic void setWaitPeriodInMillis(int waitPeriodInMillis) {\n\t\tthis.waitPeriodInMillis = waitPeriodInMillis;\n\t}\n\n\t/**\n\t * Gets the text.\n\t *\n\t * @return the text\n\t */\n\tpublic String getText() {\n\t\treturn text;\n\t}\n\n\t/**\n\t * Sets the text.\n\t *\n\t * @param text\n\t *            the new text\n\t */\n\tpublic void setText(String text) {\n\t\tthis.text = text;\n\t}\n\n\t/*\n\t * (non-Javadoc)\n\t * \n\t * @see com.synerzip.testframework.action.BaseAction#execute()\n\t */\n\t@Override\n\tpublic void execute() throws ActionFailedException {\n\t\tScreenRegion screenRegion = testDriver.getScreenRegion();\n\t\tMouse mouse = testDriver.getMouse();\n\t\tKeyboard keyboard = testDriver.getKeyboard();\n\n\t\tTarget imageTarget = contentMgr.getImage(context, image);\n\n\t\tScreenRegion newmessage = screenRegion.wait(imageTarget,\n\t\t\t\twaitPeriodInMillis);\n\n\t\tassertNotNull(errorMessage, newmessage);\n\n\t\tmouse.click(newmessage.getCenter());\n\n\t\tkeyboard.type(text);\n\t\tpause(waitPeriodInMillis);\n\t\tkeyboard.type(Key.ENTER);\n\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"TypeInImageAction [image=\" + image + \", text=\" + text\n\t\t\t\t+ \", errorMessage=\" + errorMessage + \", waitPeriodInMillis=\"\n\t\t\t\t+ waitPeriodInMillis + \", name=\" + name + \", type=\" + type\n\t\t\t\t+ \"]\";\n\t}\n\n\t@Override\n\tpublic void resolvePlaceHolders(Map\u003cString, String\u003e dictionary) {\n\t\tfor (String key : dictionary.keySet()) {\n\t\t\ttext = text.replace(\"{{\" + key + \"}}\", dictionary.get(key));\n\t\t}\n\n\t}\n\n}\n\n```\n\nTypeInWebElement (selenium)\n```\n\npublic class TypeInWebElementAction extends BaseAction {\n\n\t/** The image. */\n\tprivate String selector;\t\n\t\n\tprivate String text;\n\n\t/** The error message. */\n\tprivate String errorMessage;\n\n\t/** The wait period in millis. */\n\tprivate int waitPeriodInMillis;\n\n\t\n\t/**\n\t * @return the selector\n\t */\n\tpublic String getSelector() {\n\t\treturn selector;\n\t}\n\n\t/**\n\t * @param selector the selector to set\n\t */\n\tpublic void setSelector(String selector) {\n\t\tthis.selector = selector;\n\t}\n\n\t/**\n\t * @return the text\n\t */\n\tpublic String getText() {\n\t\treturn text;\n\t}\n\n\t/**\n\t * @param text the text to set\n\t */\n\tpublic void setText(String text) {\n\t\tthis.text = text;\n\t}\n\n\t/**\n\t * Gets the error message.\n\t *\n\t * @return the error message\n\t */\n\tpublic String getErrorMessage() {\n\t\treturn errorMessage;\n\t}\n\n\t/**\n\t * Sets the error message.\n\t *\n\t * @param errorMessage\n\t *            the new error message\n\t */\n\tpublic void setErrorMessage(String errorMessage) {\n\t\tthis.errorMessage = errorMessage;\n\t}\n\n\t/**\n\t * Gets the wait period in millis.\n\t *\n\t * @return the wait period in millis\n\t */\n\tpublic int getWaitPeriodInMillis() {\n\t\treturn waitPeriodInMillis;\n\t}\n\n\t/**\n\t * Sets the wait period in millis.\n\t *\n\t * @param waitPeriodInMillis\n\t *            the new wait period in millis\n\t */\n\tpublic void setWaitPeriodInMillis(int waitPeriodInMillis) {\n\t\tthis.waitPeriodInMillis = waitPeriodInMillis;\n\t}\n\n\t/*\n\t * (non-Javadoc)\n\t * \n\t * @see com.synerzip.testframework.action.BaseAction#execute()\n\t */\n\t@Override\n\tpublic void execute() throws ActionFailedException {\n\t\tWebDriver webDriver = testDriver.getWebDriver();\n\t\tWebSelector webSelector = testDriver.getWebSelector();\n\t\t\n\t\tBy by = webSelector.getBySelector(selector);\n\t\t\n\t\tWebDriverWait wait = new WebDriverWait(webDriver, waitPeriodInMillis/1000);\n\t\twait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));\n\t\t\n\t\tWebElement webElement = webDriver.findElement(by);\n\t\tassertNotNull(errorMessage, webElement);\n\t\twebElement.sendKeys(text);\n\t}\n\n\t\n\n\t/*\n\t * (non-Javadoc)\n\t * \n\t * @see\n\t * com.synerzip.testframework.action.BaseAction#resolvePlaceHolders(java.util.Map)\n\t */\n\t@Override\n\tpublic void resolvePlaceHolders(Map\u003cString, String\u003e dictionary) {\n\t\tfor (String key : dictionary.keySet()) {\n\t\t\ttext = text.replace(\"{{\" + key + \"}}\", dictionary.get(key));\n\t\t\tselector = selector.replace(\"{{\" + key + \"}}\", dictionary.get(key));\n\t\t}\n\n\t}\n\n\t/* (non-Javadoc)\n\t * @see java.lang.Object#toString()\n\t */\n\t@Override\n\tpublic String toString() {\n\t\treturn \"TypeInWebElementAction [selector=\" + selector + \", text=\"\n\t\t\t\t+ text + \", errorMessage=\" + errorMessage\n\t\t\t\t+ \", waitPeriodInMillis=\" + waitPeriodInMillis + \", name=\"\n\t\t\t\t+ name + \", type=\" + type + \"]\";\n\t}\n\t\n\t\n\n}\n\n```\n\n\nJson Deserilization Class which converts the Step.json into List\u003cBaseAction\u003e\n\n```\n@Component\npublic class ActionDeserializer implements JsonDeserializer\u003cList\u003cBaseAction\u003e\u003e {\n\n\t/** The map. */\n\tprivate static Map\u003cString, Class\u003e map = new TreeMap\u003cString, Class\u003e();\n\n\t\n\tstatic {\n\n\t\tmap.put(\"ClickImageAction\", ClickImageAction.class);\n\t\tmap.put(\"TypeInImageAction\", TypeInImageAction.class);\n\t\tmap.put(\"VerifyImageAction\", VerifyImageAction.class);\n\t\tmap.put(\"OpenUrlAction\", OpenUrlAction.class);\n\t\tmap.put(\"BrowserForegroundAction\", BrowserForegroundAction.class);\n\t\tmap.put(\"ClickWebElementAction\", ClickWebElementAction.class);\n\t\tmap.put(\"TypeInWebElementAction\", TypeInWebElementAction.class);\n\t\tmap.put(\"VerifyWebElementAction\", VerifyWebElementAction.class);\n\t\t\n\t}\n\n\t/** The test driver. */\n\t@Autowired\n\tprotected TestDriver testDriver;\n\t\n\t/** The content mgr. */\n\t@Autowired\n\tprotected ContentManager contentMgr;\n\t\n\t/** The context. */\n\t@Autowired\n\tprotected Context context;\n\t/*\n\t * (non-Javadoc)\n\t * \n\t * @see\n\t * com.google.gson.JsonDeserializer#deserialize(com.google.gson.JsonElement,\n\t * java.lang.reflect.Type, com.google.gson.JsonDeserializationContext)\n\t */\n\tpublic List\u003cBaseAction\u003e deserialize(JsonElement json, Type typeOfT,\n\t\t\tJsonDeserializationContext jsonContext) throws JsonParseException {\n\n\t\tList\u003cBaseAction\u003e list = new ArrayList\u003cBaseAction\u003e();\n\t\tJsonArray ja = json.getAsJsonArray();\n\n\t\tfor (JsonElement je : ja) {\n\n\t\t\tString type = je.getAsJsonObject().get(\"type\").getAsString();\n\t\t\tClass\u003cBaseAction\u003e c = map.get(type);\n\t\t\tif (c == null)\n\t\t\t\tthrow new RuntimeException(\"Unknow class: \" + type);\n\t\t\tBaseAction action = ((BaseAction)jsonContext.deserialize(je, c));\n\t\t\t\n\t\t\t//Manually Inject the contentManager, context and testDriver\n\t\t\taction.setContentMgr(this.contentMgr);\n\t\t\taction.setContext(this.context);\n\t\t\taction.setTestDriver(this.testDriver);\n\t\t\t\n\n\t\t\t\n\t\t\tlist.add(action);\n\t\t}\n\n\t\treturn list;\n\n\t}\n\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frohitghatol%2Fcucumber-sikuli-selenium-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frohitghatol%2Fcucumber-sikuli-selenium-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frohitghatol%2Fcucumber-sikuli-selenium-framework/lists"}