git.iko.soy/rowtype-yoga/purescript-playwright
on main help sign in
WIP
commit1bbb8d637a78216a48b59bff676371af57878a06 authorVladimir Kalnitsky <klntsky@gmail.com> dateSun 1 Nov 2020, 13:16 (6 years ago) parent3badb1f
8 files changed+206−20
src/Playwright.purs+38 src/Playwright/Mouse.purs+54 src/Playwright/Options.purs+29−2 src/Playwright/Response.purs+22 test/Main.purs+8−18 test/Main.js → test/TestUtils.js test/TestUtils.purs+39 test/static/index.html+16
src/Playwright.purs+38
@@ -26,6 +26,9 @@ module Playwright
2626 , click
2727 , content
2828 , dblclick
29+ , waitForNavigation
30+ , evaluateHandle
31+ , evaluate
2932 , module Playwright.Data
3033 , module Playwright.Options
3134 )
@@ -41,6 +44,8 @@ import Playwright.Options
4144import Prelude
4245import Untagged.Coercible (class Coercible)
4346import Untagged.Union (type (|+|), UndefinedOr)
47+import Foreign (Foreign)
48+import Data.String.Regex (Regex)
4449
4550launch
4651 :: forall o
@@ -252,3 +257,36 @@ dblclick
252257dblclick x s o =
253258 affCall "dblclick" typeInfo x s o
254259 where typeInfo _ = dblclick
260+
261+evaluate
262+ :: forall x
263+ . Coercible x (Page |+| Frame |+| Worker |+| JSHandle)
264+ => x
265+ -> String
266+ -- ^ Function to be evaluated in browser context
267+ -> Aff Foreign
268+evaluate x s =
269+ affCall "evaluate" typeInfo x s
270+ where typeInfo _ = evaluate
271+
272+evaluateHandle
273+ :: forall x
274+ . Coercible x (Page |+| Frame |+| Worker |+| JSHandle)
275+ => x
276+ -> String
277+ -- ^ Function to be evaluated in browser context
278+ -> Aff JSHandle
279+evaluateHandle x s =
280+ affCall "evaluateHandle" typeInfo x s
281+ where typeInfo _ = evaluateHandle
282+
283+waitForNavigation
284+ :: forall x o
285+ . Coercible x (Page |+| Frame)
286+ => Coercible o WaitForNavigationOptions
287+ => x
288+ -> o
289+ -> Aff (Null |+| Response)
290+waitForNavigation x s =
291+ affCall "waitForNavigation" typeInfo x s
292+ where typeInfo _ = waitForNavigation
src/Playwright/Mouse.pursnew file+54
@@ -0,0 +1,54 @@
1+module Playwright.Mouse where
2+
3+import Effect.Aff
4+import Playwright.Data
5+import Playwright.Internal
6+import Playwright.Options
7+import Prelude
8+import Untagged.Coercible (class Coercible)
9+import Untagged.Union
10+
11+click
12+ :: Mouse
13+ -> Int
14+ -> Int
15+ -> MouseClickOptions
16+ -> Aff Unit
17+click m x y o = affCall "click" typeInfo m x y o
18+ where typeInfo _ = click
19+
20+dblclick
21+ :: Mouse
22+ -> Int
23+ -> Int
24+ -> MouseDblClickOptions
25+ -> Aff Unit
26+dblclick m x y o = affCall "dblclick" typeInfo m x y o
27+ where typeInfo _ = dblclick
28+
29+down
30+ :: forall o
31+ . Coercible o MouseUpDownOptions
32+ => Mouse
33+ -> o
34+ -> Aff Unit
35+down m o = affCall "down" typeInfo m o
36+ where typeInfo _ = down
37+
38+move
39+ :: forall o
40+ . Coercible o MouseMoveOptions
41+ => Mouse
42+ -> o
43+ -> Aff Unit
44+move m o = affCall "move" typeInfo m o
45+ where typeInfo _ = move
46+
47+up
48+ :: forall o
49+ . Coercible o MouseUpDownOptions
50+ => Mouse
51+ -> o
52+ -> Aff Unit
53+up m o = affCall "up" typeInfo m o
54+ where typeInfo _ = up
src/Playwright/Options.purs+29−2
@@ -2,10 +2,11 @@ module Playwright.Options where
22
33import Playwright.Data
44
5−import Foreign.Object (Object)
5+import Data.String.Regex (Regex)
66import Foreign (Foreign)
7−import Untagged.Union (UndefinedOr, type (|+|))
7+import Foreign.Object (Object)
88import Literals.Null (Null)
9+import Untagged.Union (UndefinedOr, type (|+|))
910
1011type Opt a = UndefinedOr a
1112
@@ -93,3 +94,29 @@ type ClickOptions =
9394 , noWaitAfter :: Opt Boolean
9495 , timeout :: Opt Int
9596 }
97+
98+type MouseClickOptions =
99+ { button :: Opt MouseButton
100+ , clickCount :: Opt Int
101+ , delay :: Opt Int
102+ }
103+
104+type MouseDblClickOptions =
105+ { button :: Opt MouseButton
106+ , delay :: Opt Int
107+ }
108+
109+type MouseUpDownOptions =
110+ { button :: Opt MouseButton
111+ , clickCount :: Opt Int
112+ }
113+
114+type MouseMoveOptions =
115+ { steps :: Opt Int
116+ }
117+
118+type WaitForNavigationOptions =
119+ { timeout :: Opt Int
120+ , url :: Opt (String |+| Regex |+| URL -> Boolean)
121+ , waitUntil :: Opt WaitUntil
122+ }
src/Playwright/Response.pursnew file+22
@@ -0,0 +1,22 @@
1+module Playwright.Response where
2+
3+import Playwright.Data
4+import Playwright.Internal
5+import Effect.Aff (Aff)
6+import Node.Buffer (Buffer)
7+import Effect.Exception (Error)
8+import Effect (Effect)
9+import Untagged.Union
10+import Literals.Null
11+
12+body :: Response -> Aff Buffer
13+body = affCall "body" typeInfo
14+ where typeInfo _ = body
15+
16+finished :: Response -> Aff (Null |+| Error)
17+finished = affCall "finished" typeInfo
18+ where typeInfo _ = finished
19+
20+frame :: Response -> Effect Frame
21+frame = effCall "frame" typeInfo
22+ where typeInfo _ = frame
test/Main.purs+8−18
@@ -11,7 +11,7 @@ import Data.Maybe (Maybe(..))
1111import Node.FS.Aff as FS
1212import Effect.Aff (Aff)
1313import Effect.Class (liftEffect)
14−import Control.Monad.Error.Class (withResource)
14+import TestUtils
1515
1616static :: String -> URL
1717static file =
@@ -19,7 +19,9 @@ static file =
1919
2020main :: Effect Unit
2121main = runTest do
22− let hello = static "hello.html"
22+ let
23+ hello = static "hello.html"
24+ index = static "index.html"
2325 suite "browser" do
2426 test "launch, close" do
2527 browser <- launch chromium {}
@@ -56,19 +58,7 @@ main = runTest do
5658 frame <- liftEffect $ mainFrame page
5759 frameName <- liftEffect $ name frame
5860 Assert.equal "" frameName
59−
60−withBrowser :: forall a. (Browser -> Aff a) -> Aff a
61−withBrowser action = withResource acquire release action
62− where
63− acquire = launch chromium {}
64− release = close
65−
66−withBrowserPage :: forall a. URL -> (Page -> Aff a) -> Aff a
67−withBrowserPage url action = do
68− withBrowser
69− \browser -> do
70− page <- newPage browser {}
71− void $ goto page url {}
72− action page
73−
74−foreign import cwd :: String
61+ test "click" do
62+ withBrowserPage index $ testClickEvent "click" click
63+ test "dblclick" do
64+ withBrowserPage index $ testClickEvent "dblclick" dblclick
test/Main.js → test/TestUtils.jsrenamed

