git.iko.soy/rowtype-yoga/purescript-playwright
on main help sign in
Add Download and Dialog classes
ec77eb0Vladimir Kalnitsky
src/Playwright/Dialog.pursnew file+32
@@ -0,0 +1,32 @@
1+module Playwright.Dialog where
2+
3+import Prelude
4+import Playwright.Internal (affCall, effCall)
5+import Playwright.Data (Dialog)
6+import Effect (Effect)
7+import Effect.Aff (Aff)
8+
9+accept :: Dialog -> String -> Aff Unit
10+accept = affCall "accept" \_ -> accept
11+
12+defaultValue :: Dialog -> Effect String
13+defaultValue = effCall "defaultValue" \_ -> defaultValue
14+
15+dismiss :: Dialog -> Aff Unit
16+dismiss = affCall "dismiss" \_ -> dismiss
17+
18+message :: Dialog -> Effect String
19+message = effCall "message" \_ -> message
20+
21+data DialogType = Alert | Beforeunload | Confirm | Prompt
22+
23+type' :: Dialog -> Effect DialogType
24+type' = map convert <<< type''
25+ where
26+ type'' = effCall "type" \_ -> type''
27+ convert = case _ of
28+ "alert" -> Alert
29+ "beforeunload" -> Beforeunload
30+ "confirm" -> Confirm
31+ "prompt" -> Prompt
32+ _ -> Alert -- impossible
src/Playwright/Download.jsnew file+17
@@ -0,0 +1,17 @@
1+/* global exports */
2+
3+exports.createReadStream_ = function (Nothing) {
4+ return function (Just) {
5+ return function (Download) {
6+ return function () {
7+ return Download.createReadStream().then(function (result) {
8+ if (result === null) {
9+ return Nothing;
10+ } else {
11+ return Just(result);
12+ }
13+ });
14+ };
15+ };
16+ };
17+};
src/Playwright/Download.pursnew file+48
@@ -0,0 +1,48 @@
1+module Playwright.Download
2+ ( createReadStream
3+ , suggestedFilename
4+ , saveAs
5+ , path
6+ , url
7+ , failure
8+ , delete
9+ )
10+where
11+
12+import Control.Promise (Promise, toAffE)
13+import Data.Maybe (Maybe(..))
14+import Effect (Effect)
15+import Effect.Aff (Aff)
16+import Literals.Null (Null)
17+import Node.Stream (Readable)
18+import Playwright.Data (Download, URL)
19+import Playwright.Internal (affCall, effCall)
20+import Prelude
21+import Untagged.Union (type (|+|))
22+
23+createReadStream :: Download -> Aff (Maybe (Readable ()))
24+createReadStream = toAffE <<< createReadStream_ Nothing Just
25+
26+foreign import createReadStream_
27+ :: (forall a. Maybe a)
28+ -> (forall a. a -> Maybe a)
29+ -> Download
30+ -> Effect (Promise (Maybe (Readable ())))
31+
32+suggestedFilename :: Download -> Effect String
33+suggestedFilename = effCall "suggestedFilename" \_ -> suggestedFilename
34+
35+saveAs :: Download -> String -> Aff Unit
36+saveAs = affCall "saveAs" \_ -> saveAs
37+
38+path :: Download -> Effect (Null |+| String)
39+path = effCall "path" \_ -> path
40+
41+url :: Download -> Effect URL
42+url = effCall "url" \_ -> url
43+
44+failure :: Download -> Aff (Null |+| String)
45+failure = affCall "failure" \_ -> failure
46+
47+delete :: Download -> Aff Unit
48+delete = affCall "delete" \_ -> delete
src/Playwright/Event.purs+27
@@ -5,6 +5,7 @@ import Type.Proxy (Proxy(..))
5import Effect (Effect)
5import Effect (Effect)
6import Prelude (Unit)
6import Prelude (Unit)
7import Playwright.Data
7import Playwright.Data
8+import Playwright.Data as Data
8
9
9class Event e where
10class Event e where
10 getEventName :: Proxy e -> String
11 getEventName :: Proxy e -> String
@@ -26,6 +27,32 @@ instance eventPageConsole :: OnEvent Page Console ConsoleMessage
26console :: EventName Console
27console :: EventName Console
27console = EventName
28console = EventName
28
29
30+foreign import data Crash :: Type
31+instance eventCrash :: Event Crash where getEventName _ = "crash"
32+instance eventPageCrash :: OnEvent Page Crash Unit
33+crash :: EventName Crash
34+crash = EventName
35+
36+foreign import data Dialog :: Type
37+instance eventDialog :: Event Dialog where getEventName _ = "dialog"
38+instance eventPageDialog :: OnEvent Page Dialog Data.Dialog
39+dialog :: EventName Dialog
40+dialog = EventName
41+
42+foreign import data DomContentLoaded :: Type
43+instance eventDomContentLoaded :: Event DomContentLoaded where
44+ getEventName _ = "domcontentloaded"
45+instance eventPageDomContentLoaded :: OnEvent Page DomContentLoaded Unit
46+domcontentloaded :: EventName DomContentLoaded
47+domcontentloaded = EventName
48+
49+foreign import data Download :: Type
50+instance eventDownload :: Event Download where
51+ getEventName _ = "download"
52+instance eventPageDownload :: OnEvent Page Download Data.Download
53+download :: EventName Download
54+download = EventName
55+
29on
56on
30 :: forall x e a r
57 :: forall x e a r
31 . OnEvent x e a
58 . OnEvent x e a
test/Main.purs+52−4
@@ -1,21 +1,25 @@
1module Test.Main where
1module Test.Main where
2
2
3−import Control.Monad.Error.Class (try)
4import Data.Either (isLeft)
3import Data.Either (isLeft)
5import Data.Maybe (Maybe(..))
4import Data.Maybe (Maybe(..))
6import Effect (Effect)
5import Effect (Effect)
6+import Effect.Aff (launchAff_, try)
7import Effect.Class (liftEffect)
7import Effect.Class (liftEffect)
8import Effect.Ref as Ref
8import Effect.Ref as Ref
9+import Node.Encoding as Encoding
9import Node.FS.Aff as FS
10import Node.FS.Aff as FS
11+import Node.Stream as Stream
10import Playwright
12import Playwright
11import Playwright.ConsoleMessage as ConsoleMessage
13import Playwright.ConsoleMessage as ConsoleMessage
12−import Playwright.Event as Event
14+import Playwright.Dialog as Dialog
15+import Playwright.Download as Download
13import Playwright.Event (on)
16import Playwright.Event (on)
14−import Prelude (Unit, bind, discard, void, ($), (/=), (<>), (=<<))
17+import Playwright.Event as Event
18+import Prelude
15import Test.Unit (suite, test)
19import Test.Unit (suite, test)
16import Test.Unit.Assert as Assert
20import Test.Unit.Assert as Assert
17import Test.Unit.Main (runTest)
21import Test.Unit.Main (runTest)
18−import TestUtils (cwd, testClickEvent, withBrowser, withBrowserPage)
22+import TestUtils (cwd, isNull, testClickEvent, withBrowser, withBrowserPage)
19import Untagged.Union (fromOneOf)
23import Untagged.Union (fromOneOf)
20
24
21static :: String -> URL
25static :: String -> URL
@@ -110,3 +114,47 @@ main = runTest do
110 """
114 """
111 realType <- liftEffect $ Ref.read typeRef
115 realType <- liftEffect $ Ref.read typeRef
112 Assert.equal (Just ConsoleMessage.Debug) realType
116 Assert.equal (Just ConsoleMessage.Debug) realType
117+ test "download" do
118+ withBrowserPage hello
119+ \page -> do
120+ downloadRef <- liftEffect $ Ref.new Nothing
121+ liftEffect $ on Event.download page $ \download -> launchAff_ do
122+ fname <- liftEffect $ Download.suggestedFilename download
123+ Assert.equal "hello.txt" fname
124+ mbStream <- Download.createReadStream download
125+ failureStatus <- Download.failure download
126+ Assert.equal true (isNull failureStatus)
127+ case mbStream of
128+ Nothing -> Assert.assert "Unable to get stream" false
129+ Just stream -> do
130+ liftEffect $ Stream.onDataString stream Encoding.UTF8 $ \string -> do
131+ Ref.write (Just string) downloadRef
132+ void $ evaluate page
133+ """
134+ function download(filename, text) {
135+ var element = document.createElement('a');
136+ element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
137+ element.setAttribute('download', filename);
138+ document.body.appendChild(element);
139+ element.click();
140+ document.body.removeChild(element);
141+ }
142+ download("hello.txt","hiiii");
143+ """
144+ waitForTimeout page 100
145+ downloadContent <- liftEffect $ Ref.read downloadRef
146+ Assert.equal (Just "hiiii") downloadContent
147+ test "dialog" do
148+ withBrowserPage hello
149+ \page -> do
150+ downloadRef <- liftEffect $ Ref.new Nothing
151+ liftEffect $ on Event.dialog page $ \dialog -> launchAff_ do
152+ defaultValue <- liftEffect $ Dialog.defaultValue dialog
153+ Assert.equal "hello" defaultValue
154+ message <- liftEffect $ Dialog.message dialog
155+ Assert.equal "hi" message
156+ Dialog.dismiss dialog
157+ void $ evaluate page
158+ """
159+ prompt("hi", "hello");
160+ """
test/TestUtils.js+2
@@ -1,3 +1,5 @@
1/* global exports __dirname */
1/* global exports __dirname */
2
2
3exports.cwd = process.cwd();
3exports.cwd = process.cwd();
4+
5+exports.isNull = function (sth) { return sth === null; };
test/TestUtils.purs+4−1
@@ -4,6 +4,7 @@ module TestUtils
4 , withBrowserPage
4 , withBrowserPage
5 , testClickEvent
5 , testClickEvent
6 , cwd
6 , cwd
7+ , isNull
7 )
8 )
8where
9where
9
10
@@ -33,7 +34,7 @@ withBrowserPage url action = do
33 withBrowser
34 withBrowser
34 \browser -> do
35 \browser -> do
35 let
36 let
36− acquire = newPage browser {}
37+ acquire = newPage browser { acceptDownloads: true }
37 release = close
38 release = close
38 withResource acquire release
39 withResource acquire release
39 \page -> do
40 \page -> do
@@ -47,4 +48,6 @@ testClickEvent event action page = do
47 result <- evaluate page $ "checkEventHappened('" <> event <> "');"
48 result <- evaluate page $ "checkEventHappened('" <> event <> "');"
48 assertForeignTrue result
49 assertForeignTrue result
49
50
51+foreign import isNull :: forall a. a -> Boolean
52+
50foreign import cwd :: String
53foreign import cwd :: String