1 module selenium.session; 2 3 import selenium.api; 4 import std.stdio; 5 import vibe.data.json; 6 7 8 auto findOneIn(immutable ElementLocator locator, immutable SeleniumSession session) { 9 return session.findOne(locator); 10 } 11 12 auto findMany(immutable ElementLocator locator, immutable SeleniumSession session) { 13 return session.findMany(locator); 14 } 15 16 immutable class SeleniumSession 17 { 18 SeleniumApi api; 19 20 this(string serverUrl, Capabilities desiredCapabilities, 21 Capabilities requiredCapabilities = Capabilities(), Capabilities session = Capabilities()) 22 { 23 auto connector = new SeleniumApiConnector(serverUrl, 24 desiredCapabilities, requiredCapabilities, session); 25 api = connector.api; 26 } 27 28 @property 29 { 30 immutable(SeleniumWindow) currentWindow() 31 { 32 return new immutable SeleniumWindow(api, this); 33 } 34 35 immutable(SeleniumNavigation) navigation() 36 { 37 return new immutable SeleniumNavigation(api, this); 38 } 39 40 immutable(SeleniumCookie) cookie() 41 { 42 return new immutable SeleniumCookie(api, this); 43 } 44 45 auto windowHandles() 46 { 47 return api.windowHandles; 48 } 49 } 50 51 immutable(Element) findOne(immutable ElementLocator locator) 52 { 53 return Element.findOne(api, locator); 54 } 55 56 immutable(Element)[] findMany(immutable ElementLocator locator) 57 { 58 return Element.findMany(api, locator); 59 } 60 61 immutable(Element) getActiveElement() 62 { 63 return Element.getActive(api); 64 } 65 66 auto frame(string id) 67 { 68 api.frame(id); 69 return this; 70 } 71 72 auto frame(long id) 73 { 74 api.frame(id); 75 return this; 76 } 77 78 auto frame(WebElement element) 79 { 80 api.frame(element); 81 return this; 82 } 83 84 auto frameParent() 85 { 86 api.frameParent; 87 return this; 88 } 89 90 void close() 91 { 92 api.connection.disconnect; 93 } 94 } 95 96 class SeleniumCookie 97 { 98 immutable 99 { 100 SeleniumApi api; 101 SeleniumSession parent; 102 } 103 104 this(immutable SeleniumApi api, immutable SeleniumSession parent) immutable 105 { 106 this.api = api; 107 this.parent = parent; 108 } 109 110 @property immutable 111 { 112 auto all() { 113 return api.cookie; 114 } 115 116 auto set(string name, string value) { 117 api.setCookie(Cookie(name, value)); 118 return parent; 119 } 120 121 auto set(Cookie cookie) { 122 api.setCookie(cookie); 123 return parent; 124 } 125 126 auto deleteAll() { 127 api.deleteAllCookies(); 128 return parent; 129 } 130 131 auto deleteByName(string name) { 132 api.deleteCookie(name); 133 return parent; 134 } 135 } 136 } 137 138 immutable class SeleniumNavigation 139 { 140 immutable 141 { 142 SeleniumApi api; 143 SeleniumSession parent; 144 } 145 146 this(immutable SeleniumApi api, immutable SeleniumSession parent) 147 { 148 this.api = api; 149 this.parent = parent; 150 } 151 152 @property 153 { 154 auto url(string url) 155 { 156 api.url(url); 157 return parent; 158 } 159 160 auto url() 161 { 162 return api.url; 163 } 164 165 auto forward() 166 { 167 api.forward; 168 return parent; 169 } 170 171 auto back() 172 { 173 api.back; 174 return parent; 175 } 176 177 auto refresh() 178 { 179 api.refresh; 180 return parent; 181 } 182 } 183 } 184 185 immutable class SeleniumWindow 186 { 187 SeleniumApi api; 188 SeleniumSession parent; 189 190 this(immutable SeleniumApi api, immutable SeleniumSession parent) 191 { 192 this.api = api; 193 this.parent = parent; 194 } 195 196 immutable 197 { 198 auto select(string name) 199 { 200 api.selectWindow(name); 201 return parent; 202 } 203 204 auto handle() 205 { 206 return api.windowHandle; 207 } 208 209 auto size() 210 { 211 return api.windowSize; 212 } 213 214 auto size(Size value) 215 { 216 api.windowSize(value); 217 return parent; 218 } 219 220 auto maximize() 221 { 222 api.windowMaximize; 223 return parent; 224 } 225 226 auto screenshot() 227 { 228 return api.screenshot; 229 } 230 231 auto close() 232 { 233 api.windowClose; 234 return parent; 235 } 236 237 auto source() 238 { 239 return api.source; 240 } 241 242 auto title() 243 { 244 return api.title; 245 } 246 247 auto execute(T = string)(string script, Json args = Json.emptyArray) 248 { 249 return api.execute!T(script, args); 250 } 251 252 auto executeAsync(T = string)(string script, Json args = Json.emptyArray) 253 { 254 return api.executeAsync!T(script, args); 255 } 256 } 257 } 258 259 @("Session currentWindow") 260 unittest 261 { 262 auto session = new immutable SeleniumSession("http://127.0.0.1:4444/wd/hub", Capabilities.chrome); 263 264 session.currentWindow.size = Size(400, 500); 265 assert(session.currentWindow.size == Size(400, 500)); 266 267 session.currentWindow.maximize; 268 269 session.currentWindow.screenshot; 270 session.currentWindow.source; 271 session.currentWindow.title; 272 273 session.currentWindow.close; 274 275 session.close; 276 } 277 278 class Element 279 { 280 alias opEquals = Object.opEquals; 281 282 private immutable 283 { 284 SeleniumApi api; 285 WebElement element; 286 } 287 288 this(immutable SeleniumApi api, immutable WebElement element) immutable 289 { 290 this.api = api; 291 this.element = element; 292 } 293 294 static 295 { 296 immutable(Element) findOne(immutable SeleniumApi api, immutable ElementLocator locator) 297 { 298 return new immutable Element(api, api.element(locator)); 299 } 300 301 immutable(Element)[] findMany(immutable SeleniumApi api, immutable ElementLocator locator) 302 { 303 immutable(Element)[] elements; 304 305 foreach (webElement; api.elements(locator)) 306 { 307 elements ~= new immutable Element(api, webElement); 308 } 309 310 return elements; 311 } 312 313 immutable(Element) getActive(immutable SeleniumApi api) 314 { 315 return new immutable Element(api, api.activeElement); 316 } 317 318 void sendKeysToActive(immutable SeleniumApi api, const string[] value) 319 { 320 api.sendKeysToActiveElement(value); 321 } 322 } 323 324 inout 325 { 326 immutable(Element) findOne(ElementLocator locator) 327 { 328 return new immutable Element(api, api.elementFromElement(element.ELEMENT, locator)); 329 } 330 331 immutable(Element)[] findMany(ElementLocator locator) 332 { 333 immutable(Element)[] elements; 334 335 foreach (webElement; api.elementsFromElement(element.ELEMENT, locator)) 336 { 337 elements ~= new immutable Element(api, webElement); 338 } 339 340 return elements; 341 } 342 343 inout(Element) click() 344 { 345 api.clickElement(element.ELEMENT); 346 347 return this; 348 } 349 350 inout(Element) submit() 351 { 352 api.submitElement(element.ELEMENT); 353 return this; 354 } 355 356 inout(Element) sendKeys(string[] value) 357 { 358 api.sendKeys(element.ELEMENT, value); 359 return this; 360 } 361 362 inout(Element) sendKeys(string value) 363 { 364 return sendKeys([value]); 365 } 366 367 inout(Element) clear() 368 { 369 api.clearElementValue(element.ELEMENT); 370 return this; 371 } 372 373 @property 374 { 375 string text() 376 { 377 return api.elementText(element.ELEMENT); 378 } 379 380 string name() 381 { 382 return api.elementName(element.ELEMENT); 383 } 384 385 bool isSelected() 386 { 387 return api.elementSelected(element.ELEMENT); 388 } 389 390 bool isEnabled() 391 { 392 return api.elementSelected(element.ELEMENT); 393 } 394 395 bool isDisplayed() 396 { 397 return api.elementDisplayed(element.ELEMENT); 398 } 399 400 Position position() 401 { 402 return api.elementLocation(element.ELEMENT); 403 } 404 405 Position positionInView() 406 { 407 return api.elementLocationInView(element.ELEMENT); 408 } 409 410 Size size() 411 { 412 return api.elementSize(element.ELEMENT); 413 } 414 415 string seleniumId() inout 416 { 417 return element.ELEMENT; 418 } 419 } 420 421 string attribute(string name) 422 { 423 return api.elementValue(element.ELEMENT, name); 424 } 425 426 string elementCssPropertyName(string name) 427 { 428 return api.elementValue(element.ELEMENT, name); 429 } 430 431 bool opEquals(ref Element other) const 432 { 433 return api.elementEqualsOther(element.ELEMENT, other.seleniumId); 434 } 435 436 bool opEquals(Element other) const 437 { 438 return api.elementEqualsOther(element.ELEMENT, other.seleniumId); 439 } 440 } 441 } 442 443 @("Session find one element") 444 unittest 445 { 446 auto session = new immutable SeleniumSession("http://127.0.0.1:4444/wd/hub", Capabilities.chrome); 447 session.navigation.url("https://www.amazon.com/All-Light-We-Cannot-See/dp/1476746583/"); 448 449 session.findOne(ElementLocator(LocatorStrategy.ClassName, "contributorNameID")).click; 450 451 assert(session.navigation.url 452 == "https://www.amazon.com/Anthony-Doerr/e/B000APOX62/ref=dp_byline_cont_book_1"); 453 454 session.close; 455 } 456 457 @("Session find many elements") 458 unittest 459 { 460 auto session = new immutable SeleniumSession("http://127.0.0.1:4444/wd/hub", Capabilities.chrome); 461 session.navigation.url("https://www.amazon.com/All-Light-We-Cannot-See/dp/1476746583/"); 462 463 assert(session.findMany(ElementLocator(LocatorStrategy.TagName, "img")).length > 0); 464 465 session.close; 466 }