Skip to content

Commit

Permalink
Release/v1.1 (#14)
Browse files Browse the repository at this point in the history
* Change to next version.  Add develop branch to github actions (#8)

* Add playwright 1.19.0 (#9)

* Added ability to define custom field locators (#12)

* Add ability to call a method automatically after creation of page object (#13)

* Prepare v1.1 release

* Update readme with new afterCreate functionality
  • Loading branch information
uchagani authored Apr 6, 2022
1 parent 9aa64b7 commit f1a4cc1
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 38 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ name: Stagehand

on:
push:
branches: [ main ]
branches: [ main, develop ]
pull_request:
branches: [ main ]
branches: [ main, develop ]

jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
java: [ '8', '11', '17' ]
playwright: ['1.18.0']
playwright: ['1.18.0', '1.19.0', '1.20.1']
runs-on: ${{ matrix.os }}
name: ${{matrix.os}} - Java ${{ matrix.java }} - Playwright ${{matrix.playwright}}
steps:
Expand All @@ -22,4 +22,4 @@ jobs:
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
- run: mvn test "-Dplaywright.version=${{matrix.playwright}}" --file pom.xml
- run: mvn clean test "-Dplaywright.version=${{matrix.playwright}}" --file pom.xml
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,26 @@ public void myTest() {
}
```

## Hooks

Stagehand allows you to define a method that will automatically be called after creation of the page object by the PageFactory.
To define a hook implement the `AfterCreate` interface and put whatever code you want in that method.

```java
import io.github.uchagani.stagehand.AfterCreate;

@PageObject
public class HomePage implements AfterCreate {

@Find("#some-id")
private Locator myButton;

@Override
public void afterCreate() {
myButton.click();
}
}
```

## Requirements

Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

<groupId>io.github.uchagani</groupId>
<artifactId>stagehand</artifactId>
<version>1.0</version>
<version>1.1</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<playwright.version>1.18.0</playwright.version>
<playwright.version>1.20.1</playwright.version>
</properties>

<scm>
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/github/uchagani/stagehand/AfterCreate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.github.uchagani.stagehand;

public interface AfterCreate {
void afterCreate();
}
31 changes: 2 additions & 29 deletions src/main/java/io/github/uchagani/stagehand/FieldDecorator.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
package io.github.uchagani.stagehand;

import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import io.github.uchagani.stagehand.annotations.Find;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class FieldDecorator {
Page page;
LocatorFactory locatorFactory;

public FieldDecorator(Page page) {
this.page = page;
this.locatorFactory = new LocatorFactory(page);
}

public Object decorate(Field field, Object pageObjectInstance) {
Locator locator = locatorFactory.createLocator(field, pageObjectInstance);
ClassLoader loader = pageObjectInstance.getClass().getClassLoader();
return proxyForLocator(loader, locator);
}

protected Locator proxyForLocator(ClassLoader loader, Locator locator) {
InvocationHandler handler = new LocatorHandler(locator);

Locator proxy;
proxy = (Locator) Proxy.newProxyInstance(
loader, new Class[]{Locator.class}, handler);
return proxy;
}
public interface FieldDecorator {
Object decorate(Field field, Object pageObjectInstance);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.github.uchagani.stagehand;

import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class LocatorFieldDecorator implements FieldDecorator {
Page page;
LocatorFactory locatorFactory;

public LocatorFieldDecorator(Page page) {
this.page = page;
this.locatorFactory = new LocatorFactory(page);
}

@Override
public Object decorate(Field field, Object pageObjectInstance) {
Locator locator = locatorFactory.createLocator(field, pageObjectInstance);
ClassLoader loader = pageObjectInstance.getClass().getClassLoader();
return proxyForLocator(loader, locator);
}

protected Locator proxyForLocator(ClassLoader loader, Locator locator) {
InvocationHandler handler = new LocatorHandler(locator);

Locator proxy;
proxy = (Locator) Proxy.newProxyInstance(
loader, new Class[]{Locator.class}, handler);
return proxy;
}
}
11 changes: 9 additions & 2 deletions src/main/java/io/github/uchagani/stagehand/PageFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ public static <T> T create(Class<T> pageToCreate, Page page) {

public static void initElements(Object pageObject, Page page) {
if (pageObject.getClass().isAnnotationPresent(PageObject.class)) {
initElements(new FieldDecorator(page), pageObject);
initElements(new LocatorFieldDecorator(page), pageObject);
} else {
throw new MissingPageObjectAnnotation("Only pages marked with @PageObject can can be initialized by the PageFactory.");
}
}

private static void callAfterCreateHook(Object pageObjectInstance) {
if(AfterCreate.class.isAssignableFrom(pageObjectInstance.getClass())) {
((AfterCreate)pageObjectInstance).afterCreate();
}
}

private static <T> T instantiatePage(Class<T> pageClassToProxy, Page page) {
try {
if (pageClassToProxy.isAnnotationPresent(PageObject.class)) {
Expand All @@ -39,7 +45,8 @@ private static <T> T instantiatePage(Class<T> pageClassToProxy, Page page) {
} catch (NoSuchMethodException e) {
pageObjectInstance = pageClassToProxy.getDeclaredConstructor().newInstance();
}
initElements(new FieldDecorator(page), pageObjectInstance);
initElements(new LocatorFieldDecorator(page), pageObjectInstance);
callAfterCreateHook(pageObjectInstance);
return pageObjectInstance;
}
throw new MissingPageObjectAnnotation("Only pages marked with @PageObject can can be created by the PageFactory.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,30 @@

import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import io.github.uchagani.stagehand.AfterCreate;
import io.github.uchagani.stagehand.annotations.Find;
import io.github.uchagani.stagehand.annotations.PageObject;
import io.github.uchagani.stagehand.annotations.Under;

@PageObject
public class PageWithConstructor {
public class PageWithConstructor implements AfterCreate {
@Find("#headerId")
public Locator header;

@Find(".paragraph")
public Locator paragraph;

@Find("#cityDiv input")
public Locator cityInput;

private final Page page;

public PageWithConstructor(Page page) {
this.page = page;
}

@Override
public void afterCreate() {
cityInput.fill("New York");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.uchagani.stagehand.tests;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import io.github.uchagani.stagehand.PageFactory;
Expand Down Expand Up @@ -61,6 +62,13 @@ public void create_canInitializeFieldsInBaseClass_whenBeingCalledOnChildClass()
assertThat(inheritedPage.paragraph).containsText("This is a paragraph.");
}

@Test
public void afterCreateHookIsCalledSuccessfully() {
PageWithConstructor homePage = PageFactory.create(PageWithConstructor.class, page);

assertThat(homePage.cityInput).hasValue("New York");
}

@Test
public void create_canInitializeFields_inClassWithAConstructor() {
PageWithConstructor homePage = PageFactory.create(PageWithConstructor.class, page);
Expand Down

0 comments on commit f1a4cc1

Please sign in to comment.