Skip to content

Commit ab4c96a

Browse files
committed
Add exact parameter to all functions
1 parent bdad7eb commit ab4c96a

File tree

3 files changed

+192
-110
lines changed

3 files changed

+192
-110
lines changed

selenium_testing_library/locators.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ class By:
2929
class Locator:
3030
BY: Optional[str] = None
3131

32-
def __init__(self, selector: str):
32+
def __init__(self, selector: str, exact: bool = True):
3333
self.selector = selector
34+
self.exact = exact
3435

3536
def __iter__(self):
3637
yield self.BY
@@ -39,6 +40,11 @@ def __iter__(self):
3940
def find_elements(self, driver: Driver) -> List[WebElement]:
4041
return driver.find_elements(*self)
4142

43+
def _exact_or_not(self, operator):
44+
if self.exact:
45+
return f'{operator} = "{self.selector}"'
46+
return f'contains({operator}, "{self.selector}")'
47+
4248

4349
class Css(Locator):
4450
BY = By.CSS_SELECTOR
@@ -76,29 +82,31 @@ class Role(Locator):
7682
BY = By.ROLE
7783

7884
def find_elements(self, driver: Driver) -> List[WebElement]:
79-
return driver.find_elements(*XPath(f"//*[@role='{self.selector}']"))
85+
return driver.find_elements(*XPath(f"//*[{self._exact_or_not('@role')}]"))
8086

8187

8288
class Text(Locator):
8389
BY = By.TEXT
8490

8591
def find_elements(self, driver: Driver) -> List[WebElement]:
86-
return driver.find_elements(*XPath(f'//*[text() = "{self.selector}"]'))
92+
return driver.find_elements(*XPath(f'//*[{self._exact_or_not("text()")}]'))
8793

8894

8995
class PlaceholderText(Locator):
9096
BY = By.PLACEHOLDER_TEXT
9197

9298
def find_elements(self, driver: Driver) -> List[WebElement]:
93-
return driver.find_elements(*XPath(f'//*[@placeholder = "{self.selector}"]'))
99+
return driver.find_elements(
100+
*XPath(f'//*[{self._exact_or_not("@placeholder")}]')
101+
)
94102

95103

96104
class LabelText(Locator):
97105
BY = By.LABEL_TEXT
98106

99107
def find_elements(self, driver):
100108
labels: WebElement = driver.find_elements(
101-
*XPath(f'//label[text() = "{self.selector}"]')
109+
*XPath(f'//label[{self._exact_or_not("text()")}]')
102110
)
103111
elements = []
104112
for label in labels:
@@ -117,21 +125,23 @@ class AltText(Locator):
117125
BY = By.ALT_TEXT
118126

119127
def find_elements(self, driver: Driver) -> List[WebElement]:
120-
return driver.find_elements(*XPath(f'//*[@alt = "{self.selector}"]'))
128+
return driver.find_elements(*XPath(f'//*[{self._exact_or_not("@alt")}]'))
121129

122130

123131
class Title(Locator):
124132
BY = By.TITLE
125133

126134
def find_elements(self, driver: Driver) -> List[WebElement]:
127-
return driver.find_elements(*XPath(f'//*[@title = "{self.selector}"]'))
135+
return driver.find_elements(*XPath(f'//*[{self._exact_or_not("@title")}]'))
128136

129137

130138
class TestId(Locator):
131139
BY = By.TITLE
132140

133141
def find_elements(self, driver: Driver) -> List[WebElement]:
134-
return driver.find_elements(*XPath(f'//*[@data-testid = "{self.selector}"]'))
142+
return driver.find_elements(
143+
*XPath(f'//*[{self._exact_or_not("@data-testid")}]')
144+
)
135145

136146

137147
class DisplayValue(Locator):
@@ -141,7 +151,9 @@ def find_elements(self, driver: Driver) -> List[WebElement]:
141151
els = driver.find_elements(
142152
*XPath(f"//*[self::input or self::textarea or self::select]")
143153
)
144-
return [el for el in els if el.get_attribute("value") == self.selector]
154+
if self.exact:
155+
return [el for el in els if self.selector == el.get_attribute("value")]
156+
return [el for el in els if self.selector in el.get_attribute("value")]
145157

146158

