Marionette
(require marionette) | package: marionette-lib |
1 Introduction
Marionette lets you control the Firefox web browser via the Marionette Protocol. This is the same interface used by Selenium, via geckodriver.
To use this library, you need to have a running Firefox instance with the marionette protocol enabled. To do this, all you have to do is run the firefox binary with the -marionette flag.
2 Examples
Here are some simple examples of using marionette. The first saves a PNG file containing an image of the current racket-lang.org webpage:
> (require marionette racket/file) >
> (define data (call-with-marionette/browser/page! (lambda (p) (page-goto! p "https://racket-lang.org") (call-with-page-screenshot! p values)))) >
> (define filename (make-temporary-file "~a.png")) >
> (with-output-to-file filename #:exists 'truncate/replace (lambda () (write-bytes data))) 791931
> > (printf "filename of page screenshot: ~v\n" (path->string filename)) filename of page screenshot: "/var/folders/6s/8kt06x656dddy8z5y0jmf_fc0000gn/T/16266838661626683866996.png"
This next example dowloads the HTML content of a password-protected web page:
#lang racket (require marionette) (define username "zipnarg") (define nextcatalog-csc-minor-url "https://nextcatalog-admin.calpoly.edu/collegesandprograms/\ collegeofengineering/computersciencesoftwareengineering/\ computerscienceminor/") (define profile-path (build-path "/Users/zipnarg/Library/Application Support/" "Firefox/Profiles/s9y75gtr.wazoo")) (define content (call-with-marionette/browser/page! #:profile profile-path (λ (page) (page-goto! page nextcatalog-csc-minor-url) (printf "ready? ~v\n" (page-loaded? page)) (printf "page title: ~v\n" (page-title page)) (let () (define username-elt (page-query-selector! page "#username")) (cond [username-elt (element-type! username-elt username)] [else (error 'login "couldn't find username field.")])) (let () (define password-elt (page-query-selector! page "#password")) (cond [password-elt (printf "password: ") (define str (read-line)) (element-type! password-elt str)] [else (error 'login "couldn't find password field.")])) (let () (define form-button (page-query-selector! page ".form-button")) (cond [form-button (element-click! form-button)] [else (error 'login "couldn't find login button.")])) ;; wait until the page is ready and the title is no longer ;; that of the login page (let loop () (define loaded? (page-loaded? page)) (cond [loaded? (define title (page-title page)) (cond [(equal? title "Cal Poly Web Login Service") (printf "still login screen title, waiting...\n") (sleep 1) (loop)] [else 'ok])] [else (printf "not ready, waiting...\n") (sleep 1) (loop)])) (printf "final page title: ~v\n" (page-title page)) (page-content page))))
3 Reference
procedure
(start-marionette! [ #:command command #:profile profile #:user.js user.js #:port port #:safe-mode? safe-mode? #:headless? headless? #:timeout timeout]) → (-> void?) command : absolute-path? = "/usr/local/bin/firefox" profile : (or/c #f absolute-path?) = #f
user.js : (or/c #f (hash/c string? (or/c boolean? number? string?))) = #f port : (or/c #f (integer-in 1 65535)) = #f safe-mode? : boolean? = #t headless? : boolean? = #t timeout : exact-nonnegative-integer? = 5
procedure
(call-with-marionette! p) → any
p : (-> any)
procedure
p : (-> browser? any)
procedure
p : (-> page? any)
The command argument controls the path to the firefox binary. If not provided, the system PATH is searched along with the /Applications folder on macOS.
When the #:profile argument is #f, a temporary path si created for the profile and it it subsequently removed when the browser is stopped.
When the #:port argument is provided, the profile will be modified to instruct the marionette server to listen on that port.
When the #:user.js argument is provided, the contents of the hash will be set as preferences in the profile.
The call-with-marionette! procedure accepts the same keyword arguments that start-marionette! does. It starts the browser, applies its p argument then immediately stops the browser.
The call-with-marionette/browser! procedure composes call-with-marionette! and call-with-browser! together. Keyword arguments are passed through to start-marionette!.
The call-with-marionette/browser/page! procedure composes call-with-marionette/browser! and call-with-page! together. Keyword arguments are passed through to start-marionette!.
procedure
(call-with-browser! p [ #:host host #:port port #:capabilities capabilities]) → any p : (-> browser? any) host : non-empty-string? = "127.0.0.1" port : (integer-in 1 65535) = 2828 capabilities : capabilities? = (make-capabilities)
3.1 Browser
Browsers represent a connection to a marionette-driven instance of Firefox. Browsers are not thread-safe, nor is it safe to interleave commands against the same marionette server. If you need concurrency, then create multiple marionettes and control them separately.
procedure
(browser-connect! [ #:host host #:port port #:capabilities capabilities]) → browser? host : non-empty-string? = "127.0.0.1" port : (integer-in 1 65535) = 2828 capabilities : capabilities? = (make-capabilities)
procedure
(browser-disconnect! b) → void?
b : browser?
procedure
(browser-timeouts b) → timeouts?
b : browser?
procedure
(set-browser-timeouts! b t) → void?
b : browser? t : timeouts?
procedure
(browser-viewport-size b) →
exact-nonnegative-integer? exact-nonnegative-integer? b : browser?
procedure
(set-browser-viewport-size! b w h) → void?
b : browser? w : exact-nonnegative-integer? h : exact-nonnegative-integer?
procedure
(make-browser-page! b) → page?
b : browser?
procedure
b : browser?
procedure
(browser-pages b) → (listof page?)
b : browser?
procedure
(browser-focus! b p) → void?
b : browser? p : page?
3.2 Page
procedure
(page-close! p) → void?
p : page?
procedure
(page-refresh! p) → void?
p : page?
procedure
(page-go-back! p) → void?
p : page?
procedure
(page-go-forward! p) → void?
p : page?
procedure
(page-execute-async! p s arg ...) → jsexpr?
p : page? s : string? arg : any/c
procedure
(page-interactive? p) → boolean?
p : page?
procedure
(page-loaded? p) → boolean?
p : page?
procedure
(page-content p) → string?
p : page?
procedure
(set-page-content! p s) → void?
p : page? s : string?
procedure
(page-wait-for! p selector [ #:timeout timeout #:visible? visible?]) → (or/c #f element?) p : page? selector : non-empty-string? timeout : (and/c real? (not/c negative?)) = 30 visible? : boolean? = #t
procedure
(page-query-selector! p selector) → (or/c #f element?)
p : page? selector : non-empty-string?
procedure
(page-query-selector-all! p selector) → (listof element?)
p : page? selector : non-empty-string?
value
procedure
(page-cookies p) → (listof cookie/c)
p : page?
procedure
(page-add-cookie! p c) → void?
p : page? c : cookie/c
procedure
p : page?
procedure
(page-delete-cookie! p name) → void?
p : page? name : string?
procedure
(page-alert-text p) → string?
p : page?
procedure
(page-alert-accept! p) → void?
p : page?
procedure
(page-alert-dismiss! p) → void?
p : page?
procedure
(page-alert-type! p text) → void?
p : page? text : string?
procedure
(page-switch-to-frame! p e) → void?
p : page? e : element?
procedure
p : page?
procedure
(call-with-page-screenshot! page proc [ #:full? full?]) → any page : page? proc : (-> bytes? any) full? : boolean? = #t
procedure
(page-change-evt page) → (evt/c void?)
page : page?
Added in version 1.4 of package marionette-lib.
3.3 Element
Elements represent individual elements on a specific page. They are only valid for as long as the page they were queried from active. That is, if you query an element and then navigate off the page you got it from, it becomes invalid.
procedure
(element-click! e) → void?
e : element?
procedure
(element-clear! e) → void?
e : element?
procedure
(element-type! e text) → void
e : element? text : string?
procedure
(element-query-selector! e selector) → (or/c #f element?)
e : element? selector : non-empty-string?
procedure
(element-query-selector-all! e selector) → (listof element?)
e : element? selector : non-empty-string?
procedure
(element-enabled? e) → boolean?
e : element?
procedure
(element-selected? e) → boolean?
e : element?
procedure
(element-visible? e) → boolean?
e : element?
procedure
(element-tag e) → string?
e : element?
procedure
(element-text e) → string?
e : element?
procedure
(element-rect e) → rect?
e : element?
procedure
(element-attribute e name) → (or/c #f string?)
e : element? name : string?
procedure
(element-property e name) → (or/c #f string?)
e : element? name : string?
struct
(struct rect (x y w h) #:extra-constructor-name make-rect) x : real? y : real? w : real? h : real?
3.4 Capabilities
value
page-load-strategy/c : (or/c 'none 'eager 'normal)
value
unhandled-prompt-behavior/c :
(or/c 'dismiss 'dismiss-and-notify 'accept 'accept-and-notify 'ignore)
struct
(struct capabilities ( timeouts page-load-strategy unhandled-prompt-behavior accept-insecure-certs?)) timeouts : timeouts? page-load-strategy : page-load-strategy/c unhandled-prompt-behavior : unhandled-prompt-behavior/c accept-insecure-certs? : boolean?
procedure
(make-capabilities [ #:timeouts timeouts #:page-load-strategy page-load-strategy #:unhandled-prompt-behavior unhandled-prompt-behavior #:accept-insecure-certs? accept-insecure-certs?]) → capabilities? timeouts : timeouts? = (make-timeouts) page-load-strategy : page-load-strategy/c = 'normal
unhandled-prompt-behavior : unhandled-prompt-behavior/c = 'dismiss-and-notify accept-insecure-certs? : boolean? = #f
3.5 Timeouts
struct
script : exact-nonnegative-integer? page-load : exact-nonnegative-integer? implicit : exact-nonnegative-integer?
procedure
(make-timeouts [ #:script script #:page-load page-load #:implicit implicit]) → timeouts? script : exact-nonnegative-integer? = 30000 page-load : exact-nonnegative-integer? = 300000 implicit : exact-nonnegative-integer? = 0
3.6 Keys
(require marionette/key) | package: marionette-lib |
This module provides bindings for special control characters that can be typed into an element or alert. Some examples:
value
value
value
value
value
value
value
value
(require marionette/key) (map car (call-with-values (lambda () (module->exports 'marionette/key)) (compose1 cdaar list)))
Added in version 1.3 of package marionette-lib.