Introduction

There are few well-known facts about Bobcat:

  • uses Java (1.8) and Selenium - Yes. Yet Another Selenium Framework
  • uses Guice
  • uses the Page Object concept
  • allows testing AEM authoring

But how it is doing this? What mechanism lies under these facts? I won't explain everything, but maybe I will make it easier to understand or contribute to it. It's open-source after all.

Guice and Page Objects Injection

This is probably the most important part of the framework. Because dependency injection is used everywhere and Page Objects are core of Bobcat. All this starts as most of Guice magic in module. In this case - PageObjectsModule.class

Guice module

    bindListener(any(), new PageObjectTypeListener());

    Multibinder<FieldProvider> fieldProviders =
        Multibinder.newSetBinder(binder(), FieldProvider.class);
    fieldProviders.addBinding().to(PageObjectProvider.class);
    fieldProviders.addBinding().to(PageObjectListProxyProvider.class);
    fieldProviders.addBinding().to(CurrentFrameProvider.class);

    bind(Key.get(WebElement.class, CurrentScope.class)).toProvider(CurrentWebElementProvider.class);
    bind(new TypeLiteral<List<WebElement>>() {
    }).annotatedWith(CurrentScope.class).toProvider(CurrentScopeListProvider.class);

Only a few lines of code but a lot of things are going there. Some will be explained here, some we will cover in the future.

The basics:

  • create listener of PageObject annotation
  • create different providers that will return injected objects in the correct scope
  • create provider for WebElement within current scope (well actually both one object and list of them)

First Listener

PageObjectTypeListener - thanks to him Page Objects can be used. This is TypeListener which checks types that Guice encounters. It is quite simple. If PageObject annotation is present on the injected field then this listener will call another one PageObjectInjectorListener and let him handle the rest.

Main Listener

The listener above is the vanguard. It checks incoming objects and selects the correct ones. PageObjectInjectorListener is the main force of the Page Objects mechanism.

For each incoming objects it has four main tasks:

  • select correct frame from the hierarchy of frames in the page
  • inject all WebElement fields in object marked by FindBy annotation
  • inject all Page Object fields - marked with correct annotations
  • call object PostConstruct method

Of course the most interesting are two "inject" tasks, but this is a topic for part two.