From 25d4aa0c57f6887de1770161bbf12e05bec265db Mon Sep 17 00:00:00 2001 From: Daniel Ziltener Date: Tue, 17 May 2022 20:50:10 +0200 Subject: [PATCH] Graphical nonsense --- src/WebDriver/WDElement.class.st | 45 ++++++++++++- src/WebDriver/WebDriver.class.st | 73 ++++++++++++++++++--- src/WebDriver/WebDriverGeckodriver.class.st | 8 +++ 3 files changed, 114 insertions(+), 12 deletions(-) diff --git a/src/WebDriver/WDElement.class.st b/src/WebDriver/WDElement.class.st index 5737846..f743835 100644 --- a/src/WebDriver/WDElement.class.st +++ b/src/WebDriver/WDElement.class.st @@ -49,8 +49,8 @@ WDElement >> attribute: attr [ WDElement >> attributes [ | script result | script := 'var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;'. - result := driver sendWithSession: { #script -> script . #args -> { 'element-6066-11e4-a52e-4f735466cecf' -> element } asDictionary } - to: 'element/' , element , '/execute/sync' + result := driver sendWithSession: { #script -> script . #args -> {{ 'element-6066-11e4-a52e-4f735466cecf' -> element } asDictionary} } asDictionary + to: 'execute/sync' using: #POST. ^ result. ] @@ -113,6 +113,42 @@ WDElement >> element: anObject [ element := anObject ] +{ #category : #'private - utilities' } +WDElement >> inspectionWDElement [ + + | presenter attrItems attrPresenter screenshotPresenter | + attrItems := OrderedCollection new. + self attributes keysAndValuesDo: [ :aKey :aValue | attrItems add: { aKey -> aValue } ]. + + attrPresenter := SpBoxLayout newTopToBottom + add: (SpLabelPresenter new label: ('Infos about the "{1}" element:' format: {self name}); yourself) + expand: false + fill: false + padding: 5; + add: (SpTablePresenter new + addColumn: (SpStringTableColumn title: 'Attribute' evaluated: [ :anObject | (anObject at: 1) key ]); + addColumn: (SpStringTableColumn title: 'Value' evaluated: [ :anObject | (anObject at: 1) value ]); + items: attrItems; + alternateRowsColor + ) + expand: true + fill: true + padding: 5; + yourself. + + screenshotPresenter := SpBoxLayout newTopToBottom + add: (SpLabelPresenter new label: 'Preview:'; yourself) expand: false fill: false padding: 5; + add: (SpImagePresenter new image: (Form fromBinaryStream: (self screenshot readStream))); + yourself. + + presenter := SpPanedLayout newTopToBottom + add: attrPresenter; + add: screenshotPresenter; + yourself. + presenter := SpPresenter new layout: presenter; yourself. + ^ presenter. +] + { #category : #accessing } WDElement >> isEnabled [ ^ self driver @@ -156,6 +192,11 @@ WDElement >> rect [ using: #GET ] +{ #category : #accessing } +WDElement >> screenshot [ + ^ (driver sendWithSession: '' to: 'element/',element,'/screenshot' using: #GET) base64Decoded. +] + { #category : #accessing } WDElement >> text [ ^ self driver diff --git a/src/WebDriver/WebDriver.class.st b/src/WebDriver/WebDriver.class.st index bb2ed2b..2831442 100644 --- a/src/WebDriver/WebDriver.class.st +++ b/src/WebDriver/WebDriver.class.st @@ -1,13 +1,9 @@ " 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: +I am responsible for dispatching the correct messages to start remotely controlled browsers and send commands to them. -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. +My subclasses implement browser-specific behaviour. Public API and Key Messages @@ -37,7 +33,8 @@ Class { 'server', 'port', 'sessionId', - 'prefs' + 'prefs', + 'capabilities' ], #category : #'WebDriver-Base' } @@ -90,6 +87,11 @@ WebDriver >> browser: brs server: srv port: portnum [ port := portnum. ] +{ #category : #'private - utilities' } +WebDriver >> browserDetails [ + ^ self subclassResponsibility +] + { #category : #'private - utilities' } WebDriver >> constructCapabilities: caps [ @@ -145,6 +147,55 @@ WebDriver >> forward [ self send: { } to: 'session/' , sessionId , '/forward' using: #POST ] +{ #category : #'private - utilities' } +WebDriver >> inspectionWebDriver [ + + | presenter browserInfo | + browserInfo := self browserDetails. + + presenter := SpBoxLayout newTopToBottom + add: (SpLabelPresenter new label: 'Connection Infos'; yourself) expand: false fill: false padding: 5; + add: (SpTablePresenter new + addColumn: (SpStringTableColumn title: 'Key' evaluated: [ :anObject | anObject at: #title ] ); + addColumn: (SpStringTableColumn title: 'Value' evaluated: [ :anObject | anObject at: #text ] ); + items: { + Dictionary new at: #title put: 'Browser'; at: #text put: (browserInfo at: #name); yourself. + Dictionary new at: #title put: 'Driver'; at: #text put: (browserInfo at: #driver); yourself. + Dictionary new at: #title put: 'Address'; at: #text put: ('http://{1}:{2}/' format: {server.port}); yourself. + }) + expand: true + fill: true + padding: 5; + add: (SpLabelPresenter new label: 'Preferences'; yourself) expand: false fill: false padding: 5; + add: (SpTreeTablePresenter new + addColumn: (SpStringTableColumn title: 'Key' evaluated: [ :anObject | anObject key ]); + addColumn: (SpStringTableColumn title: 'Value' evaluated: [ :anObject | anObject value ]); + roots: prefs; + children: [ :anItem | anItem value isDictionary ifTrue: [ anItem value ] ifFalse: [ false ] ]) + expand: true + fill: true + padding: 5; + add: (SpLabelPresenter new label: 'Session Capabilities'; yourself) expand: false fill: false padding: 5; + add: (SpTreeTablePresenter new + addColumn: (SpStringTableColumn title: 'Key' evaluated: [ :anObject | + anObject isDictionary + ifTrue: [ anObject isEmpty ifTrue: [ '' ] ifFalse: [ anObject keys at: 1 ] ] + ifFalse: [ anObject key ] ]); + addColumn: (SpStringTableColumn title: 'Value' evaluated: [ :anObject | + anObject isDictionary ifTrue: [ '' ] ifFalse: [ anObject value ] ]); + roots: (capabilities ifNil: [ { } ] ifNotNil: [ capabilities ] ); + children: [ :anItem | + anItem value isDictionary + ifTrue: [ anItem value isEmpty ifTrue: [ {} ] ifFalse: [ anItem value ] ] + ifFalse: [ {} ] ] ) + expand: true + fill: true + padding: 5 + yourself. + presenter := SpPresenter new layout: presenter; yourself. + ^ presenter. +] + { #category : #'private - utilities' } WebDriver >> postprocessResult: result [ ^ result. @@ -187,20 +238,22 @@ WebDriver >> session [ "Initializes a new WebDriver session." + capabilities := self constructCapabilities: { } asDictionary. sessionId ifNil: [ sessionId := (self - send: (self constructCapabilities: { } asDictionary) + send: capabilities to: 'session' using: #POST) at: #sessionId ]. ^ sessionId ] { #category : #accessing } -WebDriver >> session: capabilities [ +WebDriver >> session: caps [ sessionId ifNotNil: [ ^ self session ] ifNil: [ + capabilities := self constructCapabilities: caps. sessionId := (self - send: (self constructCapabilities: capabilities) + send: capabilities to: 'session' using: #POST) at: #sessionId. ^ sessionId ] diff --git a/src/WebDriver/WebDriverGeckodriver.class.st b/src/WebDriver/WebDriverGeckodriver.class.st index 4cad1a8..e6a15ba 100644 --- a/src/WebDriver/WebDriverGeckodriver.class.st +++ b/src/WebDriver/WebDriverGeckodriver.class.st @@ -25,6 +25,14 @@ WebDriverGeckodriver class >> startWithOptions: options [ port: 4444. ] +{ #category : #'private - utilities' } +WebDriverGeckodriver >> browserDetails [ + ^ Dictionary new + at: #name put: 'Firefox'; + at: #driver put: 'Geckodriver'; + yourself. +] + { #category : #'private - utilities' } WebDriverGeckodriver >> constructCapabilities: caps [