247 lines
5.2 KiB
Smalltalk
247 lines
5.2 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
|
|
}
|
|
|
|
{ #category : #'instance creation' }
|
|
WebDriver class >> geckodriver [
|
|
| subproc |
|
|
subproc := OSSUnixSubprocess new
|
|
command: 'geckodriver'.
|
|
[ subproc run ] fork.
|
|
^ WebDriverGeckodriver new
|
|
browser: subproc
|
|
server: '127.0.0.1'
|
|
port: 4444.
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
WebDriver >> atPref: prefKey put: prefVal [
|
|
prefs at: prefKey put: prefVal.
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
WebDriver >> attribute: attr from: element [
|
|
|
|
^ self
|
|
send: { }
|
|
to:
|
|
'session/' , sessionId , '/element/' , element , '/attribute/'
|
|
, attr
|
|
using: #GET
|
|
]
|
|
|
|
{ #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 : #'event handling' }
|
|
WebDriver >> click: elem [
|
|
|
|
self
|
|
send: { }
|
|
to: 'session/' , sessionId , '/element/' , elem , '/click'
|
|
using: #POST
|
|
]
|
|
|
|
{ #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.
|
|
(reply at: #error ifPresent: [ true ] ifAbsent: [ false ])
|
|
ifTrue: [ ^ WDException raise: reply ]
|
|
ifFalse: [ ^ WDElement fromString: 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 isArray
|
|
ifTrue: [
|
|
^ reply collect: [ :elem | WDElement fromString: elem values first ] ]
|
|
ifFalse: [ ^ WDException raise: reply ]
|
|
]
|
|
|
|
{ #category : #navigation }
|
|
WebDriver >> forward [
|
|
|
|
self send: { } to: 'session/' , sessionId , '/forward' using: #POST
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
WebDriver >> property: attr from: element [
|
|
|
|
^ self
|
|
send: { }
|
|
to:
|
|
'session/' , sessionId , '/element/' , element , '/property/'
|
|
, attr
|
|
using: #GET
|
|
]
|
|
|
|
{ #category : #navigation }
|
|
WebDriver >> refresh [
|
|
|
|
self send: { } to: 'session/' , sessionId , '/refresh' using: #POST
|
|
]
|
|
|
|
{ #category : #navigation }
|
|
WebDriver >> send: dict to: url using: method [
|
|
^ self subclassResponsibility.
|
|
]
|
|
|
|
{ #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 >> title [
|
|
|
|
^ self send: { } to: 'session/' , sessionId , '/title' using: #GET
|
|
]
|
|
|
|
{ #category : #'text input' }
|
|
WebDriver >> type: text into: element [
|
|
|
|
self
|
|
send: { (#text -> text) }
|
|
to: 'session/' , sessionId , '/element/' , element , '/value'
|
|
using: #POST
|
|
]
|
|
|
|
{ #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
|
|
]
|