Skip to main content

Decorators framework

In the context of Selenium testing with Kolibrium, decorators are design pattern implementations that allow you to dynamically enhance the behavior of WebDriver and WebElement instances without modifying their core functionality. They follow the decorator pattern from software design to add supplementary behaviors to existing objects at runtime.

Core decorator concept

Decorators in Kolibrium wrap around standard Selenium WebDriver and WebElement objects to intercept and augment their methods. This enables you to add cross-cutting functionality that applies consistently across your test suite without cluttering your test code.

The decorator framework consists of:

  1. AbstractDecorator – Base type that decorates the Selenium SearchContext contract (both WebDriver and WebElement) so chaining is preserved across nested searches
  2. DecoratorManager – Manages test-level decorators per thread and applies them in insertion order
  3. Concrete decorators – Specialized implementations for specific behaviors (e.g., highlighting, slow motion, logging, caching)
  4. Optional interaction callbacks – Decorators that implement InteractionAware can receive WebDriver interaction events; Kolibrium wires them through a single Selenium EventFiringDecorator with a listener multiplexer

Available decorators

Kolibrium provides several built-in decorators.

SlowMotionDecorator

Adds configurable delays between Selenium operations, useful for:

  • Debugging tests visually
  • Creating demonstrations or recordings
  • Simulating human-like interaction timing

Example usage:

DecoratorManager.addDecorators(SlowMotionDecorator(2.seconds))

HighlighterDecorator

Visually highlights elements on the page by adding a colored border around them when they're found or interacted with:

  • Configurable border style, color, and width
  • Automatically cleans up previous highlights
  • Helps visualize which elements are being targeted during test execution

Example usage:

DecoratorManager.addDecorators(HighlighterDecorator(
style = BorderStyle.Solid,
color = Color.Blue,
width = 3
))

LoggerDecorator

Logs element discovery and basic interactions:

  • Traces findElement(s) calls and counts
  • Logs before click and sendKeys with a short preview of keys
  • Lightweight and suitable for troubleshooting

Example usage:

DecoratorManager.addDecorators(LoggerDecorator())

ElementStateCacheDecorator

Optimizes performance by caching positive state check results for elements:

  • Eliminates redundant WebDriver calls for state checks
  • Caches only positive results (true values)
  • Configurable for different state methods (displayed, enabled, selected)

Example usage:

DecoratorManager.addDecorators(ElementStateCacheDecorator(
cacheDisplayed = true,
cacheEnabled = true,
cacheSelected = false
))

Applying decorators

There are two ways to apply decorators:

  • At the test level via DecoratorManager
  • At the site level by overriding Site.decorators on your site class

Test-level vs site-level decorator precedence rule

Kolibrium applies this precedence rule to decide what decorators shall be used in tests:

  • If only site-level decorators exist (through Site.decorators), they will be used
  • If only test-level decorators exist (through DecoratorManager), they will be used
  • If both exist, test-level decorators take precedence; duplicates by class are de-duplicated with test-level winning
  • If neither exists, the original SearchContext is returned unchanged

Applying decorators at the test-level

Decorators can be applied at the test-level through the DecoratorManager:

@BeforeEach
fun setup() {
DecoratorManager.addDecorators( // Add decorators before the start of your tests
SlowMotionDecorator(1.seconds),
HighlighterDecorator(style = BorderStyle.Dashed, color = Color.Green, width = 5)
)
}

@AfterEach
fun cleanup() {
DecoratorManager.clearDecorators() // Clear decorators after tests execution
}

Decorators are applied in the order they're added, allowing you to combine multiple decorators to create a customized testing experience.

Scoped application with withDecorators

Prefer the scoped helper when you want decorators active only within a block. They are automatically cleared on exit (even if an exception is thrown):

DecoratorManager.withDecorators(
SlowMotionDecorator(1.seconds),
HighlighterDecorator(color = Color.Green, width = 5)
) {
// decorators active only within this block
}

Manual management is also available, but remember to clear them afterward to avoid cross‑test leakage:

DecoratorManager.addDecorators(SlowMotionDecorator(1.seconds))
// ... run tests ...
DecoratorManager.clearDecorators()

Benefits of using Kolibrium's decorators

  1. Separation of Concerns: Keep test logic separate from cross-cutting concerns.
  2. Reusability: Apply the same enhancements across multiple tests.
  3. Thread Safety: Decorators are managed per-thread for parallel test execution.
  4. Dynamic Application: Add or remove behaviors at runtime.
  5. Non-Invasive: Enhance functionality without modifying the core Selenium classes or requiring changes to their source code. This maintains compatibility with future Selenium updates and allows you to add behaviors without subclassing or replacing the original implementation.

Decorators provide a powerful way to enhance your Selenium tests with visual feedback, performance optimizations, and debugging capabilities while maintaining clean and modular test code.