git.iko.soy/rowtype-yoga/purescript-playwright
on main help sign in
Use untagged-union
commitd35b4e521736caf14ff771709339eea0ea269a17 authorVladimir Kalnitsky <klntsky@gmail.com> dateSat 12 Sep 2020, 22:11 (6 years ago) parent9ad8280
11 files changed+327−195
packages.dhall+2−2 spago.dhall+2 src/Playwright.purs+71−169 src/Playwright/Data.js+9 src/Playwright/Data.purs+36 src/Playwright.js → src/Playwright/Internal.js+6−15 src/Playwright/Internal.purs+59 src/Playwright/Logger.purs+43 src/Playwright/Options.purs+85 test/Main.purs+6−9 test/static/index.html+8
packages.dhall+2−2
@@ -1,8 +1,8 @@
11let upstream =
2− https://github.com/purescript/package-sets/releases/download/psc-0.13.8-20200822/packages.dhall sha256:b4f151f1af4c5cb6bf5437489f4231fbdd92792deaf32971e6bcb0047b3dd1f8
2+ https://github.com/purescript/package-sets/releases/download/psc-0.13.8-20200911-2/packages.dhall sha256:872c06349ed9c8210be43982dc6466c2ca7c5c441129826bcb9bf3672938f16e
33
44let overrides = {=}
55
66let additions = {=}
77
8−in upstream ⫽ overrides ⫽ additions
8+in upstream // overrides // additions
spago.dhall+2
@@ -7,6 +7,8 @@
77 , "aff-promise"
88 , "options"
99 , "test-unit"
10+ , "untagged-union"
11+ , "node-buffer"
1012 ]
1113, packages = ./packages.dhall
1214, sources = [ "src/**/*.purs", "test/**/*.purs" ]
src/Playwright.purs+71−169
@@ -1,180 +1,82 @@
11module Playwright
2− ( BrowserType
3− , Browser
4−
5− , firefox
6− , chromium
7− , webkit
8−
9− , launch
10− , LaunchOptions
11− , headless
12− , executablePath
13− , args
14− , ignoreDefaultArgs
15− , ProxyOptions
16− , server
17− , bypass
18− , username
19− , password
20− , proxy
21− , downloadsPath
22− , chromiumSandbox
23− , firefoxUserPrefs
24− , handleSIGINT
25− , handleSIGTERM
26− , handleSIGHUP
27− , timeout
28− , env
29− , devtools
30− , slowMo
31−
32− , class Close
2+ ( launch
3+ , contexts
4+ , isConnected
5+ , version
336 , close
34−
35− , class NewPage
367 , newPage
37− , NewpageOptions
38−
39− , Frame
40− , ElementHandle
41− , Page
42−
43− , class Query
448 , query
459 , queryMany
10+ , module Playwright.Data
11+ , module Playwright.Options
4612 )
4713where
4814
4915import Prelude
5016import Effect (Effect)
51−import Control.Promise (Promise, toAffE)
52−import Data.Options (Option, Options, opt, options)
17+import Control.Promise (toAffE)
18+import Data.Options (Options, options)
5319import Effect.Aff (Aff)
54−import Foreign (Foreign)
55−import Foreign.Object (Object)
56−
57−foreign import data BrowserType :: Type
58−foreign import data Browser :: Type
59−
60−foreign import firefox :: BrowserType
61−foreign import chromium :: BrowserType
62−foreign import webkit :: BrowserType
63−
64−foreign import _launch :: BrowserType -> Foreign -> Effect (Promise Browser)
65−
66−launch :: BrowserType -> Options LaunchOptions -> Aff Browser
67−launch bt opts = toAffE $ _launch bt (options opts)
68−
69−foreign import data LaunchOptions :: Type
70−
71−headless :: Option LaunchOptions Boolean
72−headless = opt "headless"
73−
74−executablePath :: Option LaunchOptions String
75−executablePath = opt "executablePath"
76−
77−args :: Option LaunchOptions String
78−args = opt "args"
79−
80−ignoreDefaultArgs :: Option LaunchOptions (Array String)
81−ignoreDefaultArgs = opt "ignoreDefaultArgs"
82−
83−foreign import data ProxyOptions :: Type
84−
85−server :: Option ProxyOptions String
86−server = opt "server"
87−
88−bypass :: Option ProxyOptions String
89−bypass = opt "bypass"
90−
91−username :: Option ProxyOptions String
92−username = opt "username"
93−
94−password :: Option ProxyOptions String
95−password = opt "password"
96−
97−proxy :: Option LaunchOptions (Options ProxyOptions)
98−proxy = opt "proxy"
99−
100−downloadsPath :: Option LaunchOptions String
101−downloadsPath = opt "downloadsPath"
102−
103−chromiumSandbox :: Option LaunchOptions Boolean
104−chromiumSandbox = opt "chromiumSandbox"
105−
106−firefoxUserPrefs :: Option LaunchOptions Foreign
107−firefoxUserPrefs = opt "firefoxUserPrefs"
108−
109−handleSIGINT :: Option LaunchOptions Boolean
110−handleSIGINT = opt "handleSIGINT"
111−
112−handleSIGTERM :: Option LaunchOptions Boolean
113−handleSIGTERM = opt "handleSIGTERM"
114−
115−handleSIGHUP :: Option LaunchOptions Boolean
116−handleSIGHUP = opt "handleSIGHUP"
117−
118−timeout :: Option LaunchOptions Number
119−timeout = opt "timeout"
120−
121−env :: Option LaunchOptions (Object String)
122−env = opt "env"
123−
124−devtools :: Option LaunchOptions Boolean
125−devtools = opt "devtools"
126−
127−slowMo :: Option LaunchOptions Number
128−slowMo = opt "slowMo"
129−
130−class Close sth
131−
132−instance closeBrowser :: Close Browser
133−
134−close :: forall sth. Close sth => sth -> Aff Unit
135−close = toAffE <<< _close
136−
137−foreign import _close :: forall sth. sth -> Effect (Promise Unit)
138−
139−foreign import data BrowserContext :: Type
140−
141−foreign import contexts :: Browser -> Effect (Array BrowserContext)
142−
143−foreign import isConnected :: Browser -> Effect Boolean
144−
145−foreign import version :: Browser -> Effect String
146−
147−foreign import data NewpageOptions :: Type
148−
149−foreign import data Page :: Type
150−
151−class NewPage sth
152−
153−instance newpageBrowser :: NewPage Browser
154−instance newpageBrowserContext :: NewPage BrowserContext
155−
156−newPage :: forall sth. NewPage sth => sth -> Options NewpageOptions -> Aff Page
157−newPage sth opts = toAffE $ _newPage sth (options opts)
158−
159−foreign import _newPage :: forall sth. sth -> Foreign -> Effect (Promise Page)
160−
161−foreign import data ElementHandle :: Type
162−
163−class Query sth
164−
165−instance queryElementHandle :: Query ElementHandle
166−instance queryPage :: Query Page
167−instance queryFrame :: Query Frame
168−
169−type Selector = String
170−
171−foreign import data Frame :: Type
172−
173−foreign import query_ :: forall sth. sth -> Selector -> Effect (Promise ElementHandle)
174−foreign import queryMany_ :: forall sth. sth -> Selector -> Effect (Promise (Array ElementHandle))
175−
176−query :: forall sth. Query sth => sth -> Selector -> Aff ElementHandle
177−query sth = toAffE <<< query_ sth
178−
179−queryMany :: forall sth. Query sth => sth -> Selector -> Aff (Array ElementHandle)
180−queryMany sth = toAffE <<< queryMany_ sth
20+import Untagged.Union (type (|+|))
21+import Node.Buffer (Buffer)
22+import Playwright.Data
23+import Playwright.Options
24+import Playwright.Internal (prop)
25+
26+launch :: BrowserType -> Options Launch -> Aff Browser
27+launch bt =
28+ options >>>
29+ prop "launch" (\_ -> launch) bt >>>
30+ toAffE
31+
32+close :: Browser |+| BrowserContext |+| Page -> Aff Unit
33+close =
34+ prop "close" (\_ -> close) >>> toAffE
35+
36+contexts :: Browser -> Effect (Array BrowserContext)
37+contexts =
38+ prop "contexts" (\_ -> contexts)
39+
40+isConnected :: Browser -> Effect Boolean
41+isConnected =
42+ prop "isConnected" (\_ -> isConnected)
43+
44+version :: Browser -> Effect String
45+version =
46+ prop "version" (\_ -> version)
47+
48+newPage :: Browser |+| BrowserContext -> Options Newpage -> Aff Page
49+newPage sth =
50+ options >>>
51+ prop "newPage" (\_ -> newPage) sth >>>
52+ toAffE
53+
54+-- | `sth.$(selector)`
55+query
56+ :: ElementHandle |+| Page |+| Frame
57+ -> Selector
58+ -> Aff ElementHandle
59+query sth =
60+ toAffE <<< prop "$" (\_ -> query) sth
61+
62+-- | `sth.$$(selector)
63+queryMany
64+ :: ElementHandle |+| Page |+| Frame
65+ -> Selector
66+ -> Aff (Array ElementHandle)
67+queryMany sth =
68+ toAffE <<< prop "$$" (\_ -> queryMany) sth
69+
70+screenshot
71+ :: ElementHandle |+| Page
72+ -> Options Screenshot
73+ -> Aff Buffer
74+screenshot sth =
75+ options >>>
76+ prop "screenshot" (\_ -> screenshot) sth >>>
77+ toAffE
78+
79+url
80+ :: Page |+| Frame |+| Download |+| Request |+| Response |+| Worker
81+ -> Effect String
82+url = prop "url" \_ -> url
src/Playwright/Data.jsnew file+9
@@ -0,0 +1,9 @@
1+/* global require exports */
2+var P = require('playwright');
3+
4+exports.png = "png";
5+exports.jpg = "jpg";
6+
7+exports.chromium = P.chromium;
8+exports.firefox = P.firefox;
9+exports.webkit = P.webkit;
src/Playwright/Data.pursnew file+36
@@ -0,0 +1,36 @@
1+module Playwright.Data where
2+
3+import Prelude
4+
5+foreign import data BrowserType :: Type
6+foreign import data Browser :: Type
7+foreign import data BrowserContext :: Type
8+foreign import data Page :: Type
9+foreign import data Frame :: Type
10+foreign import data ElementHandle :: Type
11+foreign import data JSHandle :: Type
12+foreign import data ConsoleMessage :: Type
13+foreign import data Dialog :: Type
14+foreign import data Download :: Type
15+foreign import data FileChooser :: Type
16+foreign import data Keyboard :: Type
17+foreign import data Mouse :: Type
18+foreign import data Request :: Type
19+foreign import data Response :: Type
20+foreign import data Selectors :: Type
21+foreign import data Route :: Type
22+foreign import data Worker :: Type
23+
24+foreign import data ScreenshotType :: Type
25+
26+foreign import png :: ScreenshotType
27+foreign import jpg :: ScreenshotType
28+
29+newtype Selector = Selector String
30+derive newtype instance eqSelector :: Eq Selector
31+derive newtype instance showSelector :: Show Selector
32+derive newtype instance ordSelector :: Ord Selector
33+
34+foreign import firefox :: BrowserType
35+foreign import chromium :: BrowserType
36+foreign import webkit :: BrowserType
src/Playwright.js → src/Playwright/Internal.jsrenamed+6−15
@@ -1,6 +1,4 @@
1−/* global require exports */
2−
3−var P = require('playwright');
1+/* global exports */
42
53/**
64 * @param {string} property - method to call on object
@@ -36,15 +34,8 @@ function effectfulGetter (property, n) {
3634 };
3735}
3836
39−exports.chromium = P.chromium;
40−exports.firefox = P.firefox;
41−exports.webkit = P.webkit;
42−
43−exports._launch = effectfulGetter('launch', 1);
44−exports._close = effectfulGetter('close', 0);
45−exports.contexts = effectfulGetter('contexts', 0);
46−exports.isConnected = effectfulGetter('isConnected', 0);
47−exports.version = effectfulGetter('version', 0);
48−exports._newPage = effectfulGetter('newPage', 1);
49−exports.queryMany_ = effectfulGetter('$$', 1);
50−exports.query_ = effectfulGetter('$', 1);
37+exports.unsafeEffectfulGetter = function (prop) {
38+ return function (argsCount) {
39+ return effectfulGetter(prop, argsCount);
40+ };
41+};
src/Playwright/Internal.pursnew file+59
@@ -0,0 +1,59 @@
1+module Playwright.Internal
2+ ( class NumberOfArgs
3+ , numberOfArgs
4+ , prop
5+ )
6+ where
7+
8+import Type.Proxy
9+import Prelude
10+
11+class NumberOfArgs x where
12+ numberOfArgs :: Proxy x -> Int
13+
14+-- More may be added later...
15+instance numberOfArgsFunction6 :: NumberOfArgs (a -> b -> c -> d -> e -> f -> g) where
16+ numberOfArgs _ = 6
17+
18+else instance numberOfArgsFunction5 :: NumberOfArgs (a -> b -> c -> d -> e -> f) where
19+ numberOfArgs _ = 5
20+
21+else instance numberOfArgsFunction4 :: NumberOfArgs (a -> b -> c -> d -> e) where
22+ numberOfArgs _ = 4
23+
24+else instance numberOfArgsFunction3 :: NumberOfArgs (a -> b -> c -> d) where
25+ numberOfArgs _ = 3
26+
27+else instance numberOfArgsFunction2 :: NumberOfArgs (a -> b -> c) where
28+ numberOfArgs _ = 2
29+
30+else instance numberOfArgsFunction1 :: NumberOfArgs (a -> b) where
31+ numberOfArgs _ = 1
32+
33+else instance numberOfArgsFunction0 :: NumberOfArgs a where
34+ numberOfArgs _ = 0
35+
36+-- | This function is used to prevent "The value of x is undefined here"
37+-- | errors.
38+-- |
39+-- | E.g.:
40+-- |
41+-- | ```purescript
42+-- | url = unsafeEffectfulGetter "url" (countArgs \_ -> url)
43+-- | ```
44+-- |
45+-- | Thus we can guarantee type safety at least in the number of arguments.
46+countArgs :: forall a. NumberOfArgs a => (Unit -> a) -> Int
47+countArgs f = numberOfArgs (proxyOf (f unit)) - 1
48+ where
49+ proxyOf :: forall a. a -> Proxy a
50+ proxyOf _ = Proxy :: Proxy a
51+
52+foreign import unsafeEffectfulGetter
53+ :: forall r
54+ . String
55+ -> Int
56+ -> r
57+
58+prop :: forall f r. NumberOfArgs f => String -> (Unit -> f) -> r
59+prop p f = unsafeEffectfulGetter p (countArgs f)
src/Playwright/Logger.pursnew file+43
@@ -0,0 +1,43 @@
1+module Playwright.Logger where
2+
3+import Prelude
4+import Effect
5+import Control.Promise
6+import Data.Options
7+import Effect.Aff
8+import Foreign
9+import Data.Function.Uncurried
10+import Data.Op
11+import Data.Functor.Contravariant
12+import Prim.Row as Row
13+import Unsafe.Coerce (unsafeCoerce)
14+
15+-- foreign import data LoggerOptions :: Type
16+
17+data Severity = Verbose | Info | Warning | Error
18+
19+showSeverity :: Severity -> String
20+showSeverity Verbose = "verbose"
21+showSeverity Info = "info"
22+showSeverity Warning = "warning"
23+showSeverity Error = "error"
24+
25+-- isEnabled :: Option LoggerOptions (Fn2 String Severity Boolean)
26+-- isEnabled = opt "isEnabled"
27+
28+type LoggerOptions =
29+ ( log :: String -> Severity -> String -> Array String -> Effect Unit
30+ , isEnabled :: String -> Severity -> Boolean
31+ )
32+
33+foreign import data Logger :: Type
34+
35+mkLogger
36+ :: forall o t
37+ . Row.Union o t LoggerOptions
38+ => { | o }
39+ -> Logger
40+mkLogger = unsafeCoerce
41+
42+-- log :: Option LoggerOptions (Fn4 String Severity String (Array String) Unit)
43+-- log = opt "log"
src/Playwright/Options.pursnew file+85
@@ -0,0 +1,85 @@
1+module Playwright.Options where
2+
3+import Data.Options (Option, Options, opt, options)
4+import Playwright.Data
5+import Foreign.Object (Object)
6+import Foreign (Foreign)
7+
8+foreign import data Launch :: Type
9+foreign import data Proxy :: Type
10+
11+headless :: Option Launch Boolean
12+headless = opt "headless"
13+
14+executablePath :: Option Launch String
15+executablePath = opt "executablePath"
16+
17+args :: Option Launch String
18+args = opt "args"
19+
20+ignoreDefaultArgs :: Option Launch (Array String)
21+ignoreDefaultArgs = opt "ignoreDefaultArgs"
22+
23+proxy :: Option Launch (Options Proxy)
24+proxy = opt "proxy"
25+
26+downloadsPath :: Option Launch String
27+downloadsPath = opt "downloadsPath"
28+
29+chromiumSandbox :: Option Launch Boolean
30+chromiumSandbox = opt "chromiumSandbox"
31+
32+firefoxUserPrefs :: Option Launch Foreign
33+firefoxUserPrefs = opt "firefoxUserPrefs"
34+
35+handleSIGINT :: Option Launch Boolean
36+handleSIGINT = opt "handleSIGINT"
37+
38+handleSIGTERM :: Option Launch Boolean
39+handleSIGTERM = opt "handleSIGTERM"
40+
41+handleSIGHUP :: Option Launch Boolean
42+handleSIGHUP = opt "handleSIGHUP"
43+
44+timeout :: Option Launch Number
45+timeout = opt "timeout"
46+
47+env :: Option Launch (Object String)
48+env = opt "env"
49+
50+devtools :: Option Launch Boolean
51+devtools = opt "devtools"
52+
53+slowMo :: Option Launch Number
54+slowMo = opt "slowMo"
55+
56+server :: Option Proxy String
57+server = opt "server"
58+
59+bypass :: Option Proxy String
60+bypass = opt "bypass"
61+
62+username :: Option Proxy String
63+username = opt "username"
64+
65+password :: Option Proxy String
66+password = opt "password"
67+
68+foreign import data Newpage :: Type
69+
70+foreign import data Screenshot :: Type
71+
72+path :: Option Screenshot String
73+path = opt "path"
74+
75+screenshotType :: Option Screenshot ScreenshotType
76+screenshotType = opt "type"
77+
78+quality :: Option Screenshot Number
79+quality = opt "quality"
80+
81+omitBackground :: Option Screenshot Boolean
82+omitBackground = opt "omitBackground"
83+
84+screenshotTimeout :: Option Screenshot Number
85+screenshotTimeout = opt "timeout"
test/Main.purs+6−9
@@ -1,13 +1,12 @@
11module Test.Main where
22
33import Prelude
4+import Playwright (close, firefox, headless, launch, slowMo)
45import Effect (Effect)
5−import Effect.Console (log)
6−import Test.Unit.Assert as Assert
7−import Playwright
8−import Data.Options
9−import Test.Unit
10−import Test.Unit.Main
6+import Data.Options ((:=))
7+import Test.Unit (suite, test)
8+import Test.Unit.Main (runTest)
9+import Untagged.Union (asOneOf)
1110
1211main :: Effect Unit
1312main = runTest do
@@ -16,6 +15,4 @@ main = runTest do
1615 browser <- launch firefox $
1716 headless := false <>
1817 slowMo := 100.0
19−
20− close browser
21− pure unit
18+ close $ asOneOf browser
test/static/index.htmlnew file+8
@@ -0,0 +1,8 @@
1+<!DOCTYPE html>
2+<html>
3+ <head>
4+ </head>
5+ <body>
6+ <div id="someid"></div>
7+ </body>
8+</html>