git.iko.soy/rowtype-yoga/purescript-playwright
on main help sign in
Add `exposeBinding`; add JSHandle methods
commite14df149893b41594970bc1b46032c653376ddc9 authorVladimir Kalnitsky <klntsky@gmail.com> dateFri 11 Dec 2020, 00:25 (6 years ago) parent3502c5f
7 files changed+147−21
src/Playwright.js+15 src/Playwright.purs+42−5 src/Playwright/Download.purs+1−1 src/Playwright/Event.purs+14−14 src/Playwright/JSHandle.js+17 src/Playwright/JSHandle.purs+34 test/Main.purs+24−1
src/Playwright.jsnew file+15
@@ -0,0 +1,15 @@
1+/* global exports */
2+
3+exports.exposeBinding_ = function (x) {
4+ return function (name) {
5+ return function (cb) {
6+ return function (opts) {
7+ return function () {
8+ return x.exposeBinding(name, function (info, arg) {
9+ return cb(info)(arg)();
10+ }, opts);
11+ };
12+ };
13+ };
14+ };
15+};
src/Playwright.purs+42−5
@@ -39,11 +39,13 @@ module Playwright
3939 , setInputFiles
4040 , setViewportSize
4141 , title
42+ , exposeBinding
4243 , module Playwright.Data
4344 , module Playwright.Options
4445 )
4546where
4647
48+import Control.Promise (Promise, fromAff, toAffE)
4749import Data.String.Regex (Regex)
4850import Effect (Effect)
4951import Effect.Aff (Aff)
@@ -53,10 +55,10 @@ import Node.Buffer (Buffer)
5355import Playwright.Data
5456import Playwright.Internal (effCall, effProp, affCall)
5557import Playwright.Options
56−import Prelude (Unit)
58+import Prelude (Unit, ($))
59+import Undefined (undefined)
5760import Untagged.Coercible (class Coercible)
5861import Untagged.Union (type (|+|), UndefinedOr)
59−import Undefined (undefined)
6062
6163launch
6264 :: forall o
@@ -137,7 +139,7 @@ hover =
137139
138140innerHTML
139141 :: forall x o
140− . Coercible x (Page |+| Frame |+| ElementHandle)
142+ . Coercible x (Page |+| Frame)
141143 => Coercible o InnerHTMLOptions
142144 => x -> Selector -> o -> Aff String
143145innerHTML =
@@ -170,7 +172,7 @@ name = effCall "name" \_ -> name
170172query
171173 :: forall x
172174 . Coercible x (ElementHandle |+| Page |+| Frame)
173− => x -> Selector -> Aff ElementHandle
175+ => x -> Selector -> Aff (Null |+| ElementHandle)
174176query =
175177 affCall "$" \_ -> query
176178
@@ -221,7 +223,7 @@ clearCookies =
221223
222224click
223225 :: forall x o
224− . Coercible x (Page |+| Frame |+| ElementHandle)
226+ . Coercible x (Page |+| Frame)
225227 => Coercible o ClickOptions
226228 => x
227229 -> Selector
@@ -385,3 +387,38 @@ title
385387 => x
386388 -> Aff String
387389title = affCall "title" \_ -> title
390+
391+exposeBinding
392+ :: forall x b
393+ . Coercible x (Page |+| BrowserContext)
394+ => x
395+ -> String
396+ -- ^ Name of the function on the window object.
397+ ->
398+ (
399+ { browserContext :: BrowserContext
400+ , page :: Page
401+ , frame :: Frame
402+ }
403+ -> Foreign
404+ -> Aff b
405+ )
406+ -> Aff Unit
407+exposeBinding x binding f =
408+ toAffE $ exposeBinding_ x binding (\d a -> fromAff $ f d a) { handle: false }
409+
410+foreign import exposeBinding_
411+ :: forall x a b
412+ . x
413+ -> String
414+ ->
415+ (
416+ { browserContext :: BrowserContext
417+ , page :: Page
418+ , frame :: Frame
419+ }
420+ -> a
421+ -> Effect (Promise b)
422+ )
423+ -> { handle :: Boolean }
424+ -> Effect (Promise Unit)
src/Playwright/Download.purs+1−1
@@ -27,7 +27,7 @@ foreign import createReadStream_
2727 :: (forall a. Maybe a)
2828 -> (forall a. a -> Maybe a)
2929 -> Download
30− -> Effect (Promise (Maybe (Readable ())))
30+ -> Effect (Promise (Maybe (Readable ())))
3131
3232suggestedFilename :: Download -> Effect String
3333suggestedFilename = effCall "suggestedFilename" \_ -> suggestedFilename
src/Playwright/Event.purs+14−14
@@ -18,7 +18,7 @@ data EventName a = EventName
1818
1919foreign import data Close :: Type
2020instance eventClose :: Event Close where getEventName _ = "close"
21−instance eventPageClose :: OnEvent Page Close Unit
21+instance eventPageClose :: OnEvent Data.Page Close Unit
2222instance eventBrowserContextClose :: OnEvent BrowserContext Close Unit
2323instance eventBrowserClose :: OnEvent Browser Close Unit
2424instance eventWorkerClose :: OnEvent Worker Close Unit
@@ -27,86 +27,86 @@ close = EventName
2727
2828foreign import data Console :: Type
2929instance eventConsole :: Event Console where getEventName _ = "console"
30−instance eventPageConsole :: OnEvent Page Console ConsoleMessage
30+instance eventPageConsole :: OnEvent Data.Page Console ConsoleMessage
3131console :: EventName Console
3232console = EventName
3333
3434foreign import data Crash :: Type
3535instance eventCrash :: Event Crash where getEventName _ = "crash"
36−instance eventPageCrash :: OnEvent Page Crash Unit
36+instance eventPageCrash :: OnEvent Data.Page Crash Unit
3737crash :: EventName Crash
3838crash = EventName
3939
4040foreign import data Dialog :: Type
4141instance eventDialog :: Event Dialog where getEventName _ = "dialog"
42−instance eventPageDialog :: OnEvent Page Dialog Data.Dialog
42+instance eventPageDialog :: OnEvent Data.Page Dialog Data.Dialog
4343dialog :: EventName Dialog
4444dialog = EventName
4545
4646foreign import data DomContentLoaded :: Type
4747instance eventDomContentLoaded :: Event DomContentLoaded where
4848 getEventName _ = "domcontentloaded"
49−instance eventPageDomContentLoaded :: OnEvent Page DomContentLoaded Unit
49+instance eventPageDomContentLoaded :: OnEvent Data.Page DomContentLoaded Unit
5050domcontentloaded :: EventName DomContentLoaded
5151domcontentloaded = EventName
5252
5353foreign import data Download :: Type
5454instance eventDownload :: Event Download where
5555 getEventName _ = "download"
56−instance eventPageDownload :: OnEvent Page Download Data.Download
56+instance eventPageDownload :: OnEvent Data.Page Download Data.Download
5757download :: EventName Download
5858download = EventName
5959
6060foreign import data FileChooser :: Type
6161instance eventFileChooser :: Event FileChooser where
6262 getEventName _ = "filechooser"
63−instance eventPageFileChooser :: OnEvent Page FileChooser Data.FileChooser
63+instance eventPageFileChooser :: OnEvent Data.Page FileChooser Data.FileChooser
6464filechooser :: EventName FileChooser
6565filechooser = EventName
6666
6767foreign import data PageError :: Type
6868instance eventPageError :: Event PageError where getEventName _ = "pageerror"
69−instance eventPagePageError :: OnEvent Page PageError Error
69+instance eventPagePageError :: OnEvent Data.Page PageError Error
7070pageerror :: EventName PageError
7171pageerror = EventName
7272
7373foreign import data Popup :: Type
7474instance eventPopup :: Event Popup where getEventName _ = "popup"
75−instance eventPagePopup :: OnEvent Page Popup Page
75+instance eventPagePopup :: OnEvent Data.Page Popup Page
7676popup :: EventName Popup
7777popup = EventName
7878
7979foreign import data Request :: Type
8080instance eventRequest :: Event Request where getEventName _ = "request"
81−instance eventPageRequest :: OnEvent Page Request Data.Request
81+instance eventPageRequest :: OnEvent Data.Page Request Data.Request
8282request :: EventName Request
8383request = EventName
8484
8585foreign import data RequestFailed :: Type
8686instance eventRequestFailed :: Event RequestFailed where
8787 getEventName _ = "requestfailed"
88−instance eventPageRequestFailed :: OnEvent Page RequestFailed Data.Request
88+instance eventPageRequestFailed :: OnEvent Data.Page RequestFailed Data.Request
8989requestfailed :: EventName RequestFailed
9090requestfailed = EventName
9191
9292foreign import data RequestFinished :: Type
9393instance eventRequestFinished :: Event RequestFinished where
9494 getEventName _ = "requestfinished"
95−instance eventPageRequestFinished :: OnEvent Page RequestFinished Data.Request
95+instance eventPageRequestFinished :: OnEvent Data.Page RequestFinished Data.Request
9696requestfinished :: EventName RequestFinished
9797requestfinished = EventName
9898
9999foreign import data Response :: Type
100100instance eventResponse :: Event Response where
101101 getEventName _ = "response"
102−instance eventPageResponse :: OnEvent Page Response Data.Response
102+instance eventPageResponse :: OnEvent Data.Page Response Data.Response
103103response :: EventName Response
104104response = EventName
105105
106106foreign import data Worker :: Type
107107instance eventWorker :: Event Worker where
108108 getEventName _ = "worker"
109−instance eventPageWorker :: OnEvent Page Worker Data.Worker
109+instance eventPageWorker :: OnEvent Data.Page Worker Data.Worker
110110worker :: EventName Worker
111111worker = EventName
112112
src/Playwright/JSHandle.jsnew file+17
@@ -0,0 +1,17 @@
1+/* global exports */
2+
3+exports.getProperties_ = function (insert) {
4+ return function (emptyMap) {
5+ return function (jsHandle) {
6+ return function () {
7+ return jsHandle.getProperties().then(function (props) {
8+ var acc = emptyMap;
9+ props.entries().forEach(function (pair) {
10+ acc = insert(pair[0])(pair[1])(acc);
11+ });
12+ return acc;
13+ });
14+ };
15+ };
16+ };
17+};
src/Playwright/JSHandle.pursnew file+34
@@ -0,0 +1,34 @@
1+module Playwright.JSHandle where
2+
3+import Playwright.Data (ElementHandle, JSHandle)
4+import Effect (Effect)
5+import Untagged.Union (type (|+|))
6+import Literals.Null (Null)
7+import Playwright.Internal (affCall)
8+import Effect.Aff (Aff)
9+import Prelude
10+import Data.Map (Map)
11+import Data.Map as Map
12+import Control.Promise (Promise, toAffE)
13+import Data.Argonaut.Core (Json)
14+
15+asElement :: JSHandle -> Effect (Null |+| ElementHandle)
16+asElement = affCall "asElement" \_ -> asElement
17+
18+dispose :: JSHandle -> Aff Unit
19+dispose = affCall "dispose" \_ -> dispose
20+
21+getProperties :: JSHandle -> Aff (Map String JSHandle)
22+getProperties = toAffE <<< getProperties_ Map.insert mempty
23+
24+getProperty :: JSHandle -> Aff JSHandle
25+getProperty = affCall "getProperty" \_ -> getProperty
26+
27+jsonValue :: JSHandle -> Aff Json
28+jsonValue = affCall "jsonValue" \_ -> jsonValue
29+
30+foreign import getProperties_
31+ :: (String -> JSHandle -> Map String JSHandle -> Map String JSHandle)
32+ -> (Map String JSHandle)
33+ -> JSHandle
34+ -> Effect (Promise (Map String JSHandle))
test/Main.purs+24−1
@@ -1,11 +1,14 @@
11module Test.Main where
22
3+import Control.Monad.Except (runExcept)
34import Data.Either (isLeft)
45import Data.Maybe (Maybe(..))
56import Effect (Effect)
67import Effect.Aff (launchAff_, try)
78import Effect.Class (liftEffect)
9+import Effect.Console as Console
810import Effect.Ref as Ref
11+import Foreign as Foreign
912import Node.Encoding as Encoding
1013import Node.FS.Aff as FS
1114import Node.Stream as Stream
@@ -87,6 +90,27 @@ main = runTest do
8790 page
8891 "document.body.textContent.includes('uniqstring')"
8992 { timeout: 5000, polling: 100 }
93+ suite "FFI" do
94+ test "exposeBinding" do
95+ withBrowserPage hello \page -> do
96+ ref <- liftEffect $ Ref.new Nothing
97+ frgnRef <- liftEffect $ Ref.new Nothing
98+ exposeBinding page "hi_ffi"
99+ (
100+ \({frame}) frgn -> do
101+ url <- liftEffect $ url frame
102+ liftEffect do
103+ Console.log "hi"
104+ Ref.write (Just frgn) frgnRef
105+ Ref.write (Just url) ref
106+ )
107+ void $ evaluate page "hi_ffi(12);"
108+ waitForTimeout page 100
109+ mbUrl <- liftEffect $ Ref.read ref
110+ mbForeign <- liftEffect $ Ref.read frgnRef
111+ Assert.equal (Just hello) mbUrl
112+ Assert.assert "exposeBinding is not able to accept an argument" $
113+ pure (pure 12) == (runExcept <<< Foreign.readInt <$> mbForeign)
90114 suite "events" do
91115 test "console" do
92116 withBrowserPage hello
@@ -147,7 +171,6 @@ main = runTest do
147171 test "dialog" do
148172 withBrowserPage hello
149173 \page -> do
150− downloadRef <- liftEffect $ Ref.new Nothing
151174 liftEffect $ on Event.dialog page $ \dialog -> launchAff_ do
152175 defaultValue <- liftEffect $ Dialog.defaultValue dialog
153176 Assert.equal "hello" defaultValue