{"id":31040192,"url":"https://github.com/mariodavid/sneferu","last_synced_at":"2025-09-14T08:13:36.421Z","repository":{"id":43891805,"uuid":"232762396","full_name":"mariodavid/sneferu","owner":"mariodavid","description":"CUBA Platform Web Integration Testing Library","archived":false,"fork":false,"pushed_at":"2022-02-14T07:00:01.000Z","size":2809,"stargazers_count":3,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-21T19:46:55.678Z","etag":null,"topics":["cuba","cuba-platform","integration-testing"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mariodavid.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-01-09T08:42:19.000Z","updated_at":"2024-04-21T19:46:55.679Z","dependencies_parsed_at":"2022-09-16T04:11:30.337Z","dependency_job_id":null,"html_url":"https://github.com/mariodavid/sneferu","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/mariodavid/sneferu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariodavid%2Fsneferu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariodavid%2Fsneferu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariodavid%2Fsneferu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariodavid%2Fsneferu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mariodavid","download_url":"https://codeload.github.com/mariodavid/sneferu/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mariodavid%2Fsneferu/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275076618,"owners_count":25401322,"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","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cuba","cuba-platform","integration-testing"],"created_at":"2025-09-14T08:13:35.376Z","updated_at":"2025-09-14T08:13:36.407Z","avatar_url":"https://github.com/mariodavid.png","language":"Java","readme":"[![Build Status](https://travis-ci.com/mariodavid/sneferu.svg?branch=master)](https://travis-ci.com/mariodavid/sneferu)\n[ ![Download](https://api.bintray.com/packages/mariodavid/cuba-components/sneferu/images/download.svg) ](https://bintray.com/mariodavid/cuba-components/sneferu/_latestVersion)\n[![license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)\n\n\n## Sneferu\n\nSneferu is a testing library to simplify web integration testing for a CUBA application.\nIt consists of a couple of APIs that allow you to express interactions and verifications with UI screens via a dedicated high-level testing language. \n\n\n### Overview\n\nInstead of spending too much time and money maintaining a selenium test suite, Sneferu is the way \nto have very good test coverage and quality assurance at a fraction of the cost.\n\nVia its easy to read language you can create integration tests that are optimized for readability,\nbecause this is what matters most for keeping a test suite maintainable \u0026 cheap to operate.\n\nSneferu enables you to:\n \n* verify any business logic in a Screen Controller\n* ensure the correct linking between a Screen XML and its Controller counterpart\n* verify correct display of any programmatic creation of Screen Components / Dialogs\n* emulate \u0026 verify data loading  \n* emulate \u0026 verify Service Interface interactions\n\nAs Sneferu is based on the web integration test facilities of CUBA, there is a certain limitation in what areas are not covered. In particular, Sneferu relies on the abstractions provided by the CUBA and Vaadin component interfaces. It assumes that behind this interface everything \"works as expected\". \n\nWhat Sneferu _does not cover_:\n\n* End-to-End data loading and displaying on a Screen\n* End-to-End Service execution (middleware)\n* Client-Side Vaadin UI logic that is executed only in the browser\n\n#### Sneferu Landscape\n\n![Sneferu Landscape](img/sneferu-overview.png)\n\nIf you can live with those trade-offs, feel free to join the lovely world of web integration testing in CUBA expressed through a beautiful API.\n\n#### Motivation \u0026 Background\n\nTesting of a CUBA application on the web layer mainly consists of two extremes:\n\n1. write a unit test for the business logic in the screen controllers\n2. write a functional UI test that executes the application through the browser\n\nBoth of those extremes have their downsides.\n\nThe first one requires mocking out every programmatic interaction with the CUBA UI interfaces. Also, unit tests do not cover any of the screen layout definitions or the data binding of a Screen.\n\nSelenium-based UI testing, on the other hand, is much more black-box, slower, more brittle and overall harder to maintain. It can achieve a higher degree of confidence since the application behaves as it is supposed to, as it exercises the application almost as the user does. But this trade-off is a very expensive one. \n\nTo mitigate that problem, CUBA 7.1 introduced web integration testing.\n\nSneferu is taking that new addition and brings it to the next level by making it accessible and very easy to use.\n\nThe documentation shows all test cases written in Spock, but Sneferu works with different testing frameworks like JUnit as well.\n\nAn example test case in Sneferu looks like this:\n\n```java\npublic class VisitBrowseToEditTest {\n\n  @Test\n  public void aVisitCanBeCreated_whenAllFieldsAreFilled(\n      @StartScreen StandardLookupTestAPI\u003cVisit,VisitBrowse\u003e visitBrowse,\n      @SubsequentScreen StandardEditorTestAPI\u003cVisit, VisitEdit\u003e visitEdit,\n      @NewEntity Pet pikachu\n  ) {\n\n    // given:\n    pikachu.setName(\"Pikachu\");\n\n    // and:\n    visitBrowse.interact(click(button(\"createBtn\")));\n\n    // when:\n    OperationResult outcome = (OperationResult) visitEdit\n        .interact(enter(dateField(\"visitDateField\"), new Date()))\n        .interact(enter(textField(\"descriptionField\"), \"Regular Visit\"))\n        .interact(select(lookupField(\"petField\"), pikachu))\n        .andThenGet(closeEditor());\n\n    // then:\n    assertThat(outcome).isEqualTo(OperationResult.success());\n\n    // and:\n    assertThat(environment.getUiTestAPI().isActive(visitEdit))\n      .isFalse();\n\n  }\n}\n```\n\n### Getting Started\n\nTo use Sneferu, it is required to add the dependency to the CUBA project. In the `build.gradle` the following dependency has to be added to the web-module:\n\n```groovy\nconfigure(webModule) {\n    // ...\n    dependencies {\n        testCompile('de.diedavids.sneferu:sneferu:**SNEFERU-VERSION**')\n    }\n}\n```\n\nAdditionally the Maven repository `https://dl.bintray.com/mariodavid/cuba-components` has to be added to the list of available repositories of the project (`build.gradle`):\n\n```groovy\nrepositories {\n        \n        // ...\n        maven {\n            url  \"https://dl.bintray.com/mariodavid/cuba-components\"\n        }\n        // ...\n    }\n```\n| CUBA Platform Version | Add-on Version |\n| --------------------- | -------------- |\n| 7.2.x                 | 0.2.x - 0.3.x  |\n\n\nThe latest version is: [ ![Download](https://api.bintray.com/packages/mariodavid/cuba-components/sneferu/images/download.svg) ](https://bintray.com/mariodavid/cuba-components/sneferu/_latestVersion)\n\n\nSneferu can be used with JUnit as well as Spock. Just add the corresponding dependencies into your CUBA project to use it with any of those frameworks.\n\nAfterward, you can create your first web integration test:\n\n```groovy\nimport de.diedavids.sneferu.UiTestAPI\n\nimport static de.diedavids.sneferu.ComponentDescriptors.*\nimport static de.diedavids.sneferu.Interactions.*\n\n\nclass FirstSneferuSpec extends Specification {\n\n    @Shared\n    @ClassRule\n    SneferuTestUiEnvironment environment =\n            new SneferuTestUiEnvironment(TestImprovementsWebTestContainer.Common.INSTANCE)\n                    .withScreenPackages(\n                            \"com.haulmont.cuba.web.app.main\",\n                            \"com.rtcab.ddceti.web.screens.customer\"\n                    )\n                    .withUserLogin(\"admin\")\n                    .withMainScreen(MainScreen)\n\n\n    def \"click a button, open a screen, enter some values and close the screen\"() {\n\n        given:\n        def customerBrowse = environment.uiTestAPI.openStandardLookup(Customer, CustomerBrowse)\n\n        when:\n        customerBrowse\n                .interact(click(button(\"createBtn\")))\n\n        and:\n        environment.uiTestAPI.getOpenedEditorScreen(CustomerEdit)\n                .interact(enter(textField(\"nameField\"), \"Bob Ross\"))\n                .andThenGet(closeEditor())\n\n        then:\n        environment.uiTestAPI.isActive(customerBrowse)\n    }\n}\n```\n\nInstead of using `com.haulmont.cuba.web.testsupport.TestUiEnvironment` a Sneferu-specific environment is used: `de.diedavids.sneferu.environment.SneferuTestUiEnvironment`\n\nThis environment-class has an additional parameter, that needs to be provided: `withMainScreen()`, where the Main Screen of the application is configured.\n\n### Example Usage\n\nA dedicated example of using Sneferu is shown via the CUBA Petclinic sample application: [cuba-platform/cuba-petclinic-using-sneferu](https://github.com/cuba-platform/cuba-petclinic-using-sneferu).\n\nIt contains a lot of example test cases that show the various usage options of Sneferu.\n\n\n### Documentation\n\nThe different concepts when using Sneferu are described below. It mainly consists of the following:\n\n1. `UiTestAPI`\n2. `ScreenTestAPI` \u0026 `ScreenObject`\n3. `ComponentTestAPI`\n4. `Interactions`\n\nLet's go through them one by one.\n\n### UI Test API\n\nThe UI Test API is the interaction point in the test case that manages screens. The API allows the developer to open/close screens and retrieve information about the opened screens. It can be accessed through the `environment` instance via its method `getUiTestAPI()`. An example of its usage looks like this:\n\n```groovy\ndef \"UI Test API usage\"() {\n\n    given: 'a screen can be opened by the test case'\n    def customerBrowse = environment.uiTestAPI\n                            .openStandardLookup(Customer, CustomerBrowse)\n                            \n    and: 'a automatically opened screen can be retrieved'\n    def customerEdit = environment.uiTestAPI\n                        .getOpenedEditorScreen(CustomerEdit)\n\n    then: 'information about active state of a screen can be retrieved'\n    uiTestAPI.isActive(customerEdit)\n}\n```\n\n\n#### JUnit 5 Screen Test Injection\n\nWhen using JUnit, instead of imperatively interact with the `UiTestAPI`, it is also possible to directly inject the screens to the test, that the test should work upon.\n\nAn example looks like this:\n\n```java\nclass JUnit5TestInjection {\n\n  @Test\n  public void a_screen_can_be_injected_to_directly_work_with_the_screens(\n      @StartScreen StandardLookupTestAPI\u003cVisit,VisitBrowse\u003e visitBrowse,\n      @SubsequentScreen StandardEditorTestAPI\u003cVisit, VisitEdit\u003e visitEdit\n  ) {\n\n    visitBrowse\n        .interact(click(button(\"createBtn\")));\n    \n    visitEdit\n        .interact(enter(dateField(\"visitDateField\"), new Date()));\n    \n    // ...\n\n  }\n\n}\n```\n\nIn this case, the test case just expresses its dependencies for the screens that should be used. There are two variants to it:\n\n* `@StartScreen` is used when a screen that needs to be started on should be injected. In case the screen is not already open in the application, it is not possible to inject it\n* `@SubsequentScreen` is used when a screen should be injected in the test but is currently not already opened. In this case, the screen fetching from the application is postponed until the first interaction  \n\n### Screen Test API\n\nThe next concept of Sneferu allows you to interact with a particular Screen and is called `ScreenTestAPI`. It consists of two main use-cases:\n\n1. apply interactions (see [Interactions](#Interactions)) on a particular screen\n2. retrieve components of a screen to interact with those through its [Component Test API](#Component-Test-API)\n\nTo interact with the `ScreenTestAPI` an instance of that must be retrieved via the `UiTestAPI` as described above. Once those instances are available (`customerBrowse` and `customerWithTabsEdit` in the following example), the API can be used to interact with a Screen via its Test API directly in the test case.\n\nA usage example looks like this:\n\n```groovy\ndef \"Screen Test API usage\"() {\n\n    when: 'interactions are applied for a particular screen'\n    customerBrowse\n             .interact(click(button(\"createBtn\")))\n\n    and: 'components can be retrieved for further reference'\n    customerWithTabsEdit\n             .component(dateField(\"birthdayField\"))\n             .enter(today)\n}\n```\n\nMore information on what Interactions are and how they can be used can be found in the corresponding [Interactions](#Interactions) section.\n\nThe following classes exists for the `ScreenTestAPI`, that should be used based on the screen you interact with:\n\n* `StandardScreenTestAPI` for all Screens that directly extend `Screen`\n* `StandardLookupTestAPI` for all Screens that extend `StandardLookup`\n* `StandardEditorTestAPI` for all Screens that extend `StandardEditor`\n\n### Screen Objects\n\nAn extension of the ScreenTestAPI is the concept of a Screen Object.\n\nInstead of using the API directly through the TestScreenAPI, it is also possible to create a [Screen Object](https://martinfowler.com/bliki/PageObject.html) that represents the API of a particular Screen of the UI. This allows creating a dedicated abstraction between the test case and the screen that is under test.\n\n##### Definition of a Screen Object (CustomerBrowseScreenObject)\n\nTo create a ScreenObject, a class needs to be created representing one screen (in this case `CustomerBrowse`). It furthermore needs to implement the interface `ScreenObject\u003cT extends ScreenTestAPI\u003e`. \n\n```java\npublic class CustomerBrowseScreenObject implements \n    ScreenObject\u003cStandardLookupTestAPI\u003cCustomer, CustomerBrowse\u003e\u003e {\n\n    private StandardLookupTestAPI\u003cCustomer, CustomerBrowse\u003e delegate;\n    private final TestUiEnvironment testUiEnvironment;\n\n    // ...\n\n    public CustomerBrowseScreenObject searchForCustomer(Customer customer) {\n        delegate\n                .component(suggestionField(\"quickSearch\"))\n                .search(customer);\n\n        return this;\n    }\n\n    public CustomerBrowseScreenObject searchForCustomer(String customerName) {\n\n        Metadata metadata = testUiEnvironment.getContainer().getBean(Metadata.class);\n\n        Customer customer = metadata.create(Customer.class);\n        customer.setName(customerName);\n\n        return searchForCustomer(customer);\n    }\n\n    public boolean isActive() {\n        return testUiEnvironment.getUiTestAPI().isActive(delegate);\n    }\n\n}\n```\n\nWith the above definition it is now possible to use this higher level abstraction in the different test cases:\n\n##### Test Case with Screen Object\n\nThe shown test case is using the API of the ScreenObject, which consists of:\n\n* `void searchForCustomer(String customerName)`\n* `void searchForCustomer(Customer customer)`\n* `boolean isActive()`\n\n```groovy\ndef \"screens can be used through its Screen Object Test API\"() {\n\n    given: \"a screen object can be created using a factory method\"\n    def customerBrowseScreenObject = CustomerBrowseScreenObject.of(\n            environment\n    )\n\n    and:\n    customerBrowseScreenObject\n            .searchForCustomer(\"Bob Ross\")\n\n    and: \"a screen object can also be created via its constructor\"\n    def customerEditScreenObject = new CustomerEditScreenObject(\n            uiTestAPI.getOpenedEditorScreen(CustomerEdit),\n            environment\n    )\n\n    when:\n    customerEditScreenObject\n            .changeNameTo(\"Meggy Simpson\")\n\n\n    then:\n    customerEditScreenObject\n        .isClosed()\n\n    and:\n    customerBrowseScreenObject\n        .isActive()\n}\n```\n\nThis variant allows having a higher abstraction in the test case. It also decouples the test cases from the API of the Screen itself.\n\n### Component Test API\n\nThe next concept of Sneferu is the Component Test API. This API is the same thing for a `Component` as the `ScreenTestAPI` is for a CUBA Screen. It is an abstraction on top of the CUBA `Component` APIs that is designed in the context of testing.\n\nTo use an instance of a Component Test API, it has to be created in the test case (or the Screen Object) via its factory method:\n\n````groovy\nimport static de.diedavids.sneferu.ComponentDescriptors.*\n\n// ...\n\ncustomerBrowse\n             .component(suggestionField(\"customerSearchField\"))\n             .search(\"Bob Ross\")\n````\n\n`suggestionField` is a factory method that is statically imported from the `ComponentDescriptors` class. The parameter `customerSearchField` is the ID of the field used in the Screen XML descriptor.\n\nIt returns an instance of a subclass of `ComponentDescriptor`. In this case, it returns an instance of `SuggestionFieldComponentDescriptor` which is aware of the specifics of this component (like searching the value via its `search` method).\n\n\n#### Support custom components\n\nSneferu currently does not support all the components of CUBA. Furthermore, if you use application-specific components or composite components, Sneferu also can not support them out-of-the-box.\n\nTherefore, it is possible to create custom Component Descriptors, that represent the component in the testing scenario.\n\nTo support a new component, first a subclass of `ComponentTestAPI` needs to be created:\n\n```java\npublic class SliderTestAPI extends GenericComponentTestAPI\u003cSlider\u003e {\n    public SliderTestAPI(Slider component) {\n        super(component);\n    }\n\n    public SliderTestAPI slideTo(int value) {\n        rawComponent().setValue(value);\n        return this;\n    }\n}\n```\n\nWith that component-specific Test API in place, a `ComponentDescriptor` can be created that is responsible for this `SliderTestAPI`:\n\n```java\npublic class SliderComponentDescriptor\n        extends GenericComponentDescriptor\u003cSlider, SliderTestAPI\u003e {\n\n    public SliderComponentDescriptor(String componentId) {\n        super(Slider.class, componentId);\n    }\n\n    @Override\n    public SliderTestAPI createTestAPI(Slider component) {\n        return new SliderTestAPI(component);\n    }\n}\n```\n\nThe last step is to create a factory method that creates a new `SliderComponentDescriptor`:\n\n```java\npublic class ApplicationComponentDescriptors {\n\n    /**\n     * creates a SliderComponentDescriptor instance\n     * @param id the id of the component as defined in the screen XMl descriptor\n     * @return a SliderComponentDescriptor instance\n     */\n    public static SliderComponentDescriptor slider(String id) {\n        return new SliderComponentDescriptor(id);\n    }\n}\n```\n\nWith those three steps, the custom component like the `Slider` in this example can be supported in the integration tests of the application.\n\n### Interactions\n\nThe last remaining concept of Sneferu is the Interactions APIs. Interactions are what bring the screens to life. An interaction reflects any action a user would normally do manually to trigger some behavior or validate some result.\n\nAn interaction usage looks like this:\n\n```groovy\nimport static de.diedavids.sneferu.ComponentDescriptors.button\nimport static de.diedavids.sneferu.Interactions.click\n\ndef \"Interaction Usage\"() {\n\n    given:\n    def customerBrowse = environment.uiTestAPI\n                            .openStandardLookup(Customer, CustomerBrowse)\n\n    when: 'using the click interaction'\n        customerBrowse\n                .interact(\n                        /* the click interaction */\n                        click( \n                            /* the target of the click interaction */\n                            button(\"createBtn\")\n                        )\n                )\n}\n```\n\nAn interaction invokes a `ScreenTestAPI` instance (like the `customerBrowse` instance in this case). Then it normally gets a target to act upon via a parameter (like the Component Descriptor `button(\"createBtn\")` instance).\n\nThe Interaction then goes ahead and performs the desired action upon the target component.\n\nAll interactions can be created via its Factory: `de.diedavids.sneferu.Interactions`. Normally, from a readability point of view, it once again makes sense to use static imports for them:\n\n`import static de.diedavids.sneferu.Interactions.*`\n\nThere are two types of Interactions:\n\n#### Chainable Interactions \nChainable interactions are interactions that can be combined via the `ScreenTestAPI` and with that represent a list of steps that should be executed against a Screen.\n\nThose interactions do not have an outcome that can be retrieved programmatically in the test case. Examples of that are `click`, `select`, `openTab` etc.\n\nThe Screen Test API is a fluent API that allows you to chain interactions:\n\n```groovy\ndef \"Interactions can be chained\"() {\n    when:\n    customerWithTabsEdit\n             .interact(openTab(tabSheet(\"contentTabSheet\"), \"ordersTab\"))\n             .andThen(select(lookupField(\"orderType\"), OrderType.BIG))\n}\n```\nThere are several alias methods, that can be used to underline the readability:\n\n* `interact(Interaction interaction)`\n* `andThen(Interaction interaction)`\n\n#### Terminating Interactions\n\nTerminating Interactions, on the other hand, return a value. By returning that value the chain of interactions is closed. An example of that is `closeEditor`. This interaction does two things:\n\n1. closing the editor;\n2. returning the `OperationResult` object to the test case that is received from the StandardEditor instance.\n\nIn the test case the result can be retrieved and used for verification purposes:\n\n```groovy\nwhen:\nOperationResult result = customerEdit\n        .interact(enter(textField(\"nameField\"), \"Bob Ross\"))\n        .andThenGet(closeEditor())\n\nthen:\nresult == OperationResult.success()\n```\n\nTerminating Interactions can be invoked via one of the following alias methods in the `ScreenTestAPI`:\n\n* `verify(InteractionWithOutcome interaction)`\n* `get(InteractionWithOutcome interaction)`\n* `interactAndGet(InteractionWithOutcome interaction)`\n* `andThenGet(InteractionWithOutcome interaction)`\n* `andThenVerify(InteractionWithOutcome interaction)`\n\n#### Using different Interactions\n\nHere is an example of how to use the two different types of interactions in a test case:\n\n```groovy\nimport static de.diedavids.sneferu.ComponentDescriptors.*\nimport static de.diedavids.sneferu.Interactions.*\n\ndef \"Chainable Interactions can be combined to perform a series of steps\"() {\n\n    when: 'an order is placed from a customer editor screen'\n    OperationResult operationResult = \n    \n         customerWithTabsEdit\n\n             /* start of an interaction chain */\n             .interact(openTab(tabSheet(\"contentTabSheet\"), \"ordersTab\"))\n             /* next interaction: select */\n             .andThen(select(lookupField(\"orderType\"), OrderType.BIG))\n             /* next interaction: click */\n             .andThen(click(button(\"placeOrderBtn\")))\n        \n             /* terminating interaction: closeEditor */\n             .andThenGet(closeEditor())\n}\n```\n\n#### Custom Interactions\n\nIt is possible to define a custom Interaction that is not included in the Sneferu library (yet).\n\nTaking the Slider example from above: the first step is to create a class defining the Interaction:\n\n```java\nimport de.diedavids.sneferu.Interaction;\nimport de.diedavids.sneferu.screen.ScreenTestAPI;\n\npublic class SlideInteraction implements Interaction\u003cScreenTestAPI\u003e {\n\n    private final int value;\n    private final SliderComponentDescriptor componentDescriptor;\n\n    public SlideInteraction(SliderComponentDescriptor sliderComponentDescriptor, int value) {\n        this.componentDescriptor = sliderComponentDescriptor;\n        this.value = value;\n    }\n\n    @Override\n    public void execute(ScreenTestAPI screenTestAPI) {\n        ((Slider)screenTestAPI.component(componentDescriptor)\n                .rawComponent())\n                .setValue(value);\n    }\n}\n```\n\nAfter that, the second optional step is to define a factory method that instantiates a new `SlideInteraction` so that it can be easily used in the test case.\n\n```java\npublic class ApplicationInteractions {\n\n    public static \u003cC extends Component, F extends ComponentTestAPI\u003cC\u003e\u003e SlideInteraction slide(\n            ComponentDescriptor\u003cC, F\u003e componentDescriptor,\n            Object value\n    ) {\n        return new SlideInteraction(componentDescriptor, value);\n    }\n}\n```\n\n\nWith that it is possible to use it directly in a test case:\n\n```groovy\nimport static ApplicationInteractions.slide\nimport static ApplicationComponentDescriptors.slider\n\ndef \"a slider component can be used through its custom interaction\"() {\n\n    when: 'an order is placed from a customer editor screen'\n         customerEditor\n             .interact(slide(slider(\"ageSlider\"), 24))\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariodavid%2Fsneferu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmariodavid%2Fsneferu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmariodavid%2Fsneferu/lists"}