From 5578a20fccbc18a9bbe3ffe7ae136fb7b6a44535 Mon Sep 17 00:00:00 2001 From: padmavemulapati Date: Thu, 18 Jun 2026 12:04:52 +0530 Subject: [PATCH 1/3] java/playwright examples updated --- java/playwright/basic/pom.xml | 79 +++++++++ .../watcher_examples/playwright/Basic.java | 7 + .../playwright/BasicTest.java | 82 +++++++++ java/playwright/manual-mode/pom.xml | 80 +++++++++ .../playwright/ManualMode.java | 7 + .../playwright/ManualModeTest.java | 112 +++++++++++++ java/playwright/multi-page/pom.xml | 79 +++++++++ .../playwright/MultiPage.java | 7 + .../playwright/MultiPageTest.java | 157 ++++++++++++++++++ 9 files changed, 610 insertions(+) create mode 100644 java/playwright/basic/pom.xml create mode 100644 java/playwright/basic/src/main/java/com/deque/watcher_examples/playwright/Basic.java create mode 100644 java/playwright/basic/src/test/java/com/deque/watcher_examples/playwright/BasicTest.java create mode 100644 java/playwright/manual-mode/pom.xml create mode 100644 java/playwright/manual-mode/src/main/java/com/deque/watcher_examples/playwright/ManualMode.java create mode 100644 java/playwright/manual-mode/src/test/java/com/deque/watcher_examples/playwright/ManualModeTest.java create mode 100644 java/playwright/multi-page/pom.xml create mode 100644 java/playwright/multi-page/src/main/java/com/deque/watcher_examples/playwright/MultiPage.java create mode 100644 java/playwright/multi-page/src/test/java/com/deque/watcher_examples/playwright/MultiPageTest.java diff --git a/java/playwright/basic/pom.xml b/java/playwright/basic/pom.xml new file mode 100644 index 0000000..aa20a80 --- /dev/null +++ b/java/playwright/basic/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + com.deque.watcher_examples.playwright + basic + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + false + + + + + com.microsoft.playwright + playwright + 1.49.0 + + + org.junit.jupiter + junit-jupiter-api + 5.10.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.2 + test + + + com.deque.axe_core + watcher + 4.4.0 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.4 + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + install-playwright-browsers + process-test-classes + + run + + + + + + + + + + + + + + + + diff --git a/java/playwright/basic/src/main/java/com/deque/watcher_examples/playwright/Basic.java b/java/playwright/basic/src/main/java/com/deque/watcher_examples/playwright/Basic.java new file mode 100644 index 0000000..104a811 --- /dev/null +++ b/java/playwright/basic/src/main/java/com/deque/watcher_examples/playwright/Basic.java @@ -0,0 +1,7 @@ +package com.deque.watcher_examples.playwright; + +public class Basic { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} diff --git a/java/playwright/basic/src/test/java/com/deque/watcher_examples/playwright/BasicTest.java b/java/playwright/basic/src/test/java/com/deque/watcher_examples/playwright/BasicTest.java new file mode 100644 index 0000000..4e93b64 --- /dev/null +++ b/java/playwright/basic/src/test/java/com/deque/watcher_examples/playwright/BasicTest.java @@ -0,0 +1,82 @@ +package com.deque.watcher_examples.playwright; + +import java.nio.file.Paths; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.deque.axe_core.commons.AxeWatcherOptions; +import com.deque.axe_core.playwright.AxeWatcherPage; +import com.deque.axe_core.playwright.AxeWatcherPlaywright; +import com.microsoft.playwright.BrowserContext; +import com.microsoft.playwright.BrowserType; +import com.microsoft.playwright.ElementHandle; +import com.microsoft.playwright.Playwright; + + +@DisplayName("My Login Application") +class BasicTest { + + String apiKey = "test-api-key"; + String projectId = "test-project-id"; + String serverUrl = "https://axe.deque.com"; + + Playwright playwright; + BrowserContext browserContext; + AxeWatcherPage page; + + @BeforeEach + void setUp() { + AxeWatcherPlaywright axeWatcher = + new AxeWatcherPlaywright( + new AxeWatcherOptions().setApiKey(apiKey).setProjectId(projectId).setServerUrl(serverUrl)) + .enableDebugLogger(); + + BrowserType.LaunchPersistentContextOptions launchOptions = + axeWatcher.configure( + new BrowserType.LaunchPersistentContextOptions() + .setHeadless(true) + .setChannel("chromium") + .setArgs(List.of("--no-sandbox", "--disable-dev-shm-usage"))); + + playwright = Playwright.create(); + // An empty user-data dir lets Playwright create a fresh temporary profile. + browserContext = playwright.chromium().launchPersistentContext(Paths.get(""), launchOptions); + page = axeWatcher.wrapPage(browserContext.newPage()); + } + + @AfterEach + void tearDown() { + page.axeWatcher().flush(); + browserContext.close(); + playwright.close(); + } + + @Nested + @DisplayName("Login") + class LoginTests { + @Nested + @DisplayName("with valid credentials") + class ShouldLoginTests { + @Test + @DisplayName("should login") + void shouldLoginTest() { + page.navigate("https://the-internet.herokuapp.com/login"); + + page.locator("#username").fill("tomsmith"); + page.locator("#password").fill("SuperSecretPassword!"); + + page.locator("button[type='submit']").click(); + + ElementHandle element = page.waitForSelector("#flash"); + assertNotNull(element); + } + } + } +} diff --git a/java/playwright/manual-mode/pom.xml b/java/playwright/manual-mode/pom.xml new file mode 100644 index 0000000..f388792 --- /dev/null +++ b/java/playwright/manual-mode/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + com.deque.watcher_examples.playwright + manual-mode + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + false + + + + + + com.microsoft.playwright + playwright + 1.49.0 + + + org.junit.jupiter + junit-jupiter-api + 5.10.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.2 + test + + + com.deque.axe_core + watcher + 4.4.0 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.4 + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + install-playwright-browsers + process-test-classes + + run + + + + + + + + + + + + + + + + diff --git a/java/playwright/manual-mode/src/main/java/com/deque/watcher_examples/playwright/ManualMode.java b/java/playwright/manual-mode/src/main/java/com/deque/watcher_examples/playwright/ManualMode.java new file mode 100644 index 0000000..fd0d604 --- /dev/null +++ b/java/playwright/manual-mode/src/main/java/com/deque/watcher_examples/playwright/ManualMode.java @@ -0,0 +1,7 @@ +package com.deque.watcher_examples.playwright; + +public class ManualMode { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} diff --git a/java/playwright/manual-mode/src/test/java/com/deque/watcher_examples/playwright/ManualModeTest.java b/java/playwright/manual-mode/src/test/java/com/deque/watcher_examples/playwright/ManualModeTest.java new file mode 100644 index 0000000..fa425cb --- /dev/null +++ b/java/playwright/manual-mode/src/test/java/com/deque/watcher_examples/playwright/ManualModeTest.java @@ -0,0 +1,112 @@ +package com.deque.watcher_examples.playwright; + +import java.nio.file.Paths; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.deque.axe_core.commons.AxeWatcherOptions; +import com.deque.axe_core.playwright.AxeWatcherPage; +import com.deque.axe_core.playwright.AxeWatcherPlaywright; +import com.microsoft.playwright.BrowserContext; +import com.microsoft.playwright.BrowserType; +import com.microsoft.playwright.ElementHandle; +import com.microsoft.playwright.Playwright; + + +@DisplayName("My Login Application") +class ManualModeTest { + + String apiKey = "test-api-key"; + String projectId = "test-project-id"; + String serverUrl = "https://axe.deque.com"; + + Playwright playwright; + BrowserContext browserContext; + AxeWatcherPage page; + + @BeforeEach + void setUp() { + AxeWatcherPlaywright axeWatcher = + new AxeWatcherPlaywright( + new AxeWatcherOptions() + .setApiKey(apiKey) + .setProjectId(projectId) + .setServerUrl(serverUrl) + // Disable automatic analysis. + .setAutoAnalyze(false)) + .enableDebugLogger(); + + BrowserType.LaunchPersistentContextOptions launchOptions = + axeWatcher.configure( + new BrowserType.LaunchPersistentContextOptions() + .setHeadless(true) + .setChannel("chromium") + .setArgs(List.of("--no-sandbox", "--disable-dev-shm-usage"))); + + playwright = Playwright.create(); + browserContext = playwright.chromium().launchPersistentContext(Paths.get(""), launchOptions); + page = axeWatcher.wrapPage(browserContext.newPage()); + } + + @AfterEach + void tearDown() { + // Flush axe-watcher results after each test. + page.axeWatcher().flush(); + browserContext.close(); + playwright.close(); + } + + @Nested + @DisplayName("Login") + class LoginTests { + @Nested + @DisplayName("with valid credentials") + class ShouldLoginTests { + @Test + @DisplayName("should login") + void shouldLoginTest() { + /* + Let's calculate the number of page states. + Auto-analyze is false, so it will not analyze automatically. + + We navigate to the page, + then manually analyze it. (+1) + We fill out the form, + then turn on auto-analysis. + We click the button, + causing an auto-analysis (+1), + then assure the element appears. + We turn off auto-analysis, + then analyze manually (+1). + + So, we expect the total number of page states to be 3. + */ + page.navigate("https://the-internet.herokuapp.com/login"); + // Analyze after navigating to the page. + page.axeWatcher().analyze(); + + page.locator("#username").fill("tomsmith"); + page.locator("#password").fill("SuperSecretPassword!"); + // Start automatic axe analysis. + page.axeWatcher().start(); + + page.locator("button[type='submit']").click(); + + ElementHandle element = page.waitForSelector("#flash"); + assertNotNull(element); + + // Stop automatic axe analysis. + page.axeWatcher().stop(); + // Analyze after logging in. + page.axeWatcher().analyze(); + } + } + } +} diff --git a/java/playwright/multi-page/pom.xml b/java/playwright/multi-page/pom.xml new file mode 100644 index 0000000..a7a2ee0 --- /dev/null +++ b/java/playwright/multi-page/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + com.deque.watcher_examples.playwright + multi-page + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + false + + + + + com.microsoft.playwright + playwright + 1.49.0 + + + org.junit.jupiter + junit-jupiter-api + 5.10.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.2 + test + + + com.deque.axe_core + watcher + 4.4.0 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.4 + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + install-playwright-browsers + process-test-classes + + run + + + + + + + + + + + + + + + + diff --git a/java/playwright/multi-page/src/main/java/com/deque/watcher_examples/playwright/MultiPage.java b/java/playwright/multi-page/src/main/java/com/deque/watcher_examples/playwright/MultiPage.java new file mode 100644 index 0000000..e0b28fe --- /dev/null +++ b/java/playwright/multi-page/src/main/java/com/deque/watcher_examples/playwright/MultiPage.java @@ -0,0 +1,7 @@ +package com.deque.watcher_examples.playwright; + +public class MultiPage { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} diff --git a/java/playwright/multi-page/src/test/java/com/deque/watcher_examples/playwright/MultiPageTest.java b/java/playwright/multi-page/src/test/java/com/deque/watcher_examples/playwright/MultiPageTest.java new file mode 100644 index 0000000..9a14e97 --- /dev/null +++ b/java/playwright/multi-page/src/test/java/com/deque/watcher_examples/playwright/MultiPageTest.java @@ -0,0 +1,157 @@ +package com.deque.watcher_examples.playwright; + +import java.nio.file.Paths; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.deque.axe_core.commons.AxeWatcherOptions; +import com.deque.axe_core.playwright.AxeWatcherPage; +import com.deque.axe_core.playwright.AxeWatcherPlaywright; +import com.microsoft.playwright.BrowserContext; +import com.microsoft.playwright.BrowserType; +import com.microsoft.playwright.ElementHandle; +import com.microsoft.playwright.Playwright; + + +@DisplayName("Multipage Test") +class MultiPageTest { + + static Playwright playwright; + static BrowserContext browserContext; + static AxeWatcherPage page; + + @BeforeAll + static void setup() { + String apiKey = "test-api-key"; + String projectId = "test-project-id"; + String serverUrl = "https://axe.deque.com"; + + AxeWatcherPlaywright axeWatcher = + new AxeWatcherPlaywright( + new AxeWatcherOptions() + .setApiKey(apiKey) + .setProjectId(projectId) + .setServerUrl(serverUrl)); + + BrowserType.LaunchPersistentContextOptions launchOptions = + axeWatcher.configure( + new BrowserType.LaunchPersistentContextOptions() + .setHeadless(true) + .setChannel("chromium") + .setArgs(List.of("--no-sandbox", "--disable-dev-shm-usage"))); + + playwright = Playwright.create(); + browserContext = playwright.chromium().launchPersistentContext(Paths.get(""), launchOptions); + page = axeWatcher.wrapPage(browserContext.newPage()); + } + + @AfterAll + static void teardown() { + browserContext.close(); + playwright.close(); + } + + @AfterEach + void tearDown() { + // Flush axe-watcher results after each test. + page.axeWatcher().flush(); + } + + @Nested + @DisplayName("Homepage") + class HomepageTests { + @BeforeEach + void visit() { + page.navigate("https://the-internet.herokuapp.com"); + } + + @Test + @DisplayName("should contain a list of links") + void shouldContainAListOfLinksTest() { + assertTrue(page.locator("ul li a").count() >= 20); + } + + @Test + @DisplayName("should contain a link to the login page") + void shouldContainALinkToTheLoginPageTest() { + ElementHandle loginLink = page.querySelector("ul li a[href='/login']"); + assertNotNull(loginLink); + } + } + + @Nested + @DisplayName("Login page") + class LoginPageTests { + + @BeforeEach + void visit() { + page.navigate("https://the-internet.herokuapp.com/login"); + } + + @Test + @DisplayName("should contain a username input") + void shouldContainAUsernameInputTest() { + ElementHandle usernameInput = page.querySelector("#username"); + assertNotNull(usernameInput); + } + + @Test + @DisplayName("should contain a password input") + void shouldContainAPasswordInputTest() { + ElementHandle passwordInput = page.querySelector("#password"); + assertNotNull(passwordInput); + } + + @Test + @DisplayName("should contain a submit button") + void shouldContainASubmitButton() { + ElementHandle submitButton = page.querySelector("button[type='submit']"); + assertNotNull(submitButton); + } + + @Test + @DisplayName("entering credentials and submitting the form should login") + void shouldLoginTest() { + page.locator("#username").fill("tomsmith"); + page.locator("#password").fill("SuperSecretPassword!"); + + page.locator("button[type='submit']").click(); + + ElementHandle element = page.waitForSelector("#flash"); + assertNotNull(element); + } + } + + @Nested + @DisplayName("Forgot password page") + class MultiPageForgotPasswordTest { + + @BeforeEach + void visit() { + page.navigate("https://the-internet.herokuapp.com/forgot_password"); + } + + @Test + @DisplayName("should contain an email input") + void shouldContainAnEmailInputTest() { + ElementHandle input = page.querySelector("#email"); + assertNotNull(input); + } + + @Test + @DisplayName("should contain a submit button") + void shouldContainASubmitButtonTest() { + ElementHandle button = page.querySelector("button[type='submit']"); + assertNotNull(button); + } + } +} From 90cc89ecb60fa259e0402c2aa3cb02a5526adde4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 06:47:24 +0000 Subject: [PATCH 2/3] Skip semantic footer check when PR body is empty --- .github/workflows/semantic-pr-footer.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/semantic-pr-footer.yml b/.github/workflows/semantic-pr-footer.yml index d5e35af..0eccfc3 100644 --- a/.github/workflows/semantic-pr-footer.yml +++ b/.github/workflows/semantic-pr-footer.yml @@ -10,6 +10,7 @@ on: jobs: semantic-pr-footer: + if: ${{ github.event.pull_request.body != '' }} runs-on: ubuntu-latest timeout-minutes: 1 steps: From ad97a516352283dedc0548ad52b7be8ddf780f50 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 06:49:35 +0000 Subject: [PATCH 3/3] Limit semantic footer workflow token permissions --- .github/workflows/semantic-pr-footer.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/semantic-pr-footer.yml b/.github/workflows/semantic-pr-footer.yml index 0eccfc3..da35cee 100644 --- a/.github/workflows/semantic-pr-footer.yml +++ b/.github/workflows/semantic-pr-footer.yml @@ -13,5 +13,7 @@ jobs: if: ${{ github.event.pull_request.body != '' }} runs-on: ubuntu-latest timeout-minutes: 1 + permissions: + pull-requests: read steps: - uses: dequelabs/axe-api-team-public/.github/actions/semantic-pr-footer-v1@main