The content is the same.

test/TestUtils.pursnew file+39
@@ -0,0 +1,39 @@
1+module TestUtils where
2+
3+import Test.Unit.Assert as Assert
4+import Foreign
5+import Control.Monad.Except
6+import Data.Either
7+import Effect.Aff
8+import Prelude
9+import Playwright
10+import Control.Monad.Error.Class (withResource)
11+
12+assertForeignTrue :: Foreign -> Aff Unit
13+assertForeignTrue value = do
14+ let
15+ eiBool = runExcept $ readBoolean value
16+ Assert.assert "Foreign value is boolean true" (eiBool == Right true)
17+
18+withBrowser :: forall a. (Browser -> Aff a) -> Aff a
19+withBrowser action = withResource acquire release action
20+ where
21+ acquire = launch chromium {}
22+ release = close
23+
24+withBrowserPage :: forall a. URL -> (Page -> Aff a) -> Aff a
25+withBrowserPage url action = do
26+ withBrowser
27+ \browser -> do
28+ page <- newPage browser {}
29+ void $ goto page url {}
30+ action page
31+
32+testClickEvent :: String -> (Page -> Selector -> {} -> Aff Unit) -> Page -> Aff Unit
33+testClickEvent event action page = do
34+ void $ evaluate page ("setEventTester('" <> event <> "');")
35+ action page (Selector $ "#event-" <> event) {}
36+ result <- evaluate page $ "checkEventHappened('" <> event <> "');"
37+ assertForeignTrue result
38+
39+foreign import cwd :: String
test/static/index.html+16
@@ -1,6 +1,22 @@
11<!DOCTYPE html>
22<html>
33 <head>
4+ <script>
5+ function setEventTester (event) {
6+ var div = document.createElement('div');
7+ div.textContent = event;
8+ div.id = 'event-' + event;
9+ document.body.appendChild(div);
10+ div.addEventListener(event, function () {
11+ div.textContent = 'OK';
12+ });
13+ }
14+
15+ function checkEventHappened (event) {
16+ var elem = document.getElementById('event-' + event);
17+ return elem && elem.textContent == 'OK';
18+ }
19+ </script>
420 </head>
521 <body>
622 <div id="someid"></div>