├── .gitignore
├── Jenkinsfile
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── qa
│ └── opencart
│ ├── constants
│ └── AppConstants.java
│ ├── factory
│ └── PlaywrightFactory.java
│ ├── listeners
│ └── ExtentReportListener.java
│ └── pages
│ ├── HomePage.java
│ └── LoginPage.java
└── test
├── java
└── com
│ └── qa
│ └── opencart
│ ├── base
│ └── BaseTest.java
│ └── tests
│ ├── HomePageTest.java
│ └── LoginPageTest.java
└── resources
├── config
└── config.properties
└── testrunners
└── testng_regressions.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | allure-results/
2 | screenshots/
3 | screenshot/
4 | test-output/
5 | build/
6 |
7 | application.log
8 | ##############################
9 | ## Java
10 | ##############################
11 | .mtj.tmp/
12 | *.class
13 | *.jar
14 | *.war
15 | *.ear
16 | *.nar
17 | hs_err_pid*
18 | activityLog.log
19 | ##############################
20 | ## Maven
21 | ##############################
22 | target/
23 | pom.xml.tag
24 | pom.xml.releaseBackup
25 | pom.xml.versionsBackup
26 | pom.xml.next
27 | pom.xml.bak
28 | release.properties
29 | dependency-reduced-pom.xml
30 | buildNumber.properties
31 | .mvn/timing.properties
32 | .mvn/wrapper/maven-wrapper.jar
33 |
34 | ##############################
35 | ## IntelliJ
36 | ##############################
37 | out/
38 | .idea/
39 | .idea_modules/
40 | *.iml
41 | *.ipr
42 | *.iws
43 | ##############################
44 | ## Eclipse
45 | ##############################
46 | .settings/
47 | bin/
48 | tmp/
49 | .metadata
50 | .classpath
51 | .project
52 | *.tmp
53 | *.bak
54 | *.swp
55 | *~.nib
56 | local.properties
57 | .loadpath
58 | .factorypath
59 |
60 | ## OS X
61 | ##############################
62 | .DS_Store
63 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | pipeline
2 | {
3 | agent any
4 |
5 | tools{
6 | maven 'maven'
7 | }
8 |
9 | stages
10 | {
11 | stage('Build')
12 | {
13 | steps
14 | {
15 | git 'https://github.com/jglick/simple-maven-project-with-tests.git'
16 | sh "mvn -Dmaven.test.failure.ignore=true clean package"
17 | }
18 | post
19 | {
20 | success
21 | {
22 | junit '**/target/surefire-reports/TEST-*.xml'
23 | archiveArtifacts 'target/*.jar'
24 | }
25 | }
26 | }
27 |
28 |
29 |
30 | stage("Deploy to QA"){
31 | steps{
32 | echo("deploy to qa")
33 | }
34 | }
35 |
36 | stage('Regression Automation Test') {
37 | steps {
38 | catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
39 | git 'https://github.com/naveenanimation20/Playwright-Java-PageObjectModel'
40 | sh "mvn clean test -Dsurefire.suiteXmlFiles=src/test/resources/testrunners/testng_regressions.xml"
41 |
42 | }
43 | }
44 | }
45 |
46 |
47 | stage('Publish Extent Report'){
48 | steps{
49 | publishHTML([allowMissing: false,
50 | alwaysLinkToLastBuild: false,
51 | keepAll: true,
52 | reportDir: 'build',
53 | reportFiles: 'TestExecutionReport.html',
54 | reportName: 'HTML Extent Report',
55 | reportTitles: ''])
56 | }
57 | }
58 |
59 |
60 |
61 |
62 | }
63 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 | 4.0.0
7 |
8 | PlaywrightPOMSeries
9 | PlaywrightPOMSeries
10 | 0.0.1-SNAPSHOT
11 |
12 | PlaywrightPOMSeries
13 |
14 | http://www.example.com
15 |
16 |
17 | UTF-8
18 | 1.8
19 | 1.8
20 | 5.0.8
21 |
22 |
23 |
24 |
25 |
26 |
27 | com.microsoft.playwright
28 | playwright
29 | 1.25.0
30 |
31 |
32 |
33 | org.testng
34 | testng
35 | 6.14.3
36 |
37 |
38 |
39 | com.aventstack
40 | extentreports
41 | ${extentreports-version}
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-compiler-plugin
53 | 3.8.1
54 |
55 | 1.8
56 | 1.8
57 |
58 |
59 |
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-surefire-plugin
64 | 2.20
65 |
66 |
67 | 3
68 | true
69 | -Xmx1024m -XX:MaxPermSize=256m
70 |
71 | src/test/resources/testrunners/testng_regressions.xml
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/src/main/java/com/qa/opencart/constants/AppConstants.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.constants;
2 |
3 | public class AppConstants {
4 |
5 |
6 | public static final String HOME_PAGE_TITLE = "Your Store";
7 |
8 | public static final String LOGIN_PAGE_TITLE = "Account Login";
9 |
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/qa/opencart/factory/PlaywrightFactory.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.factory;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.FileNotFoundException;
5 | import java.io.IOException;
6 | import java.nio.file.Paths;
7 | import java.util.Base64;
8 | import java.util.Properties;
9 |
10 | import com.microsoft.playwright.Browser;
11 | import com.microsoft.playwright.BrowserContext;
12 | import com.microsoft.playwright.BrowserType;
13 | import com.microsoft.playwright.BrowserType.LaunchOptions;
14 | import com.microsoft.playwright.Page;
15 | import com.microsoft.playwright.Playwright;
16 |
17 | public class PlaywrightFactory {
18 |
19 | Playwright playwright;
20 | Browser browser;
21 | BrowserContext browserContext;
22 | Page page;
23 | Properties prop;
24 |
25 | private static ThreadLocal tlBrowser = new ThreadLocal<>();
26 | private static ThreadLocal tlBrowserContext = new ThreadLocal<>();
27 | private static ThreadLocal tlPage = new ThreadLocal<>();
28 | private static ThreadLocal tlPlaywright = new ThreadLocal<>();
29 |
30 | public static Playwright getPlaywright() {
31 | return tlPlaywright.get();
32 | }
33 |
34 | public static Browser getBrowser() {
35 | return tlBrowser.get();
36 | }
37 |
38 | public static BrowserContext getBrowserContext() {
39 | return tlBrowserContext.get();
40 | }
41 |
42 | public static Page getPage() {
43 | return tlPage.get();
44 | }
45 |
46 | public Page initBrowser(Properties prop) {
47 |
48 | String browserName = prop.getProperty("browser").trim();
49 | System.out.println("browser name is : " + browserName);
50 |
51 | // playwright = Playwright.create();
52 | tlPlaywright.set(Playwright.create());
53 |
54 | switch (browserName.toLowerCase()) {
55 | case "chromium":
56 | tlBrowser.set(getPlaywright().chromium().launch(new BrowserType.LaunchOptions().setHeadless(false)));
57 | break;
58 | case "firefox":
59 | tlBrowser.set(getPlaywright().firefox().launch(new BrowserType.LaunchOptions().setHeadless(false)));
60 | break;
61 | case "safari":
62 | tlBrowser.set(getPlaywright().webkit().launch(new BrowserType.LaunchOptions().setHeadless(false)));
63 | break;
64 | case "chrome":
65 | tlBrowser.set(
66 | getPlaywright().chromium().launch(new LaunchOptions().setChannel("chrome").setHeadless(false)));
67 | break;
68 | case "edge":
69 | tlBrowser.set(
70 | getPlaywright().chromium().launch(new LaunchOptions().setChannel("msedge").setHeadless(false)));
71 | break;
72 |
73 | default:
74 | System.out.println("please pass the right browser name......");
75 | break;
76 | }
77 |
78 | tlBrowserContext.set(getBrowser().newContext());
79 | tlPage.set(getBrowserContext().newPage());
80 | getPage().navigate(prop.getProperty("url").trim());
81 | return getPage();
82 |
83 | }
84 |
85 | /**
86 | * this method is used to initialize the properties from config file
87 | */
88 | public Properties init_prop() {
89 |
90 | try {
91 | FileInputStream ip = new FileInputStream("./src/test/resources/config/config.properties");
92 | prop = new Properties();
93 | prop.load(ip);
94 | } catch (FileNotFoundException e) {
95 | e.printStackTrace();
96 | } catch (IOException e) {
97 | e.printStackTrace();
98 | }
99 |
100 | return prop;
101 |
102 | }
103 |
104 | /**
105 | * take screenshot
106 | *
107 | */
108 |
109 | public static String takeScreenshot() {
110 | String path = System.getProperty("user.dir") + "/screenshot/" + System.currentTimeMillis() + ".png";
111 | //getPage().screenshot(new Page.ScreenshotOptions().setPath(Paths.get(path)).setFullPage(true));
112 |
113 | byte[] buffer = getPage().screenshot(new Page.ScreenshotOptions().setPath(Paths.get(path)).setFullPage(true));
114 | String base64Path = Base64.getEncoder().encodeToString(buffer);
115 |
116 | return base64Path;
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/com/qa/opencart/listeners/ExtentReportListener.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.listeners;
2 |
3 | import java.io.IOException;
4 | import java.nio.file.Files;
5 | import java.nio.file.Path;
6 | import java.nio.file.Paths;
7 | import java.util.Calendar;
8 | import java.util.Date;
9 |
10 | import org.testng.ITestContext;
11 | import org.testng.ITestListener;
12 | import org.testng.ITestResult;
13 |
14 | import com.aventstack.extentreports.ExtentReports;
15 | import com.aventstack.extentreports.ExtentTest;
16 | import com.aventstack.extentreports.MediaEntityBuilder;
17 | import com.aventstack.extentreports.reporter.ExtentSparkReporter;
18 | import static com.qa.opencart.factory.PlaywrightFactory.takeScreenshot;
19 |
20 | public class ExtentReportListener implements ITestListener {
21 |
22 | private static final String OUTPUT_FOLDER = "./build/";
23 | private static final String FILE_NAME = "TestExecutionReport.html";
24 |
25 | private static ExtentReports extent = init();
26 | public static ThreadLocal test = new ThreadLocal();
27 | private static ExtentReports extentReports;
28 |
29 |
30 | private static ExtentReports init() {
31 |
32 | Path path = Paths.get(OUTPUT_FOLDER);
33 | // if directory exists?
34 | if (!Files.exists(path)) {
35 | try {
36 | Files.createDirectories(path);
37 | } catch (IOException e) {
38 | // fail to create directory
39 | e.printStackTrace();
40 | }
41 | }
42 |
43 | extentReports = new ExtentReports();
44 | ExtentSparkReporter reporter = new ExtentSparkReporter(OUTPUT_FOLDER + FILE_NAME);
45 | reporter.config().setReportName("Open Cart Automation Test Results");
46 | extentReports.attachReporter(reporter);
47 | extentReports.setSystemInfo("System", "MAC");
48 | extentReports.setSystemInfo("Author", "Naveen AutomationLabs");
49 | extentReports.setSystemInfo("Build#", "1.1");
50 | extentReports.setSystemInfo("Team", "OMS");
51 | extentReports.setSystemInfo("Customer Name", "NAL");
52 |
53 | //extentReports.setSystemInfo("ENV NAME", System.getProperty("env"));
54 |
55 | return extentReports;
56 | }
57 |
58 | @Override
59 | public synchronized void onStart(ITestContext context) {
60 | System.out.println("Test Suite started!");
61 |
62 | }
63 |
64 | @Override
65 | public synchronized void onFinish(ITestContext context) {
66 | System.out.println(("Test Suite is ending!"));
67 | extent.flush();
68 | test.remove();
69 | }
70 |
71 | @Override
72 | public synchronized void onTestStart(ITestResult result) {
73 | String methodName = result.getMethod().getMethodName();
74 | String qualifiedName = result.getMethod().getQualifiedName();
75 | int last = qualifiedName.lastIndexOf(".");
76 | int mid = qualifiedName.substring(0, last).lastIndexOf(".");
77 | String className = qualifiedName.substring(mid + 1, last);
78 |
79 | System.out.println(methodName + " started!");
80 | ExtentTest extentTest = extent.createTest(result.getMethod().getMethodName(),
81 | result.getMethod().getDescription());
82 |
83 | extentTest.assignCategory(result.getTestContext().getSuite().getName());
84 | /*
85 | * methodName = StringUtils.capitalize(StringUtils.join(StringUtils.
86 | * splitByCharacterTypeCamelCase(methodName), StringUtils.SPACE));
87 | */
88 | extentTest.assignCategory(className);
89 | test.set(extentTest);
90 | test.get().getModel().setStartTime(getTime(result.getStartMillis()));
91 | }
92 |
93 | public synchronized void onTestSuccess(ITestResult result) {
94 | System.out.println((result.getMethod().getMethodName() + " passed!"));
95 | test.get().pass("Test passed");
96 | test.get().pass(result.getThrowable(), MediaEntityBuilder.createScreenCaptureFromBase64String(takeScreenshot(),result.getMethod().getMethodName()).build());
97 | test.get().getModel().setEndTime(getTime(result.getEndMillis()));
98 | }
99 |
100 | public synchronized void onTestFailure(ITestResult result) {
101 | System.out.println((result.getMethod().getMethodName() + " failed!"));
102 | test.get().fail(result.getThrowable(), MediaEntityBuilder.createScreenCaptureFromBase64String(takeScreenshot(),result.getMethod().getMethodName()).build());
103 | test.get().getModel().setEndTime(getTime(result.getEndMillis()));
104 | }
105 |
106 | public synchronized void onTestSkipped(ITestResult result) {
107 | System.out.println((result.getMethod().getMethodName() + " skipped!"));
108 | test.get().skip(result.getThrowable(), MediaEntityBuilder.createScreenCaptureFromBase64String(takeScreenshot(), result.getMethod().getMethodName()).build());
109 | test.get().getModel().setEndTime(getTime(result.getEndMillis()));
110 | }
111 |
112 | public synchronized void onTestFailedButWithinSuccessPercentage(ITestResult result) {
113 | System.out.println(("onTestFailedButWithinSuccessPercentage for " + result.getMethod().getMethodName()));
114 | }
115 |
116 | private Date getTime(long millis) {
117 | Calendar calendar = Calendar.getInstance();
118 | calendar.setTimeInMillis(millis);
119 | return calendar.getTime();
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/src/main/java/com/qa/opencart/pages/HomePage.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.pages;
2 |
3 | import com.microsoft.playwright.Page;
4 |
5 | public class HomePage {
6 |
7 | private Page page;
8 |
9 | // 1. String Locators - OR
10 | private String search = "input[name='search']";
11 | private String searchIcon = "div#search button";
12 | private String searchPageHeader = "div#content h1";
13 | private String loginLink = "a:text('Login')";
14 | private String myAccountLink = "a[title='My Account']";
15 |
16 |
17 | // 2. page constructor:
18 | public HomePage(Page page) {
19 | this.page = page;
20 | }
21 |
22 | // 3. page actions/methods:
23 | public String getHomePageTitle() {
24 | String title = page.title();
25 | System.out.println("page title: " + title);
26 | return title;
27 | }
28 |
29 | public String getHomePageURL() {
30 | String url = page.url();
31 | System.out.println("page url : " + url);
32 | return url;
33 | }
34 |
35 | public String doSearch(String productName) {
36 | page.fill(search, productName);
37 | page.click(searchIcon);
38 | String header = page.textContent(searchPageHeader);
39 | System.out.println("search header: " + header);
40 | return header;
41 | }
42 |
43 | public LoginPage navigateToLoginPage() {
44 | page.click(myAccountLink);
45 | page.click(loginLink);
46 | return new LoginPage(page);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/qa/opencart/pages/LoginPage.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.pages;
2 |
3 | import com.microsoft.playwright.Page;
4 |
5 | public class LoginPage {
6 |
7 | private Page page;
8 |
9 | // 1. String Locators - OR
10 | private String emailId = "//input[@id='input-email']";
11 | private String password = "//input[@id='input-password']";
12 | private String loginBtn = "//input[@value='Login']";
13 | private String forgotPwdLink = "//div[@class='form-group']//a[normalize-space()='Forgotten Password']";
14 | private String logoutLink = "//a[@class='list-group-item'][normalize-space()='Logout']";
15 |
16 | // 2. page constructor:
17 | public LoginPage(Page page) {
18 | this.page = page;
19 | }
20 |
21 | // 3. page actions/methods:
22 | public String getLoginPageTitle() {
23 | return page.title();
24 | }
25 |
26 | public boolean isForgotPwdLinkExist() {
27 | return page.isVisible(forgotPwdLink);
28 | }
29 |
30 | public boolean doLogin(String appUserName, String appPassword) {
31 | System.out.println("App creds: " + appUserName + ":" + appPassword);
32 | page.fill(emailId, appUserName);
33 | page.fill(password, appPassword);
34 | page.click(loginBtn);
35 | page.locator(logoutLink).waitFor();
36 | if(page.locator(logoutLink).isVisible()) {
37 | System.out.println("user is logged in successfully....");
38 | return true;
39 | }else {
40 | System.out.println("user is not logged in successfully....");
41 | return false;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/test/java/com/qa/opencart/base/BaseTest.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.base;
2 |
3 | import java.util.Properties;
4 |
5 | import org.testng.annotations.AfterTest;
6 | import org.testng.annotations.BeforeTest;
7 | import org.testng.annotations.Parameters;
8 |
9 | import com.microsoft.playwright.Page;
10 | import com.qa.opencart.factory.PlaywrightFactory;
11 | import com.qa.opencart.pages.HomePage;
12 | import com.qa.opencart.pages.LoginPage;
13 |
14 | public class BaseTest {
15 |
16 | PlaywrightFactory pf;
17 | Page page;
18 | protected Properties prop;
19 |
20 | protected HomePage homePage;
21 | protected LoginPage loginPage;
22 |
23 | @Parameters({ "browser" })
24 | @BeforeTest
25 | public void setup(String browserName) {
26 | pf = new PlaywrightFactory();
27 |
28 | prop = pf.init_prop();
29 |
30 | if (browserName != null) {
31 | prop.setProperty("browser", browserName);
32 | }
33 |
34 | page = pf.initBrowser(prop);
35 | homePage = new HomePage(page);
36 | }
37 |
38 | @AfterTest
39 | public void tearDown() {
40 | page.context().browser().close();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/com/qa/opencart/tests/HomePageTest.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.tests;
2 |
3 | import org.testng.Assert;
4 | import org.testng.annotations.DataProvider;
5 | import org.testng.annotations.Test;
6 |
7 | import com.qa.opencart.base.BaseTest;
8 | import com.qa.opencart.constants.AppConstants;
9 |
10 | public class HomePageTest extends BaseTest {
11 |
12 | @Test
13 | public void homePageTitleTest() {
14 | String actualTitle = homePage.getHomePageTitle();
15 | Assert.assertEquals(actualTitle, AppConstants.HOME_PAGE_TITLE);
16 | }
17 |
18 | @Test
19 | public void homePageURLTest() {
20 | String actualURL = homePage.getHomePageURL();
21 | Assert.assertEquals(actualURL, prop.getProperty("url"));
22 | }
23 |
24 | @DataProvider
25 | public Object[][] getProductData() {
26 | return new Object[][] {
27 | { "Macbook" },
28 | { "iMac" },
29 | { "Samsung" }
30 | };
31 | }
32 |
33 | @Test(dataProvider = "getProductData")
34 | public void searchTest(String productName) throws InterruptedException {
35 | Thread.sleep(5000);
36 | String actualSearchHeader = homePage.doSearch(productName);
37 | Assert.assertEquals(actualSearchHeader, "Search - " + productName);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/test/java/com/qa/opencart/tests/LoginPageTest.java:
--------------------------------------------------------------------------------
1 | package com.qa.opencart.tests;
2 |
3 | import org.testng.Assert;
4 | import org.testng.annotations.Test;
5 |
6 | import com.qa.opencart.base.BaseTest;
7 | import com.qa.opencart.constants.AppConstants;
8 |
9 | public class LoginPageTest extends BaseTest {
10 |
11 | @Test(priority = 1)
12 | public void loginPageNavigationTest() {
13 | loginPage = homePage.navigateToLoginPage();
14 | String actLoginPageTitle = loginPage.getLoginPageTitle();
15 | System.out.println("page act title: " + actLoginPageTitle);
16 | Assert.assertEquals(actLoginPageTitle, AppConstants.LOGIN_PAGE_TITLE);
17 | }
18 |
19 | @Test(priority = 2)
20 | public void forgotPwdLinkExistTest() {
21 | Assert.assertTrue(loginPage.isForgotPwdLinkExist());
22 | }
23 |
24 | @Test(priority = 3)
25 | public void appLoginTest() {
26 | Assert.assertTrue(loginPage.doLogin(prop.getProperty("username").trim(), prop.getProperty("password").trim()));
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/resources/config/config.properties:
--------------------------------------------------------------------------------
1 | browser = chrome
2 | url = https://naveenautomationlabs.com/opencart/
3 |
4 | username = naveenanimation20@gmail.com
5 | password = Selenium@12345
6 |
7 | headless = false
--------------------------------------------------------------------------------
/src/test/resources/testrunners/testng_regressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
34 |
35 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------