WebDriver/src/WebDriver/WebDriver.class.st

265 lines
5.9 KiB
Smalltalk

"
I am a cleanroom implementation of the [W3C WebDriver protocol](https://w3c.github.io/webdriver/).
Please comment me using the following template inspired by Class Responsibility Collaborator (CRC) design:
For the Class part: State a one line summary. For example, ""I represent a paragraph of text"".
For the Responsibility part: Three sentences about my main responsibilities - what I do, what I know.
For the Collaborators Part: State my main collaborators and one line about how I interact with them.
Public API and Key Messages
- message one
- message two
- (for bonus points) how to create instances.
One simple example is simply gorgeous.
Internal Representation and Key Implementation Points.
Instance Variables
browser: <Object>
optionsName: <Object>
port: <Object>
server: <Object>
sessionId: <Object>
Implementation Points
"
Class {
#name : #WebDriver,
#superclass : #Object,
#instVars : [
'browser',
'server',
'port',
'sessionId',
'prefs'
],
#category : #'WebDriver-Base'
}
{ #category : #testing }
WebDriver class >> matchesBrowserType: browserType [
^ self subclassResponsibility.
]
{ #category : #accessing }
WebDriver class >> start: browserType [
| emptyOpts |
emptyOpts := Dictionary new.
^ self start: browserType with: emptyOpts.
]
{ #category : #'instance creation' }
WebDriver class >> start: browserType with: options [
"comment stating purpose of class-side method"
"scope: class-variables & class-instance-variables"
| matchingClass |
matchingClass := self subclasses
detect: [ :operationClass | operationClass matchesBrowserType: browserType ]
ifNone: [ self ].
^ matchingClass startWithOptions: options.
]
{ #category : #'instance creation' }
WebDriver class >> startWithOptions: options [
^ self subclassResponsibility.
]
{ #category : #accessing }
WebDriver >> atPref: prefKey put: prefVal [
prefs at: prefKey put: prefVal.
]
{ #category : #navigation }
WebDriver >> back [
self send: { } to: 'session/' , sessionId , '/back' using: #POST
]
{ #category : #initialization }
WebDriver >> browser: brs server: srv port: portnum [
browser := brs.
server := srv.
port := portnum.
]
{ #category : #'private - utilities' }
WebDriver >> constructCapabilities: caps [
self subclassResponsibility
]
{ #category : #finalization }
WebDriver >> deleteSession [
"Deletes the session."
self send: { } to: 'session/' , sessionId using: #DELETE
]
{ #category : #finalization }
WebDriver >> finalize [
browser terminate.
super finalize
]
{ #category : #accessing }
WebDriver >> findElement: elemSelector using: locStrategy [
| reply |
reply := self
send: {
(#using -> locStrategy).
(#value -> elemSelector) }
to: 'session/' , sessionId , '/element'
using: #POST.
^ WDElement new
driver: self;
element: reply values first.
]
{ #category : #accessing }
WebDriver >> findElements: elemSelector using: locStrategy [
| reply |
reply := self
send: {
(#using -> locStrategy).
(#value -> elemSelector) }
to: 'session/' , sessionId , '/elements'
using: #POST.
^ reply collect: [ :elem | WDElement new driver: self; element: elem values first. ]
]
{ #category : #navigation }
WebDriver >> forward [
self send: { } to: 'session/' , sessionId , '/forward' using: #POST
]
{ #category : #'private - utilities' }
WebDriver >> postprocessResult: result [
^ result.
]
{ #category : #navigation }
WebDriver >> refresh [
self send: { } to: 'session/' , sessionId , '/refresh' using: #POST
]
{ #category : #'private - utilities' }
WebDriver >> send: dict to: url using: method [
|result|
result := nil.
ZnClient new
host: server;
port: port;
path: url;
contents: (NeoJSONWriter toString: dict asDictionary);
contentType: ZnMimeType applicationJson;
method: method;
contentReader: [ :entity |
result := (NeoJSONReader on: (entity contents) readStream) propertyNamesAsSymbols: true; next.
result := self postprocessResult: result.
(result keys contains: #error) ifTrue: [ WDException raise: result ].
];
execute.
^result.
]
{ #category : #'private - utilities' }
WebDriver >> sendWithSession: dict to: url using: method [
^ self send: dict to: '/session/' , sessionId , '/' , url using: method
]
{ #category : #accessing }
WebDriver >> session [
"Initializes a new WebDriver session."
sessionId ifNil: [
sessionId := (self
send: (self constructCapabilities: { } asDictionary)
to: 'session'
using: #POST) at: #sessionId ].
^ sessionId
]
{ #category : #accessing }
WebDriver >> session: capabilities [
sessionId ifNotNil: [ ^ self session ] ifNil: [
sessionId := (self
send: (self constructCapabilities: capabilities)
to: 'session'
using: #POST) at: #sessionId.
^ sessionId ]
]
{ #category : #accessing }
WebDriver >> source [
^ (self
send: { }
to:
'session/' , sessionId , '/source'
using: #GET)
]
{ #category : #accessing }
WebDriver >> status [
^ self send: { } to: 'status' using: #GET
]
{ #category : #accessing }
WebDriver >> timeouts [
| toutdata |
toutdata := self send: { } to: 'session/',sessionId,'/timeouts' using: #GET.
^ WDTimeouts new
script: (toutdata at: #script);
pageLoad: (toutdata at: #pageLoad);
implicit: (toutdata at: #implicit).
]
{ #category : #accessing }
WebDriver >> timeouts: timeouts [
self
send: timeouts extract
to: 'session/' , sessionId , 'timeouts'
using: #POST
]
{ #category : #accessing }
WebDriver >> title [
^ self send: { } to: 'session/' , sessionId , '/title' using: #GET
]
{ #category : #accessing }
WebDriver >> url [
^ self send: { } to: 'session/' , sessionId , '/url' using: #GET
]
{ #category : #navigation }
WebDriver >> url: url [
"Navigates the browser to the given URL."
self
send: { (#url -> url) }
to: 'session/' , sessionId , '/url'
using: #POST
]