chore: fmt, event tests
This commit is contained in:
parent
252bbd1b1a
commit
ac1b2227d0
@ -1,4 +0,0 @@
|
||||
/** @template T */
|
||||
export class Maybe {}
|
||||
|
||||
export class Milliseconds {}
|
@ -41,7 +41,9 @@ to generate this file without the comments in this block.
|
||||
, "prelude"
|
||||
, "simple-json"
|
||||
, "spec"
|
||||
, "st"
|
||||
, "strings"
|
||||
, "tailrec"
|
||||
, "transformers"
|
||||
, "tuples"
|
||||
, "unsafe-coerce"
|
||||
|
@ -51,14 +51,14 @@ type Viewport =
|
||||
|
||||
prepareViewport :: Viewport -> Foreign
|
||||
prepareViewport { deviceScaleFactor, hasTouch, height, width, isLandscape, isMobile } =
|
||||
writeImpl
|
||||
{ deviceScaleFactor: FFI.maybeToUndefined deviceScaleFactor
|
||||
, hasTouch: FFI.maybeToUndefined hasTouch
|
||||
, isLandscape: FFI.maybeToUndefined isLandscape
|
||||
, isMobile: FFI.maybeToUndefined isMobile
|
||||
, height
|
||||
, width
|
||||
}
|
||||
writeImpl
|
||||
{ deviceScaleFactor: FFI.maybeToUndefined deviceScaleFactor
|
||||
, hasTouch: FFI.maybeToUndefined hasTouch
|
||||
, isLandscape: FFI.maybeToUndefined isLandscape
|
||||
, isMobile: FFI.maybeToUndefined isMobile
|
||||
, height
|
||||
, width
|
||||
}
|
||||
|
||||
--| [`PuppeteerNode`](https://pptr.dev/api/puppeteer.puppeteernode)
|
||||
foreign import data Puppeteer :: Row Type -> Type
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {Page, JSHandle} from 'puppeteer'
|
||||
import { Page, JSHandle } from 'puppeteer'
|
||||
|
||||
/**
|
||||
* @type {(_: string) => (_: Page | JSHandle<unknown>) => (_: Array<unknown>) => Promise<unknown>}
|
||||
*/
|
||||
/**
|
||||
* @type {(_: string) => (_: Page | JSHandle<unknown>) => (_: Array<unknown>) => Promise<unknown>}
|
||||
*/
|
||||
export const _run = s => h => a => {
|
||||
/** @type {any} */
|
||||
const f = new Function(`return (${s})(...arguments)`)
|
||||
@ -11,9 +11,9 @@ export const _run = s => h => a => {
|
||||
return ev(f, ...a)
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {(_: string) => (_: Page | JSHandle<unknown>) => (_: Array<unknown>) => Promise<JSHandle<unknown>>}
|
||||
*/
|
||||
/**
|
||||
* @type {(_: string) => (_: Page | JSHandle<unknown>) => (_: Array<unknown>) => Promise<JSHandle<unknown>>}
|
||||
*/
|
||||
export const _runh = s => h => a => {
|
||||
/** @type {any} */
|
||||
const f = new Function(`return (${s})(...arguments)`)
|
||||
|
@ -27,19 +27,19 @@ unsafeRunJsHandle0 :: forall e @r. EvalTarget e => String -> e -> Aff (Handle r)
|
||||
unsafeRunJsHandle0 js h = Promise.toAff $ _runh js (unsafeToForeign h) []
|
||||
|
||||
unsafeRunJs1 :: forall a e @r. EvalTarget e => String -> a -> e -> Aff r
|
||||
unsafeRunJs1 js a h = Promise.toAff $ _run js (unsafeToForeign h) [unsafeToForeign a]
|
||||
unsafeRunJs1 js a h = Promise.toAff $ _run js (unsafeToForeign h) [ unsafeToForeign a ]
|
||||
|
||||
unsafeRunJsHandle1 :: forall a e @r. EvalTarget e => String -> a -> e -> Aff (Handle r)
|
||||
unsafeRunJsHandle1 js a h = Promise.toAff $ _runh js (unsafeToForeign h) [unsafeToForeign a]
|
||||
unsafeRunJsHandle1 js a h = Promise.toAff $ _runh js (unsafeToForeign h) [ unsafeToForeign a ]
|
||||
|
||||
unsafeRunJs2 :: forall a b e @r. EvalTarget e => String -> a -> b-> e -> Aff r
|
||||
unsafeRunJs2 js a b h = Promise.toAff $ _run js (unsafeToForeign h) [unsafeToForeign a, unsafeToForeign b]
|
||||
unsafeRunJs2 :: forall a b e @r. EvalTarget e => String -> a -> b -> e -> Aff r
|
||||
unsafeRunJs2 js a b h = Promise.toAff $ _run js (unsafeToForeign h) [ unsafeToForeign a, unsafeToForeign b ]
|
||||
|
||||
unsafeRunJsHandle2 :: forall a b e @r. EvalTarget e => String -> a -> b -> e -> Aff (Handle r)
|
||||
unsafeRunJsHandle2 js a b h = Promise.toAff $ _runh js (unsafeToForeign h) [unsafeToForeign a, unsafeToForeign b]
|
||||
unsafeRunJsHandle2 js a b h = Promise.toAff $ _runh js (unsafeToForeign h) [ unsafeToForeign a, unsafeToForeign b ]
|
||||
|
||||
unsafeRunJs3 :: forall a b c e @r. EvalTarget e => String -> a -> b -> c -> e -> Aff r
|
||||
unsafeRunJs3 js a b c h = Promise.toAff $ _run js (unsafeToForeign h) [unsafeToForeign a, unsafeToForeign b, unsafeToForeign c]
|
||||
unsafeRunJs3 js a b c h = Promise.toAff $ _run js (unsafeToForeign h) [ unsafeToForeign a, unsafeToForeign b, unsafeToForeign c ]
|
||||
|
||||
unsafeRunJsHandle3 :: forall a b c e @r. EvalTarget e => String -> a -> b -> c -> e -> Aff (Handle r)
|
||||
unsafeRunJsHandle3 js a b c h = Promise.toAff $ _runh js (unsafeToForeign h) [unsafeToForeign a, unsafeToForeign b, unsafeToForeign c]
|
||||
unsafeRunJsHandle3 js a b c h = Promise.toAff $ _runh js (unsafeToForeign h) [ unsafeToForeign a, unsafeToForeign b, unsafeToForeign c ]
|
||||
|
@ -10,7 +10,7 @@ export const mergeRecords = rs =>
|
||||
|
||||
/** @type {(m: Array<{k: string, v: any}>) => Record<string, any>} */
|
||||
export const _mapToRecord = map =>
|
||||
map.reduce((r, {k, v}) => {
|
||||
map.reduce((r, { k, v }) => {
|
||||
r[k] = v
|
||||
return r
|
||||
}, emptyRecord())
|
||||
|
@ -15,14 +15,14 @@ import Foreign (Foreign)
|
||||
import Simple.JSON (class WriteForeign)
|
||||
|
||||
foreign import mergeRecords :: Array Foreign -> Foreign
|
||||
foreign import _mapToRecord :: forall a. Array {k :: String, v :: a} -> Foreign
|
||||
foreign import _mapToRecord :: forall a. Array { k :: String, v :: a } -> Foreign
|
||||
foreign import _maybeToUndefined :: forall a. (Maybe a -> Nullable a) -> Maybe a -> Foreign
|
||||
|
||||
makeMap :: forall k v. Ord k => Array { k :: k, v :: v } -> Map k v
|
||||
makeMap = Map.fromFoldable <<< map (\{ k, v } -> Tuple k v)
|
||||
|
||||
mapToRecord :: forall a. WriteForeign a => Map String a -> Foreign
|
||||
mapToRecord = _mapToRecord <<< foldlWithIndex (\k a v -> Array.cons {k, v} a) []
|
||||
mapToRecord = _mapToRecord <<< foldlWithIndex (\k a v -> Array.cons { k, v } a) []
|
||||
|
||||
maybeToUndefined :: forall a. WriteForeign a => Maybe a -> Foreign
|
||||
maybeToUndefined = _maybeToUndefined Nullable.toNullable
|
||||
|
@ -81,35 +81,37 @@ offsetHeight :: forall a. IsElement a => Handle a -> Aff (Array Number)
|
||||
offsetHeight = Eval.unsafeRunJs0 "e => e.offsetHeight"
|
||||
|
||||
attrs :: forall a. IsElement a => Handle a -> Aff (Map String String)
|
||||
attrs = let
|
||||
js = String.joinWith "\n"
|
||||
[ "e => Array.from(e.attributes)"
|
||||
, " .reduce("
|
||||
, " (m, a) => [...m, {k: a.name, v: a.value}],"
|
||||
, " [],"
|
||||
, " )"
|
||||
, " .filter(({k}) => k)"
|
||||
]
|
||||
attrs =
|
||||
let
|
||||
js = String.joinWith "\n"
|
||||
[ "e => Array.from(e.attributes)"
|
||||
, " .reduce("
|
||||
, " (m, a) => [...m, {k: a.name, v: a.value}],"
|
||||
, " [],"
|
||||
, " )"
|
||||
, " .filter(({k}) => k)"
|
||||
]
|
||||
in
|
||||
map FFI.makeMap <<< Eval.unsafeRunJs0 @(Array {k :: String, v :: String}) js
|
||||
map FFI.makeMap <<< Eval.unsafeRunJs0 @(Array { k :: String, v :: String }) js
|
||||
|
||||
computedStyle :: forall a. IsElement a => Handle a -> Aff (Map String String)
|
||||
computedStyle = let
|
||||
computedStyle =
|
||||
let
|
||||
js = String.joinWith "\n"
|
||||
[ "e => {"
|
||||
, " const s = window.getComputedStyle(e)"
|
||||
, " const a = []"
|
||||
, " for (let i = 0; i < s.length; i++) {"
|
||||
, " const k = s.item(i)"
|
||||
, " const v = s.getPropertyValue(k)"
|
||||
, " a.push({k, v})"
|
||||
, " }"
|
||||
, ""
|
||||
, " return a"
|
||||
, "}"
|
||||
]
|
||||
[ "e => {"
|
||||
, " const s = window.getComputedStyle(e)"
|
||||
, " const a = []"
|
||||
, " for (let i = 0; i < s.length; i++) {"
|
||||
, " const k = s.item(i)"
|
||||
, " const v = s.getPropertyValue(k)"
|
||||
, " a.push({k, v})"
|
||||
, " }"
|
||||
, ""
|
||||
, " return a"
|
||||
, "}"
|
||||
]
|
||||
in
|
||||
map FFI.makeMap <<< Eval.unsafeRunJs0 @(Array {k :: String, v :: String}) js
|
||||
map FFI.makeMap <<< Eval.unsafeRunJs0 @(Array { k :: String, v :: String }) js
|
||||
|
||||
value :: Handle HTML.HTMLInputElement -> Aff String
|
||||
value = Eval.unsafeRunJs0 "e => e.value"
|
||||
|
@ -4,14 +4,17 @@ import { ElementHandle } from 'puppeteer'
|
||||
import { JSHandle } from 'puppeteer'
|
||||
|
||||
/** @type {<T>(_: { remoteObject: (_0: string) => T, primitive: (_0: unknown) => T }) => (_: JSHandle<unknown>) => () => T} */
|
||||
export const _id = ({remoteObject, primitive}) => h => () => {
|
||||
const oid = h.remoteObject().objectId
|
||||
if (oid) {
|
||||
return remoteObject(oid)
|
||||
} else {
|
||||
return primitive(h.remoteObject().value)
|
||||
export const _id =
|
||||
({ remoteObject, primitive }) =>
|
||||
h =>
|
||||
() => {
|
||||
const oid = h.remoteObject().objectId
|
||||
if (oid) {
|
||||
return remoteObject(oid)
|
||||
} else {
|
||||
return primitive(h.remoteObject().value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {(_: string) => (_: ElementHandle<HTMLElement>) => Promise<Array<ElementHandle<Node>>>} */
|
||||
export const _find = s => h => h.$$(s)
|
||||
|
@ -60,7 +60,7 @@ import Web.HTML (HTMLElement)
|
||||
import Web.HTML as HTML
|
||||
|
||||
id :: forall a. Handle a -> Effect HandleId
|
||||
id = _id {remoteObject: HandleObject, primitive: HandlePrimitive}
|
||||
id = _id { remoteObject: HandleObject, primitive: HandlePrimitive }
|
||||
|
||||
data HandleId
|
||||
= HandleObject String
|
||||
|
@ -14,7 +14,9 @@ import Prelude
|
||||
import Control.Monad.Except (runExcept)
|
||||
import Data.Array as Array
|
||||
import Data.Either (hush)
|
||||
import Data.Generic.Rep (class Generic)
|
||||
import Data.Maybe (Maybe)
|
||||
import Data.Show.Generic (genericShow)
|
||||
import Foreign (Foreign, unsafeFromForeign)
|
||||
import Puppeteer.Base (Handle)
|
||||
import Puppeteer.FFI as FFI
|
||||
@ -54,6 +56,10 @@ data MessageType
|
||||
| TimeEnd
|
||||
| Verbose
|
||||
|
||||
derive instance eqMessageType :: Eq MessageType
|
||||
derive instance genericMessageType :: Generic MessageType _
|
||||
instance showMessageType :: Show MessageType where show = genericShow
|
||||
|
||||
messageTypeOfString :: String -> MessageType
|
||||
messageTypeOfString "debug" = Debug
|
||||
messageTypeOfString "info" = Info
|
||||
|
@ -41,7 +41,8 @@ import Puppeteer.Page.Event.Dialog (Dialog)
|
||||
import Simple.JSON (class ReadForeign, readImpl)
|
||||
|
||||
connectPageConsole :: Page -> Aff Unit
|
||||
connectPageConsole p = let
|
||||
connectPageConsole p =
|
||||
let
|
||||
onmsg m = do
|
||||
title <- Page.title p
|
||||
let t = ConsoleMessage.messageType m
|
||||
|
@ -138,7 +138,7 @@ close = Promise.toAff <<< _close
|
||||
content :: Page -> Aff String
|
||||
content = Promise.toAff <<< _content
|
||||
|
||||
setContent :: String -> LifecycleEvent -> Page -> Aff Unit
|
||||
setContent :: String -> LifecycleEvent -> Page -> Aff Unit
|
||||
setContent s ev = Promise.toAff <<< _setContent s (prepareLifecycleEvent ev)
|
||||
|
||||
setViewport :: Viewport -> Page -> Aff Unit
|
||||
|
78
test/Puppeteer.Page.Event.Spec.purs
Normal file
78
test/Puppeteer.Page.Event.Spec.purs
Normal file
@ -0,0 +1,78 @@
|
||||
module Puppeteer.Page.Event.Spec where
|
||||
|
||||
import Prelude
|
||||
|
||||
import Control.Monad.Error.Class (liftMaybe)
|
||||
import Control.Monad.Rec.Class (untilJust)
|
||||
import Control.Monad.ST.Class (liftST)
|
||||
import Control.Monad.ST.Global as ST
|
||||
import Control.Monad.ST.Ref as ST.Ref
|
||||
import Data.Array as Array
|
||||
import Data.Array.NonEmpty as NonEmptyArray
|
||||
import Data.Map as Map
|
||||
import Data.Maybe (Maybe(..))
|
||||
import Data.Newtype (wrap)
|
||||
import Data.Time.Duration (Milliseconds(..))
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Aff, forkAff, joinFiber, makeAff)
|
||||
import Effect.Class (liftEffect)
|
||||
import Effect.Exception (error)
|
||||
import Effect.Exception as Error
|
||||
import Puppeteer as Pup
|
||||
import Puppeteer.Base (timeoutThrow)
|
||||
import Puppeteer.Handle as Pup.Handle
|
||||
import Puppeteer.Handle.HTML as Pup.Handle.HTML
|
||||
import Puppeteer.Keyboard as Pup.Keyboard
|
||||
import Puppeteer.Page as Pup.Page
|
||||
import Puppeteer.Page.Event (connectPageConsole)
|
||||
import Puppeteer.Page.Event as Pup.Page.Event
|
||||
import Puppeteer.Page.Event.ConsoleMessage as ConsoleMessage
|
||||
import Puppeteer.Page.WaitFor as Pup.Page.WaitFor
|
||||
import Test.Spec (SpecT, afterAll, beforeAll, describe)
|
||||
import Test.Spec.Assertions (shouldEqual)
|
||||
import Test.Util (failOnPageError, test)
|
||||
|
||||
scriptError :: String
|
||||
scriptError = "throw new Error('eek!')"
|
||||
|
||||
scriptLog :: String
|
||||
scriptLog = "console.log('beak')"
|
||||
|
||||
listenIntoSTArray :: forall e ed. Pup.Page.Event.Event e ed => e -> Pup.Page -> Aff ({ st :: ST.Ref.STRef ST.Global (Array ed), cleanup :: Aff Unit })
|
||||
listenIntoSTArray e p = do
|
||||
st <- liftST $ ST.Ref.new []
|
||||
let
|
||||
handle ed = do
|
||||
eds <- liftST $ ST.Ref.read st
|
||||
_ <- liftST $ ST.Ref.write (eds <> [ ed ]) st
|
||||
pure unit
|
||||
t <- Pup.Page.Event.listen e handle p
|
||||
pure { st, cleanup: Pup.closeContext t }
|
||||
|
||||
spec :: SpecT Aff Unit Effect Unit
|
||||
spec =
|
||||
beforeAll (Pup.Page.new =<< Pup.launch_ =<< Pup.puppeteer unit)
|
||||
$ afterAll Pup.Page.close
|
||||
$ describe "Page" do
|
||||
test "listen, PageError" \p -> do
|
||||
{ st: errsST, cleanup } <- listenIntoSTArray Pup.Page.Event.PageError p
|
||||
_ <- Pup.Page.addScriptTag (Pup.Page.AddScriptInline Pup.Page.Script scriptError) p
|
||||
err <- timeoutThrow (wrap 1000.0)
|
||||
$ untilJust do
|
||||
errs <- liftST $ ST.Ref.read errsST
|
||||
pure $ Array.head errs
|
||||
Error.message err `shouldEqual` "eek!"
|
||||
cleanup
|
||||
|
||||
test "once" \p -> do
|
||||
errF <- forkAff $ Pup.Page.Event.once Pup.Page.Event.PageError p
|
||||
_ <- Pup.Page.addScriptTag (Pup.Page.AddScriptInline Pup.Page.Script scriptError) p
|
||||
err <- joinFiber errF
|
||||
Error.message err `shouldEqual` "eek!"
|
||||
|
||||
test "Console" \p -> do
|
||||
logF <- forkAff $ Pup.Page.Event.once Pup.Page.Event.Console p
|
||||
_ <- Pup.Page.addScriptTag (Pup.Page.AddScriptInline Pup.Page.Script scriptLog) p
|
||||
log <- joinFiber logF
|
||||
ConsoleMessage.text log `shouldEqual` "beak"
|
||||
ConsoleMessage.messageType log `shouldEqual` ConsoleMessage.Log
|
@ -105,13 +105,15 @@ spec = beforeAll (Pup.launch_ =<< Pup.puppeteer unit)
|
||||
|
||||
test "setViewport, viewport" \b -> do
|
||||
p <- Pup.Page.new b
|
||||
let vp = { deviceScaleFactor: Nothing
|
||||
, hasTouch: Nothing
|
||||
, height: 1200
|
||||
, width: 800
|
||||
, isLandscape: Nothing
|
||||
, isMobile: Nothing
|
||||
}
|
||||
let
|
||||
vp =
|
||||
{ deviceScaleFactor: Nothing
|
||||
, hasTouch: Nothing
|
||||
, height: 1200
|
||||
, width: 800
|
||||
, isLandscape: Nothing
|
||||
, isMobile: Nothing
|
||||
}
|
||||
|
||||
Pup.Page.setViewport vp p
|
||||
vp' <- liftMaybe (error "no viewport!") $ Pup.Page.viewport p
|
||||
|
@ -18,6 +18,7 @@ import Node.Process as Process
|
||||
import Node.Stream as Writable
|
||||
import Puppeteer.Browser.Spec as Spec.Browser
|
||||
import Puppeteer.Page.Spec as Spec.Page
|
||||
import Puppeteer.Page.Event.Spec as Spec.Page.Event
|
||||
import Puppeteer.Spec as Spec
|
||||
import Test.Spec (SpecT)
|
||||
import Test.Spec.Config (defaultConfig)
|
||||
@ -32,6 +33,7 @@ specs = do
|
||||
Spec.spec
|
||||
Spec.Browser.spec
|
||||
Spec.Page.spec
|
||||
Spec.Page.Event.spec
|
||||
|
||||
main :: Effect Unit
|
||||
main = launchAff_ do
|
||||
|
@ -27,7 +27,8 @@ testA :: forall m t arg g. MonadAff g => Monad m => Example t arg Aff => String
|
||||
testA = test_ liftAff
|
||||
|
||||
failOnPageError :: forall a. Pup.Page -> Aff a -> Aff a
|
||||
failOnPageError p a = let
|
||||
failOnPageError p a =
|
||||
let
|
||||
ok = parallel $ try a
|
||||
err = parallel $ Left <$> Pup.Page.Event.once Pup.Page.Event.PageError p
|
||||
in
|
||||
|
Loading…
Reference in New Issue
Block a user