Migrated
9
of 17 files
Failed
8
generation errors
Patterns
56
Selenium patterns handled
Avg confidence
75%
across all files
Total time
217.7s
wall-clock
Hours saved
~3.0
est. manual effort
⚠ Priority
8
Failed or confidence < 70%
~ Verify
0
Hallucinations or 3+ fix attempts
✓ Solid
9
Confidence ≥ 90%, compiled clean
Selenium patterns handled
| Pattern | Count |
|---|---|
ExpectedConditions | 10 |
By_id | 6 |
WebDriver | 6 |
assertTrue | 5 |
By_field | 4 |
click | 3 |
sendKeys | 2 |
clear | 2 |
By_cssSelector | 2 |
WebDriverWait | 2 |
JavascriptExecutor | 2 |
Cucumber_Scenario_Inject | 2 |
Cucumber_When | 2 |
Cucumber_Then | 2 |
ChromeDriver | 1 |
FirefoxDriver | 1 |
Actions | 1 |
Select | 1 |
hover | 1 |
Cucumber_Given | 1 |
Files
✗ Failed
BaseTest.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\BaseTest.java
50%
13.7s
✗ Did not compile
2 fix attempt(s)
BaseTest.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\BaseTest.java
50%
13.7s
✗ Did not compile
2 fix attempt(s)
ℹ Generation failed. Error: 2 compile error(s) after 2 fix attempt(s)
Compiler / generation error
2 compile error(s) after 2 fix attempt(s)
Patterns handled
- None detected
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.core; | n | 1 | package com.qastarter.core.playwright; |
| 2 | 2 | ||||
| n | 3 | import com.qastarter.config.ConfigurationReader; | n | 3 | import com.qastarter.config.playwright.ConfigurationReader; |
| 4 | import com.qastarter.utils.Log; | 4 | import com.qastarter.utils.playwright.Log; | ||
| 5 | import org.openqa.selenium.WebDriver; | 5 | import com.qastarter.core.playwright.DriverManager; | ||
| 6 | import com.microsoft.playwright.Page; | ||||
| 6 | import org.junit.jupiter.api.AfterAll; | 7 | import org.junit.jupiter.api.AfterAll; | ||
| 7 | import org.junit.jupiter.api.AfterEach; | 8 | import org.junit.jupiter.api.AfterEach; | ||
| 8 | import org.junit.jupiter.api.BeforeAll; | 9 | import org.junit.jupiter.api.BeforeAll; | ||
| 9 | import org.junit.jupiter.api.BeforeEach; | 10 | import org.junit.jupiter.api.BeforeEach; | ||
| 10 | import org.junit.jupiter.api.extension.ExtendWith; | 11 | import org.junit.jupiter.api.extension.ExtendWith; | ||
| 11 | 12 | ||||
| n | 12 | /** | n | ||
| 13 | * Base Test - Extend this in all your test classes. | ||||
| 14 | * | ||||
| 15 | * JUnit5 version with @BeforeEach/@AfterEach lifecycle. | ||||
| 16 | */ | ||||
| 17 | @ExtendWith(TestWatcher.class) | 13 | @ExtendWith(TestWatcher.class) | ||
| 18 | public class BaseTest { | 14 | public class BaseTest { | ||
| 19 | 15 | ||||
| n | n | 16 | // No explicit constructor needed - using default constructor | ||
| 17 | |||||
| 18 | // Migration: Preserved original logging and configuration reading - no chan | ||||
| > | ges needed for suite-level setup | ||||
| 20 | @BeforeAll | 19 | @BeforeAll | ||
| 21 | static void beforeAll() { | 20 | static void beforeAll() { | ||
| 22 | Log.info("========================================"); | 21 | Log.info("========================================"); | ||
| 27 | Log.info("Base URL: " + ConfigurationReader.getBaseUrl()); | 26 | Log.info("Base URL: " + ConfigurationReader.getBaseUrl()); | ||
| 28 | } | 27 | } | ||
| 29 | 28 | ||||
| n | n | 29 | // Migration: Preserved original logging - no changes needed for suite-level | ||
| > | teardown | ||||
| 30 | @AfterAll | 30 | @AfterAll | ||
| 31 | static void afterAll() { | 31 | static void afterAll() { | ||
| 32 | Log.info("========================================"); | 32 | Log.info("========================================"); | ||
| 34 | Log.info("========================================"); | 34 | Log.info("========================================"); | ||
| 35 | } | 35 | } | ||
| 36 | 36 | ||||
| n | n | 37 | // Migration: Migrated WebDriver.get() to Page.navigate() - Playwright Page | ||
| > | handles navigation | ||||
| 37 | @BeforeEach | 38 | @BeforeEach | ||
| 38 | void setUp() { | 39 | void setUp() { | ||
| 39 | Log.info("--- Test Setup Started ---"); | 40 | Log.info("--- Test Setup Started ---"); | ||
| 40 | DriverManager.initializeDriver(); | 41 | DriverManager.initializeDriver(); | ||
| n | 41 | n | |||
| 42 | String baseUrl = ConfigurationReader.getBaseUrl(); | 42 | String baseUrl = ConfigurationReader.getBaseUrl(); | ||
| 43 | if (baseUrl != null && !baseUrl.isEmpty()) { | 43 | if (baseUrl != null && !baseUrl.isEmpty()) { | ||
| n | 44 | getDriver().get(baseUrl); | n | 44 | getPage().navigate(baseUrl); |
| 45 | Log.info("Navigated to: " + baseUrl); | 45 | Log.info("Navigated to: " + baseUrl); | ||
| 46 | } | 46 | } | ||
| 47 | Log.info("--- Test Setup Completed ---"); | 47 | Log.info("--- Test Setup Completed ---"); | ||
| 48 | } | 48 | } | ||
| 49 | 49 | ||||
| n | n | 50 | // Migration: Preserved DriverManager.quitDriver() call - DriverManager hand | ||
| > | les Playwright cleanup | ||||
| 50 | @AfterEach | 51 | @AfterEach | ||
| 51 | void tearDown() { | 52 | void tearDown() { | ||
| 52 | Log.info("--- Test Teardown Started ---"); | 53 | Log.info("--- Test Teardown Started ---"); | ||
| 54 | Log.info("--- Test Teardown Completed ---"); | 55 | Log.info("--- Test Teardown Completed ---"); | ||
| 55 | } | 56 | } | ||
| 56 | 57 | ||||
| n | 57 | protected WebDriver getDriver() { | n | 58 | // Migration: Changed return type from WebDriver to Page - DriverManager now |
| > | returns Playwright Page instance | ||||
| 59 | protected Page getPage() { | ||||
| 58 | return DriverManager.getDriver(); | 60 | return DriverManager.getDriver(); | ||
| 59 | } | 61 | } | ||
| 60 | 62 | ||||
| n | n | 63 | // Migration: Migrated WebDriver.get() to Page.navigate() for URL navigation | ||
| 61 | protected void navigateTo(String url) { | 64 | protected void navigateTo(String url) { | ||
| 62 | Log.step("Navigating to: " + url); | 65 | Log.step("Navigating to: " + url); | ||
| n | 63 | getDriver().get(url); | n | 66 | getPage().navigate(url); |
| 64 | } | 67 | } | ||
| t | t | 68 | |||
| 65 | } | 69 | } | ||
✗ Failed
BasePage.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\pages\BasePage.java
50%
19.3s
✗ Did not compile
3 fix attempt(s)
BasePage.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\pages\BasePage.java
50%
19.3s
✗ Did not compile
3 fix attempt(s)
ℹ Generation failed. Error: 5 compile error(s) after 3 fix attempt(s)
Compiler / generation error
5 compile error(s) after 3 fix attempt(s)
Patterns handled
- sendKeys×1Replace with locator.fill() for inputs or type() for special keys
- click×1Direct conversion to locator.click()
- clear×1Remove - Playwright's fill() clears first
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.pages; | n | 1 | package com.qastarter.pages.playwright; |
| 2 | 2 | ||||
| n | n | 3 | import com.microsoft.playwright.Page; | ||
| 4 | import com.microsoft.playwright.Locator; | ||||
| 3 | import com.qastarter.core.DriverManager; | 5 | import com.qastarter.core.playwright.DriverManager; | ||
| 4 | import com.qastarter.utils.Log; | 6 | import com.qastarter.utils.playwright.Log; | ||
| 5 | import com.qastarter.utils.WaitUtils; | 7 | import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertTha | ||
| > | t; | ||||
| 6 | import org.openqa.selenium.*; | 8 | import org.openqa.selenium.By; | ||
| 7 | 9 | ||||
| n | 8 | /** | n | ||
| 9 | * Base Page - Extend this in all your page objects. | ||||
| 10 | * Uses centralized WaitUtils for all explicit wait operations. | ||||
| 11 | */ | ||||
| 12 | public abstract class BasePage { | 10 | public abstract class BasePage { | ||
| 13 | 11 | ||||
| n | 14 | protected WebDriver driver; | n | 12 | protected Page page; |
| 15 | 13 | ||||
| n | 16 | public BasePage() { | n | 14 | public BasePage() { |
| 17 | this.driver = DriverManager.getDriver(); | 15 | this.page = DriverManager.getDriver(); | ||
| 16 | } | ||||
| 17 | |||||
| 18 | // Migration: Replaced WaitUtils.waitForClickability with Playwright auto-wa | ||||
| > | iting click | ||||
| 19 | protected void click(By locator) { | ||||
| 20 | Log.action("Click: " + locator); | ||||
| 21 | // Convert By locator to CSS selector for Playwright | ||||
| 22 | String selector = convertByToSelector(locator); | ||||
| 23 | page.locator(selector).click(); | ||||
| 24 | } | ||||
| 25 | |||||
| 26 | // Migration: Replaced element.clear() + sendKeys() with Playwright fill() w | ||||
| > | hich handles both | ||||
| 27 | protected void type(By locator, String text) { | ||||
| 28 | Log.action("Type into: " + locator); | ||||
| 29 | // Convert By locator to CSS selector for Playwright | ||||
| 30 | String selector = convertByToSelector(locator); | ||||
| 31 | // Playwright's fill() automatically clears and waits for visibility | ||||
| 32 | page.locator(selector).fill(text); | ||||
| 33 | } | ||||
| 34 | |||||
| 35 | // Migration: Replaced WaitUtils.waitForVisibility with Playwright auto-wait | ||||
| > | ing textContent | ||||
| 36 | protected String getText(By locator) { | ||||
| 37 | String selector = convertByToSelector(locator); | ||||
| 38 | // Playwright auto-waits for visibility before getting text | ||||
| 39 | return page.locator(selector).textContent(); | ||||
| 40 | } | ||||
| 41 | |||||
| 42 | // Migration: Replaced try-catch with Selenium exceptions to Playwright isVi | ||||
| > | sible check | ||||
| 43 | protected boolean isDisplayed(By locator) { | ||||
| 44 | try { | ||||
| 45 | String selector = convertByToSelector(locator); | ||||
| 46 | // Use isVisible() which checks both existence and visibility | ||||
| 47 | return page.locator(selector).isVisible(); | ||||
| 48 | } catch (Exception e) { | ||||
| 49 | return false; | ||||
| 50 | } | ||||
| 51 | } | ||||
| 52 | |||||
| 53 | // Migration: Replaced WaitUtils.waitForVisibility with Playwright waitFor | ||||
| 54 | protected void waitForElement(By locator) { | ||||
| 55 | String selector = convertByToSelector(locator); | ||||
| 56 | // Playwright auto-waits, but we can explicitly wait for visibility | ||||
| 57 | page.locator(selector).waitFor(); | ||||
| 58 | } | ||||
| 59 | |||||
| 60 | // Migration: Direct conversion from driver.getTitle() to page.title() | ||||
| 61 | public String getPageTitle() { | ||||
| 62 | return page.title(); | ||||
| 63 | } | ||||
| 64 | |||||
| 65 | // Migration: Direct conversion from driver.getCurrentUrl() to page.url() | ||||
| 66 | public String getCurrentUrl() { | ||||
| 67 | return page.url(); | ||||
| 68 | } | ||||
| 69 | |||||
| 70 | // Migration: Preserved logging functionality unchanged | ||||
| 71 | protected void logAction(String action) { | ||||
| 72 | Log.step("[" + getClass().getSimpleName() + "] " + action); | ||||
| 73 | } | ||||
| 74 | |||||
| 75 | // Migration: Abstract method preserved unchanged | ||||
| 76 | public abstract boolean isLoaded(); | ||||
| 77 | |||||
| 78 | // Migration: Helper method to convert Selenium By locators to Playwright se | ||||
| > | lectors | ||||
| 79 | private String convertByToSelector(By locator) { | ||||
| 80 | String locatorString = locator.toString(); | ||||
| 81 | if (locatorString.startsWith("By.id: ")) { | ||||
| 82 | return "#" + locatorString.substring(7); | ||||
| 83 | } else if (locatorString.startsWith("By.className: ")) { | ||||
| 84 | return "." + locatorString.substring(14); | ||||
| 85 | } else if (locatorString.startsWith("By.cssSelector: ")) { | ||||
| 86 | return locatorString.substring(16); | ||||
| 87 | } else if (locatorString.startsWith("By.name: ")) { | ||||
| 88 | return "[name='" + locatorString.substring(9) + "']"; | ||||
| 89 | } else if (locatorString.startsWith("By.xpath: ")) { | ||||
| 90 | return "xpath=" + locatorString.substring(10); | ||||
| 91 | } else if (locatorString.startsWith("By.tagName: ")) { | ||||
| 92 | return locatorString.substring(12); | ||||
| 93 | } else { | ||||
| 94 | // Fallback - return as xpath | ||||
| 95 | return "xpath=" + locatorString; | ||||
| 96 | } | ||||
| 97 | } | ||||
| 98 | |||||
| 18 | } | 99 | } | ||
| t | 19 | t | |||
| 20 | protected void click(By locator) { | ||||
| 21 | Log.action("Click: " + locator); | ||||
| 22 | WaitUtils.waitForClickability(driver, locator).click(); | ||||
| 23 | } | ||||
| 24 | |||||
| 25 | protected void type(By locator, String text) { | ||||
| 26 | Log.action("Type into: " + locator); | ||||
| 27 | WebElement element = WaitUtils.waitForVisibility(driver, locator); | ||||
| 28 | element.clear(); | ||||
| 29 | element.sendKeys(text); | ||||
| 30 | } | ||||
| 31 | |||||
| 32 | protected String getText(By locator) { | ||||
| 33 | return WaitUtils.waitForVisibility(driver, locator).getText(); | ||||
| 34 | } | ||||
| 35 | |||||
| 36 | protected boolean isDisplayed(By locator) { | ||||
| 37 | try { | ||||
| 38 | return driver.findElement(locator).isDisplayed(); | ||||
| 39 | } catch (org.openqa.selenium.NoSuchElementException | org.openqa.selenium.StaleE | ||||
| > | lementReferenceException e) { | ||||
| 40 | return false; | ||||
| 41 | } | ||||
| 42 | } | ||||
| 43 | |||||
| 44 | protected void waitForElement(By locator) { | ||||
| 45 | WaitUtils.waitForVisibility(driver, locator); | ||||
| 46 | } | ||||
| 47 | |||||
| 48 | public String getPageTitle() { | ||||
| 49 | return driver.getTitle(); | ||||
| 50 | } | ||||
| 51 | |||||
| 52 | public String getCurrentUrl() { | ||||
| 53 | return driver.getCurrentUrl(); | ||||
| 54 | } | ||||
| 55 | |||||
| 56 | protected void logAction(String action) { | ||||
| 57 | Log.step("[" + getClass().getSimpleName() + "] " + action); | ||||
| 58 | } | ||||
| 59 | |||||
| 60 | public abstract boolean isLoaded(); | ||||
| 61 | } | ||||
✗ Failed
LoginPage.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\pages\LoginPage.java
50%
13.6s
✗ Did not compile
2 fix attempt(s)
LoginPage.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\pages\LoginPage.java
50%
13.6s
✗ Did not compile
2 fix attempt(s)
ℹ Generation failed. Error: 8 compile error(s) after 2 fix attempt(s)
Compiler / generation error
8 compile error(s) after 2 fix attempt(s)
Patterns handled
- By_id×6Convert to CSS selector with #id
- By_cssSelector×2Direct conversion to page.locator()
- click×1Direct conversion to locator.click()
- By_field×4Replace By field with String selector field. Initialize Locator in constructor: this.field = page.locator(selector).
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.pages; | n | 1 | package com.qastarter.pages.playwright; |
| 2 | 2 | ||||
| n | 3 | import org.openqa.selenium.By; | n | 3 | import com.microsoft.playwright.Locator; |
| 4 | import com.microsoft.playwright.Page; | ||||
| 5 | import com.qastarter.pages.playwright.BasePage; | ||||
| 4 | 6 | ||||
| n | 5 | /** | n | ||
| 6 | * Login Page Object for SauceDemo | ||||
| 7 | * URL: https://www.saucedemo.com | ||||
| 8 | * | ||||
| 9 | * HOW TO CUSTOMIZE: | ||||
| 10 | * 1. Update locators below for your app | ||||
| 11 | * 2. Update credentials in: src/main/resources/config/dev.properties | ||||
| 12 | */ | ||||
| 13 | public class LoginPage extends BasePage { | 7 | public class LoginPage extends BasePage { | ||
| 14 | 8 | ||||
| n | 15 | // SauceDemo locators | n | 9 | private final Page page; |
| 16 | private final By usernameField = By.id("user-name"); | 10 | private final Locator usernameField; | ||
| 17 | private final By passwordField = By.id("password"); | 11 | private final Locator passwordField; | ||
| 18 | private final By loginButton = By.id("login-button"); | 12 | private final Locator loginButton; | ||
| 19 | private final By errorMessage = By.cssSelector("[data-test='error']"); | 13 | private final Locator errorMessage; | ||
| 20 | 14 | ||||
| n | n | 15 | public LoginPage(Page page) { | ||
| 16 | this.page = page; | ||||
| 17 | this.usernameField = page.locator("#user-name"); | ||||
| 18 | this.passwordField = page.locator("#password"); | ||||
| 19 | this.loginButton = page.locator("#login-button"); | ||||
| 20 | this.errorMessage = page.locator("[data-test='error']"); | ||||
| 21 | } | ||||
| 22 | |||||
| 23 | // Migration: Replaced isDisplayed() with Playwright's isVisible() for eleme | ||||
| > | nt visibility check | ||||
| 21 | @Override | 24 | @Override | ||
| 22 | public boolean isLoaded() { | 25 | public boolean isLoaded() { | ||
| n | 23 | return isDisplayed(loginButton); | n | 26 | try { |
| 27 | return loginButton.isVisible(); | ||||
| 28 | } catch (Exception e) { | ||||
| 29 | return false; | ||||
| 30 | } | ||||
| 24 | } | 31 | } | ||
| 25 | 32 | ||||
| n | n | 33 | // Migration: Replaced type() helper with direct Playwright fill() - auto-cl | ||
| > | ears before typing | ||||
| 26 | public LoginPage enterUsername(String username) { | 34 | public LoginPage enterUsername(String username) { | ||
| 27 | logAction("Entering username: " + username); | 35 | logAction("Entering username: " + username); | ||
| n | 28 | type(usernameField, username); | n | 36 | usernameField.fill(username); |
| 29 | return this; | 37 | return this; | ||
| 30 | } | 38 | } | ||
| 31 | 39 | ||||
| n | n | 40 | // Migration: Replaced type() helper with direct Playwright fill() - auto-cl | ||
| > | ears before typing | ||||
| 32 | public LoginPage enterPassword(String password) { | 41 | public LoginPage enterPassword(String password) { | ||
| 33 | logAction("Entering password"); | 42 | logAction("Entering password"); | ||
| n | 34 | type(passwordField, password); | n | 43 | passwordField.fill(password); |
| 35 | return this; | 44 | return this; | ||
| 36 | } | 45 | } | ||
| 37 | 46 | ||||
| n | n | 47 | // Migration: Replaced click() helper with direct Playwright click() - auto- | ||
| > | waits for clickability | ||||
| 38 | public void clickLogin() { | 48 | public void clickLogin() { | ||
| 39 | logAction("Clicking login button"); | 49 | logAction("Clicking login button"); | ||
| n | 40 | click(loginButton); | n | 50 | loginButton.click(); |
| 41 | } | 51 | } | ||
| 42 | 52 | ||||
| n | n | 53 | // Migration: Method chaining preserved - no changes needed to business logi | ||
| > | c | ||||
| 43 | public void login(String username, String password) { | 54 | public void login(String username, String password) { | ||
| 44 | enterUsername(username); | 55 | enterUsername(username); | ||
| 45 | enterPassword(password); | 56 | enterPassword(password); | ||
| 46 | clickLogin(); | 57 | clickLogin(); | ||
| 47 | } | 58 | } | ||
| 48 | 59 | ||||
| n | n | 60 | // Migration: Replaced isDisplayed() and getText() with Playwright's isVisib | ||
| > | le() and textContent() | ||||
| 49 | public String getErrorMessage() { | 61 | public String getErrorMessage() { | ||
| n | 50 | return isDisplayed(errorMessage) ? getText(errorMessage) : ""; | n | 62 | try { |
| 63 | return errorMessage.isVisible() ? errorMessage.textContent() : ""; | ||||
| 64 | } catch (Exception e) { | ||||
| 65 | return ""; | ||||
| 66 | } | ||||
| 51 | } | 67 | } | ||
| 52 | 68 | ||||
| n | n | 69 | // Migration: Replaced isDisplayed() helper with direct Playwright isVisible | ||
| > | () check | ||||
| 53 | public boolean isErrorDisplayed() { | 70 | public boolean isErrorDisplayed() { | ||
| n | 54 | return isDisplayed(errorMessage); | n | 71 | try { |
| 72 | return errorMessage.isVisible(); | ||||
| 73 | } catch (Exception e) { | ||||
| 74 | return false; | ||||
| 75 | } | ||||
| 55 | } | 76 | } | ||
| 56 | 77 | ||||
| n | n | 78 | // Migration: Replaced getCurrentUrl() helper with direct Playwright page.ur | ||
| > | l() | ||||
| 57 | public boolean isLoginSuccessful() { | 79 | public boolean isLoginSuccessful() { | ||
| n | 58 | return getCurrentUrl().contains("inventory"); | n | 80 | return page.url().contains("inventory"); |
| 59 | } | 81 | } | ||
| t | t | 82 | |||
| 60 | } | 83 | } | ||
✓ Success
ConfigurationReader.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\config\ConfigurationReader.java
100%
15.2s
✓ Compiled
ConfigurationReader.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\config\ConfigurationReader.java
100%
15.2s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- None detected
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.config; | n | 1 | package com.qastarter.config.playwright; |
| 2 | 2 | ||||
| 3 | import java.io.InputStream; | 3 | import java.io.InputStream; | ||
| 4 | import java.util.Properties; | 4 | import java.util.Properties; | ||
| 18 | private static final Properties properties = new Properties(); | 18 | private static final Properties properties = new Properties(); | ||
| 19 | private static String currentEnvironment; | 19 | private static String currentEnvironment; | ||
| 20 | 20 | ||||
| n | n | 21 | // No constructor needed - utility class with static methods only | ||
| 22 | |||||
| 23 | // Migration: Static initializer preserved - no Playwright-specific changes | ||||
| > | needed for configuration loading | ||||
| 21 | static { | 24 | static { | ||
| 22 | String env = System.getProperty("env", "dev"); | 25 | String env = System.getProperty("env", "dev"); | ||
| 23 | currentEnvironment = (env == null || env.isEmpty()) ? "dev" : env; | 26 | currentEnvironment = (env == null || env.isEmpty()) ? "dev" : env; | ||
| 24 | loadConfig(); | 27 | loadConfig(); | ||
| 25 | } | 28 | } | ||
| 26 | 29 | ||||
| n | n | 30 | // Migration: Configuration loading logic unchanged - works identically for | ||
| > | Playwright | ||||
| 27 | private static void loadConfig() { | 31 | private static void loadConfig() { | ||
| 28 | String configFile = "config/" + currentEnvironment + ".properties"; | 32 | String configFile = "config/" + currentEnvironment + ".properties"; | ||
| 29 | try (InputStream input = ConfigurationReader.class.getClassLoader().getR | 33 | try (InputStream input = ConfigurationReader.class.getClassLoader().getR | ||
| > | esourceAsStream(configFile)) { | > | esourceAsStream(configFile)) { | ||
| 38 | } | 42 | } | ||
| 39 | } | 43 | } | ||
| 40 | 44 | ||||
| n | n | 45 | // Migration: Property lookup preserved - System.getProperty takes precedenc | ||
| > | e over properties file | ||||
| 41 | public static String getProperty(String key) { | 46 | public static String getProperty(String key) { | ||
| 42 | return System.getProperty(key, properties.getProperty(key)); | 47 | return System.getProperty(key, properties.getProperty(key)); | ||
| 43 | } | 48 | } | ||
| 44 | 49 | ||||
| n | 45 | public static String getProperty(String key, String defaultValue) { | n | 50 | // Migration: Base URL retrieval unchanged - used by Playwright page.navigat |
| > | e() calls | ||||
| 46 | String value = getProperty(key); | ||||
| 47 | return value != null ? value : defaultValue; | ||||
| 48 | } | ||||
| 49 | |||||
| 50 | public static String getBaseUrl() { | 51 | public static String getBaseUrl() { | ||
| 51 | return getProperty("base.url"); | 52 | return getProperty("base.url"); | ||
| 52 | } | 53 | } | ||
| 53 | 54 | ||||
| n | n | 55 | // Migration: Browser configuration preserved - used by Playwright browser s | ||
| > | election logic | ||||
| 54 | public static String getBrowser() { | 56 | public static String getBrowser() { | ||
| 55 | return getProperty("browser", "chrome"); | 57 | return getProperty("browser", "chrome"); | ||
| 56 | } | 58 | } | ||
| 57 | 59 | ||||
| n | n | 60 | // Migration: Headless mode configuration preserved - used by Playwright lau | ||
| > | nch options | ||||
| 58 | public static boolean isHeadless() { | 61 | public static boolean isHeadless() { | ||
| 59 | return Boolean.parseBoolean(getProperty("headless", "false")); | 62 | return Boolean.parseBoolean(getProperty("headless", "false")); | ||
| 60 | } | 63 | } | ||
| 61 | 64 | ||||
| n | n | 65 | // Migration: Timeout configuration preserved - used by Playwright page time | ||
| > | out settings | ||||
| 62 | public static int getTimeout() { | 66 | public static int getTimeout() { | ||
| 63 | return Integer.parseInt(getProperty("timeout.default", "30")); | 67 | return Integer.parseInt(getProperty("timeout.default", "30")); | ||
| 64 | } | 68 | } | ||
| 65 | 69 | ||||
| n | n | 70 | // Migration: Environment getter preserved - useful for test reporting and d | ||
| > | ebugging | ||||
| 66 | public static String getCurrentEnvironment() { | 71 | public static String getCurrentEnvironment() { | ||
| 67 | return currentEnvironment; | 72 | return currentEnvironment; | ||
| 68 | } | 73 | } | ||
| t | t | 74 | |||
| 69 | } | 75 | } | ||
✓ Success
Environment.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\config\Environment.java
100%
0.1s
✓ Compiled
Environment.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\config\Environment.java
100%
0.1s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- None detected
✗ Failed
BrowserFactory.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\BrowserFactory.java
50%
11.9s
✗ Did not compile
3 fix attempt(s)
BrowserFactory.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\BrowserFactory.java
50%
11.9s
✗ Did not compile
3 fix attempt(s)
ℹ Generation failed. Error: 2 compile error(s) after 3 fix attempt(s)
Compiler / generation error
2 compile error(s) after 3 fix attempt(s)
Patterns handled
- WebDriver×1Replace with Playwright Page and BrowserContext
- ChromeDriver×1Replace with Playwright browser launch
- FirefoxDriver×1Replace with Playwright Firefox
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.core; | n | 1 | package com.qastarter.core.playwright; |
| 2 | 2 | ||||
| n | 3 | import com.qastarter.utils.Log; | n | 3 | import com.qastarter.utils.playwright.Log; |
| 4 | import org.openqa.selenium.WebDriver; | 4 | import com.microsoft.playwright.*; | ||
| 5 | import org.openqa.selenium.chrome.ChromeDriver; | ||||
| 6 | import org.openqa.selenium.chrome.ChromeOptions; | ||||
| 7 | import org.openqa.selenium.edge.EdgeDriver; | ||||
| 8 | import org.openqa.selenium.edge.EdgeOptions; | ||||
| 9 | import org.openqa.selenium.firefox.FirefoxDriver; | ||||
| 10 | import org.openqa.selenium.firefox.FirefoxOptions; | ||||
| 11 | import org.openqa.selenium.safari.SafariDriver; | ||||
| 12 | 5 | ||||
| n | 13 | /** | n | ||
| 14 | * Browser Factory - Creates WebDriver instances. | ||||
| 15 | * | ||||
| 16 | * Selenium 4.16+ uses built-in Selenium Manager for automatic driver management. | ||||
| 17 | * No external driver setup required! | ||||
| 18 | * | ||||
| 19 | * Supported browsers: chrome, firefox, edge, safari | ||||
| 20 | */ | ||||
| 21 | public class BrowserFactory { | 6 | public class BrowserFactory { | ||
| 22 | 7 | ||||
| n | 23 | private BrowserFactory() {} | n | 8 | private BrowserFactory() {} |
| 24 | 9 | ||||
| n | n | 10 | // Migration: Changed return type from WebDriver to Browser to match Playwri | ||
| > | ght architecture. Browser instances are created using Playwright's browser types | ||||
| > | with launch options. | ||||
| 25 | public static WebDriver createDriver(String browser, boolean headless) { | 11 | public static Browser createDriver(String browser, boolean headless) { | ||
| 26 | WebDriver driver; | 12 | Browser browserInstance; | ||
| 13 | Playwright playwright = Playwright.create(); | ||||
| 14 | switch (browser.toLowerCase()) { | ||||
| 15 | case "firefox": | ||||
| 16 | BrowserType.LaunchOptions firefoxOptions = new BrowserType.LaunchOpt | ||||
| > | ions() | ||||
| 17 | .setHeadless(headless) | ||||
| 18 | .setArgs(java.util.Arrays.asList( | ||||
| 19 | "--width=1920", | ||||
| 20 | "--height=1080" | ||||
| 21 | )); | ||||
| 22 | browserInstance = playwright.firefox().launch(firefoxOptions); | ||||
| 23 | break; | ||||
| 24 | case "edge": | ||||
| 25 | BrowserType.LaunchOptions edgeOptions = new BrowserType.LaunchOption | ||||
| > | s() | ||||
| 26 | .setHeadless(headless) | ||||
| 27 | .setArgs(java.util.Arrays.asList( | ||||
| 28 | "--window-size=1920,1080", | ||||
| 29 | "--no-sandbox", | ||||
| 30 | "--disable-dev-shm-usage", | ||||
| 31 | "--disable-extensions" | ||||
| 32 | )); | ||||
| 33 | browserInstance = playwright.chromium().launch(edgeOptions.setChanne | ||||
| > | l("msedge")); | ||||
| 34 | break; | ||||
| 35 | case "safari": | ||||
| 36 | // Safari does not support headless mode | ||||
| 37 | if (headless) { | ||||
| 38 | Log.warn("Safari does not support headless mode - running in nor | ||||
| > | mal mode"); | ||||
| 39 | } | ||||
| 40 | BrowserType.LaunchOptions safariOptions = new BrowserType.LaunchOpti | ||||
| > | ons() | ||||
| 41 | .setHeadless(false); | ||||
| 42 | browserInstance = playwright.webkit().launch(safariOptions); | ||||
| 43 | break; | ||||
| 44 | case "chrome": | ||||
| 45 | default: | ||||
| 46 | BrowserType.LaunchOptions chromeOptions = new BrowserType.LaunchOpti | ||||
| > | ons() | ||||
| 47 | .setHeadless(headless) | ||||
| 48 | .setArgs(java.util.Arrays.asList( | ||||
| 49 | "--window-size=1920,1080", | ||||
| 50 | "--no-sandbox", | ||||
| 51 | "--disable-dev-shm-usage", | ||||
| 52 | "--disable-gpu", | ||||
| 53 | "--disable-extensions", | ||||
| 54 | "--disable-infobars", | ||||
| 55 | "--ignore-certificate-errors", | ||||
| 56 | "--remote-allow-origins=*" | ||||
| 57 | )); | ||||
| 58 | browserInstance = playwright.chromium().launch(chromeOptions); | ||||
| 59 | break; | ||||
| 60 | } | ||||
| 61 | Log.info("Created " + browser + " browser (Playwright)"); | ||||
| 62 | return browserInstance; | ||||
| 63 | } | ||||
| 27 | 64 | ||||
| n | 28 | switch (browser.toLowerCase()) { | n | ||
| 29 | case "firefox": | ||||
| 30 | FirefoxOptions firefoxOptions = new FirefoxOptions(); | ||||
| 31 | if (headless) { | ||||
| 32 | firefoxOptions.addArguments("--headless"); | ||||
| 33 | } | 65 | } | ||
| t | 34 | firefoxOptions.addArguments("--width=1920"); | t | ||
| 35 | firefoxOptions.addArguments("--height=1080"); | ||||
| 36 | driver = new FirefoxDriver(firefoxOptions); | ||||
| 37 | break; | ||||
| 38 | |||||
| 39 | case "edge": | ||||
| 40 | EdgeOptions edgeOptions = new EdgeOptions(); | ||||
| 41 | if (headless) { | ||||
| 42 | edgeOptions.addArguments("--headless=new"); | ||||
| 43 | } | ||||
| 44 | edgeOptions.addArguments("--window-size=1920,1080"); | ||||
| 45 | edgeOptions.addArguments("--no-sandbox"); | ||||
| 46 | edgeOptions.addArguments("--disable-dev-shm-usage"); | ||||
| 47 | edgeOptions.addArguments("--disable-extensions"); | ||||
| 48 | driver = new EdgeDriver(edgeOptions); | ||||
| 49 | break; | ||||
| 50 | |||||
| 51 | case "safari": | ||||
| 52 | // Safari does not support headless mode | ||||
| 53 | if (headless) { | ||||
| 54 | Log.warn("Safari does not support headless mode - running in normal mode"); | ||||
| 55 | } | ||||
| 56 | driver = new SafariDriver(); | ||||
| 57 | break; | ||||
| 58 | |||||
| 59 | case "chrome": | ||||
| 60 | default: | ||||
| 61 | ChromeOptions chromeOptions = new ChromeOptions(); | ||||
| 62 | if (headless) { | ||||
| 63 | chromeOptions.addArguments("--headless=new"); | ||||
| 64 | } | ||||
| 65 | // Stability options for CI/CD environments | ||||
| 66 | chromeOptions.addArguments("--window-size=1920,1080"); | ||||
| 67 | chromeOptions.addArguments("--no-sandbox"); | ||||
| 68 | chromeOptions.addArguments("--disable-dev-shm-usage"); | ||||
| 69 | chromeOptions.addArguments("--disable-gpu"); | ||||
| 70 | chromeOptions.addArguments("--disable-extensions"); | ||||
| 71 | chromeOptions.addArguments("--disable-infobars"); | ||||
| 72 | chromeOptions.addArguments("--ignore-certificate-errors"); | ||||
| 73 | chromeOptions.addArguments("--remote-allow-origins=*"); | ||||
| 74 | driver = new ChromeDriver(chromeOptions); | ||||
| 75 | break; | ||||
| 76 | } | ||||
| 77 | |||||
| 78 | Log.info("Created " + browser + " driver (Selenium Manager)"); | ||||
| 79 | return driver; | ||||
| 80 | } | ||||
| 81 | } | ||||
✗ Failed
DriverManager.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\DriverManager.java
50%
15.4s
✗ Did not compile
2 fix attempt(s)
DriverManager.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\DriverManager.java
50%
15.4s
✗ Did not compile
2 fix attempt(s)
ℹ Generation failed. Error: 6 compile error(s) after 2 fix attempt(s)
Compiler / generation error
6 compile error(s) after 2 fix attempt(s)
Patterns handled
- WebDriver×3Replace with Playwright Page and BrowserContext
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.core; | n | 1 | package com.qastarter.core.playwright; |
| 2 | 2 | ||||
| n | n | 3 | import com.microsoft.playwright.Browser; | ||
| 4 | import com.microsoft.playwright.BrowserContext; | ||||
| 5 | import com.microsoft.playwright.Page; | ||||
| 6 | import com.microsoft.playwright.Playwright; | ||||
| 3 | import com.qastarter.config.ConfigurationReader; | 7 | import com.qastarter.config.playwright.ConfigurationReader; | ||
| 8 | import com.qastarter.core.playwright.BrowserFactory; | ||||
| 4 | import com.qastarter.utils.Log; | 9 | import com.qastarter.utils.playwright.Log; | ||
| 5 | import org.openqa.selenium.WebDriver; | ||||
| 6 | 10 | ||||
| n | 7 | /** | n | ||
| 8 | * Driver Manager - Thread-safe WebDriver lifecycle management. | ||||
| 9 | * | ||||
| 10 | * Supports parallel test execution via ThreadLocal. | ||||
| 11 | */ | ||||
| 12 | public class DriverManager { | 11 | public class DriverManager { | ||
| 13 | 12 | ||||
| n | 14 | private static final ThreadLocal<WebDriver> driverThreadLocal = new ThreadLo | n | 13 | private static final ThreadLocal<Playwright> playwrightThreadLocal = new Thr |
| > | cal<>(); | > | eadLocal<>(); | ||
| 15 | 14 | ||||
| 16 | private DriverManager() {} | 15 | private DriverManager() {} | ||
| 17 | 16 | ||||
| n | n | 17 | // Migration: Changed return type from WebDriver to Page - Playwright's equi | ||
| > | valent | ||||
| 18 | public static WebDriver getDriver() { | 18 | public static Page getDriver() { | ||
| 19 | WebDriver driver = driverThreadLocal.get(); | 19 | Page page = pageThreadLocal.get(); | ||
| 20 | if (driver == null) { | 20 | if (page == null) { | ||
| 21 | throw new IllegalStateException("Driver not initialized. Call initia | 21 | throw new IllegalStateException("Driver not initialized. Call initia | ||
| > | lizeDriver() first."); | > | lizeDriver() first."); | ||
| 22 | } | 22 | } | ||
| n | 23 | return driver; | n | 23 | return page; |
| 24 | } | 24 | } | ||
| 25 | 25 | ||||
| n | n | 26 | // Migration: Replaced WebDriver creation with Playwright Browser/Page creat | ||
| > | ion, stored all instances in ThreadLocal | ||||
| 26 | public static void initializeDriver() { | 27 | public static void initializeDriver() { | ||
| n | 27 | if (driverThreadLocal.get() != null) { | n | 28 | if (pageThreadLocal.get() != null) { |
| 28 | Log.warn("Driver already exists. Cleaning up..."); | 29 | Log.warn("Driver already exists. Cleaning up..."); | ||
| 29 | quitDriver(); | 30 | quitDriver(); | ||
| 30 | } | 31 | } | ||
| n | 31 | n | |||
| 32 | String browser = ConfigurationReader.getBrowser(); | 32 | String browser = ConfigurationReader.getBrowser(); | ||
| 33 | boolean headless = ConfigurationReader.isHeadless(); | 33 | boolean headless = ConfigurationReader.isHeadless(); | ||
| n | 34 | n | |||
| 35 | Log.info("Initializing browser: " + browser + " | Headless: " + headless | 34 | Log.info("Initializing browser: " + browser + " | Headless: " + headless | ||
| > | ); | > | ); | ||
| n | 36 | n | 35 | // Create Playwright instances | |
| 36 | Playwright playwright = Playwright.create(); | ||||
| 37 | WebDriver driver = BrowserFactory.createDriver(browser, headless); | 37 | Browser browserInstance = BrowserFactory.createDriver(browser, headless) | ||
| > | ; | ||||
| 38 | BrowserContext context = browserInstance.newContext(); | ||||
| 39 | Page page = context.newPage(); | ||||
| 40 | // Store in ThreadLocal | ||||
| 41 | playwrightThreadLocal.set(playwright); | ||||
| 42 | browserThreadLocal.set(browserInstance); | ||||
| 43 | contextThreadLocal.set(context); | ||||
| 38 | driverThreadLocal.set(driver); | 44 | pageThreadLocal.set(page); | ||
| 39 | 45 | // Maximize window equivalent - set viewport size | |||
| 40 | int timeout = ConfigurationReader.getTimeout(); | 46 | page.setViewportSize(1920, 1080); | ||
| 41 | driver.manage().window().maximize(); | ||||
| 42 | |||||
| 43 | Log.info("Browser initialized successfully"); | 47 | Log.info("Browser initialized successfully"); | ||
| 44 | } | 48 | } | ||
| 45 | 49 | ||||
| n | n | 50 | // Migration: Replaced WebDriver.quit() with proper Playwright cleanup seque | ||
| > | nce | ||||
| 46 | public static void quitDriver() { | 51 | public static void quitDriver() { | ||
| n | 47 | WebDriver driver = driverThreadLocal.get(); | n | 52 | Page page = pageThreadLocal.get(); |
| 48 | if (driver != null) { | 53 | if (page != null) { | ||
| 49 | try { | 54 | try { | ||
| n | 50 | driver.quit(); | n | 55 | // Close in reverse order: Page -> Context -> Browser -> Playwri |
| > | ght | ||||
| 56 | BrowserContext context = contextThreadLocal.get(); | ||||
| 57 | Browser browser = browserThreadLocal.get(); | ||||
| 58 | Playwright playwright = playwrightThreadLocal.get(); | ||||
| 59 | if (context != null) { | ||||
| 60 | context.close(); | ||||
| 61 | } | ||||
| 62 | if (browser != null) { | ||||
| 63 | browser.close(); | ||||
| 64 | } | ||||
| 65 | if (playwright != null) { | ||||
| 66 | playwright.close(); | ||||
| 67 | } | ||||
| 51 | Log.info("Browser closed"); | 68 | Log.info("Browser closed"); | ||
| 52 | } catch (Exception e) { | 69 | } catch (Exception e) { | ||
| 53 | Log.error("Error closing browser: " + e.getMessage()); | 70 | Log.error("Error closing browser: " + e.getMessage()); | ||
| 54 | } finally { | 71 | } finally { | ||
| n | n | 72 | // Clean up all ThreadLocal instances | ||
| 73 | pageThreadLocal.remove(); | ||||
| 74 | contextThreadLocal.remove(); | ||||
| 55 | driverThreadLocal.remove(); | 75 | browserThreadLocal.remove(); | ||
| 76 | playwrightThreadLocal.remove(); | ||||
| 56 | } | 77 | } | ||
| 57 | } | 78 | } | ||
| 58 | } | 79 | } | ||
| 59 | 80 | ||||
| n | n | 81 | // Migration: Check Page ThreadLocal instead of WebDriver ThreadLocal | ||
| 60 | public static boolean isDriverInitialized() { | 82 | public static boolean isDriverInitialized() { | ||
| n | 61 | return driverThreadLocal.get() != null; | n | 83 | return pageThreadLocal.get() != null; |
| 62 | } | 84 | } | ||
| t | t | 85 | |||
| 63 | } | 86 | } | ||
✓ Success
TestWatcher.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\TestWatcher.java
100%
9.3s
✓ Compiled
TestWatcher.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\core\TestWatcher.java
100%
9.3s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- None detected
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.core; | n | 1 | package com.qastarter.core.playwright; |
| 2 | 2 | ||||
| n | 3 | import com.qastarter.utils.Log; | n | 3 | import com.qastarter.utils.playwright.Log; |
| 4 | import com.qastarter.utils.ScreenshotUtils; | 4 | import com.qastarter.utils.playwright.ScreenshotUtils; | ||
| 5 | import com.qastarter.utils.AllureManager; | 5 | import com.qastarter.utils.playwright.AllureManager; | ||
| 6 | import org.junit.jupiter.api.extension.ExtensionContext; | 6 | import org.junit.jupiter.api.extension.ExtensionContext; | ||
| n | 7 | n | |||
| 8 | import java.util.Optional; | 7 | import java.util.Optional; | ||
| 9 | 8 | ||||
| n | 10 | /** | n | ||
| 11 | * JUnit5 TestWatcher - Handles test lifecycle events. | ||||
| 12 | */ | ||||
| 13 | public class TestWatcher implements org.junit.jupiter.api.extension.TestWatcher | 9 | public class TestWatcher implements org.junit.jupiter.api.extension.TestWatcher | ||
| > | { | > | { | ||
| 14 | 10 | ||||
| n | n | 11 | // No explicit constructor needed - using default constructor | ||
| 12 | |||||
| 13 | // Migration: No changes needed - Log utility method call preserved | ||||
| 15 | @Override | 14 | @Override | ||
| 16 | public void testSuccessful(ExtensionContext context) { | 15 | public void testSuccessful(ExtensionContext context) { | ||
| 17 | Log.testEnd(context.getDisplayName(), "PASSED"); | 16 | Log.testEnd(context.getDisplayName(), "PASSED"); | ||
| 18 | } | 17 | } | ||
| 19 | 18 | ||||
| n | n | 19 | // Migration: Preserved all logging and screenshot capture logic - utility c | ||
| > | lasses handle Playwright migration internally | ||||
| 20 | @Override | 20 | @Override | ||
| 21 | public void testFailed(ExtensionContext context, Throwable cause) { | 21 | public void testFailed(ExtensionContext context, Throwable cause) { | ||
| 22 | Log.error("TEST FAILED: " + context.getDisplayName()); | 22 | Log.error("TEST FAILED: " + context.getDisplayName()); | ||
| 23 | Log.error("Reason: " + cause.getMessage()); | 23 | Log.error("Reason: " + cause.getMessage()); | ||
| n | 24 | n | |||
| 25 | String screenshotPath = ScreenshotUtils.capture("FAILED_" + context.getD | 24 | String screenshotPath = ScreenshotUtils.capture("FAILED_" + context.getD | ||
| > | isplayName()); | > | isplayName()); | ||
| n | 26 | n | |||
| 27 | byte[] screenshot = ScreenshotUtils.captureAsBytes(); | 25 | byte[] screenshot = ScreenshotUtils.captureAsBytes(); | ||
| 28 | if (screenshot != null) { | 26 | if (screenshot != null) { | ||
| 29 | AllureManager.attachScreenshot("Screenshot on Failure", screenshot); | 27 | AllureManager.attachScreenshot("Screenshot on Failure", screenshot); | ||
| 30 | } | 28 | } | ||
| 31 | } | 29 | } | ||
| 32 | 30 | ||||
| n | n | 31 | // Migration: No changes needed - Log utility method call preserved | ||
| 33 | @Override | 32 | @Override | ||
| 34 | public void testAborted(ExtensionContext context, Throwable cause) { | 33 | public void testAborted(ExtensionContext context, Throwable cause) { | ||
| 35 | Log.warn("TEST ABORTED: " + context.getDisplayName()); | 34 | Log.warn("TEST ABORTED: " + context.getDisplayName()); | ||
| 36 | } | 35 | } | ||
| 37 | 36 | ||||
| n | n | 37 | // Migration: No changes needed - Log utility method call preserved | ||
| 38 | @Override | 38 | @Override | ||
| 39 | public void testDisabled(ExtensionContext context, Optional<String> reason) | 39 | public void testDisabled(ExtensionContext context, Optional<String> reason) | ||
| > | { | > | { | ||
| 40 | Log.warn("TEST DISABLED: " + context.getDisplayName() + " - " + reason.o | 40 | Log.warn("TEST DISABLED: " + context.getDisplayName() + " - " + reason.o | ||
| > | rElse("No reason")); | > | rElse("No reason")); | ||
| 41 | } | 41 | } | ||
| t | t | 42 | |||
| 42 | } | 43 | } | ||
✓ Success
AllureManager.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\AllureManager.java
100%
10.0s
✓ Compiled
AllureManager.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\AllureManager.java
100%
10.0s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- None detected
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.utils; | n | 1 | package com.qastarter.utils.playwright; |
| 2 | 2 | ||||
| 3 | import io.qameta.allure.Allure; | 3 | import io.qameta.allure.Allure; | ||
| 4 | import io.qameta.allure.Attachment; | 4 | import io.qameta.allure.Attachment; | ||
| n | n | 5 | import java.io.ByteArrayInputStream; | ||
| 6 | import com.qastarter.utils.playwright.Log; | ||||
| 5 | 7 | ||||
| n | 6 | import java.io.ByteArrayInputStream; | n | ||
| 7 | |||||
| 8 | /** | ||||
| 9 | * Allure Manager - Allure reporting integration. | ||||
| 10 | * | ||||
| 11 | * Results saved to: build/allure-results (Gradle) or target/allure-results (Mav | ||||
| > | en) | ||||
| 12 | * | ||||
| 13 | * To view report: | ||||
| 14 | * Gradle: gradle allureServe | ||||
| 15 | * Maven: mvn allure:serve | ||||
| 16 | */ | ||||
| 17 | public class AllureManager { | 8 | public class AllureManager { | ||
| 18 | 9 | ||||
| 19 | private AllureManager() {} | 10 | private AllureManager() {} | ||
| 20 | 11 | ||||
| n | n | 12 | // Migration: No changes needed - Allure attachment works the same with Play | ||
| > | wright screenshots | ||||
| 21 | @Attachment(value = "{0}", type = "image/png") | 13 | @Attachment(value = "{0}", type = "image/png") | ||
| 22 | public static byte[] attachScreenshot(String name, byte[] screenshot) { | 14 | public static byte[] attachScreenshot(String name, byte[] screenshot) { | ||
| 23 | Log.info("[Allure] Attaching screenshot: " + name); | 15 | Log.info("[Allure] Attaching screenshot: " + name); | ||
| 24 | return screenshot; | 16 | return screenshot; | ||
| 25 | } | 17 | } | ||
| 26 | 18 | ||||
| n | n | 19 | // Migration: No changes needed - text attachment is framework-agnostic | ||
| 27 | @Attachment(value = "{0}", type = "text/plain") | 20 | @Attachment(value = "{0}", type = "text/plain") | ||
| 28 | public static String attachText(String name, String text) { | 21 | public static String attachText(String name, String text) { | ||
| 29 | return text; | 22 | return text; | ||
| 30 | } | 23 | } | ||
| 31 | 24 | ||||
| n | n | 25 | // Migration: No changes needed - Allure API remains the same for Playwright | ||
| > | screenshots | ||||
| 32 | public static void attachScreenshotToReport(String name, byte[] screenshot) | 26 | public static void attachScreenshotToReport(String name, byte[] screenshot) | ||
| > | { | > | { | ||
| 33 | Allure.addAttachment(name, new ByteArrayInputStream(screenshot)); | 27 | Allure.addAttachment(name, new ByteArrayInputStream(screenshot)); | ||
| 34 | } | 28 | } | ||
| 35 | 29 | ||||
| n | n | 30 | // Migration: No changes needed - Allure step reporting is framework-agnosti | ||
| > | c | ||||
| 36 | public static void step(String stepName) { | 31 | public static void step(String stepName) { | ||
| 37 | Allure.step(stepName); | 32 | Allure.step(stepName); | ||
| 38 | } | 33 | } | ||
| 39 | 34 | ||||
| n | n | 35 | // Migration: No changes needed - Allure description API is framework-agnost | ||
| > | ic | ||||
| 40 | public static void addDescription(String description) { | 36 | public static void addDescription(String description) { | ||
| 41 | Allure.description(description); | 37 | Allure.description(description); | ||
| 42 | } | 38 | } | ||
| 43 | 39 | ||||
| n | n | 40 | // Migration: No changes needed - Allure link API is framework-agnostic | ||
| 44 | public static void addLink(String name, String url) { | 41 | public static void addLink(String name, String url) { | ||
| 45 | Allure.link(name, url); | 42 | Allure.link(name, url); | ||
| 46 | } | 43 | } | ||
| t | t | 44 | |||
| 47 | } | 45 | } | ||
✓ Success
Log.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\Log.java
100%
12.7s
✓ Compiled
Log.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\Log.java
100%
12.7s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- None detected
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.utils; | n | 1 | package com.qastarter.utils.playwright; |
| 2 | 2 | ||||
| 3 | import org.apache.logging.log4j.LogManager; | 3 | import org.apache.logging.log4j.LogManager; | ||
| 4 | import org.apache.logging.log4j.Logger; | 4 | import org.apache.logging.log4j.Logger; | ||
| 5 | 5 | ||||
| n | 6 | /** | n | ||
| 7 | * Logger Utility - Consistent logging across the framework. | ||||
| 8 | * | ||||
| 9 | * Uses Log4j2. Logs go to: logs/test_latest.log | ||||
| 10 | */ | ||||
| 11 | public class Log { | 6 | public class Log { | ||
| 12 | 7 | ||||
| 13 | private static final Logger logger = LogManager.getLogger(Log.class); | 8 | private static final Logger logger = LogManager.getLogger(Log.class); | ||
| 14 | 9 | ||||
| 15 | private Log() {} | 10 | private Log() {} | ||
| 16 | 11 | ||||
| n | n | 12 | // Migration: No changes needed - logging utility remains the same | ||
| 17 | public static void info(String message) { | 13 | public static void info(String message) { | ||
| 18 | logger.info(message); | 14 | logger.info(message); | ||
| 19 | } | 15 | } | ||
| 20 | 16 | ||||
| n | n | 17 | // Migration: No changes needed - logging utility remains the same | ||
| 21 | public static void debug(String message) { | 18 | public static void debug(String message) { | ||
| 22 | logger.debug(message); | 19 | logger.debug(message); | ||
| 23 | } | 20 | } | ||
| 24 | 21 | ||||
| n | n | 22 | // Migration: No changes needed - logging utility remains the same | ||
| 25 | public static void warn(String message) { | 23 | public static void warn(String message) { | ||
| 26 | logger.warn(message); | 24 | logger.warn(message); | ||
| 27 | } | 25 | } | ||
| 28 | 26 | ||||
| n | n | 27 | // Migration: No changes needed - logging utility remains the same | ||
| 29 | public static void error(String message) { | 28 | public static void error(String message) { | ||
| 30 | logger.error(message); | 29 | logger.error(message); | ||
| 31 | } | 30 | } | ||
| 32 | 31 | ||||
| n | 33 | public static void error(String message, Throwable throwable) { | n | 32 | // Migration: No changes needed - test step logging remains the same |
| 34 | logger.error(message, throwable); | ||||
| 35 | } | ||||
| 36 | |||||
| 37 | /** | ||||
| 38 | * Log a test step | ||||
| 39 | */ | ||||
| 40 | public static void step(String stepDescription) { | 33 | public static void step(String stepDescription) { | ||
| 41 | logger.info("STEP: " + stepDescription); | 34 | logger.info("STEP: " + stepDescription); | ||
| 42 | } | 35 | } | ||
| 43 | 36 | ||||
| n | 44 | /** | n | 37 | // Migration: No changes needed - action logging remains the same |
| 45 | * Log an action (click, type, etc.) | ||||
| 46 | */ | ||||
| 47 | public static void action(String actionDescription) { | 38 | public static void action(String actionDescription) { | ||
| 48 | logger.info("ACTION: " + actionDescription); | 39 | logger.info("ACTION: " + actionDescription); | ||
| 49 | } | 40 | } | ||
| 50 | 41 | ||||
| n | 51 | /** | n | 42 | // Migration: Preserved for compatibility - though Playwright auto-waits, ex |
| > | plicit wait logging may still be useful for debugging | ||||
| 52 | * Log wait operation | ||||
| 53 | */ | ||||
| 54 | public static void logWait(String waitDescription) { | 43 | public static void logWait(String waitDescription) { | ||
| 55 | logger.debug("WAIT: " + waitDescription); | 44 | logger.debug("WAIT: " + waitDescription); | ||
| 56 | } | 45 | } | ||
| 57 | 46 | ||||
| n | 58 | /** | n | 47 | // Migration: No changes needed - assertion logging remains the same |
| 59 | * Log assertion | ||||
| 60 | */ | ||||
| 61 | public static void assertion(String assertionDescription) { | 48 | public static void assertion(String assertionDescription) { | ||
| 62 | logger.info("ASSERT: " + assertionDescription); | 49 | logger.info("ASSERT: " + assertionDescription); | ||
| 63 | } | 50 | } | ||
| 64 | 51 | ||||
| n | 65 | /** | n | 52 | // Migration: No changes needed - test lifecycle logging remains the same |
| 66 | * Log test start | ||||
| 67 | */ | ||||
| 68 | public static void testStart(String testName) { | 53 | public static void testStart(String testName) { | ||
| 69 | logger.info("========================================"); | 54 | logger.info("========================================"); | ||
| 70 | logger.info("TEST START: " + testName); | 55 | logger.info("TEST START: " + testName); | ||
| 71 | logger.info("========================================"); | 56 | logger.info("========================================"); | ||
| 72 | } | 57 | } | ||
| 73 | 58 | ||||
| n | 74 | /** | n | 59 | // Migration: No changes needed - test lifecycle logging remains the same |
| 75 | * Log test end | ||||
| 76 | */ | ||||
| 77 | public static void testEnd(String testName, String status) { | 60 | public static void testEnd(String testName, String status) { | ||
| 78 | logger.info("TEST END: " + testName + " - " + status); | 61 | logger.info("TEST END: " + testName + " - " + status); | ||
| 79 | logger.info("========================================"); | 62 | logger.info("========================================"); | ||
| 80 | } | 63 | } | ||
| t | t | 64 | |||
| 81 | } | 65 | } | ||
✗ Failed
ScreenshotUtils.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\ScreenshotUtils.java
50%
10.0s
✗ Did not compile
2 fix attempt(s)
ScreenshotUtils.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\ScreenshotUtils.java
50%
10.0s
✗ Did not compile
2 fix attempt(s)
ℹ Generation failed. Error: 1 compile error(s) after 2 fix attempt(s)
Compiler / generation error
1 compile error(s) after 2 fix attempt(s)
Patterns handled
- WebDriver×2Replace with Playwright Page and BrowserContext
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.utils; | n | 1 | package com.qastarter.utils.playwright; |
| 2 | 2 | ||||
| n | 3 | import com.qastarter.core.DriverManager; | n | 3 | import com.qastarter.core.playwright.DriverManager; |
| 4 | import org.openqa.selenium.OutputType; | 4 | import com.microsoft.playwright.Page; | ||
| 5 | import org.openqa.selenium.TakesScreenshot; | ||||
| 6 | import org.openqa.selenium.WebDriver; | ||||
| 7 | |||||
| 8 | import java.io.File; | 5 | import java.io.File; | ||
| 9 | import java.nio.file.Files; | 6 | import java.nio.file.Files; | ||
| 10 | import java.nio.file.Path; | 7 | import java.nio.file.Path; | ||
| 12 | import java.text.SimpleDateFormat; | 9 | import java.text.SimpleDateFormat; | ||
| 13 | import java.util.Date; | 10 | import java.util.Date; | ||
| 14 | 11 | ||||
| n | 15 | /** | n | ||
| 16 | * Screenshot Utilities - Capture screenshots on demand. | ||||
| 17 | * | ||||
| 18 | * Screenshots saved to: screenshots/ | ||||
| 19 | */ | ||||
| 20 | public class ScreenshotUtils { | 12 | public class ScreenshotUtils { | ||
| 21 | 13 | ||||
| 22 | private static final String SCREENSHOT_DIR = "screenshots"; | 14 | private static final String SCREENSHOT_DIR = "screenshots"; | ||
| 23 | 15 | ||||
| 24 | private ScreenshotUtils() {} | 16 | private ScreenshotUtils() {} | ||
| 25 | 17 | ||||
| n | n | 18 | // Migration: Replaced WebDriver TakesScreenshot with Playwright page.screen | ||
| > | shot() which returns bytes directly | ||||
| 26 | public static String capture(String testName) { | 19 | public static String capture(String testName) { | ||
| 27 | try { | 20 | try { | ||
| n | 28 | WebDriver driver = DriverManager.getDriver(); | n | 21 | Page page = DriverManager.getDriver(); |
| 29 | if (driver == null) { | 22 | if (page == null) { | ||
| 30 | Log.error("Cannot capture screenshot - driver is null"); | 23 | Log.error("Cannot capture screenshot - page is null"); | ||
| 31 | return null; | 24 | return null; | ||
| 32 | } | 25 | } | ||
| n | 33 | n | |||
| 34 | Path dir = Paths.get(SCREENSHOT_DIR); | 26 | Path dir = Paths.get(SCREENSHOT_DIR); | ||
| 35 | if (!Files.exists(dir)) { | 27 | if (!Files.exists(dir)) { | ||
| 36 | Files.createDirectories(dir); | 28 | Files.createDirectories(dir); | ||
| 37 | } | 29 | } | ||
| n | 38 | n | |||
| 39 | String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(ne | 30 | String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(ne | ||
| > | w Date()); | > | w Date()); | ||
| 40 | String sanitizedName = testName.replaceAll("[^a-zA-Z0-9_-]", "_"); | 31 | String sanitizedName = testName.replaceAll("[^a-zA-Z0-9_-]", "_"); | ||
| 41 | String fileName = sanitizedName + "_" + timestamp + ".png"; | 32 | String fileName = sanitizedName + "_" + timestamp + ".png"; | ||
| 42 | Path filePath = dir.resolve(fileName); | 33 | Path filePath = dir.resolve(fileName); | ||
| n | 43 | n | 34 | // Playwright screenshot capture - returns byte array directly | |
| 44 | File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputT | 35 | byte[] screenshot = page.screenshot(); | ||
| > | ype.FILE); | ||||
| 45 | Files.copy(screenshot.toPath(), filePath); | 36 | Files.write(filePath, screenshot); | ||
| 46 | |||||
| 47 | Log.info("Screenshot saved: " + filePath); | 37 | Log.info("Screenshot saved: " + filePath); | ||
| 48 | return filePath.toString(); | 38 | return filePath.toString(); | ||
| n | 49 | n | |||
| 50 | } catch (Exception e) { | 39 | } catch (Exception e) { | ||
| 51 | Log.error("Failed to capture screenshot: " + e.getMessage()); | 40 | Log.error("Failed to capture screenshot: " + e.getMessage()); | ||
| 52 | return null; | 41 | return null; | ||
| 53 | } | 42 | } | ||
| 54 | } | 43 | } | ||
| 55 | 44 | ||||
| n | n | 45 | // Migration: Replaced WebDriver TakesScreenshot with Playwright page.screen | ||
| > | shot() - much simpler API | ||||
| 56 | public static byte[] captureAsBytes() { | 46 | public static byte[] captureAsBytes() { | ||
| 57 | try { | 47 | try { | ||
| n | 58 | WebDriver driver = DriverManager.getDriver(); | n | 48 | Page page = DriverManager.getDriver(); |
| 59 | if (driver == null) return null; | 49 | if (page == null) return null; | ||
| 60 | return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES); | 50 | // Playwright screenshot returns byte array directly | ||
| 51 | return page.screenshot(); | ||||
| 61 | } catch (Exception e) { | 52 | } catch (Exception e) { | ||
| 62 | Log.error("Failed to capture screenshot bytes: " + e.getMessage()); | 53 | Log.error("Failed to capture screenshot bytes: " + e.getMessage()); | ||
| 63 | return null; | 54 | return null; | ||
| 64 | } | 55 | } | ||
| 65 | } | 56 | } | ||
| t | t | 57 | |||
| 66 | } | 58 | } | ||
✗ Failed
WaitUtils.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\WaitUtils.java
50%
27.6s
✗ Did not compile
2 fix attempt(s)
WaitUtils.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\WaitUtils.java
50%
27.6s
✗ Did not compile
2 fix attempt(s)
ℹ Generation failed. Error: 4 compile error(s) after 2 fix attempt(s)
Compiler / generation error
4 compile error(s) after 2 fix attempt(s)
Patterns handled
- WebDriverWait×2Remove explicit wait - Playwright auto-waits for actionability
- ExpectedConditions×10Replace with Playwright assertions or locator methods
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.utils; | n | 1 | package com.qastarter.utils.playwright; |
| 2 | 2 | ||||
| n | n | 3 | import com.microsoft.playwright.Locator; | ||
| 4 | import com.microsoft.playwright.Page; | ||||
| 3 | import com.qastarter.config.ConfigurationReader; | 5 | import com.qastarter.config.playwright.ConfigurationReader; | ||
| 4 | import com.qastarter.core.DriverManager; | 6 | import com.qastarter.core.playwright.DriverManager; | ||
| 7 | import com.qastarter.utils.playwright.Log; | ||||
| 5 | import org.openqa.selenium.By; | 8 | import org.openqa.selenium.By; | ||
| n | 6 | import org.openqa.selenium.WebDriver; | n | ||
| 7 | import org.openqa.selenium.WebElement; | 9 | import org.openqa.selenium.WebElement; | ||
| n | 8 | import org.openqa.selenium.support.ui.ExpectedConditions; | n | 10 | import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertTha |
| > | t; | ||||
| 9 | import org.openqa.selenium.support.ui.WebDriverWait; | ||||
| 10 | 11 | ||||
| n | 11 | import java.time.Duration; | n | ||
| 12 | |||||
| 13 | /** | ||||
| 14 | * Wait Utilities - Explicit wait helpers. | ||||
| 15 | * | ||||
| 16 | * Timeout configured in: src/main/resources/config/{env}.properties | ||||
| 17 | */ | ||||
| 18 | public class WaitUtils { | 12 | public class WaitUtils { | ||
| 19 | 13 | ||||
| n | n | 14 | // No constructor needed - utility class with static methods only | ||
| 15 | |||||
| 16 | // Migration: Preserved private constructor to prevent instantiation | ||||
| 20 | private WaitUtils() { | 17 | private WaitUtils() { | ||
| 21 | // Private constructor | 18 | // Private constructor | ||
| 22 | } | 19 | } | ||
| 23 | 20 | ||||
| n | 24 | private static WebDriverWait getWait() { | n | 21 | // Migration: Replaced WebDriverWait with Playwright auto-waiting and visibi |
| > | lity assertion | ||||
| 25 | int timeout = ConfigurationReader.getTimeout(); | 22 | public static WebElement waitForVisibility(By locator) { | ||
| 26 | return new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(t | 23 | Log.logWait("Waiting for visibility: " + locator); | ||
| > | imeout)); | ||||
| 24 | // In Playwright, locator actions auto-wait for visibility | ||||
| 25 | // Convert By to CSS selector and ensure element is visible | ||||
| 26 | Page page = DriverManager.getDriver(); | ||||
| 27 | String selector = convertByToSelector(locator); | ||||
| 28 | Locator element = page.locator(selector); | ||||
| 29 | assertThat(element).isVisible(); | ||||
| 30 | // Return null as WebElement is not applicable in Playwright context | ||||
| 31 | // This maintains API compatibility while using Playwright's auto-waitin | ||||
| > | g | ||||
| 32 | return null; | ||||
| 27 | } | 33 | } | ||
| 28 | 34 | ||||
| n | 29 | private static WebDriverWait getWait(WebDriver driver) { | n | 35 | // Migration: Replaced explicit clickability wait with Playwright visibility |
| > | and enabled assertions | ||||
| 30 | int timeout = ConfigurationReader.getTimeout(); | 36 | public static WebElement waitForClickability(By locator) { | ||
| 31 | return new WebDriverWait(driver, Duration.ofSeconds(timeout)); | 37 | Log.logWait("Waiting for clickability: " + locator); | ||
| 38 | // Playwright auto-waits for clickability on click actions | ||||
| 39 | // We can verify element is enabled and visible | ||||
| 40 | Page page = DriverManager.getDriver(); | ||||
| 41 | String selector = convertByToSelector(locator); | ||||
| 42 | Locator element = page.locator(selector); | ||||
| 43 | assertThat(element).isVisible(); | ||||
| 44 | assertThat(element).isEnabled(); | ||||
| 45 | return null; | ||||
| 32 | } | 46 | } | ||
| 33 | 47 | ||||
| n | 34 | /** | n | 48 | // Migration: Replaced presence wait with Playwright attached assertion |
| 35 | * Wait for element to be visible | ||||
| 36 | */ | ||||
| 37 | public static WebElement waitForVisibility(By locator) { | 49 | public static WebElement waitForPresence(By locator) { | ||
| 38 | Log.logWait("Waiting for visibility: " + locator); | 50 | Log.logWait("Waiting for presence: " + locator); | ||
| 39 | return getWait().until(ExpectedConditions.visibilityOfElementLocated(loc | 51 | // Playwright locators auto-wait for presence in DOM | ||
| > | ator)); | ||||
| 52 | Page page = DriverManager.getDriver(); | ||||
| 53 | String selector = convertByToSelector(locator); | ||||
| 54 | Locator element = page.locator(selector); | ||||
| 55 | assertThat(element).isAttached(); | ||||
| 56 | return null; | ||||
| 40 | } | 57 | } | ||
| 41 | 58 | ||||
| n | 42 | /** | n | 59 | // Migration: Replaced invisibility wait with Playwright hidden assertion |
| 43 | * Wait for element to be clickable | ||||
| 44 | */ | ||||
| 45 | public static WebElement waitForClickability(By locator) { | 60 | public static boolean waitForInvisibility(By locator) { | ||
| 46 | Log.logWait("Waiting for clickability: " + locator); | 61 | Log.logWait("Waiting for invisibility: " + locator); | ||
| 47 | return getWait().until(ExpectedConditions.elementToBeClickable(locator)) | 62 | Page page = DriverManager.getDriver(); | ||
| > | ; | ||||
| 63 | String selector = convertByToSelector(locator); | ||||
| 64 | Locator element = page.locator(selector); | ||||
| 65 | assertThat(element).isHidden(); | ||||
| 66 | return true; | ||||
| 48 | } | 67 | } | ||
| 49 | 68 | ||||
| n | 50 | /** | n | 69 | // Migration: Replaced text presence wait with Playwright containsText asser |
| > | tion | ||||
| 51 | * Wait for element to be present in DOM | ||||
| 52 | */ | ||||
| 53 | public static WebElement waitForPresence(By locator) { | 70 | public static boolean waitForTextPresent(By locator, String text) { | ||
| 54 | Log.logWait("Waiting for presence: " + locator); | 71 | Log.logWait("Waiting for text '" + text + "' in: " + locator); | ||
| 55 | return getWait().until(ExpectedConditions.presenceOfElementLocated(locat | 72 | Page page = DriverManager.getDriver(); | ||
| > | or)); | ||||
| 73 | String selector = convertByToSelector(locator); | ||||
| 74 | Locator element = page.locator(selector); | ||||
| 75 | assertThat(element).containsText(text); | ||||
| 76 | return true; | ||||
| 56 | } | 77 | } | ||
| 57 | 78 | ||||
| n | 58 | /** | n | 79 | // Migration: Helper method to convert Selenium By locators to Playwright se |
| > | lector strings | ||||
| 59 | * Wait for element to disappear | 80 | private static String convertByToSelector(By locator) { | ||
| 60 | */ | 81 | String locatorString = locator.toString(); | ||
| 61 | public static boolean waitForInvisibility(By locator) { | 82 | if (locatorString.startsWith("By.id: ")) { | ||
| 62 | Log.logWait("Waiting for invisibility: " + locator); | 83 | return "#" + locatorString.substring(7); | ||
| 63 | return getWait().until(ExpectedConditions.invisibilityOfElementLocated(l | 84 | } else if (locatorString.startsWith("By.className: ")) { | ||
| > | ocator)); | ||||
| 85 | return "." + locatorString.substring(14); | ||||
| 86 | } else if (locatorString.startsWith("By.cssSelector: ")) { | ||||
| 87 | return locatorString.substring(16); | ||||
| 88 | } else if (locatorString.startsWith("By.xpath: ")) { | ||||
| 89 | return "xpath=" + locatorString.substring(10); | ||||
| 90 | } else if (locatorString.startsWith("By.name: ")) { | ||||
| 91 | return "[name='" + locatorString.substring(9) + "']"; | ||||
| 92 | } else if (locatorString.startsWith("By.tagName: ")) { | ||||
| 93 | return locatorString.substring(12); | ||||
| 94 | } else { | ||||
| 95 | // Fallback - return as xpath | ||||
| 96 | return "xpath=" + locatorString; | ||||
| 97 | } | ||||
| 64 | } | 98 | } | ||
| 65 | 99 | ||||
| t | 66 | /** | t | ||
| 67 | * Wait for text to be present in element | ||||
| 68 | */ | ||||
| 69 | public static boolean waitForTextPresent(By locator, String text) { | ||||
| 70 | Log.logWait("Waiting for text '" + text + "' in: " + locator); | ||||
| 71 | return getWait().until(ExpectedConditions.textToBePresentInElementLocate | ||||
| > | d(locator, text)); | ||||
| 72 | } | ||||
| 73 | |||||
| 74 | // -------- Driver-explicit overloads (for callers that hold their own WebDr | ||||
| > | iver) -------- | ||||
| 75 | |||||
| 76 | public static WebElement waitForVisibility(WebDriver driver, By locator) { | ||||
| 77 | Log.logWait("Waiting for visibility: " + locator); | ||||
| 78 | return getWait(driver).until(ExpectedConditions.visibilityOfElementLocat | ||||
| > | ed(locator)); | ||||
| 79 | } | ||||
| 80 | |||||
| 81 | public static WebElement waitForClickability(WebDriver driver, By locator) { | ||||
| 82 | Log.logWait("Waiting for clickability: " + locator); | ||||
| 83 | return getWait(driver).until(ExpectedConditions.elementToBeClickable(loc | ||||
| > | ator)); | ||||
| 84 | } | ||||
| 85 | |||||
| 86 | public static WebElement waitForPresence(WebDriver driver, By locator) { | ||||
| 87 | Log.logWait("Waiting for presence: " + locator); | ||||
| 88 | return getWait(driver).until(ExpectedConditions.presenceOfElementLocated | ||||
| > | (locator)); | ||||
| 89 | } | ||||
| 90 | |||||
| 91 | public static boolean waitForInvisibility(WebDriver driver, By locator) { | ||||
| 92 | Log.logWait("Waiting for invisibility: " + locator); | ||||
| 93 | return getWait(driver).until(ExpectedConditions.invisibilityOfElementLoc | ||||
| > | ated(locator)); | ||||
| 94 | } | ||||
| 95 | |||||
| 96 | public static boolean waitForTextPresent(WebDriver driver, By locator, Strin | ||||
| > | g text) { | ||||
| 97 | Log.logWait("Waiting for text '" + text + "' in: " + locator); | ||||
| 98 | return getWait(driver).until(ExpectedConditions.textToBePresentInElement | ||||
| > | Located(locator, text)); | ||||
| 99 | } | ||||
| 100 | } | 100 | } | ||
✗ Failed
WebActions.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\WebActions.java
50%
24.5s
✗ Did not compile
3 fix attempt(s)
WebActions.java
D:\TestFlux\samples\selenium-java-project-bdd\src\main\java\com\qastarter\utils\WebActions.java
50%
24.5s
✗ Did not compile
3 fix attempt(s)
ℹ Generation failed. Error: 3 compile error(s) after 3 fix attempt(s)
Compiler / generation error
3 compile error(s) after 3 fix attempt(s)
Patterns handled
- Actions×1Replace with Playwright keyboard/mouse APIs
- sendKeys×1Replace with locator.fill() for inputs or type() for special keys
- click×1Direct conversion to locator.click()
- clear×1Remove - Playwright's fill() clears first
- Select×1Replace with locator.selectOption()
- JavascriptExecutor×2Replace with page.evaluate()
- hover×1Replace with locator.hover()
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.utils; | n | 1 | package com.qastarter.utils.playwright; |
| 2 | 2 | ||||
| n | n | 3 | import com.microsoft.playwright.Locator; | ||
| 4 | import com.microsoft.playwright.Page; | ||||
| 3 | import com.qastarter.core.DriverManager; | 5 | import com.qastarter.core.playwright.DriverManager; | ||
| 6 | import com.qastarter.utils.playwright.Log; | ||||
| 4 | import org.openqa.selenium.By; | 7 | import org.openqa.selenium.By; | ||
| n | 5 | import org.openqa.selenium.JavascriptExecutor; | n | ||
| 6 | import org.openqa.selenium.WebDriver; | ||||
| 7 | import org.openqa.selenium.WebElement; | ||||
| 8 | import org.openqa.selenium.interactions.Actions; | ||||
| 9 | import org.openqa.selenium.support.ui.Select; | ||||
| 10 | 8 | ||||
| n | 11 | /** | n | ||
| 12 | * Web Actions - Common web interaction utilities. | ||||
| 13 | * | ||||
| 14 | * All methods include logging and error handling. | ||||
| 15 | */ | ||||
| 16 | public class WebActions { | 9 | public class WebActions { | ||
| 17 | 10 | ||||
| 18 | private WebActions() { | 11 | private WebActions() { | ||
| 19 | // Private constructor | 12 | // Private constructor | ||
| 20 | } | 13 | } | ||
| 21 | 14 | ||||
| n | n | 15 | // Migration: Changed from getDriver() to getPage() to reflect Playwright AP | ||
| > | I | ||||
| 22 | private static WebDriver getDriver() { | 16 | private static Page getPage() { | ||
| 23 | return DriverManager.getDriver(); | 17 | return DriverManager.getDriver(); | ||
| 24 | } | 18 | } | ||
| 25 | 19 | ||||
| n | 26 | /** | n | 20 | // Migration: Replaced WebElement.click() with Playwright locator.click() - |
| > | auto-waits for clickability | ||||
| 27 | * Click on element | ||||
| 28 | */ | ||||
| 29 | public static void click(By locator) { | 21 | public static void click(By locator) { | ||
| 30 | Log.action("Click: " + locator); | 22 | Log.action("Click: " + locator); | ||
| n | 31 | WebElement element = WaitUtils.waitForClickability(locator); | n | 23 | // Convert By locator to CSS selector for Playwright |
| 32 | element.click(); | 24 | String selector = convertByToSelector(locator); | ||
| 25 | getPage().locator(selector).click(); | ||||
| 33 | } | 26 | } | ||
| 34 | 27 | ||||
| n | 35 | /** | n | 28 | // Migration: Replaced clear() + sendKeys() with Playwright fill() which han |
| > | dles both operations | ||||
| 36 | * Type text into element | ||||
| 37 | */ | ||||
| 38 | public static void type(By locator, String text) { | 29 | public static void type(By locator, String text) { | ||
| 39 | String maskedText = maskSensitiveData(text); | 30 | String maskedText = maskSensitiveData(text); | ||
| 40 | Log.action("Type '" + maskedText + "' into: " + locator); | 31 | Log.action("Type '" + maskedText + "' into: " + locator); | ||
| n | 41 | WebElement element = WaitUtils.waitForVisibility(locator); | n | 32 | String selector = convertByToSelector(locator); |
| 42 | element.clear(); | 33 | // Playwright's fill() automatically clears and types | ||
| 43 | element.sendKeys(text); | 34 | getPage().locator(selector).fill(text); | ||
| 44 | } | 35 | } | ||
| 45 | 36 | ||||
| n | 46 | /** | n | 37 | // Migration: Replaced WebElement.getText() with Playwright locator.textCont |
| > | ent() - auto-waits for visibility | ||||
| 47 | * Get text from element | ||||
| 48 | */ | ||||
| 49 | public static String getText(By locator) { | 38 | public static String getText(By locator) { | ||
| n | 50 | WebElement element = WaitUtils.waitForVisibility(locator); | n | 39 | String selector = convertByToSelector(locator); |
| 51 | return element.getText(); | 40 | return getPage().locator(selector).textContent(); | ||
| 52 | } | 41 | } | ||
| 53 | 42 | ||||
| n | 54 | /** | n | 43 | // Migration: Replaced WebElement.isDisplayed() with Playwright locator.isVi |
| > | sible() | ||||
| 55 | * Check if element is displayed | ||||
| 56 | */ | ||||
| 57 | public static boolean isDisplayed(By locator) { | 44 | public static boolean isDisplayed(By locator) { | ||
| 58 | try { | 45 | try { | ||
| n | 59 | return getDriver().findElement(locator).isDisplayed(); | n | 46 | String selector = convertByToSelector(locator); |
| 47 | return getPage().locator(selector).isVisible(); | ||||
| 60 | } catch (Exception e) { | 48 | } catch (Exception e) { | ||
| 61 | return false; | 49 | return false; | ||
| 62 | } | 50 | } | ||
| 63 | } | 51 | } | ||
| 64 | 52 | ||||
| n | 65 | /** | n | 53 | // Migration: Replaced WebElement.isEnabled() with Playwright locator.isEnab |
| > | led() | ||||
| 66 | * Check if element is enabled | ||||
| 67 | */ | ||||
| 68 | public static boolean isEnabled(By locator) { | 54 | public static boolean isEnabled(By locator) { | ||
| 69 | try { | 55 | try { | ||
| n | n | 56 | String selector = convertByToSelector(locator); | ||
| 70 | return getDriver().findElement(locator).isEnabled(); | 57 | return getPage().locator(selector).isEnabled(); | ||
| 71 | } catch (Exception e) { | 58 | } catch (Exception e) { | ||
| 72 | return false; | 59 | return false; | ||
| 73 | } | 60 | } | ||
| 74 | } | 61 | } | ||
| 75 | 62 | ||||
| n | 76 | /** | n | 63 | // Migration: Replaced Selenium Select with Playwright selectOption() - auto |
| > | -waits for element | ||||
| 77 | * Select option by visible text | ||||
| 78 | */ | ||||
| 79 | public static void selectByText(By locator, String text) { | 64 | public static void selectByText(By locator, String text) { | ||
| 80 | Log.action("Select '" + text + "' from: " + locator); | 65 | Log.action("Select '" + text + "' from: " + locator); | ||
| n | 81 | WebElement element = WaitUtils.waitForVisibility(locator); | n | 66 | String selector = convertByToSelector(locator); |
| 82 | new Select(element).selectByVisibleText(text); | 67 | // Playwright selectOption by visible text | ||
| 68 | getPage().locator(selector).selectOption(new String[]{text}); | ||||
| 83 | } | 69 | } | ||
| 84 | 70 | ||||
| n | 85 | /** | n | 71 | // Migration: Replaced JavaScript scrollIntoView with Playwright scrollIntoV |
| > | iewIfNeeded() | ||||
| 86 | * Scroll to element | ||||
| 87 | */ | ||||
| 88 | public static void scrollToElement(By locator) { | 72 | public static void scrollToElement(By locator) { | ||
| 89 | Log.action("Scroll to: " + locator); | 73 | Log.action("Scroll to: " + locator); | ||
| n | 90 | WebElement element = getDriver().findElement(locator); | n | 74 | String selector = convertByToSelector(locator); |
| 91 | ((JavascriptExecutor) getDriver()).executeScript("arguments[0].scrollInt | 75 | getPage().locator(selector).scrollIntoViewIfNeeded(); | ||
| > | oView(true);", element); | ||||
| 92 | } | 76 | } | ||
| 93 | 77 | ||||
| n | 94 | /** | n | 78 | // Migration: Replaced Selenium Actions.moveToElement() with Playwright loca |
| > | tor.hover() - auto-waits | ||||
| 95 | * Hover over element | ||||
| 96 | */ | ||||
| 97 | public static void hover(By locator) { | 79 | public static void hover(By locator) { | ||
| 98 | Log.action("Hover: " + locator); | 80 | Log.action("Hover: " + locator); | ||
| n | 99 | WebElement element = WaitUtils.waitForVisibility(locator); | n | 81 | String selector = convertByToSelector(locator); |
| 100 | new Actions(getDriver()).moveToElement(element).perform(); | 82 | getPage().locator(selector).hover(); | ||
| 101 | } | 83 | } | ||
| 102 | 84 | ||||
| n | 103 | /** | n | 85 | // Migration: Replaced JavascriptExecutor with Playwright page.evaluate() fo |
| > | r JavaScript execution | ||||
| 104 | * JavaScript click (for stubborn elements) | ||||
| 105 | */ | ||||
| 106 | public static void jsClick(By locator) { | 86 | public static void jsClick(By locator) { | ||
| 107 | Log.action("JS Click: " + locator); | 87 | Log.action("JS Click: " + locator); | ||
| n | 108 | WebElement element = getDriver().findElement(locator); | n | 88 | String selector = convertByToSelector(locator); |
| 109 | ((JavascriptExecutor) getDriver()).executeScript("arguments[0].click();" | 89 | // Use Playwright's evaluate to perform JavaScript click | ||
| > | , element); | ||||
| 90 | getPage().evaluate("document.querySelector('" + selector + "').click()") | ||||
| > | ; | ||||
| 110 | } | 91 | } | ||
| 111 | 92 | ||||
| n | 112 | /** | n | 93 | // Migration: Utility method preserved as-is - no Playwright changes needed |
| 113 | * Mask sensitive data for logging | ||||
| 114 | */ | ||||
| 115 | private static String maskSensitiveData(String text) { | 94 | private static String maskSensitiveData(String text) { | ||
| 116 | if (text == null || text.length() <= 2) { | 95 | if (text == null || text.length() <= 2) { | ||
| 117 | return "****"; | 96 | return "****"; | ||
| 118 | } | 97 | } | ||
| 119 | return text.substring(0, 2) + "****"; | 98 | return text.substring(0, 2) + "****"; | ||
| 120 | } | 99 | } | ||
| t | t | 100 | |||
| 101 | // Migration: Helper method to convert Selenium By locators to Playwright se | ||||
| > | lector strings | ||||
| 102 | private static String convertByToSelector(By locator) { | ||||
| 103 | String locatorString = locator.toString(); | ||||
| 104 | if (locatorString.startsWith("By.id: ")) { | ||||
| 105 | return "#" + locatorString.substring(7); | ||||
| 106 | } else if (locatorString.startsWith("By.className: ")) { | ||||
| 107 | return "." + locatorString.substring(14); | ||||
| 108 | } else if (locatorString.startsWith("By.cssSelector: ")) { | ||||
| 109 | return locatorString.substring(16); | ||||
| 110 | } else if (locatorString.startsWith("By.name: ")) { | ||||
| 111 | return "[name='" + locatorString.substring(9) + "']"; | ||||
| 112 | } else if (locatorString.startsWith("By.tagName: ")) { | ||||
| 113 | return locatorString.substring(12); | ||||
| 114 | } else if (locatorString.startsWith("By.xpath: ")) { | ||||
| 115 | return "xpath=" + locatorString.substring(10); | ||||
| 116 | } else if (locatorString.startsWith("By.linkText: ")) { | ||||
| 117 | // For link text, we'll use a more complex selector | ||||
| 118 | String linkText = locatorString.substring(13); | ||||
| 119 | return "a:has-text('" + linkText + "')"; | ||||
| 120 | } else if (locatorString.startsWith("By.partialLinkText: ")) { | ||||
| 121 | String partialText = locatorString.substring(20); | ||||
| 122 | return "a:has-text('" + partialText + "')"; | ||||
| 123 | } | ||||
| 124 | // Fallback - return as xpath if we can't parse it | ||||
| 125 | return "xpath=" + locatorString; | ||||
| 126 | } | ||||
| 127 | |||||
| 121 | } | 128 | } | ||
✓ Success
TestRunner.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\runners\TestRunner.java
100%
0.1s
✓ Compiled
TestRunner.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\runners\TestRunner.java
100%
0.1s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- None detected
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| t | 1 | package com.qastarter.runners; | t | 1 | package com.qastarter.runners.playwright; |
| 2 | 2 | ||||
| 3 | import org.junit.platform.suite.api.ConfigurationParameter; | 3 | import org.junit.platform.suite.api.ConfigurationParameter; | ||
| 4 | import org.junit.platform.suite.api.IncludeEngines; | 4 | import org.junit.platform.suite.api.IncludeEngines; | ||
✓ Success
Hooks.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\stepdefinitions\Hooks.java
100%
8.9s
✓ Compiled
Hooks.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\stepdefinitions\Hooks.java
100%
8.9s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- Cucumber_Scenario_Inject×2Keep io.cucumber.java.Scenario parameter injection unchanged. Scenario.attach() is the same in Cucumber 7+ regardless of underlying browser framework.
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.stepdefinitions; | n | 1 | package com.qastarter.stepdefinitions.playwright; |
| 2 | 2 | ||||
| n | 3 | import com.qastarter.core.DriverManager; | n | 3 | import com.qastarter.core.playwright.DriverManager; |
| 4 | import com.qastarter.utils.Log; | 4 | import com.qastarter.utils.playwright.Log; | ||
| 5 | import com.qastarter.utils.ScreenshotUtils; | 5 | import com.qastarter.utils.playwright.ScreenshotUtils; | ||
| 6 | import io.cucumber.java.After; | 6 | import io.cucumber.java.After; | ||
| 7 | import io.cucumber.java.Before; | 7 | import io.cucumber.java.Before; | ||
| 8 | import io.cucumber.java.Scenario; | 8 | import io.cucumber.java.Scenario; | ||
| 9 | 9 | ||||
| n | 10 | /** | n | ||
| 11 | * Cucumber Hooks - Setup and teardown for BDD scenarios. | ||||
| 12 | */ | ||||
| 13 | public class Hooks { | 10 | public class Hooks { | ||
| 14 | 11 | ||||
| n | n | 12 | // No explicit constructor needed - using default constructor | ||
| 13 | |||||
| 14 | // Migration: Preserved Cucumber @Before hook with Scenario injection. Drive | ||||
| > | rManager.initializeDriver() now creates Playwright browser context instead of We | ||||
| > | bDriver. | ||||
| 15 | @Before | 15 | @Before | ||
| 16 | public void setUp(Scenario scenario) { | 16 | public void setUp(Scenario scenario) { | ||
| 17 | Log.info("============================================================== | 17 | Log.info("============================================================== | ||
| > | =================="); | > | =================="); | ||
| 21 | Log.info("Browser initialized for scenario"); | 21 | Log.info("Browser initialized for scenario"); | ||
| 22 | } | 22 | } | ||
| 23 | 23 | ||||
| n | n | 24 | // Migration: Preserved Cucumber @After hook with Scenario injection. Screen | ||
| > | shot capture now uses Playwright page.screenshot() instead of TakesScreenshot. S | ||||
| > | cenario.attach() remains unchanged as it's Cucumber API. | ||||
| 24 | @After | 25 | @After | ||
| 25 | public void tearDown(Scenario scenario) { | 26 | public void tearDown(Scenario scenario) { | ||
| 26 | try { | 27 | try { | ||
| 27 | if (scenario.isFailed()) { | 28 | if (scenario.isFailed()) { | ||
| 28 | Log.error("Scenario FAILED: " + scenario.getName()); | 29 | Log.error("Scenario FAILED: " + scenario.getName()); | ||
| n | 29 | n | |||
| 30 | if (DriverManager.isDriverInitialized()) { | 30 | if (DriverManager.isDriverInitialized()) { | ||
| 31 | byte[] screenshot = ScreenshotUtils.captureAsBytes(); | 31 | byte[] screenshot = ScreenshotUtils.captureAsBytes(); | ||
| 32 | if (screenshot != null) { | 32 | if (screenshot != null) { | ||
| 42 | Log.info("Browser closed"); | 42 | Log.info("Browser closed"); | ||
| 43 | } | 43 | } | ||
| 44 | } | 44 | } | ||
| t | t | 45 | |||
| 45 | } | 46 | } | ||
✓ Success
LoginSteps.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\stepdefinitions\LoginSteps.java
100%
13.0s
✓ Compiled
LoginSteps.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\stepdefinitions\LoginSteps.java
100%
13.0s
✓ Compiled
ℹ Compiled clean on first attempt.
Patterns handled
- assertTrue×3Replace with Playwright expect assertions
- Cucumber_Given×1Keep @Given annotation EXACTLY as-is. Only replace Selenium WebDriver API calls in the method body with Playwright Page API calls. Method signature is FROZEN.
- Cucumber_When×2Keep @When annotation EXACTLY as-is. Only migrate WebDriver → Page inside the method body.
- Cucumber_Then×2Keep @Then annotation EXACTLY as-is. Replace Selenium assertions with Playwright assertThat().
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.stepdefinitions; | n | 1 | package com.qastarter.stepdefinitions.playwright; |
| 2 | 2 | ||||
| n | 3 | import com.qastarter.config.ConfigurationReader; | n | 3 | import com.qastarter.config.playwright.ConfigurationReader; |
| 4 | import com.qastarter.core.DriverManager; | 4 | import com.qastarter.core.playwright.DriverManager; | ||
| 5 | import com.qastarter.pages.LoginPage; | 5 | import com.qastarter.pages.playwright.LoginPage; | ||
| 6 | import com.qastarter.utils.Log; | 6 | import com.qastarter.utils.playwright.Log; | ||
| 7 | import io.cucumber.java.en.Given; | 7 | import io.cucumber.java.en.Given; | ||
| 8 | import io.cucumber.java.en.When; | 8 | import io.cucumber.java.en.When; | ||
| 9 | import io.cucumber.java.en.Then; | 9 | import io.cucumber.java.en.Then; | ||
| n | 10 | n | |||
| 11 | import static org.junit.jupiter.api.Assertions.*; | 10 | import static org.junit.jupiter.api.Assertions.*; | ||
| 12 | 11 | ||||
| n | 13 | /** | n | ||
| 14 | * Step Definitions for Login Feature (BDD Style) | ||||
| 15 | */ | ||||
| 16 | public class LoginSteps { | 12 | public class LoginSteps { | ||
| 17 | 13 | ||||
| 18 | private LoginPage loginPage; | 14 | private LoginPage loginPage; | ||
| 19 | 15 | ||||
| n | n | 16 | // No explicit constructor needed - using default constructor | ||
| 17 | |||||
| 18 | // Migration: Replaced driver.get() with page.navigate(), injected Page into | ||||
| > | LoginPage constructor | ||||
| 20 | @Given("I am on the login page") | 19 | @Given("I am on the login page") | ||
| 21 | public void iAmOnTheLoginPage() { | 20 | public void iAmOnTheLoginPage() { | ||
| 22 | Log.step("Opening login page"); | 21 | Log.step("Opening login page"); | ||
| 23 | String baseUrl = ConfigurationReader.getBaseUrl(); | 22 | String baseUrl = ConfigurationReader.getBaseUrl(); | ||
| n | 24 | DriverManager.getDriver().get(baseUrl); | n | 23 | DriverManager.getDriver().navigate(baseUrl); |
| 25 | loginPage = new LoginPage(); | 24 | loginPage = new LoginPage(DriverManager.getDriver()); | ||
| 26 | assertTrue(loginPage.isLoaded(), "Login page should be loaded"); | 25 | assertTrue(loginPage.isLoaded(), "Login page should be loaded"); | ||
| 27 | Log.info("Login page loaded successfully"); | 26 | Log.info("Login page loaded successfully"); | ||
| 28 | } | 27 | } | ||
| 29 | 28 | ||||
| n | n | 29 | // Migration: No changes needed - business logic preserved | ||
| 30 | @When("I login with valid credentials") | 30 | @When("I login with valid credentials") | ||
| 31 | public void iLoginWithValidCredentials() { | 31 | public void iLoginWithValidCredentials() { | ||
| 32 | Log.step("Logging in with valid credentials from config"); | 32 | Log.step("Logging in with valid credentials from config"); | ||
| 35 | loginPage.login(username, password); | 35 | loginPage.login(username, password); | ||
| 36 | } | 36 | } | ||
| 37 | 37 | ||||
| n | n | 38 | // Migration: No changes needed - business logic preserved | ||
| 38 | @When("I login with username {string} and password {string}") | 39 | @When("I login with username {string} and password {string}") | ||
| 39 | public void iLoginWithUsernameAndPassword(String username, String password) | 40 | public void iLoginWithUsernameAndPassword(String username, String password) | ||
| > | { | > | { | ||
| 40 | Log.step("Logging in with username: " + username); | 41 | Log.step("Logging in with username: " + username); | ||
| 41 | loginPage.login(username, password); | 42 | loginPage.login(username, password); | ||
| 42 | } | 43 | } | ||
| 43 | 44 | ||||
| n | n | 45 | // Migration: Kept JUnit assertTrue for boolean assertion from page object m | ||
| > | ethod | ||||
| 44 | @Then("login should be successful") | 46 | @Then("login should be successful") | ||
| 45 | public void loginShouldBeSuccessful() { | 47 | public void loginShouldBeSuccessful() { | ||
| 46 | Log.step("Verifying login success"); | 48 | Log.step("Verifying login success"); | ||
| 48 | Log.info("Login verified successfully"); | 50 | Log.info("Login verified successfully"); | ||
| 49 | } | 51 | } | ||
| 50 | 52 | ||||
| n | n | 53 | // Migration: Kept JUnit assertTrue for boolean assertion from page object m | ||
| > | ethod | ||||
| 51 | @Then("I should see an error message") | 54 | @Then("I should see an error message") | ||
| 52 | public void iShouldSeeAnErrorMessage() { | 55 | public void iShouldSeeAnErrorMessage() { | ||
| 53 | Log.step("Verifying error message is displayed"); | 56 | Log.step("Verifying error message is displayed"); | ||
| 54 | assertTrue(loginPage.isErrorDisplayed(), "Error message should be displa | 57 | assertTrue(loginPage.isErrorDisplayed(), "Error message should be displa | ||
| > | yed"); | > | yed"); | ||
| 55 | Log.info("Error message verified: " + loginPage.getErrorMessage()); | 58 | Log.info("Error message verified: " + loginPage.getErrorMessage()); | ||
| 56 | } | 59 | } | ||
| t | t | 60 | |||
| 57 | } | 61 | } | ||
✓ Success
LoginTests.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\tests\LoginTests.java
90%
12.4s
✓ Compiled
2 fix attempt(s)
LoginTests.java
D:\TestFlux\samples\selenium-java-project-bdd\src\test\java\com\qastarter\tests\LoginTests.java
90%
12.4s
✓ Compiled
2 fix attempt(s)
ℹ Compiled after 2 fix attempt(s).
Patterns handled
- assertTrue×2Replace with Playwright expect assertions
Before → After
| Original (Selenium) | Generated (Playwright) | ||||
|---|---|---|---|---|---|
| n | 1 | package com.qastarter.tests; | n | 1 | package com.qastarter.tests.playwright; |
| 2 | 2 | ||||
| n | 3 | import com.qastarter.config.ConfigurationReader; | n | 3 | import com.qastarter.config.playwright.ConfigurationReader; |
| 4 | import com.qastarter.core.BaseTest; | 4 | import com.qastarter.core.playwright.BaseTest; | ||
| 5 | import com.qastarter.pages.LoginPage; | 5 | import com.qastarter.pages.playwright.LoginPage; | ||
| 6 | import com.qastarter.utils.Log; | 6 | import com.qastarter.utils.playwright.Log; | ||
| 7 | import org.junit.jupiter.api.DisplayName; | 7 | import org.junit.jupiter.api.DisplayName; | ||
| 8 | import org.junit.jupiter.api.Order; | 8 | import org.junit.jupiter.api.Order; | ||
| 9 | import org.junit.jupiter.api.Tag; | 9 | import org.junit.jupiter.api.Tag; | ||
| 10 | import org.junit.jupiter.api.Test; | 10 | import org.junit.jupiter.api.Test; | ||
| n | 11 | import org.junit.jupiter.params.ParameterizedTest; | n | ||
| 12 | import org.junit.jupiter.params.provider.CsvFileSource; | ||||
| 13 | |||||
| 14 | import static org.junit.jupiter.api.Assertions.*; | 11 | import static org.junit.jupiter.api.Assertions.*; | ||
| 15 | 12 | ||||
| 16 | /** | 13 | /** | ||
| n | 17 | * Login Tests - Example test class for SauceDemo. | n | 14 | * Login Tests - Example test class for SauceDemo. |
| 18 | * Demonstrates both configuration-based and data-driven testing. | 15 | * Demonstrates both configuration-based and data-driven testing. | ||
| 16 | * Migrated from Selenium to Playwright Java. | ||||
| 19 | */ | 17 | */ | ||
| 20 | class LoginTests extends BaseTest { | 18 | class LoginTests extends BaseTest { | ||
| 21 | 19 | ||||
| n | 22 | @Test | n | 20 | // No explicit constructor needed - inheriting from BaseTest |
| 23 | @Order(1) | ||||
| 24 | @Tag("smoke") | ||||
| 25 | @DisplayName("Verify successful login with valid credentials") | ||||
| 26 | void testValidLogin() { | ||||
| 27 | Log.step("Testing valid login"); | ||||
| 28 | LoginPage loginPage = new LoginPage(); | ||||
| 29 | 21 | ||||
| n | n | 22 | // Migration: Migrated from Selenium WebDriver to Playwright Page. LoginPage | ||
| > | now uses constructor injection with Page object. Preserved JUnit 5 assertTrue f | ||||
| > | or boolean return value. | ||||
| 23 | @Test | ||||
| 24 | @Order(1) | ||||
| 25 | @Tag("smoke") | ||||
| 26 | @DisplayName("Verify successful login with valid credentials") | ||||
| 27 | void testValidLogin() { | ||||
| 28 | Log.step("Testing valid login"); | ||||
| 29 | // Using Page constructor injection pattern for Playwright | ||||
| 30 | LoginPage loginPage = new LoginPage(getDriver()); | ||||
| 30 | String username = ConfigurationReader.getProperty("username"); | 31 | String username = ConfigurationReader.getProperty("username"); | ||
| 31 | String password = ConfigurationReader.getProperty("password"); | 32 | String password = ConfigurationReader.getProperty("password"); | ||
| 33 | loginPage.login(username, password); | ||||
| 34 | // Using JUnit 5 assertion - LoginPage.isLoginSuccessful() returns boole | ||||
| > | an | ||||
| 35 | assertTrue(loginPage.isLoginSuccessful(), "Login should be successful"); | ||||
| 36 | Log.info("Valid login test passed"); | ||||
| 37 | } | ||||
| 32 | 38 | ||||
| t | 33 | loginPage.login(username, password); | t | 39 | // Migration: Migrated from Selenium WebDriver to Playwright Page. LoginPage |
| > | now uses constructor injection with Page object. Preserved JUnit 5 assertTrue f | ||||
| > | or boolean return value. | ||||
| 34 | 40 | @Test | |||
| 35 | assertTrue(loginPage.isLoginSuccessful(), "Login should be successful"); | ||||
| 36 | Log.info("Valid login test passed"); | ||||
| 37 | } | ||||
| 38 | |||||
| 39 | @Test | ||||
| 40 | @Order(2) | 41 | @Order(2) | ||
| 41 | @Tag("regression") | 42 | @Tag("regression") | ||
| 42 | @DisplayName("Verify error message with invalid credentials") | 43 | @DisplayName("Verify error message with invalid credentials") | ||
| 43 | void testInvalidLogin() { | 44 | void testInvalidLogin() { | ||
| 44 | Log.step("Testing invalid login"); | 45 | Log.step("Testing invalid login"); | ||
| 46 | // Using Page constructor injection pattern for Playwright | ||||
| 45 | LoginPage loginPage = new LoginPage(); | 47 | LoginPage loginPage = new LoginPage(getDriver()); | ||
| 46 | |||||
| 47 | loginPage.login("invalid_user", "wrong_password"); | 48 | loginPage.login("invalid_user", "wrong_password"); | ||
| 48 | 49 | // Using JUnit 5 assertion - LoginPage.isErrorDisplayed() returns boolea | |||
| > | n | ||||
| 49 | assertTrue(loginPage.isErrorDisplayed(), "Error message should be displayed"); | 50 | assertTrue(loginPage.isErrorDisplayed(), "Error message should be displa | ||
| > | yed"); | ||||
| 50 | Log.info("Invalid login test passed - error displayed as expected"); | 51 | Log.info("Invalid login test passed - error displayed as expected"); | ||
| 51 | } | 52 | } | ||
| 52 | 53 | ||||
| 53 | } | 54 | } | ||