147159
LocatorType = Union[

selenium_testing_library/screen.py

Lines changed: 116 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -121,156 +121,176 @@ def find_all_by(
121121
raise NoSuchElementException()
122122

123123
# By role
124-
def get_by_role(self, role) -> WebElement:
125-
return self.get_by(locators.Role(role))
124+
def get_by_role(self, role: str, exact: bool = True) -> WebElement:
125+
return self.get_by(locators.Role(role, exact))
126126

127-
def query_by_role(self, role: str) -> Optional[WebElement]:
128-
return self.get_by(locators.Role(role))
127+
def query_by_role(self, role: str, exact: bool = True) -> Optional[WebElement]:
128+
return self.get_by(locators.Role(role, exact))
129129

130-
def find_by_role(self, role: str) -> WebElement:
131-
return self.find_by(locators.Role(role))
130+
def find_by_role(self, role: str, exact: bool = True) -> WebElement:
131+
return self.find_by(locators.Role(role, exact))
132132

133-
def get_all_by_role(self, role) -> List[WebElement]:
134-
return self.get_all_by(locators.Role(role))
133+
def get_all_by_role(self, role: str, exact: bool = True) -> List[WebElement]:
134+
return self.get_all_by(locators.Role(role, exact))
135135

136-
def query_all_by_role(self, role: str) -> List[WebElement]:
137-
return self.query_all_by(locators.Role(role))
136+
def query_all_by_role(self, role: str, exact: bool = True) -> List[WebElement]:
137+
return self.query_all_by(locators.Role(role, exact))
138138

139-
def find_all_by_role(self, role: str) -> List[WebElement]:
140-
return self.find_all_by(locators.Role(role))
139+
def find_all_by_role(self, role: str, exact: bool = True) -> List[WebElement]:
140+
return self.find_all_by(locators.Role(role, exact))
141141

142142
# By text
143-
def get_by_text(self, text: str) -> WebElement:
144-
return self.get_by(locators.Text(text))
143+
def get_by_text(self, text: str, exact: bool = True) -> WebElement:
144+
return self.get_by(locators.Text(text, exact))
145145

146-
def query_by_text(self, text: str) -> Optional[WebElement]:
147-
return self.query_by(locators.Text(text))
146+
def query_by_text(self, text: str, exact: bool = True) -> Optional[WebElement]:
147+
return self.query_by(locators.Text(text, exact))
148148

149-
def find_by_text(self, text: str) -> WebElement:
150-
return self.find_by(locators.Text(text))
149+
def find_by_text(self, text: str, exact: bool = True) -> WebElement:
150+
return self.find_by(locators.Text(text, exact))
151151

152-
def get_all_by_text(self, text: str) -> List[WebElement]:
153-
return self.get_all_by(locators.Text(text))
152+
def get_all_by_text(self, text: str, exact: bool = True) -> List[WebElement]:
153+
return self.get_all_by(locators.Text(text, exact))
154154

155-
def query_all_by_text(self, text: str) -> List[WebElement]:
156-
return self.query_all_by(locators.Text(text))
155+
def query_all_by_text(self, text: str, exact: bool = True) -> List[WebElement]:
156+
return self.query_all_by(locators.Text(text, exact))
157157

158-
def find_all_by_text(self, text: str) -> List[WebElement]:
159-
return self.find_all_by(locators.Text(text))
158+
def find_all_by_text(self, text: str, exact: bool = True) -> List[WebElement]:
159+
return self.find_all_by(locators.Text(text, exact))
160160

161161
# By placeholder
162-
def get_by_placeholder_text(self, value: str) -> WebElement:
163-
return self.get_by(locators.PlaceholderText(value))
162+
def get_by_placeholder_text(self, value: str, exact: bool = True) -> WebElement:
163+
return self.get_by(locators.PlaceholderText(value, exact))
164164

165-
def query_by_placeholder_text(self, value: str) -> Optional[WebElement]:
166-
return self.query_by(locators.PlaceholderText(value))
165+
def query_by_placeholder_text(
166+
self, value: str, exact: bool = True
167+
) -> Optional[WebElement]:
168+
return self.query_by(locators.PlaceholderText(value, exact))
167169

168-
def find_by_placeholder_text(self, value: str) -> WebElement:
169-
return self.find_by(locators.PlaceholderText(value))
170+
def find_by_placeholder_text(self, value: str, exact: bool = True) -> WebElement:
171+
return self.find_by(locators.PlaceholderText(value, exact))
170172

171-
def get_all_by_placeholder_text(self, value: str) -> List[WebElement]:
172-
return self.get_all_by(locators.PlaceholderText(value))
173+
def get_all_by_placeholder_text(
174+
self, value: str, exact: bool = True
175+
) -> List[WebElement]:
176+
return self.get_all_by(locators.PlaceholderText(value, exact))
173177

174-
def query_all_by_placeholder_text(self, value: str) -> List[WebElement]:
175-
return self.query_all_by(locators.PlaceholderText(value))
178+
def query_all_by_placeholder_text(
179+
self, value: str, exact: bool = True
180+
) -> List[WebElement]:
181+
return self.query_all_by(locators.PlaceholderText(value, exact))
176182

177-
def find_all_by_placeholder_text(self, value: str) -> List[WebElement]:
178-
return self.find_all_by(locators.PlaceholderText(value))
183+
def find_all_by_placeholder_text(
184+
self, value: str, exact: bool = True
185+
) -> List[WebElement]:
186+
return self.find_all_by(locators.PlaceholderText(value, exact))
179187

180188
# By label text
181-
def get_by_label_text(self, text: str) -> WebElement:
182-
return self.get_by(locators.LabelText(text))
189+
def get_by_label_text(self, text: str, exact: bool = True) -> WebElement:
190+
return self.get_by(locators.LabelText(text, exact))
183191

184-
def query_by_label_text(self, text: str) -> Optional[WebElement]:
185-
return self.query_by(locators.LabelText(text))
192+
def query_by_label_text(
193+
self, text: str, exact: bool = True
194+
) -> Optional[WebElement]:
195+
return self.query_by(locators.LabelText(text, exact))
186196

187-
def find_by_label_text(self, text: str) -> WebElement:
188-
return self.find_by(locators.LabelText(text))
197+
def find_by_label_text(self, text: str, exact: bool = True) -> WebElement:
198+
return self.find_by(locators.LabelText(text, exact))
189199

190-
def get_all_by_label_text(self, text: str) -> List[WebElement]:
191-
return self.get_all_by(locators.LabelText(text))
200+
def get_all_by_label_text(self, text: str, exact: bool = True) -> List[WebElement]:
201+
return self.get_all_by(locators.LabelText(text, exact))
192202

193-
def query_all_by_label_text(self, text: str) -> List[WebElement]:
194-
return self.query_all_by(locators.LabelText(text))
203+
def query_all_by_label_text(
204+
self, text: str, exact: bool = True
205+
) -> List[WebElement]:
206+
return self.query_all_by(locators.LabelText(text, exact))
195207

196-
def find_all_by_label_text(self, text: str) -> List[WebElement]:
197-
return self.find_all_by(locators.LabelText(text))
208+
def find_all_by_label_text(self, text: str, exact: bool = True) -> List[WebElement]:
209+
return self.find_all_by(locators.LabelText(text, exact))
198210

199211
# By alt text
200-
def get_by_alt_text(self, value: str) -> WebElement:
201-
return self.get_by(locators.AltText(value))
212+
def get_by_alt_text(self, value: str, exact: bool = True) -> WebElement:
213+
return self.get_by(locators.AltText(value, exact))
202214

203-
def query_by_alt_text(self, value: str) -> Optional[WebElement]:
204-
return self.query_by(locators.AltText(value))
215+
def query_by_alt_text(self, value: str, exact: bool = True) -> Optional[WebElement]:
216+
return self.query_by(locators.AltText(value, exact))
205217

206-
def find_by_alt_text(self, value: str) -> WebElement:
207-
return self.find_by(locators.AltText(value))
218+
def find_by_alt_text(self, value: str, exact: bool = True) -> WebElement:
219+
return self.find_by(locators.AltText(value, exact))
208220

209-
def get_all_by_alt_text(self, value: str) -> List[WebElement]:
210-
return self.get_all_by(locators.AltText(value))
221+
def get_all_by_alt_text(self, value: str, exact: bool = True) -> List[WebElement]:
222+
return self.get_all_by(locators.AltText(value, exact))
211223

212-
def query_all_by_alt_text(self, value: str) -> List[WebElement]:
213-
return self.query_all_by(locators.AltText(value))
224+
def query_all_by_alt_text(self, value: str, exact: bool = True) -> List[WebElement]:
225+
return self.query_all_by(locators.AltText(value, exact))
214226

215-
def find_all_by_alt_text(self, value: str) -> List[WebElement]:
216-
return self.find_all_by(locators.AltText(value))
227+
def find_all_by_alt_text(self, value: str, exact: bool = True) -> List[WebElement]:
228+
return self.find_all_by(locators.AltText(value, exact))
217229

218230
# By title
219-
def get_by_title(self, value: str) -> WebElement:
220-
return self.get_by(locators.Title(value))
231+
def get_by_title(self, value: str, exact: bool = True) -> WebElement:
232+
return self.get_by(locators.Title(value, exact))
221233

222-
def query_by_title(self, value: str) -> Optional[WebElement]:
223-
return self.query_by(locators.Title(value))
234+
def query_by_title(self, value: str, exact: bool = True) -> Optional[WebElement]:
235+
return self.query_by(locators.Title(value, exact))
224236

225-
def find_by_title(self, value: str) -> WebElement:
226-
return self.find_by(locators.Title(value))
237+
def find_by_title(self, value: str, exact: bool = True) -> WebElement:
238+
return self.find_by(locators.Title(value, exact))
227239

228-
def get_all_by_title(self, value: str) -> List[WebElement]:
229-
return self.get_all_by(locators.Title(value))
240+
def get_all_by_title(self, value: str, exact: bool = True) -> List[WebElement]:
241+
return self.get_all_by(locators.Title(value, exact))
230242

231-
def query_all_by_title(self, value: str) -> List[WebElement]:
232-
return self.query_all_by(locators.Title(value))
243+
def query_all_by_title(self, value: str, exact: bool = True) -> List[WebElement]:
244+
return self.query_all_by(locators.Title(value, exact))
233245

234-
def find_all_by_title(self, value: str) -> List[WebElement]:
235-
return self.find_all_by(locators.Title(value))
246+
def find_all_by_title(self, value: str, exact: bool = True) -> List[WebElement]:
247+
return self.find_all_by(locators.Title(value, exact))
236248

237249
# By test id
238-
def get_by_test_id(self, value: str) -> WebElement:
239-
return self.get_by(locators.TestId(value))
250+
def get_by_test_id(self, value: str, exact: bool = True) -> WebElement:
251+
return self.get_by(locators.TestId(value, exact))
240252

241-
def query_by_test_id(self, value: str) -> Optional[WebElement]:
242-
return self.query_by(locators.TestId(value))
253+
def query_by_test_id(self, value: str, exact: bool = True) -> Optional[WebElement]:
254+
return self.query_by(locators.TestId(value, exact))
243255

244-
def find_by_test_id(self, value: str) -> WebElement:
245-
return self.find_by(locators.TestId(value))
256+
def find_by_test_id(self, value: str, exact: bool = True) -> WebElement:
257+
return self.find_by(locators.TestId(value, exact))
246258

247-
def get_all_by_test_id(self, value: str) -> List[WebElement]:
248-
return self.get_all_by(locators.TestId(value))
259+
def get_all_by_test_id(self, value: str, exact: bool = True) -> List[WebElement]:
260+
return self.get_all_by(locators.TestId(value, exact))
249261

250-
def query_all_by_test_id(self, value: str) -> List[WebElement]:
251-
return self.query_all_by(locators.TestId(value))
262+
def query_all_by_test_id(self, value: str, exact: bool = True) -> List[WebElement]:
263+
return self.query_all_by(locators.TestId(value, exact))
252264

253-
def find_all_by_test_id(self, value: str) -> List[WebElement]:
254-
return self.find_all_by(locators.TestId(value))
265+
def find_all_by_test_id(self, value: str, exact: bool = True) -> List[WebElement]:
266+
return self.find_all_by(locators.TestId(value, exact))
255267

256268
# By display value
257-
def get_by_display_value(self, value: str) -> WebElement:
258-
return self.get_by(locators.DisplayValue(value))
269+
def get_by_display_value(self, value: str, exact: bool = True) -> WebElement:
270+
return self.get_by(locators.DisplayValue(value, exact))
259271

260-
def query_by_display_value(self, value: str) -> Optional[WebElement]:
261-
return self.query_by(locators.DisplayValue(value))
272+
def query_by_display_value(
273+
self, value: str, exact: bool = True
274+
) -> Optional[WebElement]:
275+
return self.query_by(locators.DisplayValue(value, exact))
262276

263-
def find_by_display_value(self, value: str) -> WebElement:
264-
return self.find_by(locators.DisplayValue(value))
277+
def find_by_display_value(self, value: str, exact: bool = True) -> WebElement:
278+
return self.find_by(locators.DisplayValue(value, exact))
265279

266-
def get_all_by_display_value(self, value: str) -> List[WebElement]:
267-
return self.get_all_by(locators.DisplayValue(value))
280+
def get_all_by_display_value(
281+
self, value: str, exact: bool = True
282+
) -> List[WebElement]:
283+
return self.get_all_by(locators.DisplayValue(value, exact))
268284

269-
def query_all_by_display_value(self, value: str) -> List[WebElement]:
270-
return self.query_all_by(locators.DisplayValue(value))
285+
def query_all_by_display_value(
286+
self, value: str, exact: bool = True
287+
) -> List[WebElement]:
288+
return self.query_all_by(locators.DisplayValue(value, exact))
271289

272-
def find_all_by_display_value(self, value: str) -> List[WebElement]:
273-
return self.find_all_by(locators.DisplayValue(value))
290+
def find_all_by_display_value(
291+
self, value: str, exact: bool = True
292+
) -> List[WebElement]:
293+
return self.find_all_by(locators.DisplayValue(value, exact))
274294

275295
# By css
276296
def get_by_css(self, value: str) -> WebElement:

0 commit comments

Comments
 (0)