{"id":22316836,"url":"https://github.com/ajeydudhe/facile-ui-test","last_synced_at":"2026-04-10T01:03:28.333Z","repository":{"id":42547008,"uuid":"216199010","full_name":"ajeydudhe/facile-ui-test","owner":"ajeydudhe","description":"facile-ui-test can be used to write UI tests especially for Spring MVC projects. It uses BrowserMobProxy to complete the http request flow from the UI test =\u003e browser =\u003e http proxy =\u003e MockMvc =\u003e UI test. Additionally, you can use Mockito to define the mock http responses.","archived":false,"fork":false,"pushed_at":"2022-12-16T05:08:06.000Z","size":196,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-31T02:01:39.444Z","etag":null,"topics":["chrome","havascript","headless","html","selenium","spring","testing","ui"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ajeydudhe.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":"2019-10-19T11:57:06.000Z","updated_at":"2024-09-04T08:10:01.000Z","dependencies_parsed_at":"2023-01-29T09:46:03.460Z","dependency_job_id":null,"html_url":"https://github.com/ajeydudhe/facile-ui-test","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajeydudhe%2Ffacile-ui-test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajeydudhe%2Ffacile-ui-test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajeydudhe%2Ffacile-ui-test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajeydudhe%2Ffacile-ui-test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ajeydudhe","download_url":"https://codeload.github.com/ajeydudhe/facile-ui-test/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245581781,"owners_count":20639040,"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":["chrome","havascript","headless","html","selenium","spring","testing","ui"],"created_at":"2024-12-03T23:08:00.040Z","updated_at":"2025-12-30T22:49:35.362Z","avatar_url":"https://github.com/ajeydudhe.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/ajeydudhe/facile-ui-test.svg?branch=master)](https://travis-ci.org/ajeydudhe/facile-ui-test) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n# facile-ui-test - Library to test UI with mock http responses.\n**facile-ui-test** can be used to write UI tests especially for Spring MVC projects. It uses [**BrowserMobProxy**](https://github.com/lightbody/browsermob-proxy) to complete the http request flow from the UI test =\u003e browser =\u003e http proxy =\u003e [**MockMvc**](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-mvc-test-framework) =\u003e UI test. Additionally, you can use [**Mockito**](https://site.mockito.org/) to define the mock http responses.\n\u003cbr/\u003e\u003cbr/\u003e\n![Workflow](facile-ui-test.png)\n\n## Adding the library reference\nAdd the maven dependency to your pom.xml as follows:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.expedientframework.uitest\u003c/groupId\u003e\n    \u003cartifactId\u003efacile-ui-test\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0-M2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Usage for Spring MVC project\n### Pre-requisite\nMake sure that [**MockMvc**](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-mvc-test-framework) setup is complete. \nRefer [**AbstractPageTest.java**](/samples/spring-boot-web/src/test/java/org/expedientframework/uitest/AbstractPageTest.java)\n### Create [**UiTestContext**](/core/src/main/java/org/expedientframework/uitest/core/UiTestContext.java)\n```java\nthis.uiTestContext = new UiTestContext(this.mockMvc, \"/myapp\");\n```\n### Create WebDriver instance\nUse the _**UiTestContext.getProxyPort()**_ method to set the proxy for the WebDriver as below:\n```java\nprotected void createWebDriver(final UiTestContext uiTestContext) {\n  \n  if(this.webDriver != null) {\n   \n    this.webDriver.close();\n  }\n  \n  final ChromeOptions chromeOptions = new ChromeOptions();\n  \n  chromeOptions.setHeadless(true);    \n  \n  final String proxyAddress = \"localhost:\" + uiTestContext.getProxyPort();\n  final Proxy proxy = new Proxy().setHttpProxy(proxyAddress).setSslProxy(proxyAddress);   \n  \n  chromeOptions.setProxy(proxy);\n  // Required to use proxy for localhost address\n  chromeOptions.addArguments(\"--proxy-bypass-list=\" + \"\u003c-loopback\u003e\");    \n  \n  this.webDriver = new ChromeDriver(chromeOptions);\n}\n```\n**Note:** Make sure to add _**--proxy-bypass-list=\u003c-loopback\u003e**_ argument so that the _**localhost**_ address is proxied.\n\n### Mock the MVC controllers or other beans\nIn your test configuration create a bean for [_**MockInstanceBeanFactoryPostProcessor**_](/core/src/main/java/org/expedientframework/uitest/core/beans/MockInstanceBeanFactoryPostProcessor.java) as follows:\n```java\n@Configuration\npublic class TestConfiguration {\n\n  @Bean\n  public MockInstanceBeanFactoryPostProcessor mockInstanceBeanFactoryPostProcessor() {\n    \n    return new MockInstanceBeanFactoryPostProcessor(HelloWorldController.class, \n                                                    StudentController.class);\n  }\n}\n```\nIn the constructor for the bean provide the list of MVC controller or other bean classes which needs to be mocked. If your MVC controller to be mocked has other dependencies which needs to be mocked then provide those also here. Inject the mocked MVC controllers or other beans into your tests.\n### Writing a test with mocked http response\n```java\n@Test\npublic void greet_usingUiTestContext_succeeds() {\n  \n  try (UiTestContext uiTestContext = new UiTestContext(this.mockMvc)) {\n\n    // Using Mockitto we mock the response at the controller class level\n    when(helloWorldController.greet(\"John\")).thenReturn(\"Hello 'Blah' Dummy !!!\");\n    \n    // Hook into http  request\n    createWebDriver(uiTestContext.getProxyPort());\n    \n    this.webDriver.get(\"http://localhost/hello/greet/John\");\n\n    // Finally checking the response is mocked one\n    assertThat(this.webDriver.getPageSource()).as(\"Hello message\").isEqualTo(\"\u003chtml\u003e\u003chead\u003e\u003c/head\u003e\u003cbody\u003eHello 'Blah' Dummy !!!\u003c/body\u003e\u003c/html\u003e\");    \n  }    \n}\n```\n* First we are creating the _**UiTestContext**_ instance.\n* Next using _**Mockito**_ we define that _**helloWorldController.greet()**_ when called with parameter as _**John**_ should return value as _**\"Hello 'Blah' Dummy !!!\"**_.\n* Next we are creating the _**WebDriver**_ instance using the http proxy port.\n* Then we load the web page using _**this.webDriver.get(\"http://localhost/hello/greet/John\");**_\n* Finally, we verify that we are getting the mock response.\n\nAs seen above the entire web page is getting loaded as is in the browser but only the http response is getting mocked using _**Mockito**_.\n\n## Usage for non-Spring MVC project e.g. ExpressJS\nAbove example suffices when you have the Spring MVC project. But what if you have created a web application using, say, ExpressJS. For such project you can create a separate Java project for writing the test. Refer _**/samples⁩/external-server/⁨expressjs-tests⁩**_.\nHere, the setup is similar to above except that we need to:\n* Start the external web server in another project.\n* Mock only the required http calls while other calls should go to the server.\n### Sample test case\nFollowing is a sample test case [**StudentDetailsPageTestIT**](/samples/external-server/expressjs-tests/src/test/java/org/expedientframework/uitest/StudentDetailsPageTestIT.java)\n```java\n@ContextConfiguration(classes = TestConfiguration.class)\npublic class StudentDetailsPageTestIT extends AbstractTestNGSpringContextTests {\n  \n  @Test\n  public void getStudentByID_studentExists_displaysDetails() {\n    \n    final MockMvc mockMvc = MockMvcBuilders.standaloneSetup(this.studentController).build();\n\n    WebDriver webDriver = null;\n    try(UiTestContext uiTestContext = new UiTestContext(mockMvc)) {\n      \n      uiTestContext.shouldMock((method, url, headers) -\u003e url.contains(\"/api/\"));\n      \n      webDriver = createWebDriver(uiTestContext.getProxyPort());\n      \n      final String studentId = \"MyStudent\" + UUID.randomUUID().toString();\n      final Student mockedStudent = createStudent(\"Mocked-\" + UUID.randomUUID().toString());\n      \n      when(studentController.student(studentId)).thenReturn(mockedStudent);\n      \n      webDriver.get(\"http://localhost:8080/students/\" + studentId);\n      \n      TestUtils.waitForAjaxCalls(webDriver);\n      \n      final StudentDetailsPage studentPage = PageFactory.initElements(webDriver, StudentDetailsPage.class);\n      \n      LOG.info(\"Page Source: {}{}\", System.getProperty(\"line.separator\"), webDriver.getPageSource());\n      \n      // Welcome message is not mocked so should be as per stidentID passed.\n      assertThat(studentPage.getWelcomeMessage()).as(\"Welcome Message\").isEqualTo(\"Welcome \" + studentId);\n      \n      // Below all is mocked so should match mockedStudent\n      assertThat(studentPage.getStudentId()).as(\"Student ID\").isEqualTo(mockedStudent.getStudentId());\n      assertThat(studentPage.getFirstName()).as(\"First Name\").isEqualTo(mockedStudent.getFirstName());\n      assertThat(studentPage.getLastName()).as(\"Last Name\").isEqualTo(mockedStudent.getLastName());\n      assertThat(studentPage.getAge()).as(\"Age\").isEqualTo(mockedStudent.getAge());\n    } finally {\n      \n      if(webDriver != null) {\n        \n        webDriver.close();\n      }\n    }\n  }\n  \n  //... Few line omitted...\n  \n  private static Student createStudent(final String studentId) {\n    \n    final Student student = new Student();\n    \n    student.setStudentId(studentId);\n    student.setFirstName(studentId + \"-firstName\");\n    student.setLastName(studentId + \"-lastName\");\n    student.setAge(12);\n    \n    return student;\n  }\n   \n  @Autowired\n  private StudentController studentController;\n  private static final Logger LOG = LoggerFactory.getLogger(StudentDetailsPageTestIT.class);\n}\n```\n* The _**@ContextConfiguration(classes = TestConfiguration.class)**_ on the test class is used to initialized the mock controllers as mentioned in [Mock the MVC controllers or other beans](#mock-the-mvc-controllers-or-other-beans)\n* At the start of the test we create the **MockMvc** instance using the MVC controller we are going to mock.\n    ```java\n    final MockMvc mockMvc = MockMvcBuilders.standaloneSetup(this.studentController).build();\n    ```\n* We create the _**UiTestContext**_ instance and define that only the urls containing _**/api/**_ needs to be mocked.\n  ```java\n  uiTestContext.shouldMock((method, url, headers) -\u003e url.contains(\"/api/\"));\n  ```\n* We then create and initialize the **webDriver** instance as mentioned in [**Create WebDriver instance**](#create-webdriver-instance)\n  ```java\n  webDriver = createWebDriver(uiTestContext.getProxyPort());\n  ```\n* In our sample app. we request a student details passing in the student id in url and on page load make a REST call to fetch the student details.\n* For our test we are going to load this page and mock the REST call to return mocked data.\n* Below we use random studenId value and also a random mocked student object.\n  ```java\n  final String studentId = \"MyStudent\" + UUID.randomUUID().toString();\n  final Student mockedStudent = createStudent(\"Mocked-\" + UUID.randomUUID().toString());\n  ```\n* We define the mock behavior as below. It implies that we should return the _**mockedStudent**_ instance when the controller methods is called.\n  ```java\n  when(studentController.student(studentId)).thenReturn(mockedStudent);\n  ``` \n* Now, we load the web page using _**webDriver**_.\n  ```java\n  webDriver.get(\"http://localhost:8080/students/\" + studentId);\n  ```\n* Once loaded we get the Page object.\n* Now, we start the validation.\n* First on the web page there is a message for the student as \"Welcome \u0026lt;studentId\u003e\".\n* We validate that this message is formed using the studentId passed in the page url.\n  ```java\n  assertThat(studentPage.getWelcomeMessage()).as(\"Welcome Message\").isEqualTo(\"Welcome \" + studentId);      \n  ```\n* Now, below is the validation to make sure the REST request returned the _**mockedStudent**_ instance which has different studentId than the one we used in loading the page. The values on the page are retrieved using [**StudentDetailsPage**](/samples/external-server/expressjs-tests/src/test/java/org/expedientframework/uitest/StudentDetailsPage.java).\n  ```java\n  assertThat(studentPage.getStudentId()).as(\"Student ID\").isEqualTo(mockedStudent.getStudentId());\n  assertThat(studentPage.getFirstName()).as(\"First Name\").isEqualTo(mockedStudent.getFirstName());\n  assertThat(studentPage.getLastName()).as(\"Last Name\").isEqualTo(mockedStudent.getLastName());\n  assertThat(studentPage.getAge()).as(\"Age\").isEqualTo(mockedStudent.getAge());\n  ```\n\n## Open items\n* Handle all request types e.g. form upload etc.   ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajeydudhe%2Ffacile-ui-test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fajeydudhe%2Ffacile-ui-test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajeydudhe%2Ffacile-ui-test/lists"}