Skip to content

Commit 8648d08

Browse files
authored
adds a dedicated find_image method (#15)
1 parent a26a9dd commit 8648d08

File tree

10 files changed

+155
-205
lines changed

10 files changed

+155
-205
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Niobium extends the Python Selenium client with nice features.
66

77
Selenium is a good tool for web automation, but sometimes it's hard to write a clean automation script.
88

9-
With Niobium, you can keep using Selenium while simplifying your scripts. For example, Niobium adds a new element locator,` By.IMAGE`, which enables image recognition in `WebDriver.find_element` to locate an element on the webpage.
9+
With Niobium, you can keep using Selenium while simplifying your scripts. For example, Niobium adds a new method that uses image recognition to interact with the webpage.
1010

1111
The goal of Niobium is not to replace Selenium. We only want to add to Selenium the functions we will love to see in Selenium natively.
1212

@@ -30,7 +30,7 @@ In order to use Niobium, you just need to import it in your script. Selenium wil
3030
driver.implicitly_wait(10)
3131
driver.get("https://www.python.org/")
3232

33-
driver.find_element(By.IMAGE, "logo_python.png")
33+
driver.find_image("logo_python.png")
3434

3535
driver.quit()
3636
```

docs/image.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ Niobium adds computer vision to Selenium.
77
You can locate an image in the page using the following method:
88

99
```python
10-
find_element(By.IMAGE, filename)
10+
WebDriver.find_image(filename: str) -> ImageElement
1111
```
1212

1313
And to find multiple images (this method returns a list)
1414

1515
```python
16-
find_elements(By.IMAGE, filename)
16+
WebDriver.find_images(filename: str) -> list[ImageElement]
1717
```
1818

19-
These methods have the same behavior than the classic `find_element` methods but they return an `ImageElement` instead of a `WebElement` if you use the `By.IMAGE` selector.
19+
These methods have the same behavior than the classic `find_element` methods but they return an `ImageElement` instead of a `WebElement`.
2020

2121
They take only one argument which is the path to the PNG image that you search.
2222

2323
## Find element by image
2424

25-
The methods `find_element` and `find_elements` using the selector `By.IMAGE` are available only from the `WebDriver` object. Only the visible page is analyzed in order to locate the image.
25+
The methods `find_image` and `find_images` are available only from the `WebDriver` object. Only the visible page is analyzed in order to locate the image.
2626

2727
```python
2828
from selenium import webdriver
@@ -32,7 +32,7 @@ The methods `find_element` and `find_elements` using the selector `By.IMAGE` are
3232
driver.implicitly_wait(10)
3333
driver.get("https://www.python.org/")
3434

35-
driver.find_element(By.IMAGE, "logo_python.png")
35+
driver.find_image("logo_python.png")
3636

3737
driver.quit()
3838
```
@@ -42,7 +42,7 @@ The methods `find_element` and `find_elements` using the selector `By.IMAGE` are
4242
You can click on the element.
4343

4444
```python
45-
driver.find_element(By.IMAGE, "logo_python.png").click()
45+
driver.find_image("logo_python.png").click()
4646
```
4747

4848
By default, the click is performed on the center of the element.
@@ -52,21 +52,21 @@ By default, the click is performed on the center of the element.
5252
You can click to a specific location related to the top left corner of the element with the `click_at(xoffset, yoffset)` function.
5353

5454
```python
55-
driver.find_element(By.IMAGE, "logo_python.png").click_at(100, -100)
55+
driver.find_image("logo_python.png").click_at(100, -100)
5656
```
5757

5858
## Move the cursor over the element
5959

6060
You can move the cursor to the center of the element with the `move_to()` function.
6161

6262
```python
63-
driver.find_element(By.IMAGE, "logo_python.png").move_to()
63+
driver.find_image("logo_python.png").move_to()
6464
```
6565

6666
## Move the cursor with offset
6767

6868
You can move the cursor to a specific location related to the top left corner of the element with the `move_at(xoffset, yoffset)` function.
6969

7070
```python
71-
driver.find_element(By.IMAGE, "logo_python.png").move_at(20, 20)
71+
driver.find_image("logo_python.png").move_at(20, 20)
7272
```

docs/index.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Niobium extends the Python Selenium client with nice features.
66

77
Selenium is a good tool for web automation, but sometimes it's hard to write a clean automation script.
88

9-
With Niobium, you can keep using Selenium while simplifying your scripts. For example, Niobium adds a new element locator,` By.IMAGE`, which enables image recognition in `WebDriver.find_element` to locate an element on the webpage.
9+
With Niobium, you can keep using Selenium while simplifying your scripts. For example, Niobium adds a new method that uses image recognition to interact with the webpage.
10+
1011

1112
The goal of Niobium is not to replace Selenium. We only want to add to Selenium the functions we will love to see in Selenium natively.
1213

@@ -30,7 +31,7 @@ In order to use Niobium, you just need to import it in your script. Selenium wil
3031
driver.implicitly_wait(10)
3132
driver.get("https://www.python.org/")
3233

33-
driver.find_element(By.IMAGE, "logo_python.png")
34+
driver.find_image("logo_python.png")
3435

3536
driver.quit()
3637
```

niobium/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313

1414
__all__ = ["selenium"]
1515

16-
__version__ = "0.5.0"
16+
__version__ = "1.0.0"

niobium/find_image.py

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,15 @@
11
import io
2-
from typing import Optional
3-
from typing import Union
4-
52

63
import cv2
74
import numpy as np
85
from PIL import Image
96
from selenium.common.exceptions import NoSuchElementException
107
from selenium.common.exceptions import WebDriverException
11-
from selenium.webdriver.common.by import By as OriginalBy
128
from selenium.webdriver.remote.webdriver import WebDriver
13-
from selenium.webdriver.remote.webelement import WebElement
14-
159

1610
from niobium.image_element import ImageElement
1711
from niobium.timeout import ImplicitWait
1812

19-
original_webdriver_find_element = WebDriver.find_element
20-
original_webdriver_find_elements = WebDriver.find_elements
21-
22-
23-
class By(OriginalBy):
24-
IMAGE = "image"
25-
2613

2714
def match_template(img_src, img_template, threshold=0.9):
2815
# we remove alpha channel if exists
@@ -44,7 +31,7 @@ def match_template(img_src, img_template, threshold=0.9):
4431
return []
4532

4633

47-
def find_elements_by_image(self: WebDriver, filename: str) -> list[ImageElement]:
34+
def find_images(self: WebDriver, filename: str) -> list[ImageElement]:
4835
"""
4936
Locate all the occurence of an image in the webpage.
5037
@@ -70,7 +57,7 @@ def find_elements_by_image(self: WebDriver, filename: str) -> list[ImageElement]
7057
]
7158

7259

73-
def find_element_by_image(self: WebDriver, filename: str) -> ImageElement:
60+
def find_image(self: WebDriver, filename: str) -> ImageElement:
7461
"""
7562
Locate an image in the webpage.
7663
@@ -86,32 +73,14 @@ def find_element_by_image(self: WebDriver, filename: str) -> ImageElement:
8673
implicit_wait = ImplicitWait()
8774
implicit_wait.start()
8875

89-
elements = find_elements_by_image(self, filename)
76+
elements = find_images(self, filename)
9077

9178
while len(elements) == 0 and not implicit_wait.max_time_exceeded:
92-
elements = find_elements_by_image(self, filename)
79+
elements = find_images(self, filename)
9380

9481
if len(elements) == 0:
9582
raise NoSuchElementException(
9683
'Unable to locate element: [image="{filename}"]'.format(filename=filename)
9784
)
9885
else:
9986
return elements[0]
100-
101-
102-
def find_element(
103-
self: WebDriver, by=By.ID, value: Optional[str] = None
104-
) -> Union[WebElement, ImageElement]:
105-
if by == By.IMAGE and value is not None:
106-
return find_element_by_image(self, value)
107-
else:
108-
return original_webdriver_find_element(self, by, value)
109-
110-
111-
def find_elements(
112-
self: WebDriver, by=By.ID, value: Optional[str] = None
113-
) -> Union[list[WebElement], list[ImageElement]]:
114-
if by == By.IMAGE and value is not None:
115-
return find_elements_by_image(self, value)
116-
else:
117-
return original_webdriver_find_elements(self, by, value)

niobium/patch.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
from selenium.webdriver.remote.webdriver import WebDriver
22
from selenium.webdriver.remote.webelement import WebElement
3-
from selenium.webdriver.common import by
43

5-
from niobium.find_image import By as NiobiumBy
6-
from niobium.find_image import find_element
7-
from niobium.find_image import find_elements
4+
from niobium.find_image import find_image
5+
from niobium.find_image import find_images
86
from niobium.timeout import _patch_implicitly_wait
97
from niobium.webelement_action import click_at, move_to, move_at
108
from niobium.webelement_wait import wait
119

1210

1311
def patch_image():
1412

15-
by.By = NiobiumBy
13+
if not hasattr(WebDriver, "find_image"):
14+
WebDriver.find_image = find_image
1615

17-
WebDriver.find_element = find_element
18-
WebDriver.find_elements = find_elements
16+
if not hasattr(WebDriver, "find_images"):
17+
WebDriver.find_images = find_images
1918

2019

2120
def patch_timeout():
2221
WebDriver.implicitly_wait = _patch_implicitly_wait
2322

2423

2524
def patch_webelement_action():
26-
if "click_at" not in dir(WebElement):
25+
26+
if not hasattr(WebElement, "click_at"):
2727
WebElement.click_at = click_at
2828

29-
if "move_to" not in dir(WebElement):
29+
if not hasattr(WebElement, "move_to"):
3030
WebElement.move_to = move_to
3131

32-
if "move_at" not in dir(WebElement):
32+
if not hasattr(WebElement, "move_at"):
3333
WebElement.move_at = move_at
3434

3535

3636
def patch_webelement_wait():
37-
if "wait" not in dir(WebElement):
37+
if not hasattr(WebElement, "wait"):
3838
WebElement.wait = wait

tests/test_find_element_by_image.py

Lines changed: 0 additions & 94 deletions
This file was deleted.

tests/test_find_elements_by_image.py

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)