Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add testing documentation for webforJ applications #382

Merged
merged 4 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/.styles/config/vocabularies/webforj/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ Auto-Detection
CLI
POM
disabled
E2E
End-to-End
8 changes: 8 additions & 0 deletions docs/testing/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Testing",
"position": 36,
"link": {
"type": "doc",
"id": "overview"
}
}
8 changes: 8 additions & 0 deletions docs/testing/e2e/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "E2E Testing",
"position": 1,
"link": {
"type": "doc",
"id": "overview"
}
}
21 changes: 21 additions & 0 deletions docs/testing/e2e/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: End-to-End (E2E) Testing
hide_table_of_contents: true
---


<Head>
<style>{`
.container {
max-width: 65em !important;
}
`}</style>
</Head>

<!-- vale off -->
import DocCardList from '@theme/DocCardList';

<!-- vale on -->


<DocCardList className="topics-list" />
119 changes: 119 additions & 0 deletions docs/testing/e2e/playwright.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
sidebar_position: 2
title: Testing with Playwright
---

This documentation outlines the process for testing webforJ applications using Playwright, specifically focusing on the `HelloWorldView` from the `webforj-archetype-hello-world`.

:::info App Basics
To learn more about the `webforj-archetype-hello-world`, refer to the [App Basics Introduction](../../introduction/basics) section.
:::

## Prerequisites

Before writing and running the Playwright tests, ensure the following:
- The webforJ app is correctly set up and running on your local server.
- You have installed:
- Playwright Java bindings.
- A compatible browser (Playwright can automatically install browsers during setup).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [vale] reported by reviewdog 🐶
[Google.Parens] Use parentheses judiciously.

- Maven for project dependencies.

## Maven configuration

Add the necessary dependencies in your `pom.xml` for Playwright:

```xml title="pom.xml"
<dependencies>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.49.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
```

## Testing example: `HelloWorldView`

The following code demonstrates a Playwright based test for the `HelloWorldView` component.

```java title="HelloWorldViewTest.java"
package com.example.views;

import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;

class HelloWorldViewTest {

static Playwright playwright = Playwright.create();
Browser browser;
Page page;
String port = System.getProperty("server.port", "8080");

@BeforeEach
void setUp() {
browser = playwright.chromium().launch();
page = browser.newPage();
page.navigate("http://localhost:" + port + "/");
}

@Test
void shouldClickButton() {
page.locator("input").fill("webforJ");
page.getByText("Say Hello").click();

assertThat(page.locator("dwc-toast").first())
.containsText("Welcome to webforJ Starter webforJ!");
}
}
```

### Key steps

1. **Initialize Playwright**:
- Create a `Playwright` instance.
- Launch a browser instance using `playwright.chromium().launch()`.

2. **Set Up Test Environment**:
- Open a new browser page with `browser.newPage()`.
- Navigate to the `HelloWorldView` page using the `navigate` method.

