├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── auto
│ │ └── framework
│ │ ├── SpringAutoFrameworkApplication.java
│ │ ├── actions
│ │ ├── ActionsBaseClass.java
│ │ ├── ElementVerification.java
│ │ ├── ExplicitWait.java
│ │ ├── JavaScriptActions.java
│ │ ├── UIElements.java
│ │ └── UtilityClass.java
│ │ ├── config
│ │ ├── MyProperties.java
│ │ └── WebDriverConfig.java
│ │ ├── constants
│ │ └── Constants.java
│ │ ├── driverscope
│ │ ├── DriverScope.java
│ │ ├── DriverScopeConfig.java
│ │ └── DriverScopePostProcessor.java
│ │ ├── interfaces
│ │ ├── IElementVerification.java
│ │ ├── IExplicitWait.java
│ │ ├── IJavaScriptActions.java
│ │ └── IUIElements.java
│ │ └── listeners
│ │ └── TestListener.java
└── resources
│ └── application.properties
└── test
├── java
└── com
│ └── auto
│ └── framework
│ ├── ElementTests.java
│ ├── pageobjects
│ ├── common
│ │ └── BasePage.java
│ └── demoqa
│ │ ├── CheckBoxPF.java
│ │ ├── ElementsPage.java
│ │ ├── RadioButtonPF.java
│ │ ├── TextBoxPF.java
│ │ └── WebTablePF.java
│ └── testdata
│ ├── UserDataProvider.java
│ └── UserModal.java
└── resources
├── Element-Tests.xml
└── Suites.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | test-output/
4 | !.mvn/wrapper/maven-wrapper.jar
5 | !**/src/main/**/target/
6 | !**/src/test/**/target/
7 |
8 | ### Allure ###
9 | allure*
10 |
11 | ### STS ###
12 | .apt_generated
13 | .classpath
14 | .factorypath
15 | .project
16 | .settings
17 | .springBeans
18 | .sts4-cache
19 |
20 | ### IntelliJ IDEA ###
21 | .idea
22 | *.iws
23 | *.iml
24 | *.ipr
25 |
26 | ### NetBeans ###
27 | /nbproject/private/
28 | /nbbuild/
29 | /dist/
30 | /nbdist/
31 | /.nb-gradle/
32 | build/
33 | !**/src/main/**/build/
34 | !**/src/test/**/build/
35 |
36 | ### VS Code ###
37 | .vscode/
38 |
39 | # Compiled class file
40 | *.class
41 |
42 | # Log file
43 | *.log
44 |
45 | # BlueJ files
46 | *.ctxt
47 |
48 | # Mobile Tools for Java (J2ME)
49 | .mtj.tmp/
50 |
51 | # Package Files #
52 | *.jar
53 | *.war
54 | *.nar
55 | *.ear
56 | *.zip
57 | *.tar.gz
58 | *.rar
59 |
60 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
61 | hs_err_pid*
62 | replay_pid*
63 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Selenium Framework using Spring Boot
2 |
3 | A test framework that utilizes Java Spring Boot capabilities to integrate key Selenium and TestNG features that can be used to create web-based automation scripts.
4 |
5 | **Key Features**
6 |
7 | * Supports Parallel test execution and thread management
8 | * Random test data generation
9 | * Spring dependency injection for object creation
10 | * WebDriver manager-based browser initiation
11 | * Platform independent
12 | * Integration with Allure reports
13 | * Integrated with sonarQube for vulnerability analysis
14 | * Avoids boilerplate codes utilizing Lombok
15 |
16 | # Table of contents
17 | * [Installation](#installation)
18 | * [Test Framework Design Details](#test-framework-design)
19 | * [Test Execution Flow](#test-execution-flow)
20 | * [Folder Structure](#folder-structure)
21 | * [Running the tests](#running-the-tests)
22 | * [Creating new tests](#creating-new-tests)
23 | * [Generating sonar reports](#generating-sonar-and-jacoco-reports)
24 | * [Built With](#built-with)
25 | * [Contributing](#contributing)
26 | * [License](#license)
27 | * [References](#references)
28 |
29 | # Test Framework Design Details
30 |
31 | 
32 |
33 |
34 | # Test Execution Flow
35 |
36 | 1. Execution starts from **POM.xml**
37 | 2. Control goes to the parameterized **Suites.xml**
38 | 3. TestNG then invokes the methods in each of the Suites mentioned in Parallel mode based on XML config (For parallel runs separate threads are created)
39 | 4. Control goes to the **ElementTests** test file
40 | 5. Using Spring's dependency injection capabilities **BasePage** and **ElementsPage** objects are created
41 | 6. Then using the **@BeforeMethod** annotation the Spring test context is prepared
42 | 7. Execution then begins with the **SanityCheck()** method due to group dependency mentioned in the @Test annotations
43 | 8. Control then transfers to the TestNG listener mentioned using the **@Listeners(TestListener.class)** annotation at the class level
44 | 9. The overridden **onTestStart** is then invoked to log the start of the test execution
45 | 10. The control then transfers back to the test to start with the **openElementsPage()** instruction
46 | 11. The control is transferred then transferred to the ElementsPage class
47 | 12. Then utilizing the **iUIElements** object of the **IUIElements** interface implemented by the **UIElements** Class the openURL method is invoked
48 | 13. Only then do the IUIElements that inherit the **ActionsBaseClass** create the driver object since it is tagged with a **@Lazy** annotation
49 | 14. This action is completed through the Spring's **@Configuration** annotated class **WebdriverConfig**
50 | 15. Here checking on the **@ConditionalOnExpression** a Webdriver bean is created retrieving the parameters to be compared(browser=chrome, edge, etc.) from the **application.properties** file
51 | 16. As soon the bean is created the lifecycle of the same is tagged to the TestNG thread that invoked the test case using the **@Scope("driverscope")** annotation
52 | 17. The driverscope is already added to spring by extending and overriding the BeanFactoryPostProcessor interface
53 | 18. This is done by creating a **BeanFactoryPostProcessor** bean using the **DriverScopeConfig** class and **DriverScope** class that inherits **SimpleThreadScope**
54 | 19. The same @Scope("driverscope") annotation is then used to create a **WebDriverWait** bean to be utilized by various action classes
55 | 20. With the invoking of the bean, a browser is spun up and the URL stored in a constant file is opened up
56 | 21. Continuing on the test case steps, the page title is extracted utilizing a similar **iElementVerification** object of the **IElementVerification** interface implemented by the **ElementVerification** class
57 | 22. The value retrieved is then asserted against the value in the test case to determine if the test case has to be passed or failed
58 | 23. Based on the assertion, control is transferred to the **TestListener** to Pass/Fail the case
59 | 24. The results are then added to the allure report by invoking the testReportUpdate method
60 | 25. Using the **@AfterMethod(alwaysRun = true)** annotation the browsers are closed using the teardown() method in the BasePage
61 | 26. Screenshots are also then saved and weaved into the **Allure report**
62 | 27. Post sanity check completion, **textBoxVal_TC001()** is executed
63 | 28. The test data to be used is injected using the **@dataprovider** annotation
64 | 29. This is generated using **Java Faker API** in the UserDataProvider class
65 | 30. The page actions are then performed using the Page Fragment class **TextBoxPF**
66 | 31. Similarly the **checkBoxVal__TC002()** is also executed in parallel based on the TestNG config
67 | 32. This is completed through the **CheckBoxPF** Page Fragment class
68 | 33. System/Application properties can be manually updated in the **application.properties file** or overridden in the maven command
69 |
70 | # Folder Structure
71 | 
72 |
73 |
74 | # Installation
75 |
76 | Clone the repo from GitHub using below command
77 | ```git
78 | git clone https://github.com/naveenchr/SpringBoot-SeleniumFramework.git
79 | ```
80 | Clean and compile the maven project using below commands
81 |
82 | ```maven
83 | mvn clean
84 | mvn compile
85 | ```
86 |
87 | # Running the tests
88 |
89 | **From Command Prompt**
90 |
91 | ```maven
92 | mvn test
93 | ```
94 | Parameters can be overridden as follows or updated directly on application.properties file
95 |
96 | ```maven
97 | mvn test -Dmy.properties.grid-url=https://test.com/wd/hub -Dmy.properties.grid-token=123456 -Dmy.properties.grid=true
98 | ```
99 |
100 | **Report Location**
101 |
102 | 1) Navigate to the "target" folder
103 | 2) Execute the below allure command
104 |
105 | ```maven
106 | allure serve -h localhost
107 | ```
108 |
109 | **Sample Report**
110 |
111 | 
112 |
113 | 
114 |
115 | # Creating new tests
116 |
117 | ## Test Class File
118 |
119 | ```java
120 | package com.auto.framework;
121 |
122 | import static org.hamcrest.CoreMatchers.is;
123 | import static org.hamcrest.MatcherAssert.assertThat;
124 | import org.springframework.beans.factory.annotation.Autowired;
125 | import org.springframework.boot.test.context.SpringBootTest;
126 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
127 | import org.testng.annotations.AfterMethod;
128 | import org.testng.annotations.BeforeMethod;
129 | import org.testng.annotations.Listeners;
130 | import org.testng.annotations.Test;
131 | import com.auto.framework.listeners.TestListener;
132 | import com.auto.framework.pageobjects.common.BasePage;
133 | import com.auto.framework.pageobjects.demoqa.ElementsPage;
134 | import com.auto.framework.testdata.UserDataProvider;
135 | import com.auto.framework.testdata.UserModal;
136 |
137 | @SpringBootTest
138 | @Listeners(TestListener.class)
139 | public class ElementTests extends AbstractTestNGSpringContextTests {
140 |
141 | @Autowired
142 | private BasePage basePage;
143 |
144 | @Autowired
145 | public ElementsPage elementsPage;
146 |
147 | @Test(groups = "Sanity Test")
148 | public void sanityCheck() {
149 | elementsPage.openElementsPage();
150 |
151 | assertThat(elementsPage.getPageTitle(), is("DEMOQA"));
152 | }
153 |
154 | @Test(dependsOnGroups = "Sanity Test", dataProvider = "User Data", dataProviderClass = UserDataProvider.class)
155 | public void textBoxVal__TC001(UserModal userData) {
156 | // Opens browser page
157 | elementsPage.textBoxPF.openTextBoxPage();
158 |
159 | // Perform testing actions
160 | elementsPage.textBoxPF.enterFullname(userData.getFirstName());
161 | elementsPage.textBoxPF.enterEmail(userData.getEmail());
162 | elementsPage.textBoxPF.enterCurrentAddress(userData.getCurrAddress());
163 | elementsPage.textBoxPF.enterPermanentAddress(userData.getPermAddress());
164 | elementsPage.textBoxPF.submitForm();
165 |
166 | // Assert data points
167 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getFirstName(), is(userData.getFirstName()));
168 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getEmail(), is(userData.getEmail()));
169 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getCurrAddress(), is(userData.getCurrAddress()));
170 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getPermAddress(), is(userData.getPermAddress()));
171 |
172 | }
173 |
174 | @BeforeMethod
175 | @Override
176 | public void springTestContextPrepareTestInstance() throws Exception {
177 | super.springTestContextPrepareTestInstance();
178 | }
179 |
180 | @AfterMethod(alwaysRun = true)
181 | public void teardownDriver() {
182 | basePage.teardownDriver();
183 | }
184 |
185 | }
186 | ```
187 | ## Page Object File
188 |
189 | ```Java
190 | package com.auto.framework.pageobjects.demoqa;
191 |
192 | import static com.auto.framework.constants.Constants.ELEMENTS_PAGE;
193 | import org.springframework.beans.factory.annotation.Autowired;
194 | import org.springframework.stereotype.Component;
195 | import com.auto.framework.pageobjects.common.BasePage;
196 | import io.qameta.allure.Step;
197 |
198 | @Component
199 | public class ElementsPage extends BasePage {
200 |
201 | @Autowired
202 | public TextBoxPF textBoxPF;
203 |
204 | @Autowired
205 | public CheckBoxPF checkBoxPF;
206 |
207 | @Autowired
208 | public RadioButtonPF radioButtonPF;
209 |
210 | @Autowired
211 | public WebTablePF webTablePF;
212 |
213 | @Step("Open webpage")
214 | public void openElementsPage() {
215 | iUIElements.openURL(myProperties.getDemoUrl() + ELEMENTS_PAGE);
216 | }
217 |
218 | @Step("Verify Page Title")
219 | public String getPageTitle() {
220 | return iElementVerification.getTitle();
221 | }
222 |
223 | }
224 | ```
225 |
226 | # Generating sonar reports
227 |
228 | * Add sonar server URL in POM file
229 | ```XML
230 | http://localhost:9000
231 | ```
232 | * Execute the below maven command after the test run
233 | ```maven
234 | mvn sonar:sonar
235 | ```
236 |
237 | # Built With
238 |
239 | * Spring Boot
240 | * Selenium WebDriver
241 | * TestNG
242 | * Maven
243 | * Allure Reports
244 | * Hamcrest
245 | * Lombok
246 | * Java Faker
247 |
248 | # Contributing
249 | Pull requests are welcome. For major changes, please open an issue first to discuss what you want to change.
250 |
251 | # License
252 | [Apache 2.0](https://choosealicense.com/licenses/apache-2.0/)
253 |
254 | # References
255 | * https://www.youtube.com/watch?v=cG6ZLiRxn1M&list=PL6tu16kXT9PrDr6kMGQ-CgnvCsFxrq1eS
256 | * https://www.youtube.com/watch?v=Ch163VfHtvA&list=PLsyeobzWxl7oA8QOlMtQsRT_I7Rx2hoX4
257 | * https://www.youtube.com/@naveenautomationlabs
258 | * https://www.udemy.com/course/selenium-real-time-examplesinterview-questions/
259 | * https://www.udemy.com/course/spring-boot-testing/
260 | * https://www.udemy.com/course/spring-5-with-spring-boot-2/
261 | * https://allurereport.org/docs/gettingstarted-installation/
262 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 3.1.3
10 |
11 |
12 | com.auto
13 | framework
14 | 0.0.1-SNAPSHOT
15 | SpringAutoFramework
16 | Automation framework using spring boot
17 |
18 | 17
19 | 4.12.1
20 | 7.7.1
21 | 5.5.3
22 | 1.18.28
23 | 2.24.0
24 | 2.10.0
25 | 2.2
26 | 3.9.1.2184
27 | 1.0.2
28 | src/test/resources/Suites.xml
29 |
30 |
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter
35 |
36 |
37 |
38 | org.projectlombok
39 | lombok
40 | true
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-starter-test
45 | test
46 |
47 |
48 |
49 | org.seleniumhq.selenium
50 | selenium-java
51 | ${selenium.version}
52 |
53 |
54 |
55 | org.testng
56 | testng
57 | ${testng.version}
58 |
59 |
60 |
61 | io.github.bonigarcia
62 | webdrivermanager
63 | ${webdrivermanager.version}
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-configuration-processor
68 | true
69 |
70 |
71 |
72 | io.qameta.allure
73 | allure-testng
74 | ${allure-testng.version}
75 |
76 |
77 |
78 | org.hamcrest
79 | hamcrest
80 | ${hamcrest.version}
81 | test
82 |
83 |
84 | org.sonarsource.scanner.maven
85 | sonar-maven-plugin
86 | ${sonar.version}
87 |
88 |
89 | org.aspectj
90 | aspectjweaver
91 | ${aspectj.version}
92 |
93 |
94 |
95 | com.github.javafaker
96 | javafaker
97 | ${javafaker.version}
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | org.springframework.boot
106 | spring-boot-maven-plugin
107 |
108 |
109 |
110 | org.projectlombok
111 | lombok
112 |
113 |
114 |
115 |
116 |
117 |
118 | org.apache.maven.plugins
119 | maven-surefire-plugin
120 |
121 |
122 | false
123 |
124 | -javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
125 |
126 |
127 | ${suiteXmlFile}
128 |
129 |
130 |
131 |
132 | org.aspectj
133 | aspectjweaver
134 | ${aspectj.version}
135 |
136 |
137 | org.apache.maven.surefire
138 | surefire-testng
139 | 3.0.0
140 |
141 |
142 |
143 |
144 | io.qameta.allure
145 | allure-maven
146 | ${allure-maven.version}
147 |
148 | ${allure-testng.version}
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | analyze-test-classes
158 |
159 | src/test/java
160 |
161 | ${project.name}-tests
162 | ${project.groupId}:${project.artifactId}-tests
163 |
164 |
165 |
166 |
167 |
168 | true
169 |
170 |
171 | io.qameta.allure
172 | allure-maven
173 | ${allure-maven.version}
174 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/SpringAutoFrameworkApplication.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class SpringAutoFrameworkApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(SpringAutoFrameworkApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/actions/ActionsBaseClass.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.actions;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.support.ui.WebDriverWait;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.context.ApplicationContext;
7 | import org.springframework.context.annotation.Lazy;
8 | import org.springframework.stereotype.Component;
9 |
10 | import com.auto.framework.config.MyProperties;
11 |
12 | /************************************************************************************************************************
13 | * @Date : Sep. 25, 2023
14 | * @Author : naveenchr
15 | * @Description : Base class for Actions
16 | * @Version : 1.0
17 | ************************************************************************************************************************/
18 |
19 | @Component
20 | public class ActionsBaseClass {
21 |
22 | @Autowired
23 | @Lazy // to start browser only on script execution
24 | public WebDriver driver;
25 |
26 | @Autowired
27 | @Lazy
28 | public WebDriverWait webDriverWait;
29 |
30 | @Autowired
31 | public ApplicationContext applicationContext;
32 |
33 | @Autowired
34 | public MyProperties myProperties;
35 |
36 | @Autowired
37 | public UtilityClass utilityClass;
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/actions/ElementVerification.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.actions;
2 |
3 | import org.openqa.selenium.By;
4 | import org.springframework.stereotype.Component;
5 |
6 | import com.auto.framework.interfaces.IElementVerification;
7 |
8 | import lombok.extern.slf4j.Slf4j;
9 |
10 | /************************************************************************************************************************
11 | * @Date : Sep. 25, 2023
12 | * @Author : naveenchr
13 | * @Description :Element verification interface implementation
14 | * @Version : 1.0
15 | ************************************************************************************************************************/
16 |
17 | @Slf4j
18 | @Component
19 | public class ElementVerification extends ActionsBaseClass implements IElementVerification {
20 |
21 | @Override
22 | public String getTitle() {
23 | String title = driver.getTitle();
24 | log.debug("Opened Page : {}", title);
25 | return title;
26 | }
27 |
28 | @Override
29 | public String getText(By by) {
30 | String text = driver.findElement(by).getText();
31 | log.debug("Text Value: {}", text);
32 | return text;
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/actions/ExplicitWait.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.actions;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.WebElement;
5 | import org.openqa.selenium.support.ui.ExpectedConditions;
6 | import org.springframework.stereotype.Component;
7 |
8 | import com.auto.framework.interfaces.IExplicitWait;
9 |
10 | /************************************************************************************************************************
11 | * @Date : Sep. 25, 2023
12 | * @Author : naveenchr
13 | * @Description : Explicit wait implementation class
14 | * @Version : 1.0
15 | ************************************************************************************************************************/
16 | @Component
17 | public class ExplicitWait extends ActionsBaseClass implements IExplicitWait {
18 |
19 | @Override
20 | public WebElement waitForElementToBeClickable(By by) {
21 | return webDriverWait.until(ExpectedConditions.elementToBeClickable(by));
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/actions/JavaScriptActions.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.actions;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.JavascriptExecutor;
5 | import org.openqa.selenium.WebDriver;
6 | import org.openqa.selenium.WebElement;
7 | import org.openqa.selenium.support.ui.ExpectedConditions;
8 | import org.springframework.stereotype.Component;
9 |
10 | import com.auto.framework.interfaces.IJavaScriptActions;
11 |
12 | import lombok.extern.slf4j.Slf4j;
13 |
14 | /************************************************************************************************************************
15 | * @Date : Sep. 25, 2023
16 | * @Author : naveenchr
17 | * @Description : Impelementation class for interface JavaScriptActions
18 | * @Version : 1.0
19 | ************************************************************************************************************************/
20 |
21 | @Slf4j
22 | @Component
23 | public class JavaScriptActions extends ActionsBaseClass implements IJavaScriptActions {
24 |
25 | @Override
26 | public void scrollIntoView(By by) {
27 | webDriverWait.until(ExpectedConditions.elementToBeClickable(by));
28 | log.debug("Test {}", driver.getTitle());
29 | ((JavascriptExecutor) applicationContext.getBean(WebDriver.class))
30 | .executeScript("arguments[0].scrollIntoView(true);", driver.findElement(by));
31 |
32 | log.debug("Scrolled into View..");
33 | }
34 |
35 | @Override
36 | public void click(By by) {
37 | scrollIntoView(by);
38 | WebElement element = driver.findElement(by);
39 | ((JavascriptExecutor) applicationContext.getBean(WebDriver.class)).executeScript("arguments[0].click();",
40 | element);
41 |
42 | log.debug("Clicked on Link..");
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/actions/UIElements.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.actions;
2 |
3 | import static com.auto.framework.constants.Constants.UIELEMENT_ERROR_TEXT;
4 | import static java.lang.String.format;
5 |
6 | import java.util.List;
7 | import java.util.NoSuchElementException;
8 |
9 | import org.openqa.selenium.By;
10 | import org.openqa.selenium.WebDriver;
11 | import org.openqa.selenium.WebElement;
12 | import org.openqa.selenium.support.locators.RelativeLocator;
13 | import org.openqa.selenium.support.ui.ExpectedConditions;
14 | import org.springframework.stereotype.Component;
15 |
16 | import com.auto.framework.interfaces.IUIElements;
17 |
18 | import lombok.extern.slf4j.Slf4j;
19 |
20 | /************************************************************************************************************************
21 | * @Date : Sep. 25, 2023
22 | * @Author : naveenchr
23 | * @Description : Selenium UI Elements implementation class
24 | * @Version : 1.0
25 | ************************************************************************************************************************/
26 | @Slf4j
27 | @Component
28 | public class UIElements extends ActionsBaseClass implements IUIElements {
29 |
30 | @Override
31 | public void click(By by) {
32 | utilityClass.scrollHelper(driver, webDriverWait, applicationContext, by);
33 | driver.findElement(by).click();
34 | log.debug("Clicked on Link..");
35 |
36 | }
37 |
38 | @Override
39 | public void sendKeys(By by, String keysToSend) {
40 | utilityClass.scrollHelper(driver, webDriverWait, applicationContext, by);
41 | driver.findElement(by).clear();
42 | driver.findElement(by).sendKeys(keysToSend);
43 | log.debug("Typed in text : {}", keysToSend);
44 |
45 | }
46 |
47 | @Override
48 | public void openURL(String url) {
49 | log.info("Loading {}", url);
50 | driver.get(url);
51 |
52 | }
53 |
54 | @Override
55 | public void clickNestedMenus(By by, String tagName, List menuList) {
56 |
57 | utilityClass.scrollHelper(driver, webDriverWait, applicationContext, by);
58 | WebElement headerWebElement = driver.findElements(by).stream()
59 | .filter(element -> element.getText().toLowerCase().contains(menuList.get(0).toLowerCase())).findFirst()
60 | .orElseThrow(() -> new NoSuchElementException(format(UIELEMENT_ERROR_TEXT, by, menuList.get(0))));
61 | headerWebElement.click();
62 | log.debug("Found and clicked on Header Element with Text : {}", menuList.get(0));
63 |
64 | for (int i = 1; i < menuList.size(); i++) {
65 | String subMenuName = menuList.get(i);
66 | headerWebElement = headerWebElement.findElements(By.tagName(tagName)).stream()
67 | .filter(element -> element.getText().toLowerCase().contains(subMenuName.toLowerCase())).findFirst()
68 | .orElseThrow(() -> new NoSuchElementException(format(UIELEMENT_ERROR_TEXT, by, subMenuName)));
69 | headerWebElement.click();
70 | log.debug("Found and clicked on Sub Element with Text : {}", subMenuName);
71 | }
72 | }
73 |
74 | @Override
75 | public String findElementsbyIndex(By by, int index) {
76 | utilityClass.scrollHelper(driver, webDriverWait, applicationContext, by);
77 | return driver.findElements(by).get(index).getText();
78 | }
79 |
80 | @Override
81 | public void searchAndClickByText(By by, String textForSearch) {
82 | webDriverWait.until(ExpectedConditions.elementToBeClickable(by));
83 | driver.findElements(by).stream()
84 | .filter(element -> element.getText().toLowerCase().contains(textForSearch.toLowerCase())).findFirst()
85 | .orElseThrow(() -> new NoSuchElementException(format(UIELEMENT_ERROR_TEXT, by, textForSearch))).click();
86 |
87 | log.debug("Found and clicked on Element with Text : {}", textForSearch);
88 |
89 | }
90 |
91 | @Override
92 | public void clickRelativeLeftElement(By toLeftoOfBy, By withBy) {
93 | utilityClass.scrollHelper(driver, webDriverWait, applicationContext, withBy);
94 | driver.findElement(RelativeLocator.with(withBy).toLeftOf(toLeftoOfBy)).click();
95 | log.debug("Clicked on Link..");
96 |
97 | }
98 |
99 | @Override
100 | public void searchAndClickRelativeLeftElement(By toLeftoOfBy, By withBy, String textForSearch) {
101 | webDriverWait.until(ExpectedConditions.elementToBeClickable(toLeftoOfBy));
102 | driver.findElement(RelativeLocator.with(withBy).toLeftOf(driver.findElements(toLeftoOfBy).stream()
103 | .filter(element -> element.getText().toLowerCase().contains(textForSearch.toLowerCase())).findFirst()
104 | .orElseThrow(
105 | () -> new NoSuchElementException(format(UIELEMENT_ERROR_TEXT, toLeftoOfBy, textForSearch)))))
106 | .click();
107 |
108 | }
109 |
110 | @Override
111 | public void searchAndClickTableByText(By by, String textForSearch, String value) {
112 | webDriverWait.until(ExpectedConditions.elementToBeClickable(by));
113 | WebElement webElement = driver.findElements(by).stream()
114 | .flatMap(row -> row.findElements(By.tagName("td")).stream())
115 | .filter(column -> column.getText().toLowerCase().contains(textForSearch.toLowerCase())).findFirst()
116 | .orElseThrow(() -> new NoSuchElementException(format(UIELEMENT_ERROR_TEXT, by, textForSearch)));
117 | driver.findElement(RelativeLocator.with(By.tagName("input")).toRightOf(webElement)).sendKeys(value);
118 |
119 | }
120 |
121 | @Override
122 | public WebDriver getWebDriver() {
123 | return driver;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/actions/UtilityClass.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.actions;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.JavascriptExecutor;
5 | import org.openqa.selenium.WebDriver;
6 | import org.openqa.selenium.support.ui.ExpectedConditions;
7 | import org.openqa.selenium.support.ui.WebDriverWait;
8 | import org.springframework.context.ApplicationContext;
9 | import org.springframework.stereotype.Component;
10 |
11 | /************************************************************************************************************************
12 | * @Date : Oct. 20, 2023
13 | * @Author : naveenchr
14 | * @Description : Helper class for UI action classes
15 | * @Version : 1.0
16 | ************************************************************************************************************************/
17 | @Component
18 | public class UtilityClass {
19 |
20 | public void scrollHelper(WebDriver driver, WebDriverWait webDriverWait, ApplicationContext applicationContext,
21 | By by) {
22 | webDriverWait.until(ExpectedConditions.elementToBeClickable(by));
23 | ((JavascriptExecutor) applicationContext.getBean(WebDriver.class))
24 | .executeScript("arguments[0].scrollIntoView(true);", driver.findElement(by));
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/config/MyProperties.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.config;
2 |
3 | import java.time.Duration;
4 |
5 | import org.springframework.boot.context.properties.ConfigurationProperties;
6 | import org.springframework.stereotype.Component;
7 |
8 | import lombok.Data;
9 |
10 | /************************************************************************************************************************
11 | * @Date : Nov. 14, 2023
12 | * @Author : naveenchr
13 | * @Description : User properties class
14 | * @Version : 1.0
15 | ************************************************************************************************************************/
16 | @Data
17 | @ConfigurationProperties("my.properties")
18 | @Component
19 | public class MyProperties {
20 | private String browser;
21 | private Duration explicitTimeout;
22 | private String gridUrl;
23 | private String gridToken;
24 | private String username;
25 | private String password;
26 | private String grid;
27 | private String demoUrl;
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/config/WebDriverConfig.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.config;
2 |
3 | import java.net.MalformedURLException;
4 | import java.net.URL;
5 |
6 | import org.openqa.selenium.WebDriver;
7 | import org.openqa.selenium.chrome.ChromeDriver;
8 | import org.openqa.selenium.chrome.ChromeOptions;
9 | import org.openqa.selenium.edge.EdgeDriver;
10 | import org.openqa.selenium.edge.EdgeOptions;
11 | import org.openqa.selenium.remote.DesiredCapabilities;
12 | import org.openqa.selenium.remote.LocalFileDetector;
13 | import org.openqa.selenium.remote.RemoteWebDriver;
14 | import org.openqa.selenium.support.ui.WebDriverWait;
15 | import org.springframework.beans.factory.annotation.Autowired;
16 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
17 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
18 | import org.springframework.context.annotation.Bean;
19 | import org.springframework.context.annotation.Configuration;
20 | import org.springframework.context.annotation.Scope;
21 |
22 | import io.github.bonigarcia.wdm.WebDriverManager;
23 | import lombok.extern.slf4j.Slf4j;
24 |
25 | /************************************************************************************************************************
26 | * @Date : Sep. 13, 2023
27 | * @Author : naveenchr
28 | * @Description : Bean configuration for WebDriver and WebDriver wait object
29 | * based on browser
30 | * @Version : 1.0
31 | ************************************************************************************************************************/
32 |
33 | @Slf4j
34 | @Configuration
35 | public class WebDriverConfig {
36 |
37 | @Autowired
38 | private MyProperties myProperties;
39 |
40 | @Bean
41 | @ConditionalOnExpression("'${my.properties.grid}'.equals('false') and '${my.properties.browser}'.equals('chrome')")
42 | @Scope("driverscope")
43 | public WebDriver getChromeDriver() {
44 | log.info("Creating Driver");
45 | ChromeOptions options = new ChromeOptions();
46 | options.addArguments("--remote-debugging-port=9222");
47 | options.addArguments("--remote-allow-origins=*");
48 | // options.addArguments("--headless=new");
49 | WebDriverManager.chromedriver().setup();
50 | return new ChromeDriver(options);
51 | }
52 |
53 | @Bean
54 | @ConditionalOnExpression("'${my.properties.grid}'.equals('false') and '${my.properties.browser}'.equals('chrome')")
55 | @Scope("driverscope")
56 | public WebDriverWait getChromeDriverWait() {
57 | return new WebDriverWait(getChromeDriver(), myProperties.getExplicitTimeout());
58 | }
59 |
60 | @Bean
61 | @ConditionalOnProperty(name = "my.properties.grid", havingValue = "true")
62 | @Scope("driverscope")
63 | public WebDriver getGridDriver() throws MalformedURLException {
64 | DesiredCapabilities dc = new DesiredCapabilities();
65 | dc.setBrowserName(myProperties.getBrowser());
66 | dc.setCapability("e34:token", myProperties.getGridToken());
67 | log.info("Creating Driver");
68 | WebDriver driver = new RemoteWebDriver(new URL(myProperties.getGridUrl()), dc);
69 | ((RemoteWebDriver) driver).setFileDetector(new LocalFileDetector());
70 | return driver;
71 | }
72 |
73 | @Bean
74 | @ConditionalOnProperty(name = "my.properties.grid", havingValue = "true")
75 | @Scope("driverscope")
76 | public WebDriverWait getGridDriverWait() throws MalformedURLException {
77 | return new WebDriverWait(getGridDriver(), myProperties.getExplicitTimeout());
78 | }
79 |
80 | @Bean
81 | @ConditionalOnExpression("'${my.properties.grid}'.equals('false') and '${my.properties.browser}'.equals('edge')")
82 | @Scope("driverscope")
83 | public WebDriver getEdgeDriver() {
84 | EdgeOptions options = new EdgeOptions();
85 | options.addArguments("--remote-allow-origins=*");
86 | // options.addArguments("--headless=new");
87 | WebDriverManager.edgedriver().setup();
88 | return new EdgeDriver(options);
89 | }
90 |
91 | @Bean
92 | @ConditionalOnExpression("'${my.properties.grid}'.equals('false') and '${my.properties.browser}'.equals('edge')")
93 | @Scope("driverscope")
94 | public WebDriverWait getEdgeDriverWait() {
95 | return new WebDriverWait(getEdgeDriver(), myProperties.getExplicitTimeout());
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/constants/Constants.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.constants;
2 |
3 | /************************************************************************************************************************
4 | * @Date : Oct. 4, 2023
5 | * @Author : naveenchr
6 | * @Description : Final class to maintain constants
7 | * @Version : 1.0
8 | ************************************************************************************************************************/
9 | public final class Constants {
10 |
11 | private Constants() {
12 | throw new IllegalStateException("Constants Class");
13 | }
14 |
15 | public static final String UIELEMENT_ERROR_TEXT = "No element with locator [%s] containing text [%s] found";
16 |
17 | // URLs
18 | public static final String ELEMENTS_PAGE = "elements";
19 | public static final String TEXTBOX_PAGE = "text-box";
20 | public static final String CHECKBOX_PAGE = "checkbox";
21 | public static final String RADIOBUTTON_PAGE = "radio-button";
22 | public static final String WEBTABLES_PAGE = "webtables";
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/driverscope/DriverScope.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.driverscope;
2 |
3 | import org.springframework.context.support.SimpleThreadScope;
4 |
5 | /************************************************************************************************************************
6 | * @Date : Sep. 25, 2023
7 | * @Author : naveenchr
8 | * @Description : Configuration class to register driver as simple thread
9 | * @Version : 1.0
10 | ************************************************************************************************************************/
11 | public class DriverScope extends SimpleThreadScope {
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/driverscope/DriverScopeConfig.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.driverscope;
2 |
3 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 |
8 | /************************************************************************************************************************
9 | * @Date : Sep. 25, 2023
10 | * @Author : naveenchr
11 | * @Description : Creating a BeanFactoryPostProcessor for new DriverScope
12 | * @Version : 1.0
13 | ************************************************************************************************************************/
14 | @Configuration
15 | public class DriverScopeConfig {
16 |
17 | @Bean
18 | public static BeanFactoryPostProcessor beanFactoryPostProcessor() {
19 | return new DriverScopePostProcessor();
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/driverscope/DriverScopePostProcessor.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.driverscope;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
5 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
6 |
7 | /************************************************************************************************************************
8 | * @Date : Sep. 25, 2023
9 | * @Author : naveenchr
10 | * @Description : Registering driverscope to BeanFactoryPostProcessor
11 | * @Version : 1.0
12 | ************************************************************************************************************************/
13 | public class DriverScopePostProcessor implements BeanFactoryPostProcessor {
14 |
15 | @Override
16 | public void postProcessBeanFactory(
17 | ConfigurableListableBeanFactory beanFactory) throws BeansException {
18 | beanFactory.registerScope("driverscope", new DriverScope());
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/interfaces/IElementVerification.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.interfaces;
2 |
3 | import org.openqa.selenium.By;
4 |
5 | /************************************************************************************************************************
6 | * @Date : Sep. 25, 2023
7 | * @Author : naveenchr
8 | * @Description : Element verification methods
9 | * @Version : 1.0
10 | ************************************************************************************************************************/
11 | public interface IElementVerification {
12 | public String getTitle();
13 |
14 | public String getText(By by);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/interfaces/IExplicitWait.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.interfaces;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.WebElement;
5 |
6 | /************************************************************************************************************************
7 | * @Date : Sep. 25, 2023
8 | * @Author : naveenchr
9 | * @Description : Explicit wait interface
10 | * @Version : 1.0
11 | ************************************************************************************************************************/
12 | public interface IExplicitWait {
13 | public WebElement waitForElementToBeClickable(By by);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/interfaces/IJavaScriptActions.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.interfaces;
2 |
3 | import org.openqa.selenium.By;
4 |
5 | /************************************************************************************************************************
6 | * @Date : Sep. 25, 2023
7 | * @Author : naveenchr
8 | * @Description : Interface for JavaScript Actions
9 | * @Version : 1.0
10 | ************************************************************************************************************************/
11 | public interface IJavaScriptActions {
12 |
13 | public void scrollIntoView(By by);
14 |
15 | public void click(By by);
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/interfaces/IUIElements.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.interfaces;
2 |
3 | import java.util.List;
4 |
5 | import org.openqa.selenium.By;
6 | import org.openqa.selenium.WebDriver;
7 |
8 | /************************************************************************************************************************
9 | * @Date : Sep. 25, 2023
10 | * @Author : naveenchr
11 | * @Description : Interface for UIElement actions
12 | * @Version : 1.0
13 | ************************************************************************************************************************/
14 | public interface IUIElements {
15 |
16 | WebDriver getWebDriver();
17 |
18 | void sendKeys(By by, String keysToSend);
19 |
20 | void click(By by);
21 |
22 | void openURL(String url);
23 |
24 | void searchAndClickByText(By by, String textForSearch);
25 |
26 | void clickNestedMenus(By by, String tagName, List menuList);
27 |
28 | void searchAndClickTableByText(By by, String textForSearch, String value);
29 |
30 | String findElementsbyIndex(By by, int index);
31 |
32 | void searchAndClickRelativeLeftElement(By toLeftoOfBy, By withBy, String textForSearch);
33 |
34 | void clickRelativeLeftElement(By toLeftoOfBy, By withBy);
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/auto/framework/listeners/TestListener.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.listeners;
2 |
3 | import org.openqa.selenium.OutputType;
4 | import org.openqa.selenium.TakesScreenshot;
5 | import org.openqa.selenium.WebDriver;
6 | import org.openqa.selenium.WebDriverException;
7 | import org.springframework.context.annotation.Scope;
8 | import org.springframework.stereotype.Component;
9 | import org.testng.ITestResult;
10 | import org.testng.TestListenerAdapter;
11 | import org.testng.internal.TestResult;
12 |
13 | import io.qameta.allure.Allure;
14 | import io.qameta.allure.AllureLifecycle;
15 | import io.qameta.allure.Attachment;
16 | import lombok.extern.slf4j.Slf4j;
17 |
18 | /************************************************************************************************************************
19 | * @Date : Sep. 25, 2023
20 | * @Author : naveenchr
21 | * @Description : Test listener implementation to manage driver and log results
22 | * @Version : 1.0
23 | ************************************************************************************************************************/
24 | @Slf4j
25 | @Component
26 | @Scope("driverscope")
27 | public class TestListener extends TestListenerAdapter {
28 |
29 | @Override
30 | public void onTestStart(ITestResult iTestResult) {
31 | super.onTestStart(iTestResult);
32 | log.info("Started: {}", iTestResult.getName());
33 | }
34 |
35 | @Override
36 | public void onTestSuccess(ITestResult iTestResult) {
37 | super.onTestSuccess(iTestResult);
38 | testReportUpdate(iTestResult);
39 | log.info("Finished successfully: {}", iTestResult.getName());
40 | }
41 |
42 | @Override
43 | public void onTestSkipped(ITestResult iTestResult) {
44 | super.onTestSkipped(iTestResult);
45 | testReportUpdate(iTestResult);
46 | log.info("Skipped: {}", iTestResult.getName());
47 | }
48 |
49 | @Override
50 | public void onTestFailure(ITestResult iTestResult) {
51 | super.onTestFailure(iTestResult);
52 | log.error("Failed: {} with: {}", iTestResult.getName(), iTestResult.getThrowable().toString());
53 | testReportUpdate(iTestResult);
54 | }
55 |
56 | @Attachment(value = "Screen shot", type = "image/png", fileExtension = ".png")
57 | private byte[] attachScreenShot(WebDriver driver) {
58 | try {
59 | return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
60 | } catch (WebDriverException e) {
61 | log.error("Selenium screenshot capture failed: {}", e.getMessage());
62 | }
63 | return new byte[0];
64 | }
65 |
66 | public void testReportUpdate(ITestResult iTestResult) {
67 | String testSetNumber = iTestResult.getName() + " " + (((TestResult) iTestResult).getParameterIndex() + 1);
68 |
69 | log.info("Allure report : {}", iTestResult);
70 | log.info("Test Set Number : {}", testSetNumber);
71 | AllureLifecycle lifecycle = Allure.getLifecycle();
72 | if (lifecycle.getCurrentTestCase().isPresent()) {
73 | lifecycle.updateTestCase(testResult -> testResult.setName(testSetNumber));
74 | }
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #Spring Common Parameters
2 | server.port=8081
3 | logging.level.root=info
4 |
5 | #User Custom Parameters
6 | my.properties.browser=edge
7 | my.properties.explicitTimeout=60000
8 | my.properties.grid-url=
9 | my.properties.grid-token=
10 | my.properties.grid=false
11 | my.properties.demo-url=https://demoqa.com/
12 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/ElementTests.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework;
2 |
3 | import static org.hamcrest.CoreMatchers.is;
4 | import static org.hamcrest.MatcherAssert.assertThat;
5 |
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
9 | import org.testng.annotations.AfterMethod;
10 | import org.testng.annotations.BeforeMethod;
11 | import org.testng.annotations.Listeners;
12 | import org.testng.annotations.Test;
13 |
14 | import com.auto.framework.listeners.TestListener;
15 | import com.auto.framework.pageobjects.common.BasePage;
16 | import com.auto.framework.pageobjects.demoqa.ElementsPage;
17 | import com.auto.framework.testdata.UserDataProvider;
18 | import com.auto.framework.testdata.UserModal;
19 |
20 | /************************************************************************************************************************
21 | * @Date : Oct. 20, 2023
22 | * @Author : naveenchr
23 | * @Description : Element validation tests
24 | * @Version : 1.0
25 | ************************************************************************************************************************/
26 | @SpringBootTest
27 | @Listeners(TestListener.class)
28 | public class ElementTests extends AbstractTestNGSpringContextTests {
29 |
30 | @Autowired
31 | private BasePage basePage;
32 |
33 | @Autowired
34 | public ElementsPage elementsPage;
35 |
36 | @Test(groups = "Sanity Test")
37 | public void sanityCheck() {
38 | elementsPage.openElementsPage();
39 |
40 | assertThat(elementsPage.getPageTitle(), is("DEMOQA"));
41 | }
42 |
43 | @Test(dependsOnGroups = "Sanity Test", dataProvider = "User Data", dataProviderClass = UserDataProvider.class)
44 | public void textBoxVal__TC001(UserModal userData) {
45 | // Opens browser page
46 | elementsPage.textBoxPF.openTextBoxPage();
47 |
48 | // Perform testing actions
49 | elementsPage.textBoxPF.enterFullname(userData.getFirstName());
50 | elementsPage.textBoxPF.enterEmail(userData.getEmail());
51 | elementsPage.textBoxPF.enterCurrentAddress(userData.getCurrAddress());
52 | elementsPage.textBoxPF.enterPermanentAddress(userData.getPermAddress());
53 | elementsPage.textBoxPF.submitForm();
54 |
55 | // Assert data points
56 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getFirstName(), is(userData.getFirstName()));
57 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getEmail(), is(userData.getEmail()));
58 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getCurrAddress(), is(userData.getCurrAddress()));
59 | assertThat(elementsPage.textBoxPF.getConfirmationMessage().getPermAddress(), is(userData.getPermAddress()));
60 |
61 | }
62 |
63 | // @Test(dependsOnGroups = "Sanity Test")
64 | public void checkBoxVal__TC002() {
65 | elementsPage.checkBoxPF.openCheckBoxPage();
66 |
67 | elementsPage.checkBoxPF.expandLevel1Menu();
68 | elementsPage.checkBoxPF.expandLevel2Menu("Documents");
69 | elementsPage.checkBoxPF.expandLevel3Menu("Workspace");
70 | elementsPage.checkBoxPF.clickLevel4Option("Angular");
71 |
72 | assertThat(elementsPage.checkBoxPF.getConfirmationMessage(), is("angular"));
73 |
74 | }
75 |
76 | @Test(dependsOnGroups = "Sanity Test")
77 | public void RadioButtonVal__TC003() {
78 | elementsPage.radioButtonPF.openRadioButtonPage();
79 |
80 | elementsPage.radioButtonPF.clickRadioButton("Impressive");
81 |
82 | assertThat(elementsPage.radioButtonPF.getConfirmationMessage(), is("Impresive"));
83 |
84 | }
85 |
86 | @BeforeMethod
87 | @Override
88 | public void springTestContextPrepareTestInstance() throws Exception {
89 | super.springTestContextPrepareTestInstance();
90 | }
91 |
92 | @AfterMethod(alwaysRun = true)
93 | public void teardownDriver() {
94 | basePage.teardownDriver();
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/pageobjects/common/BasePage.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.pageobjects.common;
2 |
3 | import static java.util.Objects.nonNull;
4 |
5 | import org.openqa.selenium.OutputType;
6 | import org.openqa.selenium.TakesScreenshot;
7 | import org.openqa.selenium.WebDriver;
8 | import org.openqa.selenium.WebDriverException;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.context.annotation.Scope;
11 | import org.springframework.stereotype.Component;
12 |
13 | import com.auto.framework.actions.ActionsBaseClass;
14 | import com.auto.framework.interfaces.IElementVerification;
15 | import com.auto.framework.interfaces.IExplicitWait;
16 | import com.auto.framework.interfaces.IJavaScriptActions;
17 | import com.auto.framework.interfaces.IUIElements;
18 |
19 | import io.qameta.allure.Attachment;
20 | import lombok.extern.slf4j.Slf4j;
21 |
22 | /************************************************************************************************************************
23 | * @Date : Nov. 14, 2023
24 | * @Author : nachrist
25 | * @Description : Base page for all POM page classes
26 | * @Version : 1.0
27 | ************************************************************************************************************************/
28 | @Slf4j
29 | @Component
30 | //@Scope("driverscope")
31 | public class BasePage extends ActionsBaseClass {
32 |
33 | @Autowired
34 | public IUIElements iUIElements;
35 |
36 | @Autowired
37 | public IElementVerification iElementVerification;
38 |
39 | @Autowired
40 | public IExplicitWait iExplicitWait;
41 |
42 | @Autowired
43 | public IJavaScriptActions iJavaScriptActions;
44 |
45 | public void teardownDriver() {
46 | log.info("Taking Screenshots");
47 | attachScreenShot();
48 | log.info("Closing Browsers");
49 | if (nonNull(driver)) {
50 | driver.close();
51 | }
52 | }
53 |
54 | @Attachment(value = "Screen shot", type = "image/png", fileExtension = ".png")
55 | public byte[] attachScreenShot() {
56 | try {
57 | return ((TakesScreenshot) applicationContext.getBean(WebDriver.class)).getScreenshotAs(OutputType.BYTES);
58 | } catch (WebDriverException e) {
59 | log.error("Selenium screenshot capture failed: {}", e.getMessage());
60 | }
61 | return new byte[0];
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/pageobjects/demoqa/CheckBoxPF.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.pageobjects.demoqa;
2 |
3 | import static com.auto.framework.constants.Constants.CHECKBOX_PAGE;
4 |
5 | import org.openqa.selenium.By;
6 | import org.springframework.stereotype.Component;
7 |
8 | import com.auto.framework.pageobjects.common.BasePage;
9 |
10 | import io.qameta.allure.Step;
11 | import lombok.AllArgsConstructor;
12 |
13 | /************************************************************************************************************************
14 | * @Date : Nov. 14, 2023
15 | * @Author : nachrist
16 | * @Description : Page fragment class for Checkbox interactions
17 | * @Version : 1.0
18 | ************************************************************************************************************************/
19 | @Component
20 | @AllArgsConstructor
21 | public class CheckBoxPF extends BasePage {
22 |
23 | private static By level1Menu = By.xpath("//*[@id='tree-node']/ol/li/span/label/span[3]");
24 | private static By level2Menu = By.xpath("//*[@id='tree-node']/ol/li/ol/li/span/label/span[3]");
25 | private static By level3Menu = By.xpath("//*[@id='tree-node']/ol/li/ol/li/ol/li/span/label/span[3]");
26 | private static By level4Menu = By.xpath("//*[@id='tree-node']/ol/li/ol/li/ol/li/ol/li/span/label/span[3]");
27 | private static By expandButtonRL = By.xpath("//button[@title='Toggle']");
28 | private static By successMsg = By.className("text-success");
29 |
30 | public void openCheckBoxPage() {
31 | iUIElements.openURL(myProperties.getDemoUrl() + CHECKBOX_PAGE);
32 | }
33 |
34 | @Step("Expand Level 1 Menu")
35 | public void expandLevel1Menu() {
36 | iUIElements.clickRelativeLeftElement(level1Menu, expandButtonRL);
37 | }
38 |
39 | @Step("Expand Level 2 Menu")
40 | public void expandLevel2Menu(String textForSearch) {
41 | iUIElements.searchAndClickRelativeLeftElement(level2Menu, expandButtonRL, textForSearch);
42 | }
43 |
44 | @Step("Expand Level 3 Menu")
45 | public void expandLevel3Menu(String textForSearch) {
46 | iUIElements.searchAndClickRelativeLeftElement(level3Menu, expandButtonRL, textForSearch);
47 | }
48 |
49 | @Step("Select Level 4 Option")
50 | public void clickLevel4Option(String textForSearch) {
51 | iUIElements.searchAndClickByText(level4Menu, textForSearch);
52 | }
53 |
54 | public String getConfirmationMessage() {
55 | return iElementVerification.getText(successMsg);
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/pageobjects/demoqa/ElementsPage.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.pageobjects.demoqa;
2 |
3 | import static com.auto.framework.constants.Constants.ELEMENTS_PAGE;
4 |
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.stereotype.Component;
7 |
8 | import com.auto.framework.pageobjects.common.BasePage;
9 |
10 | import io.qameta.allure.Step;
11 |
12 | /************************************************************************************************************************
13 | * @Date : Oct. 14, 2023
14 | * @Author : naveenchr
15 | * @Description : Elements page object
16 | * @Version : 1.0
17 | ************************************************************************************************************************/
18 | @Component
19 | public class ElementsPage extends BasePage {
20 |
21 | @Autowired
22 | public TextBoxPF textBoxPF;
23 |
24 | @Autowired
25 | public CheckBoxPF checkBoxPF;
26 |
27 | @Autowired
28 | public RadioButtonPF radioButtonPF;
29 |
30 | @Autowired
31 | public WebTablePF webTablePF;
32 |
33 | @Step("Open webpage")
34 | public void openElementsPage() {
35 | iUIElements.openURL(myProperties.getDemoUrl() + ELEMENTS_PAGE);
36 | }
37 |
38 | @Step("Verify Page Title")
39 | public String getPageTitle() {
40 | return iElementVerification.getTitle();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/pageobjects/demoqa/RadioButtonPF.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.pageobjects.demoqa;
2 |
3 | import static com.auto.framework.constants.Constants.RADIOBUTTON_PAGE;
4 |
5 | import org.openqa.selenium.By;
6 | import org.springframework.stereotype.Component;
7 |
8 | import com.auto.framework.pageobjects.common.BasePage;
9 |
10 | import io.qameta.allure.Step;
11 | import lombok.AllArgsConstructor;
12 |
13 | /************************************************************************************************************************
14 | * @Date : Oct. 23, 2023
15 | * @Author : naveenchr
16 | * @Description : Page object fragment for Radio button
17 | * @Version : 1.0
18 | ************************************************************************************************************************/
19 | @Component
20 | @AllArgsConstructor
21 | public class RadioButtonPF extends BasePage {
22 |
23 | private static By radioButtons = By.xpath("//*[@class='custom-control custom-radio custom-control-inline']");
24 | private static By successMsg = By.className("text-success");
25 |
26 | public void openRadioButtonPage() {
27 | iUIElements.openURL(myProperties.getDemoUrl() + RADIOBUTTON_PAGE);
28 | }
29 |
30 | @Step("Clicked on the Radio Button")
31 | public void clickRadioButton(String text) {
32 | iUIElements.searchAndClickByText(radioButtons, text);
33 | }
34 |
35 | public String getConfirmationMessage() {
36 | return iElementVerification.getText(successMsg);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/pageobjects/demoqa/TextBoxPF.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.pageobjects.demoqa;
2 |
3 | import static com.auto.framework.constants.Constants.TEXTBOX_PAGE;
4 |
5 | import org.openqa.selenium.By;
6 | import org.springframework.stereotype.Component;
7 |
8 | import com.auto.framework.pageobjects.common.BasePage;
9 | import com.auto.framework.testdata.UserModal;
10 |
11 | import io.qameta.allure.Step;
12 | import lombok.AllArgsConstructor;
13 | import lombok.extern.slf4j.Slf4j;
14 |
15 | /************************************************************************************************************************
16 | * @Date : Oct. 20, 2023
17 | * @Author : naveenchr
18 | * @Description : Page object fragment for Text Box menu
19 | * @Version : 1.0
20 | ************************************************************************************************************************/
21 | @Component
22 | @AllArgsConstructor
23 | @Slf4j
24 | public class TextBoxPF extends BasePage {
25 |
26 | private static By fullnameTF = By.id("userName");
27 | private static By emailTF = By.id("userEmail");
28 | private static By currentAddressTF = By.cssSelector("#currentAddress");
29 | private static By permanentAddressTF = By.xpath("//*[@id='permanentAddress']");
30 | private static By submitButton = By.cssSelector("#submit");
31 |
32 | private static By nameText = By.cssSelector("p#name");
33 | private static By emailText = By.cssSelector("p#email");
34 | private static By currAddText = By.cssSelector("p#currentAddress");
35 | private static By permAddText = By.cssSelector("p#permanentAddress");
36 |
37 | public void openTextBoxPage() {
38 | iUIElements.openURL(myProperties.getDemoUrl() + TEXTBOX_PAGE);
39 | }
40 |
41 | public void updateTextBoxes(UserModal userData) {
42 | enterFullname(userData.getFirstName());
43 | enterEmail(userData.getEmail());
44 | enterCurrentAddress(userData.getCurrAddress());
45 | enterPermanentAddress(userData.getPermAddress());
46 | submitForm();
47 | }
48 |
49 | @Step("Enter Fullname")
50 | public void enterFullname(String fullname) {
51 | iUIElements.sendKeys(fullnameTF, fullname);
52 | }
53 |
54 | @Step("Enter Email")
55 | public void enterEmail(String email) {
56 | iUIElements.sendKeys(emailTF, email);
57 | }
58 |
59 | @Step("Enter Current Address")
60 | public void enterCurrentAddress(String currAddress) {
61 | iUIElements.sendKeys(currentAddressTF, currAddress);
62 | }
63 |
64 | @Step("Enter Permanent Address")
65 | public void enterPermanentAddress(String permAddress) {
66 | iUIElements.sendKeys(permanentAddressTF, permAddress);
67 | }
68 |
69 | @Step("Submit form")
70 | public void submitForm() {
71 | iUIElements.click(submitButton);
72 | }
73 |
74 | public UserModal getConfirmationMessage() {
75 | UserModal userModal = UserModal.builder().firstName(iElementVerification.getText(nameText).split(":")[1])
76 | .email(iElementVerification.getText(emailText).split(":")[1])
77 | .currAddress(iElementVerification.getText(currAddText).split(":")[1])
78 | .permAddress(iElementVerification.getText(permAddText).split(":")[1]).build();
79 | log.info("Confirmation Data: {}", userModal);
80 | return userModal;
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/pageobjects/demoqa/WebTablePF.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.pageobjects.demoqa;
2 |
3 | import static com.auto.framework.constants.Constants.WEBTABLES_PAGE;
4 |
5 | import org.openqa.selenium.By;
6 | import org.springframework.stereotype.Component;
7 |
8 | import com.auto.framework.pageobjects.common.BasePage;
9 | import com.auto.framework.testdata.UserModal;
10 |
11 | import io.qameta.allure.Step;
12 | import lombok.AllArgsConstructor;
13 |
14 | /************************************************************************************************************************
15 | * @Date : Oct. 23, 2023
16 | * @Author : naveenchr
17 | * @Description : Page object fragment for Web Table
18 | * @Version : 1.0
19 | ************************************************************************************************************************/
20 | @Component
21 | @AllArgsConstructor
22 | public class WebTablePF extends BasePage {
23 |
24 | private static By addButton = By.cssSelector("#addNewRecordButton");
25 | private static By firstNameTextField = By.cssSelector("#firstName");
26 | private static By lastNameTextField = By.id("lastName");
27 | private static By emailTextField = By.xpath("//*[@id='userEmail']");
28 | private static By ageTextField = By.cssSelector("#age");
29 | private static By salaryTextField = By.id("salary");
30 | private static By departmentTextField = By.id("department");
31 |
32 | public void openWebTablesPage() {
33 | iUIElements.openURL(myProperties.getDemoUrl() + WEBTABLES_PAGE);
34 | }
35 |
36 | @Step("Add User Data")
37 | public void addUserData(UserModal userData) {
38 | iUIElements.click(addButton);
39 | iUIElements.sendKeys(firstNameTextField, userData.getFirstName());
40 | iUIElements.sendKeys(lastNameTextField, userData.getLastName());
41 | iUIElements.sendKeys(emailTextField, userData.getEmail());
42 | iUIElements.sendKeys(ageTextField, userData.getAge());
43 | iUIElements.sendKeys(salaryTextField, userData.getSalary());
44 | iUIElements.sendKeys(departmentTextField, userData.getDepartment());
45 | }
46 |
47 | // public String getConfirmationMessage() {
48 | //// return iElementVerification.getText(successMsg);
49 | // }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/testdata/UserDataProvider.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.testdata;
2 |
3 | import org.springframework.stereotype.Component;
4 | import org.testng.annotations.DataProvider;
5 |
6 | import com.github.javafaker.Faker;
7 |
8 | /************************************************************************************************************************
9 | * @Date : Oct. 20, 2023
10 | * @Author : naveenchr
11 | * @Description : User Data Provider
12 | * @Version : 1.0
13 | ************************************************************************************************************************/
14 | @Component
15 | public class UserDataProvider {
16 |
17 | @DataProvider(name = "User Data", parallel = true)
18 | public Object[][] userDataProvider() {
19 | Object[][] userDataSet = { { generateUserData() }, { generateUserData() } };
20 |
21 | return userDataSet;
22 |
23 | }
24 |
25 | public UserModal generateUserData() {
26 | Faker faker = new Faker();
27 | return UserModal.builder().firstName(faker.name().firstName()).email(faker.internet().emailAddress())
28 | .currAddress(faker.address().fullAddress()).permAddress(faker.address().fullAddress())
29 | .age(faker.number().digit()).salary(faker.number().digits(5)).department(faker.company().name())
30 | .build();
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/com/auto/framework/testdata/UserModal.java:
--------------------------------------------------------------------------------
1 | package com.auto.framework.testdata;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | /************************************************************************************************************************
9 | * @Date : Oct. 17, 2023
10 | * @Author : naveenchr
11 | * @Description :Test Data modal class
12 | * @Version : 1.0
13 | ************************************************************************************************************************/
14 | @Data
15 | @Builder
16 | @AllArgsConstructor
17 | @NoArgsConstructor
18 | public class UserModal {
19 | private String firstName;
20 | private String lastName;
21 | private String email;
22 | private String currAddress;
23 | private String permAddress;
24 | private String age;
25 | private String salary;
26 | private String department;
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/resources/Element-Tests.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/test/resources/Suites.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------