2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Dependencies][Dependencies:4]]
2023-11-09 00:21:49 +00:00
( import r7rs
( chicken base )
( chicken string )
( chicken process )
( chicken gc )
2023-11-24 21:19:20 +00:00
alist-lib ;;Handling alists from JSON objects
2023-11-09 00:21:49 +00:00
base64 ;;decoding screenshot data
2023-11-24 21:19:20 +00:00
coops ;;Object system
2023-11-09 00:21:49 +00:00
http-client ;;API interaction
intarweb ;;Supporting HTTP functionality
medea ;;JSON handling
2023-11-24 21:19:20 +00:00
srfi-34 ;;Exception Handling
srfi-35 ;;Exception Types
uri-common ;;Supporting HTTP functionality
2023-11-09 00:21:49 +00:00
)
;; Dependencies:4 ends here
2023-11-09 00:21:51 +00:00
;; Error Conditions
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; #+name: raft-exception
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::raft-exception][raft-exception]]
( define-condition-type &raft-exception &error raft-exception?
( stacktrace raft-stacktrace )
( data raft-data ) )
;; raft-exception ends here
2023-11-09 00:21:49 +00:00
;; #+name: conditions
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::conditions][conditions]]
( define-condition-type &detached-shadow-root &raft-exception detached-shadow-root? )
( define-condition-type &element-click-intercepted &raft-exception element-click-intercepted? )
( define-condition-type &element-not-interactable &raft-exception element-not-interactable? )
( define-condition-type &insecure-certificate &raft-exception insecure-certificate? )
( define-condition-type &invalid-argument &raft-exception invalid-argument? )
( define-condition-type &invalid-cookie-domain &raft-exception invalid-cookie-domain? )
( define-condition-type &invalid-element-state &raft-exception invalid-element-state? )
( define-condition-type &invalid-selector &raft-exception invalid-selector? )
( define-condition-type &invalid-session-id &raft-exception invalid-session-id? )
( define-condition-type &javascript-error &raft-exception javascript-error? )
( define-condition-type &move-target-out-of-bounds &raft-exception move-target-out-of-bounds? )
( define-condition-type &no-such-alert &raft-exception no-such-alert? )
( define-condition-type &no-such-cookie &raft-exception no-such-cookie? )
( define-condition-type &no-such-element &raft-exception no-such-element? )
( define-condition-type &no-such-frame &raft-exception no-such-frame? )
( define-condition-type &no-such-shadow-root &raft-exception no-such-shadow-root? )
( define-condition-type &no-such-window &raft-exception no-such-window? )
( define-condition-type &script-timeout &raft-exception script-timeout? )
( define-condition-type &session-not-created &raft-exception session-not-created? )
( define-condition-type &stale-element-reference &raft-exception stale-element-reference? )
( define-condition-type &timeout &raft-exception timeout? )
( define-condition-type &unable-to-capture-screen &raft-exception unable-to-capture-screen? )
( define-condition-type &unable-to-set-cookie &raft-exception unable-to-set-cookie? )
( define-condition-type &unexpected-alert-open &raft-exception unexpected-alert-open? )
( define-condition-type &unknown-command &raft-exception unknown-command? )
( define-condition-type &unknown-error &raft-exception unknown-error? )
( define-condition-type &unknown-method &raft-exception unknown-method? )
( define-condition-type &unsupported-operation &raft-exception unsupported-operation? )
( define ( raft-throw data )
2023-11-09 00:21:49 +00:00
( case ( alist-ref data 'error )
( ( "detached shadow root" ) ( raise ( make-condition &detached-shadow-root ( alist-ref data 'stacktrace ) data ) ) )
( ( "element click intercepted" ) ( raise ( make-condition &element-click-intercepted ( alist-ref data 'stacktrace ) data ) ) )
( ( "element not interactable" ) ( raise ( make-condition &element-not-interactable ( alist-ref data 'stacktrace ) data ) ) )
( ( "insecure certificate" ) ( raise ( make-condition &insecure-certificate ( alist-ref data 'stacktrace ) data ) ) )
( ( "invalid argument" ) ( raise ( make-condition &invalid-argument ( alist-ref data 'stacktrace ) data ) ) )
( ( "invalid cookie domain" ) ( raise ( make-condition &invalid-cookie-domain ( alist-ref data 'stacktrace ) data ) ) )
( ( "invalid element state" ) ( raise ( make-condition &invalid-element-state ( alist-ref data 'stacktrace ) data ) ) )
( ( "invalid selector" ) ( raise ( make-condition &invalid-selector ( alist-ref data 'stacktrace ) data ) ) )
( ( "invalid session id" ) ( raise ( make-condition &invalid-session-id ( alist-ref data 'stacktrace ) data ) ) )
( ( "javascript error" ) ( raise ( make-condition &javascript-error ( alist-ref data 'stacktrace ) data ) ) )
( ( "move target out of bounds" ) ( raise ( make-condition &move-target-out-of-bounds ( alist-ref data 'stacktrace ) data ) ) )
( ( "no such alert" ) ( raise ( make-condition &no-such-alert ( alist-ref data 'stacktrace ) data ) ) )
( ( "no such cookie" ) ( raise ( make-condition &no-such-cookie ( alist-ref data 'stacktrace ) data ) ) )
( ( "no such element" ) ( raise ( make-condition &no-such-element ( alist-ref data 'stacktrace ) data ) ) )
( ( "no such frame" ) ( raise ( make-condition &no-such-frame ( alist-ref data 'stacktrace ) data ) ) )
( ( "no such shadow root" ) ( raise ( make-condition &no-such-shadow-root ( alist-ref data 'stacktrace ) data ) ) )
( ( "no such window" ) ( raise ( make-condition &no-such-window ( alist-ref data 'stacktrace ) data ) ) )
( ( "script timeout" ) ( raise ( make-condition &script-timeout ( alist-ref data 'stacktrace ) data ) ) )
( ( "session not created" ) ( raise ( make-condition &session-not-created ( alist-ref data 'stacktrace ) data ) ) )
( ( "stale element reference" ) ( raise ( make-condition &stale-element-reference ( alist-ref data 'stacktrace ) data ) ) )
( ( "timeout" ) ( raise ( make-condition &timeout ( alist-ref data 'stacktrace ) data ) ) )
( ( "unable to capture screen" ) ( raise ( make-condition &unable-to-capture-screen ( alist-ref data 'stacktrace ) data ) ) )
( ( "unable to set cookie" ) ( raise ( make-condition &unable-to-set-cookie ( alist-ref data 'stacktrace ) data ) ) )
( ( "unexpected alert open" ) ( raise ( make-condition &unexpected-alert-open ( alist-ref data 'stacktrace ) data ) ) )
( ( "unknown command" ) ( raise ( make-condition &unknown-command ( alist-ref data 'stacktrace ) data ) ) )
( ( "unknown error" ) ( raise ( make-condition &unknown-error ( alist-ref data 'stacktrace ) data ) ) )
( ( "unknown method" ) ( raise ( make-condition &unknown-method ( alist-ref data 'stacktrace ) data ) ) )
( ( "unsupported operation" ) ( raise ( make-condition &unsupported-operation ( alist-ref data 'stacktrace ) data ) ) )
2023-11-24 21:19:20 +00:00
( else ( raise ( make-condition &raft-exception ( alist-ref data 'stacktrace ) data ) ) )
2023-11-09 00:21:49 +00:00
)
)
;; conditions ends here
2023-11-09 00:21:51 +00:00
;; WebDriver
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; The core element of the library is the ~<Raft>~ class and its subclasses. The class has the following fields:
2023-11-09 00:21:49 +00:00
;; #+name: webdriver-class
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::webdriver-class][webdriver-class]]
( define-class <Raft> ( )
2023-11-09 00:21:49 +00:00
( ( browser #f )
( active? #f )
( browser-pid #f )
( server #f )
( port #f )
( session-id #f )
( prefs #f )
( capabilities #f ) ) )
;; webdriver-class ends here
;; The parent class provides a handful of methods, but does not implement all of them; some are the sole responsibility of the subclass. The ~launch~ method, on the other hand, bears shared responsibility. It sets a finalizer to ensure termination of the web driver process in case the class is disposed of with a still-open driver.
;; #+name: webdriver-basics
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::webdriver-basics][webdriver-basics]]
( define-method ( launch # :after ( instance <Raft> ) options )
2023-11-09 00:21:49 +00:00
( set-finalizer! instance ( lambda ( obj )
( when ( slot-value instance 'active? )
( terminate instance ) ) ) ) )
2023-11-24 21:19:20 +00:00
( define-method ( terminate ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( terminate-session instance )
( process-signal ( slot-value instance 'browser-pid ) )
( set! ( slot-value instance 'browser-pid ) #f )
( set! ( slot-value instance 'active? ) #f ) )
2023-11-24 21:19:20 +00:00
( define-method ( construct-capabilities ( instance <Raft> ) # !optional caps )
2023-11-09 00:21:49 +00:00
( raise 'subclass-responsibility ) )
2023-11-24 21:19:20 +00:00
( define-method ( postprocess-result ( instance <Raft> ) result )
2023-11-09 00:21:49 +00:00
result )
;; webdriver-basics ends here
2023-11-24 21:19:20 +00:00
;; Main initialization is done by calling the ~make-Raft~ procedure with the respective class name and optionally an alist of options.
2023-11-09 00:21:49 +00:00
;; #+name: webdriver-init
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::webdriver-init][webdriver-init]]
( define ( make-Raft browser # !optional options )
2023-11-09 00:21:49 +00:00
( let ( ( instance ( make browser ) ) )
( launch instance options )
( sleep 1 )
instance ) )
;; webdriver-init ends here
2023-11-09 00:21:51 +00:00
;; Geckodriver
2023-11-09 00:21:49 +00:00
;; The Geckodriver is used to control Firefox.
;; #+name: geckodriver-basic
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::geckodriver-basic][geckodriver-basic]]
( define-class <Gecko> ( <Raft> )
2023-11-09 00:21:49 +00:00
( ( browser # :firefox )
( server "127.0.0.1" )
( port 4444 ) ) )
( define-method ( launch ( instance <Gecko> ) options )
( let ( ( pid ( process-run "geckodriver > /dev/null 2>&1" ) ) )
( set! ( slot-value instance 'browser-pid ) pid )
( set! ( slot-value instance 'active? ) #t )
( set! ( slot-value instance 'capabilities ) options ) ) )
;; geckodriver-basic ends here
;; The capabilities object for Geckodriver is of the form ={"capabilities": {...}}=.
;; For more information on capabilities, see https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities.
;; #+name: geckodriver-capabilities
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::geckodriver-capabilities][geckodriver-capabilities]]
2023-11-09 00:21:49 +00:00
( define-method ( construct-capabilities ( instance <Gecko> ) )
( let ( ( caps ( or ( slot-value instance 'capabilities ) ( list ) ) ) )
` ( ( capabilities . , caps ) ) ) )
;; geckodriver-capabilities ends here
;; Sometimes, Geckodriver returns the results of a command in a JSON object with the sole key ="value"=. We have to correct that before returning the data to the user.
;; #+name: geckodriver-postprocess
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::geckodriver-postprocess][geckodriver-postprocess]]
2023-11-09 00:21:49 +00:00
( define-method ( postprocess-result ( instance <Gecko> ) result )
( alist-ref/default result 'value result ) )
;; geckodriver-postprocess ends here
2023-11-09 00:21:51 +00:00
;; Communication
2023-11-09 00:21:49 +00:00
;; Data is sent to the API via a central class method. For convenience, there is a ~send-with-session~ variant that automatically adds the session id.
2023-11-24 21:19:20 +00:00
;; #+name: raft-send
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::raft-send][raft-send]]
( define-method ( send ( instance <Raft> ) data uri method )
2023-11-09 00:21:49 +00:00
( let* ( ( remote ( string-append "http://" ( slot-value instance 'server ) ":" ( ->string ( slot-value instance 'port ) ) "/" ) )
( result ( postprocess-result instance
( with-input-from-request
( make-request # :method method
# :uri ( uri-reference ( string-append remote uri ) )
# :headers ( headers ` ( ( content-type application/json ) ) ) )
( if data ( json->string data ) "" )
read-json ) ) ) )
( if ( and ( list? result ) ( alist-ref/default result 'error #f ) )
2023-11-24 21:19:20 +00:00
( raft-throw result )
2023-11-09 00:21:49 +00:00
result ) ) )
2023-11-24 21:19:20 +00:00
( define-method ( send-with-session ( instance <Raft> ) data uri method )
2023-11-09 00:21:49 +00:00
( send instance data ( string-append "session/" ( slot-value instance 'session-id ) "/" uri ) method ) )
2023-11-24 21:19:20 +00:00
;; raft-send ends here
2023-11-09 00:21:49 +00:00
2023-11-09 00:21:51 +00:00
;; Session management
2023-11-09 00:21:49 +00:00
;; Session management is very simple. There is just one method to initialize a new session. Everything else is handled automatically.
2023-11-24 21:19:20 +00:00
;; #+name: raft-init-session
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::raft-init-session][raft-init-session]]
( define-method ( initialize-session ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( let ( ( result ( send instance ( construct-capabilities instance ) "session" 'POST ) ) )
( set! ( slot-value instance 'session-id ) ( alist-ref result 'sessionId ) ) ) )
2023-11-24 21:19:20 +00:00
;; raft-init-session ends here
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; #+name: raft-term-session
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::raft-term-session][raft-term-session]]
( define-method ( terminate-session ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( when ( slot-value instance 'session-id )
( send instance #f ( string-append "session/" ( slot-value instance 'session-id ) ) 'DELETE ) )
( set! ( slot-value instance 'session-id ) #f ) )
2023-11-24 21:19:20 +00:00
;; raft-term-session ends here
2023-11-09 00:21:49 +00:00
2023-11-09 00:21:51 +00:00
;; API Access Methods
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; #+name: raft-url
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::raft-url][raft-url]]
( define-method ( set-url ( instance <Raft> ) url )
2023-11-09 00:21:49 +00:00
( send-with-session instance ` ( ( url . , url ) ) "url" 'POST ) )
2023-11-24 21:19:20 +00:00
( define-method ( url ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "url" 'GET ) )
2023-11-24 21:19:20 +00:00
;; raft-url ends here
2023-11-09 00:21:49 +00:00
2023-11-24 21:19:20 +00:00
;; #+RESULTS: raft-url-test
2023-11-09 00:21:49 +00:00
;; : -- testing url ---------------------------------------------------------------
;; : Initial state ........................................................ [ PASS]
;; : Navigating to the first website ...................................... [ PASS]
;; : 2 tests completed in 5.247 seconds.
;; : 2 out of 2 (100%) tests passed.
;; : -- done testing url ----------------------------------------------------------
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:3]]
( define-method ( back ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "back" 'POST ) )
;; API Access Methods:3 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:4]]
( define-method ( forward ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "forward" 'POST ) )
;; API Access Methods:4 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:5]]
( define-method ( refresh ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "refresh" 'POST ) )
;; API Access Methods:5 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:6]]
( define-method ( title ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "title" 'GET ) )
;; API Access Methods:6 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:7]]
( define-method ( status ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "status" 'GET ) )
;; API Access Methods:7 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:8]]
( define-method ( source ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "source" 'GET ) )
;; API Access Methods:8 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:9]]
( define-method ( screenshot ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( base64-decode ( send-with-session instance #f "screenshot" 'GET ) ) )
;; API Access Methods:9 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:10]]
( define-method ( print-page ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "print" 'POST ) )
;; API Access Methods:10 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:11]]
( define-method ( execute-async ( instance <Raft> ) script args )
2023-11-09 00:21:49 +00:00
( send-with-session instance ` ( ( script . , script ) ( args . , args ) ) "execute/async" 'POST ) )
;; API Access Methods:11 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*API Access Methods][API Access Methods:12]]
( define-method ( execute-sync ( instance <Raft> ) script args )
2023-11-09 00:21:49 +00:00
( send-with-session instance ` ( ( script . , script ) ( args . , args ) ) "execute/sync" 'POST ) )
;; API Access Methods:12 ends here
2023-11-09 00:21:51 +00:00
;; Timeouts
2023-11-09 00:21:49 +00:00
;; The following timeouts are defined:
;; - =script=: defaults to 30'000, specifies when to interrupt a script that is being evaluated. A nil value implies that scripts should never be interrupted, but instead run indefinitely.
;; - =pageLoad=: defaults to 300'000, provides the timeout limit used to interrupt an explicit navigation attempt.
;; - =implicit=: defaults to 0, specifies a time to wait for the element location strategy to complete when locating an element.
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Timeouts][Timeouts:1]]
( define-class <RaftTimeouts> ( )
2023-11-09 00:21:49 +00:00
( ( script 30000 )
( pageLoad 300000 )
( implicit 0 ) ) )
;; Timeouts:1 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Timeouts][Timeouts:2]]
( define-method ( extract ( instance <RaftTimeouts> ) )
2023-11-09 00:21:49 +00:00
` ( ( script . , ( slot-value instance 'script ) )
( pageLoad . , ( slot-value instance 'pageLoad ) )
( implicit . , ( slot-value instance 'implicit ) ) ) )
;; Timeouts:2 ends here
2023-11-09 00:21:51 +00:00
;; Setting and getting timeouts
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Setting and getting timeouts][Setting and getting timeouts:1]]
( define-method ( set-timeouts ( instance <Raft> ) ( timeouts <RaftTimeouts> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance ( extract timeouts ) "timeouts" 'POST ) )
2023-11-24 21:19:20 +00:00
( define-method ( timeouts ( instance <Raft> ) )
2023-11-09 00:21:49 +00:00
( let ( ( result ( send-with-session instance #f "timeouts" 'GET ) ) )
2023-11-24 21:19:20 +00:00
( make <RaftTimeouts>
2023-11-09 00:21:49 +00:00
'script ( alist-ref result 'script )
'pageLoad ( alist-ref result 'pageLoad )
'implicit ( alist-ref result 'implicit ) ) ) )
;; Setting and getting timeouts:1 ends here
2023-11-09 00:21:51 +00:00
;; Element Class
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Element Class][Element Class:1]]
( define-class <RaftElement> ( )
2023-11-09 00:21:49 +00:00
( ( driver #f )
( element #f ) ) )
;; Element Class:1 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Element Class][Element Class:2]]
( define-method ( send-with-session ( instance <RaftElement> ) data uri method )
2023-11-09 00:21:49 +00:00
( send-with-session ( slot-value instance 'driver ) data
( string-append "element/" ( slot-value instance 'element ) "/" uri )
method ) )
;; Element Class:2 ends here
2023-11-09 00:21:51 +00:00
;; Location Strategies
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Location Strategies][Location Strategies:1]]
2023-11-09 00:21:49 +00:00
( define css-selector "css selector" )
( define link-text "link text" )
( define partial-link-text "partial link text" )
( define tag-name "tag name" )
( define xpath "xpath" )
;; Location Strategies:1 ends here
2023-11-09 00:21:51 +00:00
;; Accessor Methods
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Accessor Methods][Accessor Methods:1]]
( define-method ( find-element ( instance <Raft> ) strategy selector )
2023-11-09 00:21:49 +00:00
( let ( ( result ( send-with-session instance ` ( ( using . , strategy ) ( value . , selector ) ) "element" 'POST ) ) )
2023-11-24 21:19:20 +00:00
( make <RaftElement> 'driver instance 'element ( car ( alist-values result ) ) ) ) )
2023-11-09 00:21:49 +00:00
;; Accessor Methods:1 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Accessor Methods][Accessor Methods:2]]
( define-method ( find-elements ( instance <Raft> ) strategy selector )
2023-11-09 00:21:49 +00:00
( let ( ( result ( send-with-session instance ` ( ( using . , strategy ) ( value . , selector ) ) "elements" 'POST ) ) )
( map
( lambda ( elem )
2023-11-24 21:19:20 +00:00
( make <RaftElement> 'driver instance 'element ( car ( alist-values elem ) ) ) )
2023-11-09 00:21:49 +00:00
result ) ) )
;; Accessor Methods:2 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Accessor Methods][Accessor Methods:3]]
( define-method ( find-element ( instance <RaftElement> ) strategy selector )
2023-11-09 00:21:49 +00:00
( let ( ( result ( send-with-session instance ` ( ( using . , strategy ) ( value . , selector ) ) "element" 'POST ) ) )
2023-11-24 21:19:20 +00:00
( make <RaftElement> 'driver ( slot-value instance 'driver ) 'element ( car ( alist-values result ) ) ) ) )
2023-11-09 00:21:49 +00:00
;; Accessor Methods:3 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Accessor Methods][Accessor Methods:4]]
( define-method ( find-elements ( instance <RaftElement> ) strategy selector )
2023-11-09 00:21:49 +00:00
( let ( ( result ( send-with-session instance ` ( ( using . , strategy ) ( value . , selector ) ) "elements" 'POST ) ) )
( map
( lambda ( elem )
2023-11-24 21:19:20 +00:00
( make <RaftElement> 'driver ( slot-value instance 'driver ) 'element ( car ( alist-values elem ) ) ) )
2023-11-09 00:21:49 +00:00
result ) ) )
;; Accessor Methods:4 ends here
2023-11-09 00:21:51 +00:00
;; Working with Elements
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:1]]
( define-method ( attribute ( instance <RaftElement> ) attribute )
2023-11-09 00:21:49 +00:00
( let ( ( result ( send-with-session instance #f
( string-append "attribute/" attribute )
'GET ) ) )
( if ( equal? "true" result )
#t
result ) ) )
;; Working with Elements:1 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:2]]
( define-method ( property ( instance <RaftElement> ) property )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f ( string-append "property/" property ) 'GET ) )
;; Working with Elements:2 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:3]]
( define-method ( clear ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "clear" 'POST ) )
;; Working with Elements:3 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:4]]
( define-method ( click ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "click" 'POST ) )
;; Working with Elements:4 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:5]]
( define-method ( computed-label ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "computedlabel" 'GET ) )
;; Working with Elements:5 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:6]]
( define-method ( computed-role ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "computedrole" 'GET ) )
;; Working with Elements:6 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:7]]
( define-method ( enabled? ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "enabled" 'GET ) )
;; Working with Elements:7 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:8]]
( define-method ( selected? ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "selected" 'GET ) )
;; Working with Elements:8 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:9]]
( define-method ( name ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "name" 'GET ) )
;; Working with Elements:9 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:10]]
( define-method ( rect ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "rect" 'GET ) )
;; Working with Elements:10 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:11]]
( define-method ( screenshot ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( base64-decode ( send-with-session instance #f "screenshot" 'GET ) ) )
;; Working with Elements:11 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:12]]
( define-method ( text ( instance <RaftElement> ) )
2023-11-09 00:21:49 +00:00
( send-with-session instance #f "text" 'GET ) )
;; Working with Elements:12 ends here
2023-11-24 21:19:20 +00:00
;; [[file:raft.org::*Working with Elements][Working with Elements:13]]
( define-method ( set-value ( instance <RaftElement> ) value )
2023-11-09 00:21:49 +00:00
( send-with-session instance ` ( ( text . , value ) ) "value" 'POST ) )
;; Working with Elements:13 ends here