├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── kz
│ └── qwertukg
│ ├── searchContextElementsExtensions.kt
│ ├── searchContextExtensions.kt
│ ├── webDriver.kt
│ ├── webDriverOptions.kt
│ └── webDriverWaitExtensions.kt
└── test
└── java
└── kz
└── qwertukg
├── WebDriverKtTest.kt
└── base.kt
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Common ###
2 | target/
3 | resources/
4 |
5 |
6 |
7 | ### IntelliJ IDEA ###
8 | .idea
9 | *.iml
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Daniil Rakhmatulin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SeleniumBuilder
2 | DSL for Selenium. Provide a possibility to write tests in [Kotlin type-safe builders](https://kotlinlang.org/docs/reference/type-safe-builders.html#a-type-safe-builder-example) style
3 |
4 | ## Sample
5 | ```kotlin
6 | driver(ChromeDriver()) {
7 | get("http://cool-website.com")
8 |
9 | elementByClass("login") {
10 | sendKeys("user@example.com")
11 | }
12 |
13 | elementByName("password") {
14 | sendKeys("123456")
15 | submit()
16 | }
17 |
18 | element(By.className("search")) {
19 | sendKeys("kotlin")
20 | }
21 |
22 | wait(10) {
23 | elementVisibilityById("result-item") {
24 | elementByClass("salary") {
25 | item.salary = text
26 | }
27 | }
28 | }
29 | }
30 | ```
31 |
32 | ## Total function list
33 |
34 | #### Driver builders
35 |
36 | `driver(driver: WebDriver) {}`
37 |
38 | `chromeDriver {}`
39 |
40 | `chromeDriver(pathToDriver: String) {}`
41 |
42 | `firefoxDriver {}`
43 |
44 | `firefoxDriver(pathToDriver: String) {}`
45 |
46 | #### `WebDriver` and `WebElement` element builders
47 |
48 | `element(by: By) {}`
49 |
50 | `elementById(id: String) {}`
51 |
52 | `elementByClass(className: String) {}`
53 |
54 | `elementByName(name: String) {}`
55 |
56 | `elementBySelector(selector: String) {}`
57 |
58 | `elementByXpath(selector: String) {}`
59 |
60 | #### `WebDriver` and `WebElement` element list builders
61 |
62 | `elements(by: By) {}`
63 |
64 | `elementsById(id: String) {}`
65 |
66 | `elementsByClass(className: String) {}`
67 |
68 | `elementsByName(name: String) {}`
69 |
70 | `elementsBySelector(selector: String) {}`
71 |
72 | `elementsByXpath(selector: String) {}`
73 |
74 | #### `WebDriver` and `WebElement` element exists functions
75 |
76 | `elementExists(by: By): Boolean`
77 |
78 | `elementByIdExists(id: String): Boolean`
79 |
80 | `elementByClassExists(className: String): Boolean`
81 |
82 | `elementByNameExists(name: String): Boolean`
83 |
84 | `elementBySelectorExists(selector: String): Boolean`
85 |
86 | `elementByXpathExists(selector: String): Boolean`
87 |
88 | #### `WebDriver` `WebDriverWait` builder
89 |
90 | `wait(timeout: Long) {}`
91 |
92 | #### `WebDriverWait` element visibility builders
93 |
94 | `elementVisibility(by: By) {}`
95 |
96 | `elementVisibilityById(id: String) {}`
97 |
98 | `elementVisibilityByClass(className: String) {}`
99 |
100 | `elementVisibilityByName(name: String) {}`
101 |
102 | `elementVisibilityBySelector(selector: String) {}`
103 |
104 | `elementVisibilityByXpath(xpath: String) {}`
105 |
106 | #### `WebDriverWait` element invisibility functions
107 |
108 | `elementInvisibility(by: By): Boolean`
109 |
110 | `elementInvisibilityById(id: String): Boolean`
111 |
112 | `elementInvisibilityByClass(className: String): Boolean`
113 |
114 | `elementInvisibilityByName(name: String): Boolean`
115 |
116 | `elementInvisibilityBySelector(selector: String): Boolean`
117 |
118 | `elementInvisibilityByXpath(xpath: String): Boolean`
119 |
120 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | kz.qwertukg
8 | SeleniumBuilder
9 | 0.1
10 |
11 |
12 | 1.2.30
13 |
14 |
15 |
16 |
17 | org.jetbrains.kotlin
18 | kotlin-stdlib-jdk8
19 | ${kotlin.version}
20 |
21 |
22 | org.jetbrains.kotlin
23 | kotlin-test-junit
24 | ${kotlin.version}
25 | test
26 |
27 |
28 |
29 | com.google.guava
30 | guava
31 | 23.6-jre
32 |
33 |
34 |
35 |
36 | org.seleniumhq.selenium
37 | selenium-java
38 | 3.10.0
39 |
40 |
41 |
42 |
43 |
44 |
45 | org.jetbrains.kotlin
46 | kotlin-maven-plugin
47 | ${kotlin.version}
48 |
49 |
50 | compile
51 | compile
52 |
53 | compile
54 |
55 |
56 |
57 | test-compile
58 | test-compile
59 |
60 | test-compile
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/main/java/kz/qwertukg/searchContextElementsExtensions.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("unused")
2 |
3 | package kz.qwertukg
4 |
5 | import org.openqa.selenium.By
6 | import org.openqa.selenium.SearchContext
7 | import org.openqa.selenium.WebElement
8 |
9 | /*
10 | * withElements collection functions
11 | * */
12 |
13 | /*
14 | * Find elementS by
15 | * */
16 | inline fun SearchContext.withElements(by: By, init: Iterable.() -> Unit) {
17 | findElements(by).init()
18 | }
19 |
20 | /*
21 | * Find elementS by class
22 | * */
23 | inline fun SearchContext.withElementsByClass(className: String, init: Iterable.() -> Unit) =
24 | withElements(By.className(className), init)
25 |
26 | /*
27 | * Find elementS by name
28 | * */
29 | inline fun SearchContext.withElementsByName(name: String, init: Iterable.() -> Unit) =
30 | withElements(By.name(name), init)
31 |
32 | /*
33 | * Find elementS by css selector.
34 | * */
35 | inline fun SearchContext.withElementsBySelector(selector: String, init: Iterable.() -> Unit) =
36 | withElements(By.cssSelector(selector), init)
37 |
38 | /*
39 | * Find element by xpath
40 | * */
41 | inline fun SearchContext.withElementsByXpath(xpath: String, init: Iterable.() -> Unit) {
42 | withElements(By.xpath(xpath), init)
43 | }
44 |
45 | /*
46 | * Find elementS by
47 | * */
48 | inline fun SearchContext.eachElement(by: By, init: WebElement.() -> Unit) {
49 | findElements(by).forEach(init)
50 | }
51 |
52 | /*
53 | * Find element by tag
54 | * */
55 | inline fun SearchContext.eachElementByTag(tag: String, init: WebElement.() -> Unit) {
56 | eachElement(By.tagName(tag), init)
57 | }
58 |
59 | /*
60 | * Find element by xpath
61 | * */
62 | inline fun SearchContext.eachElementByXPath(xpath: String, init: WebElement.() -> Unit) {
63 | eachElement(By.xpath(xpath), init)
64 | }
65 |
66 | /*
67 | * Find element by class name
68 | * */
69 | inline fun SearchContext.eachElementByClassName(className: String, init: WebElement.() -> Unit) {
70 | eachElement(By.className(className), init)
71 | }
72 |
73 | /*
74 | * Find element by class name
75 | * */
76 | inline fun SearchContext.eachElementByCssSelector(cssSelector: String, init: WebElement.() -> Unit) {
77 | eachElement(By.cssSelector(cssSelector), init)
78 | }
79 |
80 | /*
81 | * Find withElements by xpath
82 | * */
83 | inline fun SearchContext.elementsByXPath(xpath: String, init: List.() -> T): T {
84 | return findElements(By.xpath(xpath)).init()
85 | }
86 |
87 | /*
88 | * Find elementS by
89 | * */
90 | fun SearchContext.elements(by: By) : List = findElements(by)
91 |
92 | fun SearchContext.elementsByTag(tag: String) = elements(By.tagName(tag))
93 |
94 | fun SearchContext.elementsByName(tag: String) = elements(By.name(tag))
95 |
96 | fun SearchContext.elementsByXPath(tag: String) = elements(By.xpath(tag))
97 |
98 | fun SearchContext.elementsByLinkText(tag: String) = elements(By.linkText(tag))
99 |
100 | fun SearchContext.elementsByClassName(tag: String) = elements(By.className(tag))
101 |
102 | fun SearchContext.elementsByCssSelector(tag: String) = elements(By.cssSelector(tag))
103 |
104 | fun SearchContext.elementsByPartialLinkText(tag: String) = elements(By.partialLinkText(tag))
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/src/main/java/kz/qwertukg/searchContextExtensions.kt:
--------------------------------------------------------------------------------
1 | package kz.qwertukg
2 |
3 | import org.openqa.selenium.By
4 | import org.openqa.selenium.SearchContext
5 | import org.openqa.selenium.WebDriver
6 | import org.openqa.selenium.WebElement
7 | import org.openqa.selenium.support.ui.WebDriverWait
8 |
9 | /**
10 | * Selenium Kotlin Builder
11 | * Created by Daniil Rakhmatulin
12 | * http://daniil.rakhmatulin.kz
13 | */
14 |
15 | /*
16 | * Build WebDriverWait with timeout
17 | * */
18 | fun WebDriver.wait(timeout: Long, sleepTimeout: Long = 500, init: WebDriverWait.() -> Unit) {
19 | WebDriverWait(this, timeout, sleepTimeout).init()
20 | }
21 |
22 | /*
23 | * Single element functions
24 | * */
25 |
26 | /*
27 | * Find element by
28 | * */
29 | inline fun SearchContext.element(by: By, init: WebElement.() -> Unit) {
30 | findElement(by).init()
31 | }
32 |
33 | /*
34 | * Find element by id
35 | * */
36 |
37 | inline fun SearchContext.elementById(id: String, init: WebElement.() -> Unit) {
38 | findElement(By.id(id)).init()
39 | }
40 |
41 | /*
42 | * Find element by class
43 | * */
44 | inline fun SearchContext.elementByClass(className: String, init: WebElement.() -> T): T {
45 | return findElement(By.className(className)).init()
46 | }
47 |
48 | /*
49 | * Find element by name
50 | * */
51 | inline fun SearchContext.elementByName(name: String, init: WebElement.() -> Unit) {
52 | findElement(By.name(name)).init()
53 | }
54 |
55 | /*
56 | * Find element by tag
57 | * */
58 | inline fun SearchContext.elementByTag(tag: String, init: WebElement.() -> T): T {
59 | return findElement(By.tagName(tag)).init()
60 | }
61 |
62 | /*
63 | * Find element by selector
64 | * */
65 | inline fun SearchContext.elementBySelector(selector: String, init: WebElement.() -> Unit) {
66 | findElement(By.cssSelector(selector)).init()
67 | }
68 |
69 | /*
70 | * Find element by xpath
71 | * */
72 | inline fun SearchContext.elementByXpath(xpath: String, init: WebElement.() -> Unit) {
73 | findElement(By.xpath(xpath)).init()
74 | }
75 |
76 |
77 |
78 |
79 |
80 | /*
81 | * element existing functions.
82 | * */
83 |
84 | /*
85 | * Element exists by.
86 | * */
87 | fun SearchContext.elementExists(by: By) = findElements(by).isNotEmpty()
88 |
89 | /*
90 | * Element exists by id
91 | * */
92 | fun SearchContext.elementByIdExists(id: String) = findElements(By.id(id)).isNotEmpty()
93 |
94 | /*
95 | * Element exists by class name
96 | * */
97 | fun SearchContext.elementByClassExists(className: String) = findElements(By.className(className)).isNotEmpty()
98 |
99 | /*
100 | * Element exists by name
101 | * */
102 | fun SearchContext.elementByNameExists(name: String) = findElements(By.name(name)).isNotEmpty()
103 |
104 | /*
105 | * Element exists by css selector
106 | * */
107 | fun SearchContext.elementBySelectorExists(selector: String) = findElements(By.cssSelector(selector)).isNotEmpty()
108 |
109 | /*
110 | * Element exists by xpath
111 | * */
112 | fun SearchContext.elementByXpathExists(xpath: String) = findElements(By.xpath(xpath)).isNotEmpty()
113 |
--------------------------------------------------------------------------------
/src/main/java/kz/qwertukg/webDriver.kt:
--------------------------------------------------------------------------------
1 | package kz.qwertukg
2 |
3 | import org.openqa.selenium.WebDriver
4 | import org.openqa.selenium.chrome.ChromeDriver
5 | import org.openqa.selenium.firefox.FirefoxDriver
6 |
7 | /**
8 | * Selenium Kotlin Builder
9 | * Created by Daniil Rakhmatulin
10 | * http://daniil.rakhmatulin.kz
11 | */
12 |
13 | /*
14 | * Web Driver
15 | * */
16 | inline fun driver(driver: T, init: T.() -> Unit) {
17 | try {
18 | driver.init()
19 | } finally {
20 | driver.close()
21 | }
22 | }
23 |
24 | /*
25 | * Web Driver Chrome
26 | * */
27 | fun chromeDriver(init: WebDriver.() -> Unit) = driver(ChromeDriver(), init)
28 |
29 | /*
30 | * Web Driver Chrome with path to driver
31 | * */
32 | fun chromeDriver(
33 | settings: ChromeDriverSettings,
34 | init: ChromeDriver.() -> Unit
35 | ) {
36 | return driver(ChromeDriver(settings.driverOptions), init)
37 | }
38 |
39 | /*
40 | * Web Driver FireFox
41 | * */
42 | inline fun firefoxDriver(init: WebDriver.() -> Unit) = driver(FirefoxDriver(), init)
43 |
44 | /*
45 | * Web Driver FireFox with path to driver
46 | * */
47 | inline fun firefoxDriver(pathToDriver: String, init: WebDriver.() -> Unit) {
48 | System.setProperty("webdriver.firefox.driver", pathToDriver)
49 | driver(FirefoxDriver(), init)
50 | }
--------------------------------------------------------------------------------
/src/main/java/kz/qwertukg/webDriverOptions.kt:
--------------------------------------------------------------------------------
1 | package kz.qwertukg
2 |
3 | import org.openqa.selenium.chrome.ChromeOptions
4 |
5 | open class DriverOptions(
6 | pathToDriver: String
7 | ) {
8 | init {
9 | System.setProperty("webdriver.chrome.driver", pathToDriver)
10 | }
11 | }
12 |
13 | class ChromeDriverSettings(
14 | pathToDriver: String,
15 | val driverOptions: ChromeOptions = ChromeOptions()
16 | ) : DriverOptions(pathToDriver)
--------------------------------------------------------------------------------
/src/main/java/kz/qwertukg/webDriverWaitExtensions.kt:
--------------------------------------------------------------------------------
1 | package kz.qwertukg
2 |
3 | import org.openqa.selenium.By
4 | import org.openqa.selenium.WebElement
5 | import org.openqa.selenium.support.ui.ExpectedConditions
6 | import org.openqa.selenium.support.ui.WebDriverWait
7 |
8 | /**
9 | * Selenium Kotlin Builder
10 | * Created by Daniil Rakhmatulin
11 | * http://daniil.rakhmatulin.kz
12 | */
13 |
14 | /*
15 | * Visibility of element
16 | * */
17 |
18 | /*
19 | * Web driver wait element is visible
20 | * */
21 | inline fun WebDriverWait.elementVisibility(by: By, init: WebElement.() -> Unit) {
22 | until(ExpectedConditions.visibilityOfElementLocated(by)).init()
23 | }
24 |
25 | /*
26 | * Web driver wait element by id is visible
27 | * */
28 | inline fun WebDriverWait.elementVisibilityById(id: String, init: WebElement.() -> Unit) {
29 | until(ExpectedConditions.visibilityOfElementLocated(By.id(id))).init()
30 | }
31 |
32 | /*
33 | * Web driver wait element by class is visible
34 | * */
35 | inline fun WebDriverWait.elementVisibilityByClass(className: String, init: WebElement.() -> T) : T{
36 | return until(ExpectedConditions.visibilityOfElementLocated(By.className(className))).init()
37 | }
38 |
39 | /*
40 | * Web driver wait element by name is visible
41 | * */
42 | inline fun WebDriverWait.elementVisibilityByName(name: String, init: WebElement.() -> Unit) {
43 | until(ExpectedConditions.visibilityOfElementLocated(By.name(name))).init()
44 | }
45 |
46 | /*
47 | * Web driver wait element by link is visible
48 | * */
49 | inline fun WebDriverWait.elementVisibilityByLink(link: String, init: WebElement.() -> Unit) {
50 | until(ExpectedConditions.visibilityOfElementLocated(By.linkText(link))).init()
51 | }
52 |
53 | /*
54 | * Web driver wait element by tag is visible
55 | * */
56 | inline fun WebDriverWait.elementVisibilityByTag(tag: String, init: WebElement.() -> T) : T{
57 | return until(ExpectedConditions.visibilityOfElementLocated(By.tagName(tag))).init()
58 | }
59 |
60 | /*
61 | * Web driver wait element by css selector is visible
62 | * */
63 | inline fun WebDriverWait.elementVisibilityBySelector(selector: String, init: WebElement.() -> Unit) {
64 | until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(selector))).init()
65 | }
66 |
67 | /*
68 | * Web driver wait element by css selector is visible
69 | * */
70 | inline fun WebDriverWait.elementVisibilityByXpath(xpath: String, init: WebElement.() -> Unit) {
71 | until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath))).init()
72 | }
73 |
74 | /*
75 | * Invisibility of element
76 | * */
77 |
78 | /*
79 | * Web driver wait element is invisible
80 | * */
81 | fun WebDriverWait.elementInvisibility(by: By) = until(ExpectedConditions.invisibilityOfElementLocated(by))
82 |
83 | /*
84 | * Web driver wait element by id is invisible
85 | * */
86 | fun WebDriverWait.elementInvisibilityById(id: String) = until(ExpectedConditions.invisibilityOfElementLocated(By.id(id)))
87 |
88 | /*
89 | * Web driver wait element by class is invisible
90 | * */
91 | fun WebDriverWait.elementInvisibilityByClass(className: String) = until(ExpectedConditions.invisibilityOfElementLocated(By.className(className)))
92 |
93 | /*
94 | * Web driver wait element by name is invisible
95 | * */
96 | fun WebDriverWait.elementInvisibilityByName(name: String) = until(ExpectedConditions.invisibilityOfElementLocated(By.name(name)))
97 |
98 | /*
99 | * Web driver wait element by class is invisible
100 | * */
101 | fun WebDriverWait.elementInvisibilityBySelector(selector: String) = until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(selector)))
102 |
103 | /*
104 | * Web driver wait element by class is invisible
105 | * */
106 | fun WebDriverWait.elementInvisibilityByXpath(xpath: String) = until(ExpectedConditions.invisibilityOfElementLocated(By.xpath(xpath)))
107 |
--------------------------------------------------------------------------------
/src/test/java/kz/qwertukg/WebDriverKtTest.kt:
--------------------------------------------------------------------------------
1 | package kz.qwertukg
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | class WebDriverKtTest {
7 | @Test
8 | fun `test chromeDriver, elementById, wait, elementVisibilityById, elementVisibilityBySelector functions on google`() {
9 | var result = ""
10 |
11 | chromeDriver(settings) {
12 | get("http://google.com")
13 |
14 | elementById("lst-ib") {
15 | sendKeys("kotlin")
16 |
17 | wait(10) {
18 | elementVisibilityByName("btnK") {
19 | click()
20 | }
21 |
22 | elementVisibilityBySelector("a[href = 'https://kotlinlang.org/']") {
23 | result = text
24 | }
25 | }
26 | }
27 | }
28 |
29 | assertEquals("Kotlin Programming Language", result)
30 | }
31 | }
--------------------------------------------------------------------------------
/src/test/java/kz/qwertukg/base.kt:
--------------------------------------------------------------------------------
1 | package kz.qwertukg
2 |
3 | import org.openqa.selenium.chrome.ChromeOptions
4 |
5 | val settings = ChromeDriverSettings(
6 | pathToDriver = "c:/chromedriver.exe",
7 | driverOptions = ChromeOptions().apply {
8 | setHeadless(true)
9 | }
10 | )
11 |
12 | //val settings2 = ChromeDriverSettings(
13 | // pathToDriver = "/Users/alex/Downloads/chromedriver",
14 | // driverOptions = ChromeOptions().apply { setHeadless(false) }
15 | //)
--------------------------------------------------------------------------------