Skip to content

Module : Tzatziki front

Alexandre Patelli edited this page Mar 26, 2024 · 5 revisions
  • Proposed In Progress
  • Prototype: In Progress
  • Implementation: Not Started
  • Specification: Not Started

Summary

This new tzatziki module will bring the ability to easily setup front components testing.
It will provide tools and Gherkin to navigate and assert on web pages.
The approach is to create an agnostic front module with multiple submodules implementations (Playwright, selenium...)
So the user can switch from an implementation to another without changing anything.

Motivation

Today we are aware of multiples projects that are using tzatziki to test front apps.
The implementation is made directly in the app and is not really optimal with a lot of code duplication.
The goal of the feature is to provide an easy tzatziki module to replace those custom codes and gather our efforts.

Detailed design

Modules

tzatziki-front

This root module defined 3 important interfaces that will be used to interact with front components :

Browser
Interface that expose method to manipulate the browser

  • get(url) : navigate to the provided url
  • find(cssSelector) : return a list of HTMLElement from the css selectors
  • actionOn(cssSelector, action , params) : perform specified action on list of HTMLElement that match the css selector
  • waitForElement(cssSelector, isVisible) : wait until this cssSelector is available on page (and visible if needed)
  • waitForUrl(url) : wait until the browser is redirected to this url
  • reload() : reload page with current url

We can notice that we can add a timeout parameter on a lof of those methods with default value.
cssSelector accept CSS or XPath format

Keyboard press ? waitForPopup ?

HTMLElement
Interface that expose method to manipulate HTMLElement

  • getId() : return id of the html element
  • getClasses() : return classes of the html element
  • getAttributes() : return a Map of the attributes of the html element

Action
Enum of actions that can be made on an HTMLElement

  • CLICK
  • FILL

Submodule tzatziki-playwright

As a first implementation, we suggest Playwright because it is already uses on tzatziki users projects. This implementation will implements all the interfaces defined just above with Playwright engine.

Gherkin steps

Navigate to an url with the possibility to wait for an element

browser navigate to 'url' (waiting 'cssSelector' (visible))

Perform an action (CLICK, FILL...) with optional parameters on one or multiple elements.

we perform a 'action' (with 'parameters...') on 'cssSelector' (waiting 'cssSelector' (visible)) 

Perform a list of actions ordered

we perform a list of actions :
 yaml : 
 - action : FILL
   parameters : fill input
   css_selector : '#select1'
   wait_for: '#save_button'
   wait_for_visible: true
 - action : CLICK
   css_selector : '#button1'

Assert an html element is on page optionally with attributes

the page contains 'cssSelector' (visible) (with attributes 'key1:value1', 'key2:value2'...)

Assert html elements are on page providing yaml list

the page contains :
 yaml : 
 - css_selector : '#select1'
   attributes :
   - key : required
     value: true
   - key : style
     value : 'display:block'
   visible : true
 - css_selector : '#button1'
   attributes :
   - key : name
     value: 'button_name'
   - key : style
     value : 'display:none' 

Assert what browser url is

browser url is 'url'

CSS selectors referential

In a lot of scenario, you want to check on the same type of html element across multiple tests.
Those css selectors are some times really complex and really not readable if present in a lot of tests.

The idea is to offer the possibility to specify those 'constant css selectors' in a parameter file that can be used directly in Gherkins syntax.

For example, in src/test/resources/css_const.yml :

save-button: "//button[contains(@class,'MuiButton-root') and @aria-label='Save']"

We can directly use it in feature test :

we perform a CLICK on save-button

We can also imagine some specific css_const yaml file that can override global const for specific features.

Maybe also add the possibility to use variable in constant :

mui-button: "//button[contains(@class,'MuiButton-root') and @aria-label=%1]"
we perform a CLICK on click-button('Save')

Mocking Operation Steps

It can be useful to mock external api calls performed by the browser during our test. In order to do that we can reuse and adapt the syntax created in tzatziki-http module to define mocks.

Given that in browser "http://backend/something" is mocked as:
  """
  request:
    method: POST
    body:
      type: User
      payload:
        name: bob
        id: 1
  response:
    status: ACCEPTED
  """

We can also add other syntax provided by tzatziki-http.

Use existing MockFaster and overriding call urls could be enough ?

Setup

Import

User needs only to import tzatziki-front and an implementation (tzatziki-playwright)

Browser configuration

Browser type can be setup using env variable : TZATZIKI_BROWSER
Some others parameters could also be taken into account like headless etc...

Screenshot on test failure ?

Add a property to take a screenshot on test failure
Check how we can implement that and how it can be integrated in test report

Parallel testing

This module must take into account that tests could be run in parallel so we need to develop proper thread isolation with browser.

Drawbacks

We need to be sure to offer global functionnality and method but also enough specific to cover all use cases.

We don't want that at the end the user recreate from scratch all his steps with a lot of duplicate code.

Alternatives

For the moment, no alternative has been really thought of.

Unresolved questions

Do we offer the possibility to the user to access to the internal browser engine (like playwright browser) in case user has a specific need not covered by the module.
=> it could discourage people to open an issue on this repo or contribute directly to it. Moreover, it would encourage people to add hacks in their tests which will require a ton of maintainability issue as well as maybe some breaking change upon dependencies upgrades (while having such feature embed inside tzatziki would allow to detect failure before releasing it and only require a single change in tzatziki).