Skip to content

Commit

Permalink
core: add page-change-evt
Browse files Browse the repository at this point in the history
  • Loading branch information
Bogdanp committed Feb 6, 2025
1 parent c47a61b commit 29ad377
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 3 deletions.
60 changes: 60 additions & 0 deletions examples/page-change-evt.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#lang racket/base

(require marionette
web-server/servlet
(only-in xml current-unescaped-tags html-unescaped-tags))

(current-unescaped-tags html-unescaped-tags)

(define ((app n) _req)
(send/suspend/dispatch
(lambda (embed/url)
(sleep 1)
(response/xexpr
#:preamble #"<!DOCTYPE html>"
`(html
(head
(script ([src "https://cdn.jsdelivr.net/npm/unpoly@3.10.2/unpoly.min.js"])))
(body
(div.content
(p ,(format "Counter: ~a" n))
(a
([class "continue-button"]
[href ,(embed/url (app (add1 n)))]
[up-target ".content"])
"Continue"))))))))

(define (run-marionette port)
(call-with-marionette/browser/page!
#:headless? #f
(lambda (p)
(page-goto! p (format "http://127.0.0.1:~a" port))
(define e (page-change-evt p))
(element-click! (page-wait-for! p ".continue-button"))
(println (page-url p))
(println `(sync-result ,(sync e)))
(println (page-url p)))))

(module+ main
(require racket/async-channel
web-server/servlet-dispatch
web-server/web-server)

(define port-or-exn-ch
(make-async-channel))
(define stop
(serve
#:confirmation-channel port-or-exn-ch
#:dispatch (dispatch/servlet (app 1))
#:port 0))
(define port-or-exn
(sync port-or-exn-ch))
(when (exn:fail? port-or-exn)
(raise port-or-exn))
(define marionette-thd
(thread
(lambda ()
(run-marionette port-or-exn))))
(with-handlers ([exn:break? void])
(sync/enable-break marionette-thd))
(stop))
10 changes: 10 additions & 0 deletions marionette-doc/scribblings/marionette.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,16 @@ separately.
the entire page is captured.
}

@defproc[(page-change-evt [page page?]) (evt/c void?)]{
Returns a synchronizable event that becomes ready for synchronization
when the page contents have changed (for example, when user navigates
to another page). The synchronization result of a page change event is
@racket[void]. Once a page change event has synchronized, a new event
must be created in order to observe new page changes.

@history[#:added "1.4"]
}


@subsection[#:tag "reference/element"]{Element}

Expand Down
2 changes: 1 addition & 1 deletion marionette-lib/info.rkt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#lang info

(define license 'BSD-3-Clause)
(define version "1.3.1")
(define version "1.4")
(define collection "marionette")
(define deps
'("base"
Expand Down
30 changes: 28 additions & 2 deletions marionette-lib/page.rkt
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#lang racket/base

(require json
(require file/sha1
json
net/base64
net/url
racket/contract/base
racket/match
racket/promise
racket/random
racket/string
"private/browser.rkt"
"private/json.rkt"
Expand Down Expand Up @@ -130,7 +133,10 @@
(with-page p
(sync
(handle-evt
(marionette-execute-async-script! (page-marionette p) (wrap-async-script s) args)
(marionette-execute-async-script!
(page-marionette p)
(wrap-async-script s)
args)
(λ (res)
(match (hash-ref res 'value)
[(hash-table ('error (js-null))
Expand Down Expand Up @@ -303,6 +309,26 @@
res-value/decode)))))


;; page-change-evt ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(provide
page-change-evt)

(define (page-change-evt p)
(define token (bytes->hex-string (crypto-random-bytes 32)))
(page-execute! p (template "support/set-page-change-token.js") token)
(log-marionette-debug "set PageChangeToken=~s" token)
(handle-evt
(delay/thread
(let loop ()
(define current (page-execute! p (template "support/get-page-change-token.js")))
(log-marionette-debug "get PageChangeToken=~a" current)
(when (equal? current token)
(sleep 0.1)
(loop))))
void))


;; element ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(provide
Expand Down
1 change: 1 addition & 0 deletions marionette-lib/support/get-page-change-token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
return (window.$$marionette || {}).PageChangeToken;
16 changes: 16 additions & 0 deletions marionette-lib/support/set-page-change-token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const Marionette = window.$$marionette || {};
if (Marionette.PageChangeToken === undefined) {
Marionette.PageChangeToken = arguments[0];
if (Marionette.patchedHistory === undefined) {
Marionette.patchedHistory = true;
for (const method of ["pushState", "replaceState"]) {
window.history[method] = new Proxy(window.history[method], {
apply: (target, self, args) => {
delete Marionette["PageChangeToken"];
return target.apply(self, args);
},
});
}
}
}
window.$$marionette = Marionette;

0 comments on commit 29ad377

Please # to comment.