├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── query.yml │ ├── feature_request.yml │ └── bug_report.yml ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ ├── stale.yml │ ├── codeql-analysis.yml │ └── test.yml └── CONTRIBUTING.md ├── lombok.config ├── assets ├── semver.png ├── browserstack-logo.png └── coteafs-selenium-logo.png ├── testng-grid.yaml ├── src ├── test │ ├── resources │ │ ├── listener-config.yml │ │ ├── logger-config.yml │ │ └── selenium-config.yaml │ └── java │ │ └── com │ │ └── github │ │ └── wasiqb │ │ └── coteafs │ │ └── selenium │ │ ├── pages │ │ ├── action │ │ │ ├── DropDownPageAction.java │ │ │ ├── CheckboxPageAction.java │ │ │ └── LoginPageAction.java │ │ ├── DropDownPage.java │ │ ├── SuccessLoginPage.java │ │ ├── CheckboxPage.java │ │ ├── MainPage.java │ │ └── LoginPage.java │ │ └── SeleniumTest.java └── main │ ├── java │ └── com │ │ └── github │ │ └── wasiqb │ │ └── coteafs │ │ └── selenium │ │ ├── core │ │ ├── page │ │ │ ├── ElementKey.java │ │ │ ├── AbstractPageAction.java │ │ │ ├── IPageAction.java │ │ │ └── IPage.java │ │ ├── enums │ │ │ ├── AlertDecision.java │ │ │ ├── ApplicationType.java │ │ │ ├── RemoteSource.java │ │ │ ├── ScreenState.java │ │ │ ├── WaitStrategy.java │ │ │ ├── Platform.java │ │ │ ├── PlatformOs.java │ │ │ ├── AvailableBrowser.java │ │ │ └── Protocol.java │ │ ├── element │ │ │ ├── ITextBoxActions.java │ │ │ ├── IKeyboardActions.java │ │ │ ├── IMouseActions.java │ │ │ ├── IWaitStrategy.java │ │ │ ├── IElementActions.java │ │ │ ├── IVerifyElement.java │ │ │ ├── IFindableAction.java │ │ │ └── ISelectBoxActions.java │ │ ├── driver │ │ │ ├── IScriptAction.java │ │ │ ├── IWebWindow.java │ │ │ ├── IWebDriver.java │ │ │ ├── IServiceAction.java │ │ │ ├── IWaitAction.java │ │ │ ├── IPlatformAction.java │ │ │ ├── IWebFrame.java │ │ │ ├── IDriverActions.java │ │ │ ├── IAlertAction.java │ │ │ ├── IDriver.java │ │ │ ├── IWebDriverActions.java │ │ │ └── IScreenAction.java │ │ ├── BrowserSession.java │ │ ├── base │ │ │ ├── driver │ │ │ │ ├── PlatformAction.java │ │ │ │ ├── WebDriverAction.java │ │ │ │ ├── ParallelSession.java │ │ │ │ ├── AlertAction.java │ │ │ │ ├── BaseDriverAction.java │ │ │ │ ├── DriverSession.java │ │ │ │ ├── AbstractDriver.java │ │ │ │ ├── ScreenAction.java │ │ │ │ └── CustomScreenRecorder.java │ │ │ └── element │ │ │ │ ├── KeyboardAction.java │ │ │ │ ├── FindableAction.java │ │ │ │ ├── ElementAction.java │ │ │ │ ├── VerifyElement.java │ │ │ │ ├── AbstractElementAction.java │ │ │ │ └── BaseElementAction.java │ │ ├── WebElementAction.java │ │ ├── BrowserTest.java │ │ ├── BrowserActions.java │ │ └── BrowserPage.java │ │ ├── config │ │ ├── RecorderSetting.java │ │ ├── DriverSetting.java │ │ ├── ScreenshotSetting.java │ │ ├── ScreenResolution.java │ │ ├── SeleniumConfig.java │ │ ├── PlaybackSetting.java │ │ ├── RemoteSetting.java │ │ ├── DelaySetting.java │ │ ├── ConfigUtil.java │ │ └── BrowserSetting.java │ │ ├── constants │ │ ├── ConfigKeys.java │ │ └── OS.java │ │ ├── error │ │ ├── VideoRecordingError.java │ │ └── DriverNotSetupError.java │ │ └── listeners │ │ └── DriverListener.java │ └── resources │ └── log4j2.yaml ├── .gitignore ├── .gitpod.yml ├── testng-local.yaml ├── testng.yaml ├── .all-contributorsrc ├── testng-browserstack.yaml ├── setting └── settings.xml ├── checkstyle-suppressions.xml ├── testng-all-browsers.xml ├── CODE_OF_CONDUCT.md └── pom.xml /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @WasiqB -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: wasiqb # Replace with a single Patreon username 2 | -------------------------------------------------------------------------------- /lombok.config: -------------------------------------------------------------------------------- 1 | config.stopBubbling = true 2 | lombok.addLombokGeneratedAnnotation = true -------------------------------------------------------------------------------- /assets/semver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WasiqB/coteafs-selenium/HEAD/assets/semver.png -------------------------------------------------------------------------------- /assets/browserstack-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WasiqB/coteafs-selenium/HEAD/assets/browserstack-logo.png -------------------------------------------------------------------------------- /assets/coteafs-selenium-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WasiqB/coteafs-selenium/HEAD/assets/coteafs-selenium-logo.png -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Want to discuss anything else? 4 | url: https://github.com/WasiqB/coteafs-selenium/discussions/new 5 | about: Create a discussion about it. -------------------------------------------------------------------------------- /testng-grid.yaml: -------------------------------------------------------------------------------- 1 | name: Selenium Grid Suite 2 | tests: 3 | - name: Test Grid 4 | parameters: { 5 | test.browser: grid 6 | } 7 | classes: 8 | - name: com.github.wasiqb.coteafs.selenium.SeleniumTest 9 | includedMethods: 10 | - testLogin 11 | -------------------------------------------------------------------------------- /src/test/resources/listener-config.yml: -------------------------------------------------------------------------------- 1 | log: 2 | configurations: true 3 | data_provider: true 4 | execution: true 5 | suites: true 6 | tests: true 7 | recover: 8 | enable: true 9 | logging: true 10 | max_retry: 1 11 | on_exceptions: 12 | - java.io.FileNotFoundException -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ IDEA 2 | /.idea/ 3 | *.iml 4 | 5 | # Eclipse IDE 6 | /.settings/ 7 | /.classpath 8 | /.project 9 | 10 | # VS Code 11 | /.vscode 12 | 13 | # Other output folders 14 | /target/ 15 | /bin/ 16 | /test-output/ 17 | /logs/ 18 | /reports/ 19 | /video/ 20 | /screenshots/ 21 | 22 | # Mac OSX 23 | .DS_Store -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/query.yml: -------------------------------------------------------------------------------- 1 | name: "❓ Query" 2 | description: Any query related to coteafs-selenium 3 | title: "[Query]" 4 | labels: 5 | - help 6 | body: 7 | - type: textarea 8 | attributes: 9 | label: Write your query here 10 | placeholder: What query you have? 11 | validations: 12 | required: true -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | github: 2 | prebuilds: 3 | master: true 4 | branches: true 5 | pullRequests: true 6 | pullRequestsFromForks: true 7 | addCheck: true 8 | addComment: false 9 | addBadge: true 10 | tasks: 11 | - before: echo y | sdk install java 17.0.1-oracle 12 | init: mvn clean install -DskipTests 13 | -------------------------------------------------------------------------------- /testng-local.yaml: -------------------------------------------------------------------------------- 1 | name: Local Suite 2 | tests: 3 | - name: Test Local 4 | preserveOrder: true 5 | parameters: { 6 | test.browser: local 7 | } 8 | classes: 9 | - name: com.github.wasiqb.coteafs.selenium.SeleniumTest 10 | includedMethods: 11 | - testLogin 12 | - testCheckboxes 13 | - testDropDownBox 14 | -------------------------------------------------------------------------------- /testng.yaml: -------------------------------------------------------------------------------- 1 | name: Coteafs-Selenium Suite 2 | listeners: 3 | - com.github.wasiqb.coteafs.listeners.ConfigListener 4 | - com.github.wasiqb.coteafs.listeners.SuiteListener 5 | - com.github.wasiqb.coteafs.listeners.TestListener 6 | - com.github.wasiqb.coteafs.listeners.ExecutionListener 7 | - com.github.wasiqb.coteafs.listeners.DataProviderListener 8 | - com.github.wasiqb.coteafs.listeners.AnnotationTransformer 9 | - com.github.wasiqb.coteafs.listeners.SuiteResultReporter 10 | 11 | suiteFiles: 12 | - testng-local.yaml 13 | - testng-grid.yaml 14 | - testng-browserstack.yaml 15 | -------------------------------------------------------------------------------- /src/test/resources/logger-config.yml: -------------------------------------------------------------------------------- 1 | status: WARN 2 | log_dir: /logs 3 | loggers: 4 | - name: console-log 5 | type: CONSOLE 6 | message_pattern: "[%d{HH:mm:ss.SSS}] [%-5level] - %msg (%logger{1}:%L) %throwable{short.message}%n" 7 | level: DEBUG 8 | - name: test-log-appender 9 | type: FILE 10 | file_name: new-log-main 11 | path_pattern: my-log-main-%d{yyyy-MM-dd}.log 12 | message_pattern: "[%d{HH:mm:ss.SSS}] [%-5level] - %msg (%logger{1}:%L) %throwable{short.message}%n" 13 | level: INFO 14 | archive: 15 | after_days: 1 16 | after_size: 5 17 | on_every_run: true -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Closes: #[ticket no] 2 | 3 | ### What are the changes and their implications? 4 | Describe the changes done. 5 | 6 | ### Checklist 7 | Select all the applicable options: 8 | 9 | - [ ] Breaking (_non-backward compatible_) changes 10 | - [ ] Tests added for changes 11 | - [ ] JavaDoc updated in main and test classes 12 | - [ ] README updated (if applicable) 13 | - [ ] PR with the documentation for the feature raised in the [documentation repo](https://github.com/WasiqB/wasiqb.github.io) 14 | 15 | -------------------------------------------------------------------------------- /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "contributorsPerLine": 7, 7 | "contributorsSortAlphabetically": false, 8 | "badgeTemplate": "[![All Contributors](https://img.shields.io/badge/all_contributors-<%= contributors.length %>-17BB8A.svg?style=for-the-badge&labelColor=000000)](#contributors)", 9 | "types": { 10 | "custom": { 11 | "symbol": "🔭", 12 | "description": "A custom contribution type.", 13 | "link": "[<%= symbol %>](<%= url %> \"<%= description %>\")," 14 | } 15 | }, 16 | "skipCi": true, 17 | "contributors": [], 18 | "projectName": "coteafs-selenium", 19 | "projectOwner": "WasiqB", 20 | "repoType": "github", 21 | "repoHost": "https://github.com" 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/stale@v3 13 | with: 14 | repo-token: ${{ github.token }} 15 | stale-issue-message: 'Ticket is stale since last 90 days.' 16 | stale-pr-message: 'PR is stale since last 90 days' 17 | stale-issue-label: 'no-issue-activity' 18 | stale-pr-label: 'no-pr-activity' 19 | days-before-stale: 90 20 | days-before-close: 120 21 | close-issue-message: 'Ticket is closed since no activity for last 120 days' 22 | close-pr-message: 'PR is closed without merge since last 120 days.' 23 | -------------------------------------------------------------------------------- /testng-browserstack.yaml: -------------------------------------------------------------------------------- 1 | name: BrowserStack Suite 2 | parallel: tests 3 | threadCount: 5 4 | tests: 5 | - name: Test BrowserStack Chrome 6 | preserveOrder: true 7 | parameters: { 8 | test.browser: bs_chrome 9 | } 10 | classes: 11 | - name: com.github.wasiqb.coteafs.selenium.SeleniumTest 12 | includedMethods: 13 | - testLogin 14 | - testCheckboxes 15 | - testDropDownBox 16 | - name: Test BrowserStack Firefox 17 | parameters: { 18 | test.browser: bs_firefox 19 | } 20 | classes: 21 | - name: com.github.wasiqb.coteafs.selenium.SeleniumTest 22 | includedMethods: 23 | - testLogin 24 | - name: Test BrowserStack Edge 25 | parameters: { 26 | test.browser: bs_edge 27 | } 28 | classes: 29 | - name: com.github.wasiqb.coteafs.selenium.SeleniumTest 30 | includedMethods: 31 | - testLogin 32 | -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/action/DropDownPageAction.java: -------------------------------------------------------------------------------- 1 | package com.github.wasiqb.coteafs.selenium.pages.action; 2 | 3 | import com.github.wasiqb.coteafs.selenium.core.page.AbstractPageAction; 4 | import com.github.wasiqb.coteafs.selenium.pages.DropDownPage; 5 | 6 | /** 7 | * @author Faisal Khatri 8 | * @since Jul 19, 2020 9 | */ 10 | public class DropDownPageAction extends AbstractPageAction { 11 | @Override 12 | public void perform () { 13 | final DropDownPage dropDown = new DropDownPage (); 14 | 15 | final String dropDownOption = value (DropDownPage.DropDownKeys.OPTION); 16 | dropDown.dropDownField () 17 | .selectByText (dropDownOption); 18 | 19 | dropDown.dropDownField () 20 | .selectedOptions () 21 | .get (0) 22 | .verifyText () 23 | .isEqualTo (dropDownOption); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/page/ElementKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.page; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | */ 21 | public interface ElementKey { 22 | /** 23 | * Gets the element key. 24 | * 25 | * @return Element Key 26 | */ 27 | String getKey (); 28 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/AlertDecision.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 06-Jun-2019 21 | */ 22 | public enum AlertDecision { 23 | /** 24 | * Accept alert. 25 | */ 26 | ACCEPT, 27 | /** 28 | * Dismiss alert. 29 | */ 30 | DISMISS 31 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/RecorderSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import lombok.Data; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since 27-Oct-2019 23 | */ 24 | @Data 25 | public class RecorderSetting { 26 | private boolean enable; 27 | private String path = "./video"; 28 | private String prefix = "VID"; 29 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/ApplicationType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 06-Jun-2019 21 | */ 22 | public enum ApplicationType { 23 | /** 24 | * Hybrid app. 25 | */ 26 | HYBRID, 27 | /** 28 | * Native app. 29 | */ 30 | NATIVE, 31 | /** 32 | * Web app. 33 | */ 34 | WEB 35 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/RemoteSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 01-Aug-2019 21 | */ 22 | public enum RemoteSource { 23 | /** 24 | * BrowserStack. 25 | */ 26 | BROWSERSTACK, 27 | /** 28 | * Grid. 29 | */ 30 | GRID, 31 | /** 32 | * SauceLabs. 33 | */ 34 | SAUCELABS 35 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/ITextBoxActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 07-Jun-2019 21 | */ 22 | public interface ITextBoxActions extends IMouseActions { 23 | /** 24 | * @param text input text 25 | * 26 | * @author Wasiq Bhamla 27 | * @since 07-Jun-2019 28 | */ 29 | void enterText (String text); 30 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/DriverSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import lombok.Data; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since 03-Aug-2019 23 | */ 24 | @Data 25 | public class DriverSetting { 26 | private String exeUrl; 27 | private boolean forceCache; 28 | private boolean forceDownload; 29 | private String path; 30 | private String version; 31 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/ScreenState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since Apr 8, 2018 2:46:38 PM 21 | */ 22 | public enum ScreenState { 23 | /** 24 | * Full screen. 25 | */ 26 | FULL_SCREEN, 27 | /** 28 | * Maximized. 29 | */ 30 | MAXIMIZED, 31 | /** 32 | * Normal. 33 | */ 34 | NORMAL 35 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/IKeyboardActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | import org.openqa.selenium.Keys; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since 08-Jun-2019 23 | */ 24 | public interface IKeyboardActions extends IVerifyElement { 25 | /** 26 | * @param keys Keys 27 | * 28 | * @author Wasiq Bhamla 29 | * @since 07-Jun-2019 30 | */ 31 | void pressKey (Keys... keys); 32 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/IMouseActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 07-Jun-2019 21 | */ 22 | public interface IMouseActions extends IFindableAction { 23 | /** 24 | * @author Wasiq Bhamla 25 | * @since 07-Jun-2019 26 | */ 27 | void click (); 28 | 29 | /** 30 | * @author Wasiq Bhamla 31 | * @since 07-Jun-2019 32 | */ 33 | void hover (); 34 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: "⭐ Feature / enhancement request" 2 | description: Propose something new in coteafs-selenium framework. 3 | title: "[Feature]" 4 | labels: 5 | - "type: feature" 6 | body: 7 | - type: textarea 8 | attributes: 9 | label: Description of the new feature / enhancement 10 | placeholder: What is the expected behavior of the proposed feature? 11 | validations: 12 | required: true 13 | 14 | - type: textarea 15 | attributes: 16 | label: Scenario when this would be used? 17 | placeholder: | 18 | What is the scenario this would be used? Why is this important to your workflow? 19 | validations: 20 | required: true 21 | 22 | - type: textarea 23 | attributes: 24 | label: Supporting information 25 | placeholder: | 26 | Having additional evidence, data, tweets, blog posts, research, ... anything is extremely helpful. 27 | This information provides context to the scenario that may otherwise be lost. 28 | validations: 29 | required: false 30 | 31 | - type: markdown 32 | attributes: 33 | value: | 34 | Please limit one request per issue. -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/WaitStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 09-Jun-2019 21 | */ 22 | public enum WaitStrategy { 23 | /** 24 | * Wait until clickable. 25 | */ 26 | CLICKABLE, 27 | /** 28 | * Wait until invisible. 29 | */ 30 | INVISIBLE, 31 | /** 32 | * None. 33 | */ 34 | NONE, 35 | /** 36 | * Wait until visible. 37 | */ 38 | VISIBLE 39 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/ScreenshotSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import lombok.Data; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since Apr 8, 2018 3:00:06 PM 23 | */ 24 | @Data 25 | public class ScreenshotSetting { 26 | private boolean captureAll; 27 | private boolean captureOnError; 28 | private String extension = "jpeg"; 29 | private String path = "./screenshots"; 30 | private String prefix = "SCR"; 31 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/Platform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 06-Jun-2019 21 | */ 22 | public enum Platform { 23 | /** 24 | * Desktop. 25 | */ 26 | DESKTOP, 27 | /** 28 | * Mobiles. 29 | */ 30 | MOBILE, 31 | /** 32 | * Tablets. 33 | */ 34 | TABLET, 35 | /** 36 | * Smart TV. 37 | */ 38 | TV, 39 | /** 40 | * Smart watch. 41 | */ 42 | WATCH 43 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/ScreenResolution.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import static java.text.MessageFormat.format; 19 | 20 | import lombok.Data; 21 | 22 | /** 23 | * @author Wasiq Bhamla 24 | * @since 28 Apr 2019 25 | */ 26 | @Data 27 | public class ScreenResolution { 28 | private int height = 1024; 29 | private int width = 1366; 30 | 31 | @Override 32 | public String toString () { 33 | return format ("{0}x{1}", this.width, this.height); 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IScriptAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 03-Jul-2019 21 | */ 22 | public interface IScriptAction { 23 | /** 24 | * @param output type 25 | * @param script script 26 | * @param args args 27 | * 28 | * @return result 29 | * 30 | * @author Wasiq Bhamla 31 | * @since 06-Jun-2019 32 | */ 33 | T execute (final String script, final Object... args); 34 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IWebWindow.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 16-Jun-2019 21 | */ 22 | public interface IWebWindow { 23 | /** 24 | * @author Wasiq Bhamla 25 | * @since 16-Jun-2019 26 | */ 27 | void switchWindow (); 28 | 29 | /** 30 | * @param title window title 31 | * 32 | * @author Wasiq Bhamla 33 | * @since 16-Jun-2019 34 | */ 35 | void switchWindow (String title); 36 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IWebDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import org.openqa.selenium.support.events.EventFiringWebDriver; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since 06-Jun-2019 23 | */ 24 | public interface IWebDriver extends IDriver { 25 | /** 26 | * @param browser Browser under test 27 | * 28 | * @author Wasiq Bhamla 29 | * @since 06-Jun-2019 30 | */ 31 | void setBrowserSettingName (String browser); 32 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/SeleniumConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import java.util.Map; 19 | 20 | import com.github.wasiqb.coteafs.datasource.annotation.DataFile; 21 | import lombok.Data; 22 | 23 | @Data 24 | @DataFile 25 | public class SeleniumConfig { 26 | private BrowserSetting browser; 27 | private Map browsers; 28 | 29 | public BrowserSetting getBrowserSetting (final String name) { 30 | return this.browsers.get (name); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/DropDownPage.java: -------------------------------------------------------------------------------- 1 | package com.github.wasiqb.coteafs.selenium.pages; 2 | 3 | import com.github.wasiqb.coteafs.selenium.core.BrowserPage; 4 | import com.github.wasiqb.coteafs.selenium.core.element.ISelectBoxActions; 5 | import com.github.wasiqb.coteafs.selenium.core.page.ElementKey; 6 | import org.openqa.selenium.By; 7 | 8 | /** 9 | * @author Faisal Khatri 10 | * @since Jul 19, 2020 11 | */ 12 | public class DropDownPage extends BrowserPage { 13 | /** 14 | * @author Faisal Khatri 15 | * @since Jul 19, 2020 16 | */ 17 | public enum DropDownKeys implements ElementKey { 18 | /** 19 | * @since Jul 19, 2020 20 | */ 21 | OPTION ("Option"); 22 | 23 | String key; 24 | 25 | DropDownKeys (final String key) { 26 | this.key = key; 27 | } 28 | 29 | @Override 30 | public String getKey () { 31 | return this.key; 32 | } 33 | } 34 | 35 | /** 36 | * @return dropdown field 37 | * 38 | * @since Jul 19, 2020 39 | */ 40 | public ISelectBoxActions dropDownField () { 41 | return onDropdown (By.id ("dropdown"), "DropDown List"); 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/PlatformOs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 06-Jun-2019 21 | */ 22 | public enum PlatformOs { 23 | /** 24 | * Android. 25 | */ 26 | ANDROID, 27 | /** 28 | * iOS. 29 | */ 30 | IOS, 31 | /** 32 | * Linux. 33 | */ 34 | LINUX, 35 | /** 36 | * Mac OSX. 37 | */ 38 | MAC, 39 | /** 40 | * tvOS. 41 | */ 42 | TV_OS, 43 | /** 44 | * Windows. 45 | */ 46 | WINDOWS 47 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IServiceAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 03-Jul-2019 21 | */ 22 | public interface IServiceAction { 23 | /** 24 | * @return is running 25 | * 26 | * @author Wasiq Bhamla 27 | * @since 24-Jul-2019 28 | */ 29 | boolean isRunning (); 30 | 31 | /** 32 | * @author Wasiq Bhamla 33 | * @since 06-Jun-2019 34 | */ 35 | void start (); 36 | 37 | /** 38 | * @author Wasiq Bhamla 39 | * @since 06-Jun-2019 40 | */ 41 | void stop (); 42 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/AvailableBrowser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since Apr 8, 2018 2:42:01 PM 21 | */ 22 | public enum AvailableBrowser { 23 | /** 24 | * Chrome. 25 | */ 26 | CHROME, 27 | /** 28 | * Edge. 29 | */ 30 | EDGE, 31 | /** 32 | * Firefox. 33 | */ 34 | FIREFOX, 35 | /** 36 | * IE. 37 | */ 38 | IE, 39 | /** 40 | * Remote Grid or Cloud instance. 41 | */ 42 | REMOTE, 43 | /** 44 | * Safari. 45 | */ 46 | SAFARI 47 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/BrowserSession.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.base.driver.DriverSession; 19 | import org.openqa.selenium.support.events.EventFiringWebDriver; 20 | 21 | /** 22 | * @author Wasiq Bhamla 23 | * @since 28-Sep-2019 24 | */ 25 | public class BrowserSession extends DriverSession { 26 | /** 27 | * @param browserName Browser name 28 | * 29 | * @author Wasiq Bhamla 30 | * @since 28-Sep-2019 31 | */ 32 | public BrowserSession (final String browserName) { 33 | super (browserName); 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IWaitAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import org.openqa.selenium.WebDriver; 19 | import org.openqa.selenium.support.ui.WebDriverWait; 20 | 21 | /** 22 | * @param 23 | * 24 | * @author Wasiq Bhamla 25 | * @since 27-Jul-2019 26 | */ 27 | public interface IWaitAction { 28 | /** 29 | * @return driver 30 | * 31 | * @author Wasiq Bhamla 32 | * @since 27-Jul-2019 33 | */ 34 | D driver (); 35 | 36 | /** 37 | * @return wait 38 | * 39 | * @author Wasiq Bhamla 40 | * @since 27-Jul-2019 41 | */ 42 | WebDriverWait driverWait (); 43 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/constants/ConfigKeys.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.constants; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since Aug 9, 2018 8:24:45 PM 21 | */ 22 | public interface ConfigKeys { 23 | /** 24 | * Browser key. 25 | */ 26 | String BROWSER = "test.browser"; 27 | /** 28 | * Config file key. 29 | */ 30 | String CONFIG = "test.config"; 31 | /** 32 | * Selenium config key. 33 | */ 34 | String COTEAFS_CONFIG_KEY = "coteafs.selenium.config"; 35 | /** 36 | * Ignore package. 37 | */ 38 | String FILTER_PKG = "com.github.wasiqb"; 39 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IPlatformAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.enums.Platform; 19 | import com.github.wasiqb.coteafs.selenium.core.enums.PlatformOs; 20 | 21 | /** 22 | * @author Wasiq Bhamla 23 | * @since 03-Jul-2019 24 | */ 25 | public interface IPlatformAction { 26 | /** 27 | * @return platform 28 | * 29 | * @author Wasiq Bhamla 30 | * @since 06-Jun-2019 31 | */ 32 | Platform getPlatform (); 33 | 34 | /** 35 | * @return platform os. 36 | * 37 | * @author Wasiq Bhamla 38 | * @since 06-Jun-2019 39 | */ 40 | PlatformOs getPlatformOs (); 41 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/enums/Protocol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.enums; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 01-Aug-2019 21 | */ 22 | public enum Protocol { 23 | /** 24 | * http 25 | */ 26 | HTTP ("http://"), 27 | /** 28 | * https 29 | */ 30 | HTTPS ("https://"); 31 | 32 | private final String prefix; 33 | 34 | Protocol (final String prefix) { 35 | this.prefix = prefix; 36 | } 37 | 38 | /** 39 | * @return prefix 40 | * 41 | * @author Wasiq Bhamla 42 | * @since 01-Aug-2019 43 | */ 44 | public String getPrefix () { 45 | return this.prefix; 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IWebFrame.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 06-Jul-2019 21 | */ 22 | public interface IWebFrame { 23 | /** 24 | * @author Wasiq Bhamla 25 | * @since 06-Jul-2019 26 | */ 27 | void switchFrame (); 28 | 29 | /** 30 | * @param index frame index 31 | * 32 | * @author Wasiq Bhamla 33 | * @since 06-Jul-2019 34 | */ 35 | void switchFrame (int index); 36 | 37 | /** 38 | * @param nameOrId frame name or id 39 | * 40 | * @author Wasiq Bhamla 41 | * @since 06-Jul-2019 42 | */ 43 | void switchFrame (String nameOrId); 44 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/error/VideoRecordingError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.error; 17 | 18 | import java.io.Serial; 19 | 20 | import com.github.wasiqb.coteafs.error.CoteafsError; 21 | 22 | /** 23 | * @author Wasiq Bhamla 24 | * @since 28-Nov-2019 25 | */ 26 | public class VideoRecordingError extends CoteafsError { 27 | @Serial 28 | private static final long serialVersionUID = 6184267334962964373L; 29 | 30 | /** 31 | * @param message Message 32 | * @param cause Exception 33 | * 34 | * @author Wasiq Bhamla 35 | * @since 28-Nov-2019 36 | */ 37 | public VideoRecordingError (final String message, final Throwable cause) { 38 | super (message, cause); 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IDriverActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import com.google.common.truth.StringSubject; 19 | import org.openqa.selenium.WebDriver; 20 | 21 | /** 22 | * @param 23 | * 24 | * @author Wasiq Bhamla 25 | * @since 06-Jun-2019 26 | */ 27 | public interface IDriverActions extends IScriptAction, IScreenAction, IWaitAction { 28 | /** 29 | * @return title 30 | * 31 | * @author Wasiq Bhamla 32 | * @since 06-Jun-2019 33 | */ 34 | String title (); 35 | 36 | /** 37 | * @return string subject 38 | * 39 | * @author Wasiq Bhamla 40 | * @since 08-Jun-2019 41 | */ 42 | StringSubject verifyTitle (); 43 | } -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/SuccessLoginPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.pages; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.BrowserPage; 19 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 20 | import org.openqa.selenium.By; 21 | 22 | /** 23 | * @author Wasiq Bhamla 24 | */ 25 | public class SuccessLoginPage extends BrowserPage { 26 | /** 27 | * @return logout button 28 | */ 29 | public IMouseActions logout () { 30 | return onClickable (By.className ("button"), "Logout"); 31 | } 32 | 33 | /** 34 | * @return success message 35 | */ 36 | public IMouseActions successMessage () { 37 | return onClickable (By.id ("flash"), "Success message"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: "🐛 Bug report" 2 | description: Report errors or unexpected behavior in coteafs-selenium framework. 3 | title: "[Bug]" 4 | labels: 5 | - "type: bug" 6 | body: 7 | - type: input 8 | attributes: 9 | label: Version? 10 | placeholder: 3.0.0 11 | description: The version of coteafs-selenium which caused the issue. 12 | validations: 13 | required: true 14 | 15 | - type: dropdown 16 | attributes: 17 | label: Browser? 18 | description: Which Browser caused the issue? 19 | multiple: false 20 | options: 21 | - Chrome 22 | - Firefox 23 | - IE 24 | - Edge 25 | - Safari 26 | - Other 27 | - Not Required 28 | validations: 29 | required: true 30 | 31 | - type: textarea 32 | attributes: 33 | label: Steps to reproduce 34 | description: We highly suggest including a screenshots and a bug report log (GitHub Gist link). 35 | placeholder: Tell us the steps required to trigger your bug. 36 | validations: 37 | required: true 38 | 39 | - type: textarea 40 | attributes: 41 | label: ✔️ Expected Behavior 42 | placeholder: What were you expecting? 43 | validations: 44 | required: true 45 | 46 | - type: textarea 47 | attributes: 48 | label: ❌ Actual Behavior 49 | placeholder: What happened instead? 50 | validations: 51 | required: true -------------------------------------------------------------------------------- /setting/settings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 21 | 22 | 23 | ossrh 24 | 25 | true 26 | 27 | 28 | gpg 29 | ${env.GPG_PASSPHRASE} 30 | 31 | 32 | 33 | 34 | 35 | ossrh 36 | ${env.NEXUS_USERNAME} 37 | ${env.NEXUS_PASSWORD} 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/PlaybackSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.enums.ScreenState; 19 | import lombok.Data; 20 | 21 | /** 22 | * @author Wasiq Bhamla 23 | * @since Apr 8, 2018 2:45:29 PM 24 | */ 25 | @Data 26 | public class PlaybackSetting { 27 | private DelaySetting delays = new DelaySetting (); 28 | private boolean highlight = true; 29 | private RecorderSetting recording = new RecorderSetting (); 30 | private ScreenResolution screenResolution = new ScreenResolution (); 31 | private ScreenState screenState = ScreenState.NORMAL; 32 | private ScreenshotSetting screenshot = new ScreenshotSetting (); 33 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/RemoteSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import java.util.Map; 19 | 20 | import com.github.wasiqb.coteafs.selenium.core.enums.Protocol; 21 | import com.github.wasiqb.coteafs.selenium.core.enums.RemoteSource; 22 | import lombok.Data; 23 | 24 | /** 25 | * @author Wasiq Bhamla 26 | * @since 01-Aug-2019 27 | */ 28 | @Data 29 | public class RemoteSetting { 30 | private Map capabilities; 31 | private Map cloudCapabilities; 32 | private String password; 33 | private int port; 34 | private Protocol protocol = Protocol.HTTP; 35 | private RemoteSource source; 36 | private String url; 37 | private String userId; 38 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/DelaySetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import lombok.Data; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since Apr 8, 2018 2:48:55 PM 23 | */ 24 | @Data 25 | public class DelaySetting { 26 | private long afterClick; 27 | private long afterFrameSwitch = 500; 28 | private long afterKeyPress; 29 | private long afterMouseMove; 30 | private long afterWindowSwitch = 500; 31 | private long beforeClick; 32 | private long beforeKeyPress; 33 | private long beforeMouseMove; 34 | private long explicit = 30; 35 | private long highlight = 200; 36 | private long implicit = 1; 37 | private long pageLoad = 60; 38 | private long scriptLoad = 60; 39 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IAlertAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.enums.AlertDecision; 19 | import com.google.common.truth.StringSubject; 20 | 21 | /** 22 | * @author Wasiq Bhamla 23 | * @since 03-Jul-2019 24 | */ 25 | public interface IAlertAction { 26 | /** 27 | * @param decision alert decision 28 | * 29 | * @return message 30 | * 31 | * @author Wasiq Bhamla 32 | * @since 06-Jun-2019 33 | */ 34 | String alert (AlertDecision decision); 35 | 36 | /** 37 | * @param decision alert decision 38 | * 39 | * @return string subject 40 | * 41 | * @author Wasiq Bhamla 42 | * @since 06-Jun-2019 43 | */ 44 | StringSubject verifyAlertMessage (AlertDecision decision); 45 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/page/AbstractPageAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.page; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getSession; 19 | 20 | /** 21 | * @param 22 | * 23 | * @author wasiqb 24 | * @since Sep 1, 2018 4:28:28 PM 25 | */ 26 | public abstract class AbstractPageAction> implements IPageAction { 27 | @SuppressWarnings ("unchecked") 28 | @Override 29 | public T addInputValue (final ElementKey elementKey, final Object value) { 30 | getSession ().setContext (elementKey.getKey (), value); 31 | return (T) this; 32 | } 33 | 34 | @Override 35 | public E value (final ElementKey elementKey) { 36 | return getSession ().getContext (elementKey.getKey ()); 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/ConfigUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import com.github.wasiqb.coteafs.datasource.DataSource; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since Aug 9, 2018 8:23:23 PM 23 | */ 24 | public final class ConfigUtil { 25 | /** 26 | * @param browserName Browser setting name. 27 | * 28 | * @return setting 29 | * 30 | * @author Wasiq Bhamla 31 | * @since Aug 9, 2018 8:39:04 PM 32 | */ 33 | public static BrowserSetting appSetting (final String browserName) { 34 | return DataSource.parse (SeleniumConfig.class) 35 | .getBrowserSetting (browserName); 36 | } 37 | 38 | private ConfigUtil () { 39 | // Remove default constructor since class is static util class. 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/config/BrowserSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.config; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | import com.github.wasiqb.coteafs.selenium.core.enums.AvailableBrowser; 22 | import lombok.Data; 23 | 24 | /** 25 | * @author Wasiq Bhamla 26 | * @since Apr 8, 2018 2:41:06 PM 27 | */ 28 | @Data 29 | public class BrowserSetting { 30 | private AvailableBrowser browser = AvailableBrowser.CHROME; 31 | private DriverSetting driver = new DriverSetting (); 32 | private boolean headlessMode; 33 | private String hubUrl; 34 | private Map params = new HashMap<> (); 35 | private PlaybackSetting playback = new PlaybackSetting (); 36 | private RemoteSetting remote; 37 | private String url; 38 | } -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/CheckboxPage.java: -------------------------------------------------------------------------------- 1 | package com.github.wasiqb.coteafs.selenium.pages; 2 | 3 | import com.github.wasiqb.coteafs.selenium.core.BrowserPage; 4 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 5 | import com.github.wasiqb.coteafs.selenium.core.page.ElementKey; 6 | import org.openqa.selenium.By; 7 | 8 | /** 9 | * @author Faisal Khatri 10 | * @since Jul 19, 2020 11 | */ 12 | public class CheckboxPage extends BrowserPage { 13 | /** 14 | * @author Faisal Khatri 15 | * @since Jul 19, 2020 16 | */ 17 | public enum CheckboxPageKeys implements ElementKey { 18 | /** 19 | * @since Jul 19, 2020 20 | */ 21 | CHECK ("check"); 22 | 23 | String key; 24 | 25 | CheckboxPageKeys (final String key) { 26 | this.key = key; 27 | } 28 | 29 | @Override 30 | public String getKey () { 31 | return this.key; 32 | } 33 | } 34 | 35 | /** 36 | * @return checkbox 1 37 | * 38 | * @since Jul 19, 2020 39 | */ 40 | public IMouseActions checkBoxOne () { 41 | return onClickable (By.cssSelector ("#checkboxes > input[type=checkbox]:nth-child(1)"), "Checkbox 1"); 42 | } 43 | 44 | /** 45 | * @return checkbox 2 46 | * 47 | * @since Jul 19, 2020 48 | */ 49 | public IMouseActions checkBoxTwo () { 50 | return onClickable (By.cssSelector ("#checkboxes > input[type=checkbox]:nth-child(3)"), "Checkbox 2"); 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/IWaitStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 07-Jun-2019 21 | */ 22 | public interface IWaitStrategy { 23 | /** 24 | * @param attribute element attribute 25 | * @param value attribute value 26 | * 27 | * @author Wasiq Bhamla 28 | * @since 07-Jun-2019 29 | */ 30 | void waitUntilAttributeIs (final String attribute, final String value); 31 | 32 | /** 33 | * @author Wasiq Bhamla 34 | * @since 07-Jun-2019 35 | */ 36 | void waitUntilClickable (); 37 | 38 | /** 39 | * @author Wasiq Bhamla 40 | * @since 07-Jun-2019 41 | */ 42 | void waitUntilInvisible (); 43 | 44 | /** 45 | * @author Wasiq Bhamla 46 | * @since 07-Jun-2019 47 | */ 48 | void waitUntilVisible (); 49 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/error/DriverNotSetupError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.error; 17 | 18 | import java.io.Serial; 19 | 20 | import com.github.wasiqb.coteafs.error.CoteafsError; 21 | import com.github.wasiqb.coteafs.error.enums.Category; 22 | import com.github.wasiqb.coteafs.error.enums.Reason; 23 | import com.github.wasiqb.coteafs.error.enums.Severity; 24 | 25 | /** 26 | * @author Wasiq Bhamla 27 | * @since 03-Aug-2019 28 | */ 29 | public class DriverNotSetupError extends CoteafsError { 30 | @Serial 31 | private static final long serialVersionUID = -8652506910306288004L; 32 | 33 | /** 34 | * @param message Message 35 | * 36 | * @author Wasiq Bhamla 37 | * @since 03-Aug-2019 38 | */ 39 | public DriverNotSetupError (final String message) { 40 | super (message, Reason.R1, Category.C1, Severity.HIGH); 41 | } 42 | } -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/action/CheckboxPageAction.java: -------------------------------------------------------------------------------- 1 | package com.github.wasiqb.coteafs.selenium.pages.action; 2 | 3 | import com.github.wasiqb.coteafs.selenium.core.page.AbstractPageAction; 4 | import com.github.wasiqb.coteafs.selenium.pages.CheckboxPage; 5 | import com.github.wasiqb.coteafs.selenium.pages.CheckboxPage.CheckboxPageKeys; 6 | 7 | /** 8 | * @author Faisal Khatri 9 | * @since Jul 19, 2020 10 | */ 11 | public class CheckboxPageAction extends AbstractPageAction { 12 | @Override 13 | public void perform () { 14 | final CheckboxPage checkbox = new CheckboxPage (); 15 | 16 | final String checkValue = (value (CheckboxPageKeys.CHECK)); 17 | switch (checkValue) { 18 | case "check": 19 | checkbox.checkBoxOne () 20 | .click (); 21 | checkbox.checkBoxOne () 22 | .verifySelected () 23 | .isTrue (); 24 | checkbox.checkBoxTwo () 25 | .verifySelected () 26 | .isTrue (); 27 | break; 28 | 29 | case "uncheck": 30 | default: 31 | checkbox.checkBoxTwo () 32 | .click (); 33 | checkbox.checkBoxOne () 34 | .verifySelected () 35 | .isFalse (); 36 | checkbox.checkBoxTwo () 37 | .verifySelected () 38 | .isFalse (); 39 | break; 40 | 41 | } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/MainPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.pages; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.BrowserPage; 19 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 20 | import org.openqa.selenium.By; 21 | 22 | /** 23 | * @author wasiqb 24 | */ 25 | public class MainPage extends BrowserPage { 26 | 27 | /** 28 | * @param name link name 29 | * 30 | * @return menu name 31 | */ 32 | public IMouseActions links (final String name) { 33 | return navigationLinks ().finds (By.cssSelector ("li > a"), name) 34 | .stream () 35 | .filter (m -> m.text () 36 | .trim () 37 | .equals (name)) 38 | .findFirst () 39 | .get (); 40 | } 41 | 42 | private IMouseActions navigationLinks () { 43 | return onClickable (By.cssSelector ("div#content ul"), "Links"); 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/page/IPageAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.page; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 08-Jun-2019 21 | */ 22 | public interface IPageAction { 23 | /** 24 | * @param page action 25 | * @param elementKey element alias 26 | * @param value element input value 27 | * 28 | * @return page action 29 | * 30 | * @author Wasiq Bhamla 31 | * @since 08-Jun-2019 32 | */ 33 | T addInputValue (final ElementKey elementKey, final Object value); 34 | 35 | /** 36 | * @author Wasiq Bhamla 37 | * @since 08-Jun-2019 38 | */ 39 | void perform (); 40 | 41 | /** 42 | * @param input value 43 | * @param elementKey element alias 44 | * 45 | * @return input value 46 | * 47 | * @author Wasiq Bhamla 48 | * @since 08-Jun-2019 49 | */ 50 | T value (final ElementKey elementKey); 51 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.enums.ApplicationType; 19 | import org.openqa.selenium.WebDriver; 20 | 21 | /** 22 | * @param 23 | * 24 | * @author Wasiq Bhamla 25 | * @since 06-Jun-2019 26 | */ 27 | public interface IDriver extends IServiceAction, IPlatformAction { 28 | /** 29 | * @return application type. 30 | * 31 | * @author Wasiq Bhamla 32 | * @since 06-Jun-2019 33 | */ 34 | ApplicationType getApplicationType (); 35 | 36 | /** 37 | * @return driver 38 | * 39 | * @author Wasiq Bhamla 40 | * @since 06-Jun-2019 41 | */ 42 | D getDriver (); 43 | 44 | /** 45 | * @param driver action 46 | * 47 | * @return actions 48 | * 49 | * @author Wasiq Bhamla 50 | * @since 06-Jun-2019 51 | */ 52 | > T perform (); 53 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IWebDriverActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import org.openqa.selenium.WebDriver; 19 | 20 | /** 21 | * @param Driver 22 | * 23 | * @author Wasiq Bhamla 24 | * @since 06-Jun-2019 25 | */ 26 | public interface IWebDriverActions extends IDriverActions { 27 | /** 28 | * @author Wasiq Bhamla 29 | * @since 06-Jun-2019 30 | */ 31 | void back (); 32 | 33 | /** 34 | * @author Wasiq Bhamla 35 | * @since 06-Jun-2019 36 | */ 37 | void deleteCookies (); 38 | 39 | /** 40 | * @author Wasiq Bhamla 41 | * @since 06-Jun-2019 42 | */ 43 | void forward (); 44 | 45 | /** 46 | * @param url URL 47 | * 48 | * @author Wasiq Bhamla 49 | * @since 06-Jun-2019 50 | */ 51 | void navigateTo (String url); 52 | 53 | /** 54 | * @author Wasiq Bhamla 55 | * @since 06-Jun-2019 56 | */ 57 | void refresh (); 58 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/driver/IScreenAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.driver; 17 | 18 | import java.io.File; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since 03-Jul-2019 23 | */ 24 | public interface IScreenAction { 25 | /** 26 | * @return screenshot 27 | * 28 | * @author Wasiq Bhamla 29 | * @since 06-Jun-2019 30 | */ 31 | byte[] attachScreenshot (); 32 | 33 | /** 34 | * @return file 35 | * 36 | * @author Wasiq Bhamla 37 | * @since 25-Jul-2019 38 | */ 39 | File saveScreenshot (); 40 | 41 | /** 42 | * @param path Screenshot path 43 | * 44 | * @return file 45 | * 46 | * @author Wasiq Bhamla 47 | * @since 25-Jul-2019 48 | */ 49 | File saveScreenshot (String path); 50 | 51 | /** 52 | * @author Wasiq Bhamla 53 | * @since 27-Oct-2019 54 | */ 55 | void startRecording (); 56 | 57 | /** 58 | * @author Wasiq Bhamla 59 | * @since 27-Oct-2019 60 | */ 61 | void stopRecording (); 62 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/PlatformAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.driver.IPlatformAction; 19 | import com.github.wasiqb.coteafs.selenium.core.enums.Platform; 20 | import com.github.wasiqb.coteafs.selenium.core.enums.PlatformOs; 21 | 22 | /** 23 | * @author Wasiq Bhamla 24 | * @since 26-Jul-2019 25 | */ 26 | public class PlatformAction implements IPlatformAction { 27 | private final Platform platform; 28 | private final PlatformOs platformOs; 29 | 30 | /** 31 | * @param platform platform 32 | * @param platformOs platformOs 33 | * 34 | * @author Wasiq Bhamla 35 | * @since 26-Jul-2019 36 | */ 37 | public PlatformAction (final Platform platform, final PlatformOs platformOs) { 38 | this.platform = platform; 39 | this.platformOs = platformOs; 40 | } 41 | 42 | @Override 43 | public Platform getPlatform () { 44 | return this.platform; 45 | } 46 | 47 | @Override 48 | public PlatformOs getPlatformOs () { 49 | return this.platformOs; 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/IElementActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | /** 19 | * @author Wasiq Bhamla 20 | * @since 07-Jun-2019 21 | */ 22 | public interface IElementActions extends IWaitStrategy { 23 | /** 24 | * @param name attribute name 25 | * 26 | * @return attribute 27 | * 28 | * @author Wasiq Bhamla 29 | * @since 07-Jun-2019 30 | */ 31 | String attribute (String name); 32 | 33 | /** 34 | * @author Wasiq Bhamla 35 | * @since 07-Jun-2019 36 | */ 37 | void clear (); 38 | 39 | /** 40 | * @return is displayed 41 | * 42 | * @author Wasiq Bhamla 43 | * @since 07-Jun-2019 44 | */ 45 | boolean isDisplayed (); 46 | 47 | /** 48 | * @return is enabled 49 | * 50 | * @author Wasiq Bhamla 51 | * @since 07-Jun-2019 52 | */ 53 | boolean isEnabled (); 54 | 55 | /** 56 | * @return is selected 57 | * 58 | * @author Wasiq Bhamla 59 | * @since 07-Jun-2019 60 | */ 61 | boolean isSelected (); 62 | 63 | /** 64 | * @return text 65 | * 66 | * @author Wasiq Bhamla 67 | * @since 07-Jun-2019 68 | */ 69 | String text (); 70 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/WebDriverAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.driver.IWebDriverActions; 19 | import org.openqa.selenium.WebDriver; 20 | 21 | /** 22 | * @param 23 | * 24 | * @author Wasiq Bhamla 25 | * @since 27-Jul-2019 26 | */ 27 | public class WebDriverAction extends AlertAction implements IWebDriverActions { 28 | protected WebDriverAction (final D driver) { 29 | super (driver); 30 | } 31 | 32 | @Override 33 | public void back () { 34 | perform (d -> d.navigate () 35 | .back ()); 36 | } 37 | 38 | @Override 39 | public void deleteCookies () { 40 | perform (d -> d.manage () 41 | .deleteAllCookies ()); 42 | } 43 | 44 | @Override 45 | public void forward () { 46 | perform (d -> d.navigate () 47 | .forward ()); 48 | } 49 | 50 | @Override 51 | public void navigateTo (final String url) { 52 | perform (d -> d.navigate () 53 | .to (url)); 54 | } 55 | 56 | @Override 57 | public void refresh () { 58 | perform (d -> d.navigate () 59 | .refresh ()); 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/IVerifyElement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | import com.google.common.truth.BooleanSubject; 19 | import com.google.common.truth.StringSubject; 20 | 21 | /** 22 | * @author Wasiq Bhamla 23 | * @since 07-Jun-2019 24 | */ 25 | public interface IVerifyElement extends IElementActions { 26 | /** 27 | * @param attribute element attribute 28 | * 29 | * @return subject 30 | * 31 | * @author Wasiq Bhamla 32 | * @since 07-Jun-2019 33 | */ 34 | StringSubject verifyAttribute (final String attribute); 35 | 36 | /** 37 | * @return subject 38 | * 39 | * @author Wasiq Bhamla 40 | * @since 07-Jun-2019 41 | */ 42 | BooleanSubject verifyDisplayed (); 43 | 44 | /** 45 | * @return subject 46 | * 47 | * @author Wasiq Bhamla 48 | * @since 07-Jun-2019 49 | */ 50 | BooleanSubject verifyEnabled (); 51 | 52 | /** 53 | * @return subject 54 | * 55 | * @author Wasiq Bhamla 56 | * @since 07-Jun-2019 57 | */ 58 | BooleanSubject verifySelected (); 59 | 60 | /** 61 | * @return subject 62 | * 63 | * @author Wasiq Bhamla 64 | * @since 07-Jun-2019 65 | */ 66 | StringSubject verifyText (); 67 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/WebElementAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.base.element.AbstractElementAction; 19 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 20 | import org.openqa.selenium.By; 21 | import org.openqa.selenium.WebElement; 22 | import org.openqa.selenium.support.events.EventFiringWebDriver; 23 | 24 | /** 25 | * @author Wasiq Bhamla 26 | * @since 27-Jul-2019 27 | */ 28 | class WebElementAction extends AbstractElementAction { 29 | WebElementAction (final BrowserActions browserAction, final By by, final String name) { 30 | super (browserAction, by, name); 31 | } 32 | 33 | WebElementAction (final BrowserActions browserAction, final By by, final String name, final WaitStrategy strategy) { 34 | super (browserAction, by, name, strategy); 35 | } 36 | 37 | WebElementAction (final BrowserActions browserAction, final WebElement element, final String name) { 38 | super (browserAction, element, name); 39 | } 40 | 41 | WebElementAction (final BrowserActions browserAction, final WebElement element, final String name, 42 | final WaitStrategy strategy) { 43 | super (browserAction, element, name, strategy); 44 | } 45 | } -------------------------------------------------------------------------------- /checkstyle-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | 39 | -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/action/LoginPageAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.pages.action; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.page.AbstractPageAction; 19 | import com.github.wasiqb.coteafs.selenium.pages.LoginPage; 20 | import com.github.wasiqb.coteafs.selenium.pages.LoginPage.LoginPageKeys; 21 | import com.github.wasiqb.coteafs.selenium.pages.SuccessLoginPage; 22 | 23 | /** 24 | * @author Wasiq Bhamla 25 | */ 26 | public class LoginPageAction extends AbstractPageAction { 27 | @Override 28 | public void perform () { 29 | LoginPage login = new LoginPage (); 30 | login.userId () 31 | .enterText (value (LoginPageKeys.USER_ID)); 32 | login.password () 33 | .enterText (value (LoginPageKeys.PASS)); 34 | login.signIn () 35 | .click (); 36 | 37 | final SuccessLoginPage successPage = login.nextPage (SuccessLoginPage.class); 38 | 39 | successPage.successMessage () 40 | .verifyText () 41 | .startsWith ("You logged into a secure area!"); 42 | 43 | successPage.logout () 44 | .click (); 45 | 46 | login = successPage.nextPage (LoginPage.class); 47 | login.loginMessage () 48 | .verifyText () 49 | .startsWith ("You logged out of the secure area!"); 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/ParallelSession.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import com.github.wasiqb.coteafs.selenium.config.BrowserSetting; 19 | import com.github.wasiqb.coteafs.selenium.core.BrowserSession; 20 | import org.openqa.selenium.support.events.EventFiringWebDriver; 21 | 22 | /** 23 | * @author Wasiq Bhamla 24 | * @since 27-Sep-2019 25 | */ 26 | public class ParallelSession { 27 | private static final ThreadLocal SESSION = new ThreadLocal<> (); 28 | 29 | /** 30 | * @author Wasiq Bhamla 31 | * @since 28-Nov-2019 32 | */ 33 | public static void close () { 34 | SESSION.remove (); 35 | } 36 | 37 | public static BrowserSetting getBrowserSetting () { 38 | return SESSION.get () 39 | .getSetting (); 40 | } 41 | 42 | /** 43 | * @return session 44 | * 45 | * @author Wasiq Bhamla 46 | * @since 28-Sep-2019 47 | */ 48 | public static BrowserSession getSession () { 49 | return SESSION.get (); 50 | } 51 | 52 | public static void setDriver (final EventFiringWebDriver driver) { 53 | SESSION.get () 54 | .setDriver (driver); 55 | } 56 | 57 | /** 58 | * @param browserName Browser name 59 | * 60 | * @author Wasiq Bhamla 61 | * @since 28-Sep-2019 62 | */ 63 | public static void setSession (final String browserName) { 64 | SESSION.set (new BrowserSession (browserName)); 65 | } 66 | 67 | private ParallelSession () { 68 | // Utility class. 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/element/KeyboardAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.element; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 19 | import com.github.wasiqb.coteafs.selenium.core.element.IKeyboardActions; 20 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 21 | import org.openqa.selenium.By; 22 | import org.openqa.selenium.Keys; 23 | import org.openqa.selenium.WebDriver; 24 | import org.openqa.selenium.WebElement; 25 | 26 | /** 27 | * @param 28 | * @param 29 | * @param 30 | * 31 | * @author Wasiq Bhamla 32 | * @since 27-Jul-2019 33 | */ 34 | public abstract class KeyboardAction> 35 | extends VerifyElement implements IKeyboardActions { 36 | KeyboardAction (final B browserAction, final By by, final String name) { 37 | super (browserAction, by, name); 38 | } 39 | 40 | KeyboardAction (final B browserAction, final By by, final String name, final WaitStrategy strategy) { 41 | super (browserAction, by, name, strategy); 42 | } 43 | 44 | KeyboardAction (final B browserAction, final E element, final String name) { 45 | super (browserAction, element, name); 46 | } 47 | 48 | KeyboardAction (final B browserAction, final E element, final String name, final WaitStrategy strategy) { 49 | super (browserAction, element, name, strategy); 50 | } 51 | 52 | @Override 53 | public void pressKey (final Keys... keys) { 54 | perform (e -> e.sendKeys (keys)); 55 | } 56 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/AlertAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.listeners.DriverListener.setAlias; 19 | import static com.google.common.truth.Truth.assertThat; 20 | 21 | import com.github.wasiqb.coteafs.selenium.core.driver.IAlertAction; 22 | import com.github.wasiqb.coteafs.selenium.core.enums.AlertDecision; 23 | import com.google.common.truth.StringSubject; 24 | import org.openqa.selenium.Alert; 25 | import org.openqa.selenium.WebDriver; 26 | import org.openqa.selenium.support.ui.ExpectedConditions; 27 | 28 | /** 29 | * @param 30 | * 31 | * @author Wasiq Bhamla 32 | * @since 27-Jul-2019 33 | */ 34 | public class AlertAction extends ScreenAction implements IAlertAction { 35 | AlertAction (final D driver) { 36 | super (driver); 37 | } 38 | 39 | @Override 40 | public String alert (final AlertDecision decision) { 41 | final Alert alert = driverWait ().until (ExpectedConditions.alertIsPresent ()); 42 | String message = null; 43 | if (alert != null) { 44 | message = alert.getText (); 45 | setAlias (message); 46 | if (decision == AlertDecision.ACCEPT) { 47 | alert.accept (); 48 | } else { 49 | alert.dismiss (); 50 | } 51 | } 52 | return message; 53 | } 54 | 55 | @Override 56 | public StringSubject verifyAlertMessage (final AlertDecision decision) { 57 | final String actual = alert (decision); 58 | return assertThat (actual); 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/resources/log4j2.yaml: -------------------------------------------------------------------------------- 1 | Configuration: 2 | status: warn 3 | name: Default 4 | monitorInterval: 30 5 | 6 | properties: 7 | property: 8 | - name: log-path 9 | value: logs 10 | - name: error-log 11 | value: coteafs-selenium-log-error 12 | - name: all-log 13 | value: coteafs-selenium-log-all 14 | - name: test-log 15 | value: coteafs-selenium-log-main 16 | - name: log-pattern 17 | value: "[%d{HH:mm:ss.SSS}] [%-5level] - %msg (%logger{1}:%L) %throwable{short.message}%n" 18 | 19 | appenders: 20 | Console: 21 | name: "console-log" 22 | target: SYSTEM_OUT 23 | PatternLayout: 24 | pattern: ${log-pattern} 25 | RollingFile: 26 | - name: "all-log-appender" 27 | fileName: ${log-path}/${all-log}.log 28 | filePattern: ${log-path}/${all-log}-%d{yyyy-MM-dd}.log 29 | append: false 30 | immediateFlush: true 31 | PatternLayout: 32 | pattern: ${log-pattern} 33 | Policies: 34 | TimeBasedTriggeringPolicy: 35 | interval: 1 36 | modulate: true 37 | SizeBasedTriggeringPolicy: 38 | size: 5MB 39 | - name: "test-log-appender" 40 | fileName: ${log-path}/${test-log}.log 41 | filePattern: ${log-path}/${test-log}-%d{yyyy-MM-dd}.log 42 | append: false 43 | immediateFlush: true 44 | PatternLayout: 45 | pattern: ${log-pattern} 46 | Policies: 47 | TimeBasedTriggeringPolicy: 48 | interval: 1 49 | modulate: true 50 | SizeBasedTriggeringPolicy: 51 | size: 5MB 52 | - name: "error-log-appender" 53 | fileName: ${log-path}/${error-log}.log 54 | filePattern: ${log-path}/${error-log}-%d{yyyy-MM-dd}.log 55 | append: false 56 | immediateFlush: true 57 | PatternLayout: 58 | pattern: ${log-pattern} 59 | Policies: 60 | TimeBasedTriggeringPolicy: 61 | interval: 1 62 | modulate: true 63 | SizeBasedTriggeringPolicy: 64 | size: 5MB 65 | Async: 66 | name: async 67 | AppenderRef: 68 | ref: "test-log-appender" 69 | 70 | Loggers: 71 | Root: 72 | level: all 73 | AppenderRef: 74 | - ref: "console-log" 75 | level: debug 76 | - ref: "async" 77 | level: info 78 | - ref: "all-log-appender" 79 | level: trace 80 | - ref: "error-log-appender" 81 | level: error -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/constants/OS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.constants; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.core.enums.PlatformOs.LINUX; 19 | import static com.github.wasiqb.coteafs.selenium.core.enums.PlatformOs.MAC; 20 | import static com.github.wasiqb.coteafs.selenium.core.enums.PlatformOs.WINDOWS; 21 | import static java.lang.System.getProperty; 22 | 23 | import com.github.wasiqb.coteafs.selenium.core.enums.PlatformOs; 24 | 25 | /** 26 | * @author Wasiq Bhamla 27 | * @since Aug 10, 2018 2:37:10 PM 28 | */ 29 | public class OS { 30 | private static final String NAME = getProperty ("os.name").toLowerCase (); 31 | 32 | /** 33 | * @return is Mac 34 | * 35 | * @since Aug 10, 2018 2:38:12 PM 36 | */ 37 | public static boolean isMac () { 38 | return NAME.contains ("mac"); 39 | } 40 | 41 | /** 42 | * @return is unix 43 | * 44 | * @since Aug 10, 2018 2:38:47 PM 45 | */ 46 | public static boolean isUnix () { 47 | return NAME.contains ("nix") || NAME.contains ("nux") || NAME.contains ("aix"); 48 | } 49 | 50 | /** 51 | * @return is win 52 | * 53 | * @since Aug 10, 2018 2:38:57 PM 54 | */ 55 | public static boolean isWindows () { 56 | return NAME.contains ("win"); 57 | } 58 | 59 | /** 60 | * @return platform 61 | * 62 | * @since Aug 10, 2018 2:50:40 PM 63 | */ 64 | public static PlatformOs platform () { 65 | if (isWindows ()) { 66 | return WINDOWS; 67 | } 68 | if (isMac ()) { 69 | return MAC; 70 | } 71 | if (isUnix ()) { 72 | return LINUX; 73 | } 74 | return null; 75 | } 76 | 77 | private OS () { 78 | // Util class. 79 | } 80 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/IFindableAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | import java.util.List; 19 | 20 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 21 | import org.openqa.selenium.By; 22 | 23 | /** 24 | * @author Wasiq Bhamla 25 | * @since 27-Jul-2019 26 | */ 27 | public interface IFindableAction extends IKeyboardActions { 28 | /** 29 | * @param Mouse action type 30 | * @param byLocator locator 31 | * @param name Element name 32 | * 33 | * @return actions 34 | * 35 | * @author Wasiq Bhamla 36 | * @since 27-Jul-2019 37 | */ 38 | E find (final By byLocator, final String name); 39 | 40 | /** 41 | * @param Mouse action type 42 | * @param byLocator locator 43 | * @param name Element name 44 | * @param strategy wait strategy 45 | * 46 | * @return list of actions 47 | * 48 | * @author Wasiq Bhamla 49 | * @since 27-Jul-2019 50 | */ 51 | E find (final By byLocator, final String name, WaitStrategy strategy); 52 | 53 | /** 54 | * @param Mouse action type 55 | * @param byLocator locator 56 | * @param name Element name 57 | * 58 | * @return list of actions 59 | * 60 | * @author Wasiq Bhamla 61 | * @since 27-Jul-2019 62 | */ 63 | List finds (final By byLocator, final String name); 64 | 65 | /** 66 | * @param Mouse action type 67 | * @param byLocator locator 68 | * @param name Element name 69 | * @param strategy wait strategy 70 | * 71 | * @return list of actions 72 | * 73 | * @author Wasiq Bhamla 74 | * @since 27-Jul-2019 75 | */ 76 | List finds (final By byLocator, final String name, WaitStrategy strategy); 77 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/element/FindableAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.element; 17 | 18 | import java.util.List; 19 | 20 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 21 | import com.github.wasiqb.coteafs.selenium.core.element.IFindableAction; 22 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 23 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 24 | import org.openqa.selenium.By; 25 | import org.openqa.selenium.WebDriver; 26 | import org.openqa.selenium.WebElement; 27 | 28 | /** 29 | * @param 30 | * @param 31 | * @param 32 | * 33 | * @author Wasiq Bhamla 34 | * @since 27-Jul-2019 35 | */ 36 | public abstract class FindableAction> 37 | extends KeyboardAction implements IFindableAction { 38 | protected FindableAction (final B browserAction, final By by, final String name) { 39 | super (browserAction, by, name); 40 | } 41 | 42 | protected FindableAction (final B browserAction, final By by, final String name, final WaitStrategy strategy) { 43 | super (browserAction, by, name, strategy); 44 | } 45 | 46 | protected FindableAction (final B browserAction, final E element, final String name) { 47 | super (browserAction, element, name); 48 | } 49 | 50 | protected FindableAction (final B browserAction, final E element, final String name, final WaitStrategy strategy) { 51 | super (browserAction, element, name, strategy); 52 | } 53 | 54 | @Override 55 | public T find (final By byLocator, final String name) { 56 | return find (byLocator, name, WaitStrategy.NONE); 57 | } 58 | 59 | @Override 60 | public List finds (final By byLocator, final String name) { 61 | return finds (byLocator, name, WaitStrategy.NONE); 62 | } 63 | } -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/pages/LoginPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.pages; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.BrowserPage; 19 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 20 | import com.github.wasiqb.coteafs.selenium.core.element.ITextBoxActions; 21 | import com.github.wasiqb.coteafs.selenium.core.page.ElementKey; 22 | import org.openqa.selenium.By; 23 | 24 | /** 25 | * @author wasiqb 26 | * @since Aug 31, 2018 9:33:22 PM 27 | */ 28 | public class LoginPage extends BrowserPage { 29 | /** 30 | * @author Wasiq Bhamla 31 | */ 32 | public enum LoginPageKeys implements ElementKey { 33 | /** 34 | * User Id 35 | */ 36 | USER_ID ("userId"), 37 | /** 38 | * Password 39 | */ 40 | PASS ("password"); 41 | 42 | String key; 43 | 44 | LoginPageKeys (final String key) { 45 | this.key = key; 46 | } 47 | 48 | @Override 49 | public String getKey () { 50 | return this.key; 51 | } 52 | } 53 | 54 | /** 55 | * @return success message 56 | */ 57 | public IMouseActions loginMessage () { 58 | return onClickable (By.id ("flash"), "Login message"); 59 | } 60 | 61 | /** 62 | * @return password 63 | * 64 | * @since Aug 31, 2018 9:40:05 PM 65 | */ 66 | public ITextBoxActions password () { 67 | return form ().find (By.id ("password"), "Password"); 68 | } 69 | 70 | /** 71 | * @return signIn button 72 | * 73 | * @since Aug 31, 2018 9:40:56 PM 74 | */ 75 | public IMouseActions signIn () { 76 | return form ().find (By.tagName ("button"), "Login"); 77 | } 78 | 79 | /** 80 | * @return user id 81 | * 82 | * @since Aug 31, 2018 9:34:38 PM 83 | */ 84 | public ITextBoxActions userId () { 85 | return form ().find (By.id ("username"), "User ID"); 86 | } 87 | 88 | private IMouseActions form () { 89 | return onClickable (By.id ("login"), "Login Form"); 90 | } 91 | } -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: 17 | - master 18 | - main 19 | - release 20 | - issue-* 21 | schedule: 22 | - cron: "0 21 * * *" 23 | 24 | jobs: 25 | analyze: 26 | name: Analyze 27 | runs-on: ubuntu-latest 28 | permissions: 29 | actions: read 30 | contents: read 31 | security-events: write 32 | 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | language: [ "java" ] 37 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 38 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | - name: Install Java and Maven 45 | uses: actions/setup-java@v2 46 | with: 47 | java-version: "15" 48 | distribution: "adopt" 49 | 50 | # Initializes the CodeQL tools for scanning. 51 | - name: Initialize CodeQL 52 | uses: github/codeql-action/init@v1 53 | with: 54 | languages: ${{ matrix.language }} 55 | # If you wish to specify custom queries, you can do so here or in a config file. 56 | # By default, queries listed here will override any specified in a config file. 57 | # Prefix the list here with "+" to use these queries and those in the config file. 58 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 59 | 60 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 61 | # If this step fails, then you should remove it and run the build manually (see below) 62 | - name: Autobuild 63 | uses: github/codeql-action/autobuild@v1 64 | 65 | # ℹ️ Command-line programs to run using the OS shell. 66 | # 📚 https://git.io/JvXDl 67 | 68 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 69 | # and modify them (or add more) to build your code if your project 70 | # uses a compiled language 71 | 72 | #- run: | 73 | # make bootstrap 74 | # make release 75 | 76 | - name: Perform CodeQL Analysis 77 | uses: github/codeql-action/analyze@v1 78 | -------------------------------------------------------------------------------- /testng-all-browsers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/BaseDriverAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 19 | import static java.time.Duration.ofSeconds; 20 | 21 | import java.util.function.Consumer; 22 | import java.util.function.Function; 23 | 24 | import com.github.wasiqb.coteafs.selenium.core.driver.IScriptAction; 25 | import com.github.wasiqb.coteafs.selenium.core.driver.IWaitAction; 26 | import org.openqa.selenium.WebDriver; 27 | import org.openqa.selenium.remote.RemoteWebDriver; 28 | import org.openqa.selenium.support.events.EventFiringWebDriver; 29 | import org.openqa.selenium.support.ui.WebDriverWait; 30 | 31 | /** 32 | * @param 33 | * 34 | * @author Wasiq Bhamla 35 | * @since 27-Jul-2019 36 | */ 37 | public class BaseDriverAction implements IWaitAction, IScriptAction { 38 | protected D driver; 39 | private final WebDriverWait wait; 40 | 41 | BaseDriverAction (final D driver) { 42 | this.driver = driver; 43 | this.wait = new WebDriverWait (driver, ofSeconds (getBrowserSetting ().getPlayback () 44 | .getDelays () 45 | .getExplicit ()).getSeconds ()); 46 | } 47 | 48 | @Override 49 | public D driver () { 50 | return this.driver; 51 | } 52 | 53 | @Override 54 | public WebDriverWait driverWait () { 55 | return this.wait; 56 | } 57 | 58 | @SuppressWarnings ("unchecked") 59 | @Override 60 | public T execute (final String script, final Object... args) { 61 | return (T) get (d -> { 62 | if (d instanceof EventFiringWebDriver) { 63 | return ((EventFiringWebDriver) d).executeScript (script, args); 64 | } 65 | return ((RemoteWebDriver) d).executeScript (script, args); 66 | }); 67 | } 68 | 69 | protected E get (final Function func) { 70 | return func.apply (this.driver); 71 | } 72 | 73 | protected void perform (final Consumer action) { 74 | action.accept (this.driver); 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/element/ElementAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.element; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 19 | import com.github.wasiqb.coteafs.selenium.core.element.IElementActions; 20 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 21 | import org.openqa.selenium.By; 22 | import org.openqa.selenium.WebDriver; 23 | import org.openqa.selenium.WebElement; 24 | 25 | /** 26 | * @param 27 | * @param 28 | * @param 29 | * 30 | * @author Wasiq Bhamla 31 | * @since 27-Jul-2019 32 | */ 33 | public class ElementAction> 34 | extends BaseElementAction implements IElementActions { 35 | protected ElementAction (final B browserAction, final By by, final String name) { 36 | super (browserAction, by, name); 37 | } 38 | 39 | protected ElementAction (final B browserAction, final By by, final String name, final WaitStrategy strategy) { 40 | super (browserAction, by, name, strategy); 41 | } 42 | 43 | protected ElementAction (final B browserAction, final E element, final String name) { 44 | super (browserAction, element, name); 45 | } 46 | 47 | protected ElementAction (final B browserAction, final E element, final String name, final WaitStrategy strategy) { 48 | super (browserAction, element, name, strategy); 49 | } 50 | 51 | @Override 52 | public String attribute (final String name) { 53 | return get (e -> e.getAttribute (name)); 54 | } 55 | 56 | @Override 57 | public void clear () { 58 | perform (WebElement::clear); 59 | } 60 | 61 | @Override 62 | public boolean isDisplayed () { 63 | return get (WebElement::isDisplayed); 64 | } 65 | 66 | @Override 67 | public boolean isEnabled () { 68 | return get (WebElement::isEnabled); 69 | } 70 | 71 | @Override 72 | public boolean isSelected () { 73 | return get (WebElement::isSelected); 74 | } 75 | 76 | @Override 77 | public String text () { 78 | return get (WebElement::getText); 79 | } 80 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/element/ISelectBoxActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.element; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * @author Wasiq Bhamla 22 | * @since 07-Jun-2019 23 | */ 24 | public interface ISelectBoxActions extends IMouseActions { 25 | /** 26 | * @author Wasiq Bhamla 27 | * @since 07-Jun-2019 28 | */ 29 | void deselectAll (); 30 | 31 | /** 32 | * @param index item indoex 33 | * 34 | * @author Wasiq Bhamla 35 | * @since 12-Jul-2019 36 | */ 37 | void deselectByIndex (int index); 38 | 39 | /** 40 | * @param value item value 41 | * 42 | * @author Wasiq Bhamla 43 | * @since 07-Jun-2019 44 | */ 45 | void deselectByText (String value); 46 | 47 | /** 48 | * @param value item value 49 | * 50 | * @author Wasiq Bhamla 51 | * @since 12-Jul-2019 52 | */ 53 | void deselectByValue (String value); 54 | 55 | /** 56 | * @return is multi select 57 | * 58 | * @author Wasiq Bhamla 59 | * @since 12-Jul-2019 60 | */ 61 | boolean isMultiSelect (); 62 | 63 | /** 64 | * @return all options 65 | * 66 | * @author Wasiq Bhamla 67 | * @since 12-Jul-2019 68 | */ 69 | List options (); 70 | 71 | /** 72 | * @param index item indoex 73 | * 74 | * @author Wasiq Bhamla 75 | * @since 12-Jul-2019 76 | */ 77 | void selectByIndex (int index); 78 | 79 | /** 80 | * @param value item value 81 | * 82 | * @author Wasiq Bhamla 83 | * @since 07-Jun-2019 84 | */ 85 | void selectByText (String value); 86 | 87 | /** 88 | * @param value item value 89 | * 90 | * @author Wasiq Bhamla 91 | * @since 12-Jul-2019 92 | */ 93 | void selectByValue (String value); 94 | 95 | /** 96 | * @param Mouse action type 97 | * 98 | * @return all selected options 99 | * 100 | * @author Wasiq Bhamla 101 | * @since 12-Jul-2019 102 | */ 103 | List selectedOptions (); 104 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/element/VerifyElement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.element; 17 | 18 | import static com.google.common.truth.Truth.assertThat; 19 | import static com.google.common.truth.Truth.assertWithMessage; 20 | 21 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 22 | import com.github.wasiqb.coteafs.selenium.core.element.IVerifyElement; 23 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 24 | import com.google.common.truth.BooleanSubject; 25 | import com.google.common.truth.StringSubject; 26 | import org.openqa.selenium.By; 27 | import org.openqa.selenium.WebDriver; 28 | import org.openqa.selenium.WebElement; 29 | 30 | /** 31 | * @param 32 | * @param 33 | * @param 34 | * 35 | * @author Wasiq Bhamla 36 | * @since 27-Jul-2019 37 | */ 38 | public class VerifyElement> 39 | extends ElementAction implements IVerifyElement { 40 | VerifyElement (final B browserAction, final By by, final String name) { 41 | super (browserAction, by, name); 42 | } 43 | 44 | VerifyElement (final B browserAction, final By by, final String name, final WaitStrategy strategy) { 45 | super (browserAction, by, name, strategy); 46 | } 47 | 48 | VerifyElement (final B browserAction, final E element, final String name) { 49 | super (browserAction, element, name); 50 | } 51 | 52 | VerifyElement (final B browserAction, final E element, final String name, final WaitStrategy strategy) { 53 | super (browserAction, element, name, strategy); 54 | } 55 | 56 | @Override 57 | public StringSubject verifyAttribute (final String attribute) { 58 | return assertThat (attribute (attribute)); 59 | } 60 | 61 | @Override 62 | public BooleanSubject verifyDisplayed () { 63 | return assertWithMessage ("Is Displayed?").that (isDisplayed ()); 64 | } 65 | 66 | @Override 67 | public BooleanSubject verifyEnabled () { 68 | return assertWithMessage ("Is Enabled?").that (isEnabled ()); 69 | } 70 | 71 | @Override 72 | public BooleanSubject verifySelected () { 73 | return assertWithMessage ("Is Selected?").that (isSelected ()); 74 | } 75 | 76 | @Override 77 | public StringSubject verifyText () { 78 | return assertThat (text ().trim ()); 79 | } 80 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/BrowserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.constants.ConfigKeys.BROWSER; 19 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 20 | 21 | import java.io.File; 22 | 23 | import com.github.wasiqb.coteafs.selenium.config.ScreenshotSetting; 24 | import org.apache.logging.log4j.LogManager; 25 | import org.apache.logging.log4j.Logger; 26 | import org.testng.ITestResult; 27 | import org.testng.annotations.AfterMethod; 28 | import org.testng.annotations.AfterTest; 29 | import org.testng.annotations.BeforeTest; 30 | import org.testng.annotations.Optional; 31 | import org.testng.annotations.Parameters; 32 | 33 | /** 34 | * @author wasiqb 35 | * @since Sep 13, 2018 9:54:10 PM 36 | */ 37 | public class BrowserTest { 38 | private static final Logger LOG = LogManager.getLogger (); 39 | private Browser browser; 40 | 41 | /** 42 | * @param browserName Browser setting name 43 | * 44 | * @author wasiqb 45 | * @since Sep 13, 2018 9:55:41 PM 46 | */ 47 | @Parameters ({ BROWSER }) 48 | @BeforeTest (alwaysRun = true) 49 | public void setupTest (@Optional final String browserName) { 50 | this.browser = new Browser (); 51 | this.browser.setBrowserSettingName (browserName); 52 | this.browser.start (); 53 | } 54 | 55 | /** 56 | * @param result test result 57 | * 58 | * @author wasiqb 59 | * @since Mar 21, 2019 6:46:47 PM 60 | */ 61 | @AfterMethod (alwaysRun = true) 62 | public void tearDownMethod (final ITestResult result) { 63 | final ScreenshotSetting screenshotSetting = getBrowserSetting ().getPlayback () 64 | .getScreenshot (); 65 | final boolean screenshotOnError = screenshotSetting.isCaptureOnError (); 66 | final boolean captureAll = screenshotSetting.isCaptureAll (); 67 | if (captureAll || screenshotOnError && result.getStatus () == ITestResult.FAILURE && this.browser.isRunning ()) { 68 | final File screenshot = this.browser.perform () 69 | .saveScreenshot (); 70 | final Throwable cause = result.getThrowable (); 71 | if (cause != null) { 72 | LOG.error ("Test Failed: Screenshot captured at [{}]", screenshot.getPath ()); 73 | } else { 74 | LOG.info ("Screenshot captured at path [{}]", screenshot.getPath ()); 75 | } 76 | } 77 | } 78 | 79 | /** 80 | * @author wasiqb 81 | * @since Sep 13, 2018 9:57:12 PM 82 | */ 83 | @AfterTest (alwaysRun = true) 84 | public void tearDownTest () { 85 | this.browser.stop (); 86 | } 87 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/DriverSession.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.config.ConfigUtil.appSetting; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | import com.github.wasiqb.coteafs.selenium.config.BrowserSetting; 24 | import org.openqa.selenium.WebDriver; 25 | 26 | /** 27 | * @param 28 | * 29 | * @author Wasiq Bhamla 30 | * @since 27-Sep-2019 31 | */ 32 | public class DriverSession { 33 | private final Map context; 34 | private D driver; 35 | private final BrowserSetting setting; 36 | 37 | /** 38 | * @param browserName Browser name 39 | * 40 | * @author Wasiq Bhamla 41 | * @since 28-Sep-2019 42 | */ 43 | public DriverSession (final String browserName) { 44 | this.setting = appSetting (browserName); 45 | this.context = new HashMap<> (); 46 | } 47 | 48 | /** 49 | * @author Wasiq Bhamla 50 | * @since 28-Sep-2019 51 | */ 52 | public void clearContext () { 53 | this.context.clear (); 54 | } 55 | 56 | /** 57 | * @author Wasiq Bhamla 58 | * @since 28-Sep-2019 59 | */ 60 | public void close () { 61 | clearContext (); 62 | this.driver.quit (); 63 | this.driver = null; 64 | } 65 | 66 | /** 67 | * @param Return type 68 | * @param key Context key 69 | * 70 | * @return context 71 | * 72 | * @author Wasiq Bhamla 73 | * @since 28-Sep-2019 74 | */ 75 | @SuppressWarnings ("unchecked") 76 | public T getContext (final String key) { 77 | return (T) this.context.get (key); 78 | } 79 | 80 | /** 81 | * @return the driver 82 | * 83 | * @author Wasiq Bhamla 84 | * @since 27-Sep-2019 85 | */ 86 | public D getDriver () { 87 | return this.driver; 88 | } 89 | 90 | /** 91 | * @return Browser setting 92 | */ 93 | public BrowserSetting getSetting () { 94 | return this.setting; 95 | } 96 | 97 | /** 98 | * @param Return type 99 | * @param key Context key 100 | * @param value Context value 101 | * 102 | * @author Wasiq Bhamla 103 | * @since 28-Sep-2019 104 | */ 105 | public void setContext (final String key, final T value) { 106 | this.context.put (key, value); 107 | } 108 | 109 | /** 110 | * @param driver the driver to set 111 | * 112 | * @author Wasiq Bhamla 113 | * @since 28-Sep-2019 114 | */ 115 | public void setDriver (final D driver) { 116 | this.driver = driver; 117 | } 118 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/BrowserActions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 19 | 20 | import java.util.Set; 21 | 22 | import com.github.wasiqb.coteafs.selenium.config.DelaySetting; 23 | import com.github.wasiqb.coteafs.selenium.core.base.driver.WebDriverAction; 24 | import com.github.wasiqb.coteafs.selenium.core.driver.IWebFrame; 25 | import com.github.wasiqb.coteafs.selenium.core.driver.IWebWindow; 26 | import org.openqa.selenium.WebDriver; 27 | import org.openqa.selenium.support.events.EventFiringWebDriver; 28 | 29 | /** 30 | * @author Wasiq Bhamla 31 | * @since Aug 18, 2018 4:41:56 PM 32 | */ 33 | public class BrowserActions extends WebDriverAction implements IWebFrame, IWebWindow { 34 | private final DelaySetting delaySetting; 35 | 36 | /** 37 | * @param driver driver 38 | * 39 | * @author Wasiq Bhamla 40 | * @since 02-Jun-2019 41 | */ 42 | BrowserActions (final EventFiringWebDriver driver) { 43 | super (driver); 44 | this.delaySetting = getBrowserSetting ().getPlayback () 45 | .getDelays (); 46 | } 47 | 48 | @Override 49 | public void switchFrame () { 50 | switchFrame (0); 51 | } 52 | 53 | @Override 54 | public void switchFrame (final int index) { 55 | perform (d -> { 56 | d.switchTo () 57 | .frame (index); 58 | pause (this.delaySetting.getAfterFrameSwitch ()); 59 | }); 60 | } 61 | 62 | @Override 63 | public void switchFrame (final String nameOrId) { 64 | perform (d -> { 65 | d.switchTo () 66 | .frame (nameOrId); 67 | pause (this.delaySetting.getAfterFrameSwitch ()); 68 | }); 69 | } 70 | 71 | @Override 72 | public void switchWindow () { 73 | perform (d -> { 74 | d.switchTo () 75 | .defaultContent (); 76 | pause (this.delaySetting.getAfterWindowSwitch ()); 77 | }); 78 | } 79 | 80 | @Override 81 | public void switchWindow (final String title) { 82 | perform (d -> { 83 | final String currentHandle = d.getWindowHandle (); 84 | final Set wins = d.getWindowHandles (); 85 | for (final String win : wins) { 86 | if (currentHandle.equals (win)) { 87 | continue; 88 | } 89 | final WebDriver w = d.switchTo () 90 | .window (win); 91 | if (w.getTitle () 92 | .contains (title)) { 93 | return; 94 | } 95 | } 96 | pause (this.delaySetting.getAfterWindowSwitch ()); 97 | }); 98 | } 99 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at wasbhamla2005@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test coteafs-selenium project 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | - release 9 | - issue-* 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Check out Git repository 16 | uses: actions/checkout@v2 17 | 18 | - name: Install Java and Maven 19 | uses: actions/setup-java@v2 20 | with: 21 | java-version: '15' 22 | distribution: 'adopt' 23 | 24 | - name: Build the project 25 | run: mvn install -DskipTests 26 | 27 | - name: Upload target folder 28 | uses: actions/upload-artifact@v2 29 | with: 30 | name: target 31 | path: ${{ github.workspace }}/target 32 | 33 | - name: Cache local Maven repository 34 | uses: actions/cache@v2 35 | with: 36 | path: ~/.m2/repository 37 | key: ${{ runner.os }}-maven-${{ github.sha }} 38 | 39 | test: 40 | needs: 41 | - build 42 | runs-on: ubuntu-latest 43 | steps: 44 | - name: Check out Git repository 45 | uses: actions/checkout@v2 46 | 47 | - name: Install Java and Maven 48 | uses: actions/setup-java@v2 49 | with: 50 | java-version: '15' 51 | distribution: 'adopt' 52 | 53 | - name: Restore local Maven repository 54 | uses: actions/cache@v2 55 | with: 56 | path: ~/.m2/repository 57 | key: ${{ runner.os }}-maven-${{ github.sha }} 58 | 59 | - name: Download target folder 60 | uses: actions/download-artifact@v2 61 | with: 62 | name: target 63 | 64 | - name: Install Chrome 65 | run: | 66 | wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - 67 | sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' 68 | sudo apt-get update 69 | sudo apt-get install google-chrome-stable 70 | docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome:4.1.1 71 | 72 | - name: Test execution 73 | env: 74 | CLOUD_USER: ${{ secrets.CLOUD_USER }} 75 | CLOUD_KEY: ${{ secrets.CLOUD_KEY }} 76 | run: mvn org.jacoco:jacoco-maven-plugin:prepare-agent install -Pcoverage-per-test 77 | 78 | - name: Test Report 79 | uses: dorny/test-reporter@v1 80 | if: success() || failure() 81 | with: 82 | name: Test Results 83 | path: ${{ github.workspace }}/target/surefire-reports/*.xml 84 | reporter: java-junit 85 | 86 | - name: Upload target folder 87 | uses: actions/upload-artifact@v2 88 | with: 89 | name: target 90 | path: | 91 | ${{ github.workspace }}/target 92 | ${{ github.workspace }}/reports 93 | 94 | analysis: 95 | needs: 96 | - test 97 | runs-on: ubuntu-latest 98 | steps: 99 | - name: Check out Git repository 100 | uses: actions/checkout@v2 101 | with: 102 | fetch-depth: 0 103 | 104 | - name: Install Java and Maven 105 | uses: actions/setup-java@v2 106 | with: 107 | java-version: '15' 108 | distribution: 'adopt' 109 | 110 | - name: Restore local Maven repository 111 | uses: actions/cache@v2 112 | with: 113 | path: ~/.m2/repository 114 | key: ${{ runner.os }}-maven-${{ github.sha }} 115 | 116 | - name: Download target folder 117 | uses: actions/download-artifact@v2 118 | with: 119 | name: target 120 | 121 | - name: Build and analyze 122 | env: 123 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 124 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 125 | run: mvn -B sonar:sonar -DskipTests -Dcheckstyle.skip -------------------------------------------------------------------------------- /src/test/resources/selenium-config.yaml: -------------------------------------------------------------------------------- 1 | browser: &default_browser 2 | browser: CHROME 3 | url: https://the-internet.herokuapp.com 4 | params: 5 | user: tomsmith 6 | password: SuperSecretPassword! 7 | playback: 8 | screen_state: NORMAL 9 | highlight: true 10 | screen_resolution: 11 | width: 1280 12 | height: 768 13 | delays: 14 | implicit: 60 15 | explicit: 60 16 | before_key_press: 0 17 | after_key_press: 0 18 | before_mouse_move: 0 19 | after_mouse_move: 0 20 | before_click: 0 21 | after_click: 0 22 | page_load: 60 23 | script_load: 60 24 | highlight: 100 25 | screenshot: 26 | path: ./screenshots 27 | prefix: SCR 28 | extension: jpeg 29 | capture_on_error: false 30 | capture_all: true 31 | recording: 32 | enable: false 33 | path: ./video 34 | prefix: VID 35 | 36 | browsers: 37 | local: 38 | <<: *default_browser 39 | headless_mode: true 40 | #driver: 41 | # force_cache: true 42 | # force_download: true 43 | # path: /drivers/ 44 | # version: 2.14 45 | # exe_url: https://driver/download/url 46 | grid: 47 | browser: REMOTE 48 | <<: *default_browser 49 | headless_mode: true 50 | remote: 51 | url: localhost 52 | port: 4444 53 | source: GRID 54 | capabilities: 55 | browserName: chrome 56 | version: 77.0.3865.75 57 | platform: LINUX 58 | bs_chrome: 59 | browser: REMOTE 60 | <<: *default_browser 61 | remote: 62 | user_id: ${env:CLOUD_USER} 63 | password: ${env:CLOUD_KEY} 64 | protocol: HTTPS 65 | url: hub-cloud.browserstack.com 66 | source: BROWSERSTACK 67 | capabilities: 68 | browser: Chrome 69 | browser_version: latest 70 | os: Windows 71 | os_version: 10 72 | resolution: 1024x768 73 | name: Bstack-[Java] Sample Chrome Test 74 | bs_edge: 75 | browser: REMOTE 76 | <<: *default_browser 77 | remote: 78 | user_id: ${env:CLOUD_USER} 79 | password: ${env:CLOUD_KEY} 80 | protocol: HTTPS 81 | url: hub-cloud.browserstack.com 82 | source: BROWSERSTACK 83 | capabilities: 84 | browser: Edge 85 | browser_version: latest 86 | os: Windows 87 | os_version: 10 88 | resolution: 1024x768 89 | name: Bstack-[Java] Sample Edge Test 90 | bs_firefox: 91 | browser: REMOTE 92 | <<: *default_browser 93 | remote: 94 | user_id: ${env:CLOUD_USER} 95 | password: ${env:CLOUD_KEY} 96 | protocol: HTTPS 97 | url: hub-cloud.browserstack.com 98 | source: BROWSERSTACK 99 | capabilities: 100 | browser: Firefox 101 | browser_version: latest 102 | os: Windows 103 | os_version: 10 104 | resolution: 1024x768 105 | name: Bstack-[Java] Sample Firefox Test 106 | bs_ie: 107 | browser: REMOTE 108 | <<: *default_browser 109 | remote: 110 | user_id: ${env:CLOUD_USER} 111 | password: ${env:CLOUD_KEY} 112 | protocol: HTTPS 113 | url: hub-cloud.browserstack.com 114 | source: BROWSERSTACK 115 | capabilities: 116 | browser: IE 117 | browser_version: latest 118 | os: Windows 119 | os_version: 10 120 | resolution: 1024x768 121 | name: Bstack-[Java] Sample IE Test 122 | bs_safari: 123 | browser: REMOTE 124 | <<: *default_browser 125 | remote: 126 | user_id: ${env:CLOUD_USER} 127 | password: ${env:CLOUD_KEY} 128 | protocol: HTTPS 129 | url: hub-cloud.browserstack.com 130 | source: BROWSERSTACK 131 | capabilities: 132 | browser: Safari 133 | browser_version: latest 134 | os: OS X 135 | os_version: Big Sur 136 | resolution: 1024x768 137 | name: Bstack-[Java] Sample Safari Test 138 | sl_chrome: 139 | <<: *default_browser 140 | browser: REMOTE 141 | url: http://demo.guru99.com/V4/ 142 | headless_mode: true 143 | remote: 144 | user_id: ${env:CLOUD_USER} 145 | password: ${env:CLOUD_KEY} 146 | protocol: HTTPS 147 | url: ondemand.saucelabs.com 148 | source: SAUCELABS 149 | capabilities: 150 | browserName: chrome 151 | browserVersion: 75.0 152 | platformVersion: Windows 10 153 | cloud_capabilities: 154 | seleniumVersion: 3.141.59 155 | name: Sauce-[Java] Sample Test -------------------------------------------------------------------------------- /src/test/java/com/github/wasiqb/coteafs/selenium/SeleniumTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 19 | import static com.github.wasiqb.coteafs.selenium.pages.CheckboxPage.CheckboxPageKeys.CHECK; 20 | import static com.github.wasiqb.coteafs.selenium.pages.DropDownPage.DropDownKeys.OPTION; 21 | import static com.github.wasiqb.coteafs.selenium.pages.LoginPage.LoginPageKeys.PASS; 22 | import static com.github.wasiqb.coteafs.selenium.pages.LoginPage.LoginPageKeys.USER_ID; 23 | 24 | import java.util.ArrayList; 25 | import java.util.Iterator; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import com.github.wasiqb.coteafs.selenium.core.BrowserTest; 30 | import com.github.wasiqb.coteafs.selenium.pages.MainPage; 31 | import com.github.wasiqb.coteafs.selenium.pages.action.CheckboxPageAction; 32 | import com.github.wasiqb.coteafs.selenium.pages.action.DropDownPageAction; 33 | import com.github.wasiqb.coteafs.selenium.pages.action.LoginPageAction; 34 | import org.testng.annotations.BeforeMethod; 35 | import org.testng.annotations.DataProvider; 36 | import org.testng.annotations.Test; 37 | 38 | /** 39 | * @author Wasiq Bhamla 40 | */ 41 | public class SeleniumTest extends BrowserTest { 42 | private MainPage main; 43 | 44 | @BeforeMethod 45 | public void setupMethod () { 46 | this.main = new MainPage (); 47 | this.main.onDriver () 48 | .navigateTo (getBrowserSetting ().getUrl ()); 49 | } 50 | 51 | /** 52 | * @param value 53 | * 54 | * @since Jul 19, 2020 55 | */ 56 | @Test (dataProvider = "testDataForCheckbox") 57 | public void testCheckboxes (final String value) { 58 | setupMethod (); 59 | this.main.links ("Checkboxes") 60 | .click (); 61 | final CheckboxPageAction checkbox = new CheckboxPageAction (); 62 | checkbox.addInputValue (CHECK, value) 63 | .perform (); 64 | } 65 | 66 | /** 67 | * @return test data for checkbox 68 | * 69 | * @since Jul 19, 2020 70 | */ 71 | @DataProvider 72 | public Iterator testDataForCheckbox () { 73 | final List testData = new ArrayList<> (); 74 | testData.add (new Object[] { "check" }); 75 | testData.add (new Object[] { "uncheck" }); 76 | return testData.iterator (); 77 | } 78 | 79 | /** 80 | * @return dropDown data 81 | * 82 | * @since Jul 19, 2020 83 | */ 84 | @DataProvider 85 | public Iterator testDataForDropDownBox () { 86 | final List testData = new ArrayList<> (); 87 | testData.add (new Object[] { "Option 1" }); 88 | testData.add (new Object[] { "Option 2" }); 89 | return testData.iterator (); 90 | } 91 | 92 | /** 93 | * @param testValue 94 | * 95 | * @since Jul 19, 2020 96 | */ 97 | @Test (dataProvider = "testDataForDropDownBox") 98 | public void testDropDownBox (final String testValue) { 99 | setupMethod (); 100 | this.main.links ("Dropdown") 101 | .click (); 102 | final DropDownPageAction dropDownAction = new DropDownPageAction (); 103 | dropDownAction.addInputValue (OPTION, testValue) 104 | .perform (); 105 | } 106 | 107 | /** 108 | * @since Apr 8, 2019 10:34:29 PM 109 | */ 110 | @Test 111 | public void testLogin () { 112 | this.main.links ("Form Authentication") 113 | .click (); 114 | final Map loginParams = getBrowserSetting ().getParams (); 115 | final LoginPageAction login = new LoginPageAction (); 116 | login.addInputValue (USER_ID, loginParams.get ("user")) 117 | .addInputValue (PASS, loginParams.get ("password")) 118 | .perform (); 119 | } 120 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/AbstractDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 19 | import static com.github.wasiqb.coteafs.selenium.core.enums.Platform.DESKTOP; 20 | import static java.util.concurrent.TimeUnit.SECONDS; 21 | 22 | import java.util.function.Consumer; 23 | 24 | import com.github.wasiqb.coteafs.selenium.config.DelaySetting; 25 | import com.github.wasiqb.coteafs.selenium.config.PlaybackSetting; 26 | import com.github.wasiqb.coteafs.selenium.config.ScreenResolution; 27 | import com.github.wasiqb.coteafs.selenium.constants.OS; 28 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriver; 29 | import com.github.wasiqb.coteafs.selenium.core.enums.Platform; 30 | import com.github.wasiqb.coteafs.selenium.core.enums.ScreenState; 31 | import org.apache.logging.log4j.LogManager; 32 | import org.apache.logging.log4j.Logger; 33 | import org.openqa.selenium.Dimension; 34 | import org.openqa.selenium.Point; 35 | import org.openqa.selenium.WebDriver; 36 | import org.openqa.selenium.WebDriver.Options; 37 | import org.openqa.selenium.WebDriver.Timeouts; 38 | import org.openqa.selenium.WebDriver.Window; 39 | import org.openqa.selenium.remote.RemoteWebDriver; 40 | 41 | /** 42 | * @param 43 | * 44 | * @author Wasiq Bhamla 45 | * @since 26-Jul-2019 46 | */ 47 | public abstract class AbstractDriver extends PlatformAction implements IDriver { 48 | private static final Logger LOG = LogManager.getLogger (); 49 | 50 | /** 51 | * @param platform target platform 52 | * 53 | * @author Wasiq Bhamla 54 | * @since 26-Jul-2019 55 | */ 56 | protected AbstractDriver (final Platform platform) { 57 | super (platform, OS.platform ()); 58 | } 59 | 60 | @Override 61 | public boolean isRunning () { 62 | return ((RemoteWebDriver) getDriver ()).getSessionId () != null; 63 | } 64 | 65 | protected void setupDriverOptions () { 66 | final PlaybackSetting playback = getBrowserSetting ().getPlayback (); 67 | final DelaySetting delays = playback.getDelays (); 68 | manageTimeouts (t -> t.pageLoadTimeout (delays.getPageLoad (), SECONDS)); 69 | manageTimeouts (t -> t.setScriptTimeout (delays.getScriptLoad (), SECONDS)); 70 | manageTimeouts (t -> t.implicitlyWait (delays.getImplicit (), SECONDS)); 71 | manageOptions (Options::deleteAllCookies); 72 | setScreen (playback); 73 | } 74 | 75 | private void manageOptions (final Consumer options) { 76 | options.accept (getDriver ().manage ()); 77 | } 78 | 79 | private void manageTimeouts (final Consumer timeouts) { 80 | timeouts.accept (getDriver ().manage () 81 | .timeouts ()); 82 | } 83 | 84 | private void manageWindow (final Consumer window) { 85 | window.accept (getDriver ().manage () 86 | .window ()); 87 | } 88 | 89 | private void setScreen (final PlaybackSetting playback) { 90 | final ScreenState state = playback.getScreenState (); 91 | if (getPlatform () == DESKTOP) { 92 | LOG.info ("Setting screen size of Browser to {}...", state); 93 | switch (state) { 94 | case FULL_SCREEN -> manageWindow (Window::fullscreen); 95 | case MAXIMIZED -> manageWindow (Window::maximize); 96 | default -> { 97 | final ScreenResolution resolution = playback.getScreenResolution (); 98 | LOG.info ("Setting screen resolution to [{}]...", resolution); 99 | manageWindow (w -> w.setSize (new Dimension (resolution.getWidth (), resolution.getHeight ()))); 100 | manageWindow (w -> w.setPosition (new Point (0, 0))); 101 | } 102 | } 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/ScreenAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import static com.github.wasiqb.coteafs.error.util.ErrorUtil.handleError; 19 | import static com.github.wasiqb.coteafs.selenium.constants.ConfigKeys.FILTER_PKG; 20 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 21 | import static com.google.common.truth.Truth.assertThat; 22 | import static java.lang.String.format; 23 | import static java.lang.Thread.currentThread; 24 | import static java.lang.Thread.sleep; 25 | import static org.apache.commons.io.FileUtils.copyFile; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.text.SimpleDateFormat; 30 | import java.util.Calendar; 31 | 32 | import com.github.wasiqb.coteafs.selenium.config.ScreenshotSetting; 33 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 34 | import com.google.common.truth.StringSubject; 35 | import org.apache.logging.log4j.LogManager; 36 | import org.apache.logging.log4j.Logger; 37 | import org.openqa.selenium.OutputType; 38 | import org.openqa.selenium.TakesScreenshot; 39 | import org.openqa.selenium.WebDriver; 40 | import org.openqa.selenium.remote.RemoteWebDriver; 41 | 42 | /** 43 | * @param 44 | * 45 | * @author Wasiq Bhamla 46 | * @since 27-Jul-2019 47 | */ 48 | public class ScreenAction extends BaseDriverAction implements IDriverActions { 49 | private static final Logger LOG = LogManager.getLogger (); 50 | 51 | protected static void pause (final long delay) { 52 | try { 53 | sleep (delay); 54 | } catch (final InterruptedException e) { 55 | LOG.error ("Error while pausing: {}", e.getMessage ()); 56 | currentThread ().interrupt (); 57 | } 58 | } 59 | 60 | ScreenAction (final D driver) { 61 | super (driver); 62 | } 63 | 64 | @Override 65 | public byte[] attachScreenshot () { 66 | return get (d -> ((RemoteWebDriver) d).getScreenshotAs (OutputType.BYTES)); 67 | } 68 | 69 | @Override 70 | public File saveScreenshot () { 71 | final ScreenshotSetting setting = getBrowserSetting ().getPlayback () 72 | .getScreenshot (); 73 | final String path = setting.getPath (); 74 | final String prefix = setting.getPrefix (); 75 | final SimpleDateFormat date = new SimpleDateFormat ("yyyyMMdd-HHmmss"); 76 | final String timeStamp = date.format (Calendar.getInstance () 77 | .getTime ()); 78 | final String fileName = "%s/%s-%s.%s"; 79 | return saveScreenshot (format (fileName, path, prefix, timeStamp, "jpeg")); 80 | } 81 | 82 | @Override 83 | public File saveScreenshot (final String path) { 84 | final String msg = "Capturing screenshot and saving at [{}]..."; 85 | LOG.info (msg, path); 86 | try { 87 | final File source = ((TakesScreenshot) this.driver).getScreenshotAs (OutputType.FILE); 88 | final File destination = new File (path); 89 | copyFile (source, destination); 90 | return destination; 91 | } catch (final IOException e) { 92 | LOG.error ("Error while saving screenshot.", e); 93 | handleError (FILTER_PKG, e).forEach (LOG::error); 94 | } 95 | return null; 96 | } 97 | 98 | /* 99 | * (non-Javadoc) 100 | * @see @see 101 | * com.github.wasiqb.coteafs.selenium.core.driver.IScreenAction#startRecording() 102 | */ 103 | @Override 104 | public void startRecording () { 105 | try { 106 | CustomScreenRecorder.startRecording (); 107 | } catch (final Exception e) { 108 | handleError (FILTER_PKG, e).forEach (LOG::error); 109 | } 110 | } 111 | 112 | /* 113 | * (non-Javadoc) 114 | * @see @see 115 | * com.github.wasiqb.coteafs.selenium.core.driver.IScreenAction#stopRecording() 116 | */ 117 | @Override 118 | public void stopRecording () { 119 | try { 120 | CustomScreenRecorder.stopRecording (); 121 | } catch (final Exception e) { 122 | handleError (FILTER_PKG, e).forEach (LOG::error); 123 | } 124 | } 125 | 126 | @Override 127 | public String title () { 128 | return get (WebDriver::getTitle); 129 | } 130 | 131 | @Override 132 | public StringSubject verifyTitle () { 133 | return assertThat (title ()); 134 | } 135 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/BrowserPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core; 17 | 18 | import static com.github.wasiqb.coteafs.error.util.ErrorUtil.handleError; 19 | import static com.github.wasiqb.coteafs.selenium.constants.ConfigKeys.FILTER_PKG; 20 | 21 | import java.lang.reflect.InvocationTargetException; 22 | 23 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 24 | import com.github.wasiqb.coteafs.selenium.core.element.ISelectBoxActions; 25 | import com.github.wasiqb.coteafs.selenium.core.element.ITextBoxActions; 26 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 27 | import com.github.wasiqb.coteafs.selenium.core.page.IPage; 28 | import org.apache.logging.log4j.LogManager; 29 | import org.apache.logging.log4j.Logger; 30 | import org.openqa.selenium.By; 31 | import org.openqa.selenium.WebElement; 32 | import org.openqa.selenium.support.events.EventFiringWebDriver; 33 | 34 | /** 35 | * @author Wasiq Bhamla 36 | * @since Aug 19, 2018 4:15:31 PM 37 | */ 38 | @SuppressWarnings ("unchecked") 39 | public class BrowserPage implements IPage { 40 | private static final Logger LOG = LogManager.getLogger (); 41 | private final Browser browser; 42 | 43 | /** 44 | * @author Wasiq Bhamla 45 | * @since 02-Jun-2019 46 | */ 47 | public BrowserPage () { 48 | this.browser = new Browser (); 49 | } 50 | 51 | @Override 52 | public > T nextPage (final Class pageCls) { 53 | T page = null; 54 | try { 55 | page = pageCls.getConstructor () 56 | .newInstance (); 57 | } catch (final InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { 58 | handleError (FILTER_PKG, e).forEach (LOG::error); 59 | } 60 | return page; 61 | } 62 | 63 | @Override 64 | public IMouseActions onClickable (final By locator, final String name) { 65 | return new WebElementAction (onDriver (), locator, name); 66 | } 67 | 68 | @Override 69 | public IMouseActions onClickable (final By locator, final String name, final WaitStrategy strategy) { 70 | return new WebElementAction (onDriver (), locator, name, strategy); 71 | } 72 | 73 | @Override 74 | public IMouseActions onClickable (final WebElement element, final String name) { 75 | return new WebElementAction (onDriver (), element, name); 76 | } 77 | 78 | @Override 79 | public IMouseActions onClickable (final WebElement element, final String name, final WaitStrategy strategy) { 80 | return new WebElementAction (onDriver (), element, name, strategy); 81 | } 82 | 83 | @Override 84 | public BrowserActions onDriver () { 85 | return new BrowserActions (this.browser.getDriver ()); 86 | } 87 | 88 | @Override 89 | public ISelectBoxActions onDropdown (final By locator, final String name) { 90 | return new WebElementAction (onDriver (), locator, name); 91 | } 92 | 93 | @Override 94 | public ISelectBoxActions onDropdown (final By locator, final String name, final WaitStrategy strategy) { 95 | return new WebElementAction (onDriver (), locator, name, strategy); 96 | } 97 | 98 | @Override 99 | public ISelectBoxActions onDropdown (final WebElement element, final String name) { 100 | return new WebElementAction (onDriver (), element, name); 101 | } 102 | 103 | @Override 104 | public ISelectBoxActions onDropdown (final WebElement element, final String name, final WaitStrategy strategy) { 105 | return new WebElementAction (onDriver (), element, name, strategy); 106 | } 107 | 108 | @Override 109 | public ITextBoxActions onTextBox (final By locator, final String name) { 110 | return new WebElementAction (onDriver (), locator, name); 111 | } 112 | 113 | @Override 114 | public ITextBoxActions onTextBox (final By locator, final String name, final WaitStrategy strategy) { 115 | return new WebElementAction (onDriver (), locator, name, strategy); 116 | } 117 | 118 | @Override 119 | public ITextBoxActions onTextBox (final WebElement element, final String name) { 120 | return new WebElementAction (onDriver (), element, name); 121 | } 122 | 123 | @Override 124 | public ITextBoxActions onTextBox (final WebElement element, final String name, final WaitStrategy strategy) { 125 | return new WebElementAction (onDriver (), element, name, strategy); 126 | } 127 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/page/IPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.page; 17 | 18 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 19 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 20 | import com.github.wasiqb.coteafs.selenium.core.element.ISelectBoxActions; 21 | import com.github.wasiqb.coteafs.selenium.core.element.ITextBoxActions; 22 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 23 | import org.openqa.selenium.By; 24 | import org.openqa.selenium.WebDriver; 25 | import org.openqa.selenium.WebElement; 26 | 27 | /** 28 | * @param 29 | * @param 30 | * @param 31 | * 32 | * @author Wasiq Bhamla 33 | * @since 08-Jun-2019 34 | */ 35 | public interface IPage, E extends WebElement> { 36 | /** 37 | * @param Page type 38 | * @param pageCls Page class 39 | * 40 | * @return next page instance 41 | * 42 | * @author Wasiq Bhamla 43 | * @since 14-Oct-2019 44 | */ 45 | > T nextPage (Class pageCls); 46 | 47 | /** 48 | * @param Mouse action type 49 | * @param locator locator 50 | * @param name Name of element 51 | * 52 | * @return element action 53 | * 54 | * @author Wasiq Bhamla 55 | * @since 08-Jun-2019 56 | */ 57 | T onClickable (By locator, final String name); 58 | 59 | /** 60 | * @param Mouse action type 61 | * @param locator locator 62 | * @param name Name of element 63 | * @param strategy strategy 64 | * 65 | * @return element action 66 | * 67 | * @author Wasiq Bhamla 68 | * @since 12-Jul-2019 69 | */ 70 | T onClickable (By locator, final String name, WaitStrategy strategy); 71 | 72 | /** 73 | * @param Mouse action type 74 | * @param element element 75 | * @param name Element name 76 | * 77 | * @return element action 78 | * 79 | * @author Wasiq Bhamla 80 | * @since 08-Jun-2019 81 | */ 82 | T onClickable (E element, final String name); 83 | 84 | /** 85 | * @param Mouse action type 86 | * @param element element 87 | * @param name Element name 88 | * @param strategy wait strategy 89 | * 90 | * @return element action 91 | * 92 | * @author Wasiq Bhamla 93 | * @since 12-Jul-2019 94 | */ 95 | T onClickable (E element, final String name, WaitStrategy strategy); 96 | 97 | /** 98 | * @return driver action 99 | * 100 | * @author Wasiq Bhamla 101 | * @since 08-Jun-2019 102 | */ 103 | B onDriver (); 104 | 105 | /** 106 | * @param SelectBox action type 107 | * @param locator locator 108 | * @param name Element name 109 | * 110 | * @return element action 111 | * 112 | * @author Wasiq Bhamla 113 | * @since 08-Jun-2019 114 | */ 115 | T onDropdown (By locator, final String name); 116 | 117 | /** 118 | * @param SelectBox action type 119 | * @param locator locator 120 | * @param name Element name 121 | * @param strategy strategy 122 | * 123 | * @return element action 124 | * 125 | * @author Wasiq Bhamla 126 | * @since 12-Jul-2019 127 | */ 128 | T onDropdown (By locator, final String name, WaitStrategy strategy); 129 | 130 | /** 131 | * @param SelectBox action type 132 | * @param element element 133 | * @param name Element name 134 | * 135 | * @return element action 136 | * 137 | * @author Wasiq Bhamla 138 | * @since 08-Jun-2019 139 | */ 140 | T onDropdown (E element, final String name); 141 | 142 | /** 143 | * @param SelectBox action type 144 | * @param element element 145 | * @param name Element name 146 | * @param strategy strategy 147 | * 148 | * @return element action 149 | * 150 | * @author Wasiq Bhamla 151 | * @since 12-Jul-2019 152 | */ 153 | T onDropdown (E element, final String name, WaitStrategy strategy); 154 | 155 | /** 156 | * @param TextBox action type 157 | * @param locator locator 158 | * @param name Element name 159 | * 160 | * @return element action 161 | * 162 | * @author Wasiq Bhamla 163 | * @since 08-Jun-2019 164 | */ 165 | T onTextBox (By locator, final String name); 166 | 167 | /** 168 | * @param TextBox action type 169 | * @param locator locator 170 | * @param name Element name 171 | * @param strategy strategy 172 | * 173 | * @return element action 174 | * 175 | * @author Wasiq Bhamla 176 | * @since 12-Jul-2019 177 | */ 178 | T onTextBox (By locator, final String name, WaitStrategy strategy); 179 | 180 | /** 181 | * @param TextBox action type 182 | * @param element element 183 | * @param name Element name 184 | * 185 | * @return element action 186 | * 187 | * @author Wasiq Bhamla 188 | * @since 08-Jun-2019 189 | */ 190 | T onTextBox (E element, final String name); 191 | 192 | /** 193 | * @param TextBox action type 194 | * @param element element 195 | * @param name Element name 196 | * @param strategy strategy 197 | * 198 | * @return element action 199 | * 200 | * @author Wasiq Bhamla 201 | * @since 12-Jul-2019 202 | */ 203 | T onTextBox (E element, final String name, WaitStrategy strategy); 204 | } -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to . 2 | 3 | :+1: :tada: Firstly, thanks for taking the time to contribute! :tada: :+1: 4 | 5 | The following are the set of guidelines for contributing towards this repository on Github. These are mostly guidelines 6 | , not rules. Use your best judgement, and feel free to propose changes to this project in a pull request. 7 | 8 | ## Code Contribution 9 | 10 | ## 1. Where to start from? 11 | 12 | If you've noticed a bug or have a question, then kindly [search the issue tracker][tracker] to see if someone 13 | else has already created a ticket. If not, go ahead and [add one][new issue]! 14 | 15 | ## 2. Want to fix an issue or add a new feature? 16 | 17 | If this is something you think you can fix, then follow the following steps: 18 | 19 | ### Step 1: Discuss 20 | 21 | Before jumping on any ticket or any feature which you think should be there in the framework, discuss with me on my [site][] or email me @ wasbhamla2005@gmail.com. Once you get go-ahead, you can proceed by following the steps mentioned hereafter. 22 | 23 | ### Step 2: Setup your E-mail in Git 24 | 25 | Assuming you have already done this. But if you are new and may forget this, you can do it as described [here][setup]. 26 | 27 | ### Step 3: Fork and clone the repository 28 | 29 | To Fork and clone the repository, see this useful [post][fork]. 30 | 31 | ### Step 4: Create new Branch 32 | 33 | Now create a new branch with a descriptive name in your forked repo. Refer [here][branch] to know about Git branches. 34 | 35 | ### Step 5: Commit with a descriptive message 36 | 37 | If committing a fix for a ticket, always start with `Fixed #[Ticket ID]` than describe the changes in detail. 38 | For an example on how to write a proper commit message, see [this][commitHelp] post. 39 | 40 | ### Step 6: Push changes to your cloned fork 41 | 42 | After committing the changes, you need to push the commit to your cloned repo by executing `git push origin your-branch-name` command in the terminal. 43 | 44 | ### Step 7: Send Pull Request 45 | 46 | Sending Pull Request will be the last step of your contribution. To know how to raise a Pull Request, see [this][pr] post. 47 | 48 | > **NOTE:** From your second contribution onwards, you can skip steps **(1) and (2)**. 49 | 50 | ## Process and Guidelines 51 | 52 | There is a process in place to help maintain the quality of the framework. To adhere to this process, some coding standards and CI pipelines are defined along with static code analysis. The same are detailed below: 53 | 54 | ### Git workflow 55 | 56 | Since the repository is hosted on GitHub, it has been configured to only accept **signed commits** from any 57 | contributor (_including me :wink:_). So make sure to **sign your commits** before sending Pull Request, **else the 58 | PR will be rejected**. To know more about signed commits, check out this [post][sign-commit]. 59 | 60 | ### Branching strategy 61 | 62 | Specific Branching strategy has been defined on this project where **NO COMMITS** are done directly into `master` branch. 63 | 64 | There are 3 main branches: 65 | - `develop`: All feature branches will be merged into this branch after `Pull Request` review. 66 | - `release`: When `develop` branch is clean and all CI tests are **green**, then `develop` branch will be merged into this branch via `Pull Request`. After merge, a `beta` release of version would published to Maven central. 67 | - `master`: After successful Beta testing, `release` branch will then be merged into `master` via `Pull Request`. After merge, final release version cut would published to Maven central. 68 | 69 | ### Working on open tickets 70 | 71 | Any work being done on any open tickets, should be done in a new branch with naming pattern `issue-` created from `develop` branch. 72 | 73 | ### Pull Request pre-requisites 74 | 75 | Any Pull Request raised should make sure following checks are successful: 76 | - Pull Request is raised to merge changes to `develop` branch. 77 | - Commits is GPG signed. 78 | - There is at least one reviewer. 79 | - Circle CI tests are green. 80 | - Branch is up to date with `develop` branch. 81 | 82 | ### Project tracking 83 | 84 | Whatever is being committed to the code base, is tracked against an issue ticket. Hence, each planned versions are being tracked in `Project` tab on GitHub. Hence, it is mandatory to keep the ticket status updated which is being worked upon. 85 | 86 | ### Circle CI pipelines 87 | 88 | This framework is configured with Circle CI to run tests on **Chrome browser** to make sure that the framework is healthy. This integration is useful when there are multiple contributors working on the project and it is mandatory to add unit tests for the code. These tests will be executed on every commits to the issue branch. 89 | 90 | Following are the checks which are executed: 91 | - Tests coverage 92 | - Static Code analysis 93 | 94 | ### Code Styling 95 | 96 | There is always a chance of different code styling when many contributors work together on a project. To make sure every member is using same coding style, it is advisable that you import code styling formatter from the [java formatter][formatter] repository into your IDE. 97 | 98 | Make sure to format the code before sending the **Pull Request**. 99 | 100 | ### Test coverage 101 | 102 | For assuring quality of framework to prospective users, test coverage plays an important role. That's why a benchmark of **80% or more** is set to be required for overall test coverage on this project. It is advisable to add unit tests for any new code which is being added. 103 | 104 | ### SonarCloud Code Quality monitoring 105 | 106 | For each commit to any of the branches described above, CI will also execute static code analysis. 107 | 108 | ## Issues and Suggestions. 109 | 110 | If you find any issue in the framework or you have any suggestions for enhancement, please feel free to raise a ticket for it. Together we can make the framework even more effective and easy for other Test Engineers to use it in their daily automation tasks. 111 | 112 | [sign-commit]: https://help.github.com/en/articles/signing-commits 113 | [formatter]: https://github.com/WasiqB/java-formatter 114 | [tracker]: https://github.com/WasiqB/coteafs-selenium/issues?q=something 115 | [new issue]: https://github.com/WasiqB/coteafs-selenium/issues/new 116 | [fork]: https://help.github.com/articles/fork-a-repo/ 117 | [branch]: https://www.atlassian.com/git/tutorials/using-branches 118 | [setup]: https://help.github.com/articles/setting-your-commit-email-address-in-git 119 | [commitHelp]: https://github.com/erlang/otp/wiki/Writing-good-commit-messages 120 | [pr]: https://help.github.com/articles/creating-a-pull-request 121 | [site]: https://wasiqb.github.io -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/driver/CustomScreenRecorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.driver; 17 | 18 | import static com.github.wasiqb.coteafs.error.util.ErrorUtil.handleError; 19 | import static com.github.wasiqb.coteafs.selenium.constants.ConfigKeys.FILTER_PKG; 20 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 21 | import static java.text.MessageFormat.format; 22 | import static org.monte.media.FormatKeys.EncodingKey; 23 | import static org.monte.media.FormatKeys.FrameRateKey; 24 | import static org.monte.media.FormatKeys.KeyFrameIntervalKey; 25 | import static org.monte.media.FormatKeys.MIME_AVI; 26 | import static org.monte.media.FormatKeys.MediaTypeKey; 27 | import static org.monte.media.FormatKeys.MimeTypeKey; 28 | import static org.monte.media.Registry.getInstance; 29 | import static org.monte.media.VideoFormatKeys.CompressorNameKey; 30 | import static org.monte.media.VideoFormatKeys.DepthKey; 31 | import static org.monte.media.VideoFormatKeys.ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE; 32 | import static org.monte.media.VideoFormatKeys.QualityKey; 33 | 34 | import java.awt.AWTException; 35 | import java.awt.Dimension; 36 | import java.awt.GraphicsConfiguration; 37 | import java.awt.GraphicsEnvironment; 38 | import java.awt.Rectangle; 39 | import java.awt.Toolkit; 40 | import java.io.File; 41 | import java.io.IOException; 42 | import java.text.SimpleDateFormat; 43 | import java.util.Date; 44 | 45 | import com.github.wasiqb.coteafs.selenium.config.RecorderSetting; 46 | import com.github.wasiqb.coteafs.selenium.error.VideoRecordingError; 47 | import org.apache.logging.log4j.LogManager; 48 | import org.apache.logging.log4j.Logger; 49 | import org.monte.media.Format; 50 | import org.monte.media.FormatKeys.MediaType; 51 | import org.monte.media.math.Rational; 52 | import org.monte.screenrecorder.ScreenRecorder; 53 | 54 | /** 55 | * @author Wasiq Bhamla 56 | * @since 27-Oct-2019 57 | */ 58 | class CustomScreenRecorder extends ScreenRecorder { 59 | private static final Logger LOG = LogManager.getLogger (); 60 | private static final RecorderSetting RECORDER_SETTING = getBrowserSetting ().getPlayback () 61 | .getRecording (); 62 | private static ScreenRecorder screenRecorder; 63 | 64 | static void startRecording () { 65 | if (checkIfEnabled ()) { 66 | LOG.info ("Started Video screen recording..."); 67 | final File file = new File (RECORDER_SETTING.getPath ()); 68 | 69 | final Dimension screenSize = Toolkit.getDefaultToolkit () 70 | .getScreenSize (); 71 | final int width = screenSize.width; 72 | final int height = screenSize.height; 73 | 74 | final Rectangle captureSize = new Rectangle (0, 0, width, height); 75 | 76 | final GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment () 77 | .getDefaultScreenDevice () 78 | .getDefaultConfiguration (); 79 | 80 | try { 81 | screenRecorder = new CustomScreenRecorder (gc, captureSize, 82 | new Format (MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI), 83 | new Format (MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, 84 | CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, 24, FrameRateKey, 85 | Rational.valueOf (15), QualityKey, 1.0f, KeyFrameIntervalKey, 15 * 60), 86 | new Format (MediaTypeKey, MediaType.VIDEO, EncodingKey, "black", FrameRateKey, 87 | Rational.valueOf (30)), null, file); 88 | screenRecorder.start (); 89 | } catch (final IOException | AWTException e) { 90 | handleError (FILTER_PKG, e).forEach (LOG::error); 91 | throw new VideoRecordingError ("Error while starting video recording.", e); 92 | } 93 | } else { 94 | LOG.warn ("Video screen recording is Disabled, cannot start..."); 95 | } 96 | } 97 | 98 | static void stopRecording () { 99 | if (checkIfEnabled ()) { 100 | LOG.info ("Stopping Video screen recording..."); 101 | try { 102 | screenRecorder.stop (); 103 | } catch (final IOException e) { 104 | handleError (FILTER_PKG, e).forEach (LOG::error); 105 | throw new VideoRecordingError ("Error while stopping video recording.", e); 106 | } 107 | } else { 108 | LOG.warn ("Video screen recording is Disabled, cannot stop..."); 109 | } 110 | } 111 | 112 | private static boolean checkIfEnabled () { 113 | return RECORDER_SETTING != null && RECORDER_SETTING.isEnable (); 114 | } 115 | 116 | private final String prefix; 117 | 118 | private CustomScreenRecorder (final GraphicsConfiguration cfg, final Rectangle captureArea, final Format fileFormat, 119 | final Format screenFormat, final Format mouseFormat, final Format audioFormat, final File movieFolder) 120 | throws IOException, AWTException { 121 | super (cfg, captureArea, fileFormat, screenFormat, mouseFormat, audioFormat, movieFolder); 122 | this.prefix = RECORDER_SETTING.getPrefix (); 123 | } 124 | 125 | @Override 126 | protected File createMovieFile (final Format fileFormat) throws IOException { 127 | if (!this.movieFolder.exists ()) { 128 | this.movieFolder.mkdirs (); 129 | } else if (!this.movieFolder.isDirectory ()) { 130 | throw new IOException (format ("\"{0}\" is not a directory.", this.movieFolder)); 131 | } 132 | final SimpleDateFormat dateFormat = new SimpleDateFormat ("yyyyMMdd-HHmmss"); 133 | return new File (this.movieFolder, format ("{0}-{1}.{2}", this.prefix, dateFormat.format (new Date ()), 134 | getInstance ().getExtension (fileFormat))); 135 | } 136 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | selenium 6 | 4.2.0 7 | Selenium WebDriver wrapper framework for clean and maintainable tests. 8 | https://github.com/WasiqB/coteafs-selenium 9 | 10 | 11 | com.github.wasiqb.coteafs 12 | parent 13 | 3.9.0 14 | 15 | 16 | 17 | scm:git:git@github.com:WasiqB/coteafs-selenium.git 18 | scm:git:git@github.com:WasiqB/coteafs-selenium.git 19 | git@github.com:WasiqB/coteafs-selenium.git 20 | 21 | 22 | 23 | GitHub Actions 24 | https://github.com/WasiqB/coteafs-selenium/actions 25 | 26 | 27 | 28 | 1.5.0 29 | 1.15.0 30 | 2.17.1 31 | 3.4.0 32 | 4.1.1 33 | 2.11.0 34 | 5.0.3 35 | 1.0.2 36 | 1.9 37 | 0.7.7.0 38 | 1.18.22 39 | 2.13.1 40 | com.github.wasiqb.coteafs:selenium 41 | target/dependency/*.jar 42 | 43 | 44 | 45 | 46 | com.github.wasiqb.coteafs 47 | datasource 48 | ${coteafs.data.version} 49 | 50 | 51 | com.github.wasiqb.coteafs 52 | listeners 53 | ${coteafs.listener.version} 54 | 55 | 56 | com.github.wasiqb.coteafs 57 | error 58 | ${coteafs.error.version} 59 | 60 | 61 | org.apache.logging.log4j 62 | log4j-api 63 | ${log4j.version} 64 | 65 | 66 | org.apache.logging.log4j 67 | log4j-core 68 | ${log4j.version} 69 | 70 | 71 | com.fasterxml.jackson.dataformat 72 | jackson-dataformat-yaml 73 | ${jackson.version} 74 | 75 | 76 | com.fasterxml.jackson.core 77 | jackson-databind 78 | ${jackson.version} 79 | 80 | 81 | org.apache.commons 82 | commons-text 83 | ${commons.text.version} 84 | provided 85 | 86 | 87 | org.testng 88 | testng 89 | ${testng.version} 90 | 91 | 92 | com.google.guava 93 | guava 94 | 95 | 96 | provided 97 | 98 | 99 | org.apache.commons 100 | commons-lang3 101 | ${commons.version} 102 | provided 103 | 104 | 105 | commons-io 106 | commons-io 107 | ${commons.io.version} 108 | provided 109 | 110 | 111 | com.google.truth 112 | truth 113 | ${truth.version} 114 | 115 | 116 | com.google.guava 117 | guava 118 | 119 | 120 | 121 | 122 | org.seleniumhq.selenium 123 | selenium-java 124 | ${selenium-version} 125 | 126 | 127 | io.github.bonigarcia 128 | webdrivermanager 129 | ${webdrivermanager-version} 130 | 131 | 132 | com.google.guava 133 | guava 134 | ${guava.version} 135 | 136 | 137 | com.github.javafaker 138 | javafaker 139 | ${faker.version} 140 | test 141 | 142 | 143 | com.github.stephenc.monte 144 | monte-screen-recorder 145 | ${recorder.version} 146 | 147 | 148 | org.projectlombok 149 | lombok 150 | ${lombok.version} 151 | provided 152 | 153 | 154 | -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/listeners/DriverListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 - 2020, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.listeners; 17 | 18 | import static java.util.Arrays.stream; 19 | 20 | import org.apache.logging.log4j.LogManager; 21 | import org.apache.logging.log4j.Logger; 22 | import org.openqa.selenium.By; 23 | import org.openqa.selenium.OutputType; 24 | import org.openqa.selenium.WebDriver; 25 | import org.openqa.selenium.WebElement; 26 | import org.openqa.selenium.support.events.WebDriverEventListener; 27 | 28 | /** 29 | * @author Wasiq Bhamla 30 | * @since Apr 28, 2019 31 | */ 32 | public class DriverListener implements WebDriverEventListener { 33 | private static final Logger LOG = LogManager.getLogger (); 34 | private static String name; 35 | 36 | /** 37 | * @param alias the Element alias to set 38 | * 39 | * @author Wasiq Bhamla 40 | * @since 25-Sep-2019 41 | */ 42 | public static void setAlias (final String alias) { 43 | name = alias; 44 | } 45 | 46 | @Override 47 | public void afterAlertAccept (final WebDriver driver) { 48 | LOG.trace ("Alert dialog accepted with message [{}]...", name); 49 | } 50 | 51 | @Override 52 | public void afterAlertDismiss (final WebDriver driver) { 53 | LOG.trace ("Alert dialog dismissed [{}]...", name); 54 | } 55 | 56 | @Override 57 | public void afterChangeValueOf (final WebElement element, final WebDriver driver, final CharSequence[] keysToSend) { 58 | if (keysToSend != null) { 59 | final String message = "Text {} has been entered in element [{}]..."; 60 | LOG.trace (message, keysToSend, name); 61 | } 62 | } 63 | 64 | @Override 65 | public void afterClickOn (final WebElement element, final WebDriver driver) { 66 | LOG.trace ("Clicked on element [{}]...", name); 67 | } 68 | 69 | @Override 70 | public void afterFindBy (final By by, final WebElement element, final WebDriver driver) { 71 | LOG.trace ("Element [{}] found using {}...", name, by); 72 | } 73 | 74 | @Override 75 | public void afterGetScreenshotAs (final OutputType target, final X screenshot) { 76 | LOG.trace ("Taken screenshot successfully..."); 77 | } 78 | 79 | @Override 80 | public void afterGetText (final WebElement element, final WebDriver driver, final String text) { 81 | LOG.trace ("Got text {} from element [{}]...", text, name); 82 | } 83 | 84 | @Override 85 | public void afterNavigateBack (final WebDriver driver) { 86 | LOG.trace ("Navigated backward..."); 87 | } 88 | 89 | @Override 90 | public void afterNavigateForward (final WebDriver driver) { 91 | LOG.trace ("Navigated forward..."); 92 | } 93 | 94 | @Override 95 | public void afterNavigateRefresh (final WebDriver driver) { 96 | LOG.trace ("Page refreshed..."); 97 | } 98 | 99 | @Override 100 | public void afterNavigateTo (final String url, final WebDriver driver) { 101 | LOG.trace ("Navigated to url {}...", url); 102 | } 103 | 104 | @Override 105 | public void afterScript (final String script, final WebDriver driver) { 106 | LOG.trace ("Script {} executed successfully...", script); 107 | } 108 | 109 | @Override 110 | public void afterSwitchToWindow (final String windowName, final WebDriver driver) { 111 | LOG.trace ("Window switched to {}...", windowName); 112 | } 113 | 114 | @Override 115 | public void beforeAlertAccept (final WebDriver driver) { 116 | LOG.info ("Accepting Alert pop-up with message [{}]...", name); 117 | } 118 | 119 | @Override 120 | public void beforeAlertDismiss (final WebDriver driver) { 121 | LOG.info ("Dismissing Alert pop-up with message [{}]...", name); 122 | } 123 | 124 | @Override 125 | public void beforeChangeValueOf (final WebElement element, final WebDriver driver, 126 | final CharSequence[] keysToSend) { 127 | if (keysToSend != null) { 128 | LOG.info ("Writing text {} in element [{}]...", keysToSend, name); 129 | } 130 | } 131 | 132 | @Override 133 | public void beforeClickOn (final WebElement element, final WebDriver driver) { 134 | LOG.info ("Clicking on element [{}]...", name); 135 | } 136 | 137 | @Override 138 | public void beforeFindBy (final By by, final WebElement element, final WebDriver driver) { 139 | LOG.trace ("Finding element [{}] using {}", name, by); 140 | } 141 | 142 | @Override 143 | public void beforeGetScreenshotAs (final OutputType target) { 144 | LOG.trace ("Taking screenshot..."); 145 | } 146 | 147 | @Override 148 | public void beforeGetText (final WebElement element, final WebDriver driver) { 149 | LOG.trace ("Getting text from element [{}]...", name); 150 | } 151 | 152 | @Override 153 | public void beforeNavigateBack (final WebDriver driver) { 154 | LOG.info ("Navigating back..."); 155 | } 156 | 157 | @Override 158 | public void beforeNavigateForward (final WebDriver driver) { 159 | LOG.info ("Navigating forward..."); 160 | } 161 | 162 | @Override 163 | public void beforeNavigateRefresh (final WebDriver driver) { 164 | LOG.info ("Refreshing the page..."); 165 | } 166 | 167 | @Override 168 | public void beforeNavigateTo (final String url, final WebDriver driver) { 169 | LOG.info ("Navigating to {}...", url); 170 | } 171 | 172 | @Override 173 | public void beforeScript (final String script, final WebDriver driver) { 174 | final String message = "Executing script {}..."; 175 | LOG.trace (message, script); 176 | } 177 | 178 | @Override 179 | public void beforeSwitchToWindow (final String windowName, final WebDriver driver) { 180 | LOG.info ("Switching to window {}...", windowName); 181 | } 182 | 183 | @Override 184 | public void onException (final Throwable throwable, final WebDriver driver) { 185 | LOG.catching (throwable); 186 | LOG.error ("Error occurred: {}", throwable.getMessage ()); 187 | stream (throwable.getStackTrace ()).forEach (s -> LOG.error ("\tat: {}", s)); 188 | } 189 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/element/AbstractElementAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.element; 17 | 18 | import static java.time.Duration.ofMillis; 19 | import static org.apache.commons.lang3.StringUtils.isNoneEmpty; 20 | 21 | import java.util.List; 22 | import java.util.stream.Collectors; 23 | 24 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 25 | import com.github.wasiqb.coteafs.selenium.core.element.IMouseActions; 26 | import com.github.wasiqb.coteafs.selenium.core.element.ISelectBoxActions; 27 | import com.github.wasiqb.coteafs.selenium.core.element.ITextBoxActions; 28 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 29 | import org.openqa.selenium.By; 30 | import org.openqa.selenium.WebDriver; 31 | import org.openqa.selenium.WebElement; 32 | import org.openqa.selenium.support.ui.Select; 33 | 34 | /** 35 | * @param 36 | * @param 37 | * @param 38 | * 39 | * @author Wasiq Bhamla 40 | * @since 27-Jul-2019 41 | */ 42 | @SuppressWarnings ("unchecked") 43 | public class AbstractElementAction> 44 | extends FindableAction implements ITextBoxActions, ISelectBoxActions { 45 | protected AbstractElementAction (final B browserAction, final By by, final String name) { 46 | super (browserAction, by, name); 47 | } 48 | 49 | protected AbstractElementAction (final B browserAction, final By by, final String name, 50 | final WaitStrategy strategy) { 51 | super (browserAction, by, name, strategy); 52 | } 53 | 54 | protected AbstractElementAction (final B browserAction, final E element, final String name) { 55 | super (browserAction, element, name); 56 | } 57 | 58 | protected AbstractElementAction (final B browserAction, final E element, final String name, 59 | final WaitStrategy strategy) { 60 | super (browserAction, element, name, strategy); 61 | } 62 | 63 | @Override 64 | public void click () { 65 | perform (e -> { 66 | pause (this.delays.getBeforeClick ()); 67 | e.click (); 68 | pause (this.delays.getAfterClick ()); 69 | }); 70 | } 71 | 72 | @Override 73 | public void deselectAll () { 74 | perform (e -> { 75 | final Select select = new Select (e); 76 | select.deselectAll (); 77 | }); 78 | } 79 | 80 | @Override 81 | public void deselectByIndex (final int index) { 82 | perform (e -> { 83 | final Select select = new Select (e); 84 | select.deselectByIndex (index); 85 | }); 86 | } 87 | 88 | @Override 89 | public void deselectByText (final String value) { 90 | perform (e -> { 91 | final Select select = new Select (e); 92 | select.deselectByVisibleText (value); 93 | }); 94 | } 95 | 96 | @Override 97 | public void deselectByValue (final String value) { 98 | perform (e -> { 99 | final Select select = new Select (e); 100 | select.deselectByValue (value); 101 | }); 102 | } 103 | 104 | @Override 105 | public void enterText (final String text) { 106 | perform (e -> { 107 | if (isNoneEmpty (text)) { 108 | pause (this.delays.getBeforeKeyPress ()); 109 | e.sendKeys (text); 110 | pause (this.delays.getAfterKeyPress ()); 111 | } 112 | }); 113 | } 114 | 115 | @Override 116 | public T find (final By byLocator, final String name, final WaitStrategy strategy) { 117 | waitForStrategy (byLocator, strategy); 118 | return get (e -> (T) new AbstractElementAction<> (this.browserAction, e.findElement (byLocator), name)); 119 | } 120 | 121 | @Override 122 | public List finds (final By byLocator, final String name, 123 | final WaitStrategy strategy) { 124 | waitForStrategy (byLocator, strategy); 125 | return get (e -> e.findElements (byLocator)).stream () 126 | .map (e -> (T) new AbstractElementAction<> (this.browserAction, e, name)) 127 | .collect (Collectors.toList ()); 128 | } 129 | 130 | @Override 131 | public void hover () { 132 | perform (e -> this.actions.pause (ofMillis (this.delays.getBeforeMouseMove ())) 133 | .moveToElement (e) 134 | .pause (ofMillis (this.delays.getAfterMouseMove ())) 135 | .perform ()); 136 | } 137 | 138 | @Override 139 | public boolean isMultiSelect () { 140 | return get (e -> { 141 | final Select select = new Select (e); 142 | return select.isMultiple (); 143 | }); 144 | } 145 | 146 | @Override 147 | public List options () { 148 | return get (e -> { 149 | final Select select = new Select (e); 150 | return select.getOptions () 151 | .stream () 152 | .map (o -> (T) new AbstractElementAction<> (this.browserAction, o, o.getText ())) 153 | .collect (Collectors.toList ()); 154 | }); 155 | } 156 | 157 | @Override 158 | public void selectByIndex (final int index) { 159 | perform (e -> { 160 | final Select select = new Select (e); 161 | select.selectByIndex (index); 162 | }); 163 | } 164 | 165 | @Override 166 | public void selectByText (final String value) { 167 | perform (e -> { 168 | final Select select = new Select (e); 169 | select.selectByVisibleText (value); 170 | }); 171 | } 172 | 173 | @Override 174 | public void selectByValue (final String value) { 175 | perform (e -> { 176 | final Select select = new Select (e); 177 | select.selectByValue (value); 178 | }); 179 | } 180 | 181 | @Override 182 | public List selectedOptions () { 183 | return get (e -> { 184 | final Select select = new Select (e); 185 | return select.getAllSelectedOptions () 186 | .stream () 187 | .map (o -> (T) new AbstractElementAction<> (this.browserAction, o, o.getText ())) 188 | .collect (Collectors.toList ()); 189 | }); 190 | } 191 | } -------------------------------------------------------------------------------- /src/main/java/com/github/wasiqb/coteafs/selenium/core/base/element/BaseElementAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, Wasiq Bhamla. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.wasiqb.coteafs.selenium.core.base.element; 17 | 18 | import static com.github.wasiqb.coteafs.selenium.core.base.driver.ParallelSession.getBrowserSetting; 19 | import static com.github.wasiqb.coteafs.selenium.listeners.DriverListener.setAlias; 20 | import static java.lang.Thread.currentThread; 21 | import static java.lang.Thread.sleep; 22 | import static java.text.MessageFormat.format; 23 | import static org.openqa.selenium.support.ui.ExpectedConditions.attributeToBe; 24 | import static org.openqa.selenium.support.ui.ExpectedConditions.elementToBeClickable; 25 | import static org.openqa.selenium.support.ui.ExpectedConditions.invisibilityOf; 26 | import static org.openqa.selenium.support.ui.ExpectedConditions.invisibilityOfElementLocated; 27 | import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOf; 28 | import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated; 29 | 30 | import java.util.function.Consumer; 31 | import java.util.function.Function; 32 | 33 | import com.github.wasiqb.coteafs.selenium.config.DelaySetting; 34 | import com.github.wasiqb.coteafs.selenium.core.driver.IDriverActions; 35 | import com.github.wasiqb.coteafs.selenium.core.element.IWaitStrategy; 36 | import com.github.wasiqb.coteafs.selenium.core.enums.WaitStrategy; 37 | import org.apache.logging.log4j.LogManager; 38 | import org.apache.logging.log4j.Logger; 39 | import org.openqa.selenium.By; 40 | import org.openqa.selenium.WebDriver; 41 | import org.openqa.selenium.WebElement; 42 | import org.openqa.selenium.interactions.Actions; 43 | import org.openqa.selenium.support.ui.WebDriverWait; 44 | 45 | /** 46 | * @param 47 | * @param 48 | * @param 49 | * 50 | * @author Wasiq Bhamla 51 | * @since 27-Jul-2019 52 | */ 53 | @SuppressWarnings ("unchecked") 54 | public class BaseElementAction> 55 | implements IWaitStrategy { 56 | private static final Logger LOG = LogManager.getLogger (); 57 | 58 | static void pause (final long delay) { 59 | try { 60 | sleep (delay); 61 | } catch (final InterruptedException e) { 62 | LOG.error ("Error while pausing: {}", e.getMessage ()); 63 | currentThread ().interrupt (); 64 | } 65 | } 66 | 67 | final Actions actions; 68 | final B browserAction; 69 | final DelaySetting delays; 70 | private boolean alreadyHighlighted; 71 | private By by; 72 | private final D driver; 73 | private E element; 74 | private final String name; 75 | private WaitStrategy strategy; 76 | private String style; 77 | private boolean useBy; 78 | private final WebDriverWait wait; 79 | 80 | BaseElementAction (final B browserAction, final By by, final String name) { 81 | this (browserAction, name); 82 | this.by = by; 83 | this.useBy = true; 84 | } 85 | 86 | BaseElementAction (final B browserAction, final By by, final String name, final WaitStrategy strategy) { 87 | this (browserAction, by, name); 88 | if (strategy != null) { 89 | this.strategy = strategy; 90 | } 91 | } 92 | 93 | BaseElementAction (final B browserAction, final E element, final String name) { 94 | this (browserAction, name); 95 | this.element = element; 96 | this.useBy = false; 97 | } 98 | 99 | BaseElementAction (final B browserAction, final E element, final String name, final WaitStrategy strategy) { 100 | this (browserAction, element, name); 101 | if (strategy != null) { 102 | this.strategy = strategy; 103 | } 104 | } 105 | 106 | private BaseElementAction (final B browserAction, final String name) { 107 | this.browserAction = browserAction; 108 | this.name = name; 109 | this.driver = browserAction.driver (); 110 | this.actions = new Actions (this.driver); 111 | this.wait = browserAction.driverWait (); 112 | this.alreadyHighlighted = false; 113 | this.delays = getBrowserSetting ().getPlayback () 114 | .getDelays (); 115 | this.strategy = WaitStrategy.NONE; 116 | } 117 | 118 | @Override 119 | public void waitUntilAttributeIs (final String attribute, final String value) { 120 | if (this.useBy) { 121 | waitUntilLocatorAttributeIs (attribute, value); 122 | } else { 123 | this.wait.until (attributeToBe (this.element, attribute, value)); 124 | } 125 | } 126 | 127 | @Override 128 | public void waitUntilClickable () { 129 | if (this.useBy) { 130 | waitUntilLocatorClickable (); 131 | } else { 132 | this.wait.until (elementToBeClickable (this.element)); 133 | } 134 | } 135 | 136 | @Override 137 | public void waitUntilInvisible () { 138 | if (this.useBy) { 139 | waitUntilLocatorInvisible (); 140 | } else { 141 | this.wait.until (invisibilityOf (this.element)); 142 | } 143 | } 144 | 145 | @Override 146 | public void waitUntilVisible () { 147 | if (this.useBy) { 148 | waitUntilLocatorVisible (); 149 | } else { 150 | this.wait.until (visibilityOf (this.element)); 151 | } 152 | } 153 | 154 | protected T get (final Function func) { 155 | prepareForAction ("green"); 156 | return func.apply (this.element); 157 | } 158 | 159 | protected void perform (final Consumer action) { 160 | prepareForAction ("red"); 161 | action.accept (this.element); 162 | } 163 | 164 | protected void waitForStrategy (final By locator, final WaitStrategy newStrategy) { 165 | final BaseElementAction elementAction = new BaseElementAction<> (this.browserAction, locator, 166 | this.name, newStrategy); 167 | elementAction.waitForStrategy (); 168 | } 169 | 170 | private void highlight (final String color) { 171 | if (!this.alreadyHighlighted) { 172 | this.style = this.element.getAttribute ("style"); 173 | this.browserAction.execute ("arguments[0].setAttribute('style', arguments[1] + arguments[2]);", 174 | this.element, this.style, format ("color: {0}; border: 3px solid {0};", color)); 175 | } 176 | } 177 | 178 | private void prepareForAction (final String color) { 179 | waitForStrategy (); 180 | highlight (color); 181 | pause (this.delays.getHighlight ()); 182 | unhighlight (); 183 | setAlias (this.name); 184 | } 185 | 186 | private void unhighlight () { 187 | if (!this.alreadyHighlighted) { 188 | this.browserAction.execute ("arguments[0].setAttribute('style', arguments[1]);", this.element, this.style); 189 | this.alreadyHighlighted = true; 190 | } 191 | } 192 | 193 | private void waitForStrategy () { 194 | switch (this.strategy) { 195 | case CLICKABLE: 196 | waitUntilClickable (); 197 | break; 198 | case VISIBLE: 199 | waitUntilVisible (); 200 | break; 201 | case INVISIBLE: 202 | waitUntilInvisible (); 203 | break; 204 | case NONE: 205 | default: 206 | if (this.useBy) { 207 | this.element = (E) this.driver.findElement (this.by); 208 | } 209 | break; 210 | } 211 | } 212 | 213 | private void waitUntilLocatorAttributeIs (final String attribute, final String value) { 214 | this.wait.until (attributeToBe (this.by, attribute, value)); 215 | } 216 | 217 | private void waitUntilLocatorClickable () { 218 | this.element = (E) this.wait.until (elementToBeClickable (this.by)); 219 | } 220 | 221 | private void waitUntilLocatorInvisible () { 222 | this.wait.until (invisibilityOfElementLocated (this.by)); 223 | } 224 | 225 | private void waitUntilLocatorVisible () { 226 | this.element = (E) this.wait.until (visibilityOfElementLocated (this.by)); 227 | } 228 | } --------------------------------------------------------------------------------