3. **Interact with Elements**:
- Use [Playwright's locators](https://playwright.dev/java/docs/api/class-locator) to interact with DOM elements.
- Fill input fields using `locator("input").fill()` and trigger actions using `getByText("Say Hello").click()`.

4. **Assertions**:
- Verify the displayed toast message with `PlaywrightAssertions.assertThat()`.

5. **Teardown**:
- Playwright automatically handles browser cleanup when the test finishes. For manual cleanup, you can close the browser using `browser.close()`.

### Running tests

1. Start the webforJ server:
```bash
mvn jetty:run
```

2. Execute the test cases:
```bash
mvn test
```

## Expected behavior

- On visiting `http://localhost:<port>/`, the `HelloWorldView` page loads.
- Input webforJ into the text field and click the `Say Hello` button.
- A toast message should appear with the text: `Welcome to webforJ Starter webforJ!`.
137 changes: 137 additions & 0 deletions docs/testing/e2e/selenium.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
sidebar_position: 3
title: Testing with Selenium
---

This documentation outlines the process for testing a webforJ apps using Selenium, specifically focusing on the `HelloWorldView` from
the `webforj-archetype-hello-world`.

:::info App Basics
To learn more about the `webforj-archetype-hello-world`, refer to the [App Basics Introduction](../../introduction/basics) section.
:::

## Prerequisites

Before running the Selenium tests, ensure the following:
- webforJ app is correctly set up and running on your local server.
- You have installed:
- Selenium Java bindings.
- A compatible WebDriver for your browser.
- Maven for project dependencies.

## Maven configuration

Add the necessary dependencies in your `pom.xml` for Selenium and other testing libraries:

```xml title="pom.xml"
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.27.0</version>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.9.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
```

## Testing example: `HelloWorldView`

The following code demonstrates a Selenium based test for the `HelloWorldView` component.

```java title="HelloWorldViewTest.java"
package com.example.views;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;

import static java.time.Duration.ofSeconds;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs;
import io.github.bonigarcia.wdm.WebDriverManager;

class HelloWorldViewTest {

private WebDriver driver;
private static final String PORT = System.getProperty("server.port", "8080");

@BeforeAll
static void setupAll() {
WebDriverManager.chromedriver().setup();
}

@BeforeEach
void setup() {
driver = new ChromeDriver();
driver.get("http://localhost:" + PORT + "/");
new WebDriverWait(driver, ofSeconds(30))
.until(titleIs("webforJ Hello World"));
}

@AfterEach
void teardown() {
if (driver != null) {
driver.quit();
}
}

@Test
void shouldClickButton() {
WebElement button = driver.findElement(By.tagName("dwc-button"));
assertEquals("Say Hello", button.getText(), "Button text mismatch!");
}
}
```

### Key steps

1. **Initialize WebDriver**:
- Use [`WebDriverManager`](https://github.com/bonigarcia/webdrivermanager) to automatically manage the driver executable for the browser.

2. **Set Up Test Environment**:
- Start the test server on `http://localhost:<port>/`.
- Wait until the page title matches the expected `webforJ Hello World`.

3. **Interact with Elements**:
- Locate elements using `By.tagName`, `By.id`, or other Selenium locators.
- Verify expected behaviors like button clicks or text changes.

:::info
Because webforJ produces a single-page web app, Selenium isn’t aware of DOM manipulation after the initial page has been loaded. You can use Selenium’s [WebDriverWait API](https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/WebDriverWait.html) to wait until the DOM has been compiled.
:::

4. **Teardown**:
- Quit the WebDriver session to release resources.

### Running tests

1. Start the webforJ server:
```bash
mvn jetty:run
```

2. Execute the test cases:
```bash
mvn test
```

## Expected behavior

- On visiting `http://localhost:<port>/`, the `HelloWorldView` page loads.
- The `dwc-button` element with the text `Say Hello` should be present.
42 changes: 42 additions & 0 deletions docs/testing/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
sidebar_position: 1
title: Testing
hide_table_of_contents: true
---

<Head>
<style>{`
.container {
max-width: 65em !important;
}
`}</style>
</Head>

# webforJ Testing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [vale] reported by reviewdog 🐶
[Google.Headings] 'webforJ Testing' should use sentence-style capitalization.


Testing in webforJ apps involves a combination of unit and end-to-end (E2E) testing to ensure a stable and reliable app. Each type of testing serves a distinct purpose in maintaining app quality.

## Unit testing

Unit testing focuses on verifying individual components or backend logic in isolation. By following standard Java testing practices, such as using [JUnit](https://junit.org/junit5/), developers can efficiently validate specific app logic and ensure that each "unit" performs as expected.

## End-to-End (E2E) testing

End-to-end testing is important for validating the user experience in webforJ apps, which generate dynamic, single-page web interfaces. These tests simulate user interactions and verify the features of the entire app.

Using tools like [**Selenium**](https://www.selenium.dev/) and [**Playwright**](https://playwright.dev/java/docs/intro), you can:

- Automate browser interactions, such as button clicks and form submissions.
- Verify consistent rendering and interactivity of dynamic UI components.
- Ensure behavior consistency across different browsers and devices.

## Combining testing strategies

By combining unit and E2E testing:

1. **Isolate Issues**: Detect and resolve component-level bugs early with unit testing.
2. **Ensure Reliability**: Validate complete user journeys and system integrations with E2E testing.

## Topics

<DocCardList className="topics-section" />
Loading
Loading