diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c5d11e..35cf944 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,20 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Run tests - run: | - PATH="$PATH:./node_modules/.bin/" - npm install - npm install spago@next purescript - npx playwright install --with-deps chromium - spago test + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - run: npm install + - run: npm install purescript + - run: npx playwright install --with-deps chromium + - run: npx spago@next test + + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - run: npm run check diff --git a/package.json b/package.json index 2c3123f..53f516a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "playwright": "^1.45.1" }, "scripts": { - "test": "pulp test" + "test": "npx spago@next test", + "format": "npx prettier --write src/**/*.js test/**/*.js; npx purs-tidy format-in-place src/**/*.purs test/**/*.purs", + "check": "npx prettier --check src/**/*.js test/**/*.js; npx purs-tidy check src/**/*.purs test/**/*.purs" }, "repository": { "type": "git", diff --git a/src/Playwright.js b/src/Playwright.js index bfca7f7..2486342 100644 --- a/src/Playwright.js +++ b/src/Playwright.js @@ -1,21 +1,21 @@ /* global exports */ -export const exposeBinding_ = x => name => cb => opts => () => { +export const exposeBinding_ = (x) => (name) => (cb) => (opts) => () => { return x.exposeBinding( name, function (info, arg) { - return cb(info)(arg)() + return cb(info)(arg)(); }, - opts - ) -} + opts, + ); +}; export const onResponse = function (page) { - return function (cb) { - return function () { - page.on('response', function (response) { - cb(response)(); - }); - }; + return function (cb) { + return function () { + page.on("response", function (response) { + cb(response)(); + }); }; + }; }; diff --git a/src/Playwright.purs b/src/Playwright.purs index fe95bfb..80882f1 100644 --- a/src/Playwright.purs +++ b/src/Playwright.purs @@ -1,57 +1,55 @@ module Playwright - ( launch - , connect - , connectOverCDP - , close - , contexts - , context - , isConnected - , version - , newPage - , goForward - , goBack - , goto - , addCookies - , cookies - , hover - , innerHTML - , innerText - , isClosed - , keyboard - , mainFrame - , name - , query - , queryMany - , screenshot - , textContent - , url - , addInitScript - , clearCookies - , click - , content - , dblclick - , evaluate - , evaluateHandle - , waitForNavigation - , waitForRequest - , waitForResponse - , waitForSelector - , waitForFunction - , waitForLoadState - , waitForTimeout - , pdf - , setInputFiles - , setViewportSize - , title - , exposeBinding - , fill - , focus - , onResponse - , connect - , module Playwright.Data - , module Playwright.Options - ) -where + ( launch + , connect + , connectOverCDP + , close + , contexts + , context + , isConnected + , version + , newPage + , goForward + , goBack + , goto + , addCookies + , cookies + , hover + , innerHTML + , innerText + , isClosed + , keyboard + , mainFrame + , name + , query + , queryMany + , screenshot + , textContent + , url + , addInitScript + , clearCookies + , click + , content + , dblclick + , evaluate + , evaluateHandle + , waitForNavigation + , waitForRequest + , waitForResponse + , waitForSelector + , waitForFunction + , waitForLoadState + , waitForTimeout + , pdf + , setInputFiles + , setViewportSize + , title + , exposeBinding + , fill + , focus + , onResponse + , module Playwright.Data + , module Playwright.Options + ) where import Playwright.Options @@ -60,34 +58,43 @@ import Data.String.Regex (Regex) import Data.Unit (unit) import Effect (Effect) import Effect.Aff (Aff) -import Foreign (Foreign, unsafeToForeign) +import Foreign (Foreign) import Literals.Null (Null) import Node.Buffer (Buffer) import Playwright.Data (Browser, BrowserContext, BrowserType, ConsoleMessage, Dialog, Download, ElementHandle, ElementState, FileChooser, Frame, JSHandle, Keyboard, Modifier, Mouse, MouseButton, Page, Raf, Request, Response, Route, ScreenshotType, Selector(..), Selectors, URL(..), WaitUntil, Worker, alt, attached, chromium, control, detached, domcontentloaded, firefox, hidden, jpg, left, load, meta, middle, networkidle, png, raf, right, shift, visible, webkit) import Playwright.Internal (effCall, effProp, affCall) import Prelude (Unit, ($)) import Untagged.Castable (class Castable) -import Untagged.Union (type (|+|), UndefinedOr) +import Untagged.Union (type (|+|)) import Playwright.Types (Cookie) foreign import onResponse :: Page -> (Response -> Effect Unit) -> Effect Unit fill :: forall o - . Castable o FillOptions - => Page -> Selector -> String -> o -> Aff Unit + . Castable o FillOptions + => Page + -> Selector + -> String + -> o + -> Aff Unit fill = affCall "fill" \_ -> fill focus :: forall o - . Castable o FocusOptions - => Page -> Selector -> o -> Aff Unit + . Castable o FocusOptions + => Page + -> Selector + -> o + -> Aff Unit focus = affCall "focus" \_ -> focus launch :: forall o - . Castable o LaunchOptions - => BrowserType -> o -> Aff Browser + . Castable o LaunchOptions + => BrowserType + -> o + -> Aff Browser launch = affCall "launch" \_ -> launch @@ -102,10 +109,6 @@ connect -> Aff Browser connect = affCall "connect" \_ -> connect -type ConnectOptions = - { timeout :: UndefinedOr Number - } - connectOverCDP :: forall o . Castable o ConnectOverCDPOptions @@ -116,14 +119,11 @@ connectOverCDP connectOverCDP = affCall "connectOverCDP" \_ -> connectOverCDP -type ConnectOverCDPOptions = - { timeout :: UndefinedOr Number - } - close :: forall x - . Castable x (Browser |+| BrowserContext |+| Page) - => x -> Aff Unit + . Castable x (Browser |+| BrowserContext |+| Page) + => x + -> Aff Unit close = affCall "close" \_ -> close @@ -141,31 +141,40 @@ version = newPage :: forall x o - . Castable x (Browser |+| BrowserContext) + . Castable x (Browser |+| BrowserContext) => Castable o NewpageOptions - => x -> o -> Aff Page + => x + -> o + -> Aff Page newPage = affCall "newPage" \_ -> newPage goForward :: forall o - . Castable o GoOptions - => Page -> o -> Aff (Null |+| Response) + . Castable o GoOptions + => Page + -> o + -> Aff (Null |+| Response) goForward = affCall "goForward" \_ -> goForward goBack :: forall o - . Castable o GoOptions - => Page -> o -> Aff (Null |+| Response) -goBack = + . Castable o GoOptions + => Page + -> o + -> Aff (Null |+| Response) +goBack = affCall "goBack" \_ -> goBack goto :: forall x o - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => Castable o GotoOptions - => x -> URL -> o -> Aff (Null |+| Response) + => x + -> URL + -> o + -> Aff (Null |+| Response) goto = affCall "goto" \_ -> goto @@ -177,7 +186,7 @@ cookies -> Aff (Array Cookie) cookies = affCall "cookies" \_ -> cookies - + addCookies :: BrowserContext -> Array Cookie @@ -187,29 +196,34 @@ addCookies = hover :: forall x o - . Castable x (Page |+| Frame |+| ElementHandle) + . Castable x (Page |+| Frame |+| ElementHandle) => Castable o HoverOptions - => x -> o -> Aff Unit + => x + -> o + -> Aff Unit hover = affCall "hover" \_ -> hover innerHTML :: forall x o - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => Castable o InnerHTMLOptions - => x -> Selector -> o -> Aff String + => x + -> Selector + -> o + -> Aff String innerHTML = affCall "innerHTML" \_ -> innerHTML innerText :: forall x o - . Castable o InnerTextOptions + . Castable o InnerTextOptions => Castable x (Page |+| Frame |+| ElementHandle) => x -> Selector -> o -> Aff String -innerText = +innerText = affCall "innerText" \_ -> innerText isClosed :: Page -> Effect Boolean @@ -227,37 +241,45 @@ name = effCall "name" \_ -> name -- | `sth.$(selector)` query :: forall x - . Castable x (ElementHandle |+| Page |+| Frame) - => x -> Selector -> Aff (Null |+| ElementHandle) + . Castable x (ElementHandle |+| Page |+| Frame) + => x + -> Selector + -> Aff (Null |+| ElementHandle) query = affCall "$" \_ -> query -- | `sth.$$(selector)` queryMany :: forall x - . Castable x (ElementHandle |+| Page |+| Frame) - => x -> Selector -> Aff (Array ElementHandle) + . Castable x (ElementHandle |+| Page |+| Frame) + => x + -> Selector + -> Aff (Array ElementHandle) queryMany = affCall "$$" \_ -> queryMany screenshot :: forall x o - . Castable x (ElementHandle |+| Page) + . Castable x (ElementHandle |+| Page) => Castable o ScreenshotOptions - => x -> o -> Aff Buffer + => x + -> o + -> Aff Buffer screenshot = affCall "screenshot" \_ -> screenshot textContent :: forall x - . Castable x (Page |+| Frame |+| ElementHandle) - => x -> Selector -> Aff (Null |+| String) + . Castable x (Page |+| Frame |+| ElementHandle) + => x + -> Selector + -> Aff (Null |+| String) textContent = affCall "textContent" \_ -> textContent url :: forall x - . Castable x (Page |+| Frame |+| Download |+| Request |+| Response |+| Worker) + . Castable x (Page |+| Frame |+| Download |+| Request |+| Response |+| Worker) => x -> Effect URL url = @@ -265,7 +287,7 @@ url = addInitScript :: forall x o - . Castable x (Page |+| BrowserContext) + . Castable x (Page |+| BrowserContext) => Castable o AddInitScriptOptions => x -> o @@ -279,7 +301,7 @@ clearCookies = click :: forall x o - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => Castable o ClickOptions => x -> Selector @@ -290,7 +312,7 @@ click = content :: forall x - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => x -> Aff String content = @@ -298,7 +320,7 @@ content = dblclick :: forall x o - . Castable x (Page |+| Frame |+| ElementHandle) + . Castable x (Page |+| Frame |+| ElementHandle) => Castable o ClickOptions => x -> Selector @@ -309,7 +331,7 @@ dblclick = evaluate :: forall x - . Castable x (Page |+| Frame |+| Worker |+| JSHandle) + . Castable x (Page |+| Frame |+| Worker |+| JSHandle) => x -> String -- ^ Function to be evaluated in browser context @@ -319,7 +341,7 @@ evaluate = evaluateHandle :: forall x - . Castable x (Page |+| Frame |+| Worker |+| JSHandle) + . Castable x (Page |+| Frame |+| Worker |+| JSHandle) => x -> String -- ^ Function to be evaluated in browser context @@ -329,7 +351,7 @@ evaluateHandle = waitForNavigation :: forall x o - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => Castable o WaitForNavigationOptions => x -> o @@ -339,7 +361,7 @@ waitForNavigation = waitForRequest :: forall url o - . Castable url (URL |+| Regex |+| URL -> Boolean) + . Castable url (URL |+| Regex |+| URL -> Boolean) => Castable o WaitForRequestOptions => Page -> url @@ -349,7 +371,7 @@ waitForRequest = affCall "waitForRequest" \_ -> waitForRequest waitForResponse :: forall url o - . Castable url (URL |+| Regex |+| URL -> Boolean) + . Castable url (URL |+| Regex |+| URL -> Boolean) => Castable o WaitForResponseOptions => Page -> url @@ -359,7 +381,7 @@ waitForResponse = affCall "waitForResponse" \_ -> waitForResponse waitForSelector :: forall x o - . Castable x (Page |+| Frame |+| ElementHandle) + . Castable x (Page |+| Frame |+| ElementHandle) => Castable o WaitForSelectorOptions => x -> Selector @@ -369,7 +391,7 @@ waitForSelector = affCall "waitForSelector" \_ -> waitForSelector waitForFunction :: forall x o - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => Castable o WaitForFunctionOptions => x -> String @@ -378,11 +400,11 @@ waitForFunction -> Aff JSHandle waitForFunction x s o = waitForFunction' x s unit o where - waitForFunction' = affCall "waitForFunction" \_ -> waitForFunction' + waitForFunction' = affCall "waitForFunction" \_ -> waitForFunction' waitForLoadState :: forall x o - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => Castable o WaitForLoadStateOptions => x -> WaitUntil @@ -392,7 +414,7 @@ waitForLoadState = affCall "waitForLoadState" \_ -> waitForLoadState waitForTimeout :: forall x - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => x -> Int -> Aff Unit @@ -400,7 +422,7 @@ waitForTimeout = affCall "waitForTimeout" \_ -> waitForTimeout pdf :: forall o - . Castable o PdfOptions + . Castable o PdfOptions => Page -> o -> Aff Buffer @@ -408,20 +430,22 @@ pdf = affCall "pdf" \_ -> pdf setInputFiles :: forall x o f - . Castable x (Page |+| Frame |+| ElementHandle) + . Castable x (Page |+| Frame |+| ElementHandle) => Castable o SetFilesOptions => Castable f - ( String - |+| Array String - |+| { name :: String - , mimeType :: String - , buffer :: Buffer - } - |+| Array { name :: String + ( String + |+| Array String + |+| + { name :: String , mimeType :: String , buffer :: Buffer } - ) + |+| Array + { name :: String + , mimeType :: String + , buffer :: Buffer + } + ) => x -> Selector -> f @@ -431,50 +455,46 @@ setInputFiles = affCall "setInputFiles" \_ -> setInputFiles setViewportSize :: Page - -> { width :: Number + -> { width :: Number , height :: Number } - -> Aff Unit + -> Aff Unit setViewportSize = affCall "setViewportSize" \_ -> setViewportSize title :: forall x - . Castable x (Page |+| Frame) + . Castable x (Page |+| Frame) => x -> Aff String title = affCall "title" \_ -> title exposeBinding :: forall x b - . Castable x (Page |+| BrowserContext) + . Castable x (Page |+| BrowserContext) => x -> String -- ^ Name of the function on the window object. - -> - ( - { browserContext :: BrowserContext - , page :: Page - , frame :: Frame - } - -> Foreign - -> Aff b - ) + -> ( { browserContext :: BrowserContext + , page :: Page + , frame :: Frame + } + -> Foreign + -> Aff b + ) -> Aff Unit exposeBinding x binding f = toAffE $ exposeBinding_ x binding (\d a -> fromAff $ f d a) { handle: false } foreign import exposeBinding_ :: forall x a b - . x + . x -> String - -> - ( - { browserContext :: BrowserContext - , page :: Page - , frame :: Frame - } - -> a - -> Effect (Promise b) - ) + -> ( { browserContext :: BrowserContext + , page :: Page + , frame :: Frame + } + -> a + -> Effect (Promise b) + ) -> { handle :: Boolean } -> Effect (Promise Unit) diff --git a/src/Playwright/ConsoleMessage.purs b/src/Playwright/ConsoleMessage.purs index f3aadc6..9712498 100644 --- a/src/Playwright/ConsoleMessage.purs +++ b/src/Playwright/ConsoleMessage.purs @@ -15,9 +15,24 @@ type ConsoleMessageLocation = } data ConsoleMessageType - = Log | Debug | Info | Error | Warning | Dir | Dirxml | Table | Trace | Clear - | StartGroup | StartGroupCollapsed | EndGroup | Assert | Profile | ProfileEnd - | Count | TimeEnd + = Log + | Debug + | Info + | Error + | Warning + | Dir + | Dirxml + | Table + | Trace + | Clear + | StartGroup + | StartGroupCollapsed + | EndGroup + | Assert + | Profile + | ProfileEnd + | Count + | TimeEnd derive instance genericConsoleMessageType :: Generic ConsoleMessageType _ derive instance eqConsoleMessageType :: Eq ConsoleMessageType @@ -37,25 +52,25 @@ text = effCall "text" \_ -> text type' :: ConsoleMessage -> Effect ConsoleMessageType type' = map convert <<< type'' where - type'' :: ConsoleMessage -> Effect String - type'' = effCall "type" \_ -> type'' - convert = case _ of - "log" -> Log - "debug" -> Debug - "info" -> Info - "error" -> Error - "warning" -> Warning - "dir" -> Dir - "dirxml" -> Dirxml - "table" -> Table - "trace" -> Trace - "clear" -> Clear - "startGroup" -> StartGroup - "startGroupCollapsed" -> StartGroupCollapsed - "endGroup" -> EndGroup - "assert" -> Assert - "profile" -> Profile - "profileEnd" -> ProfileEnd - "count" -> Count - "timeEnd" -> TimeEnd - _ -> Log -- impossible + type'' :: ConsoleMessage -> Effect String + type'' = effCall "type" \_ -> type'' + convert = case _ of + "log" -> Log + "debug" -> Debug + "info" -> Info + "error" -> Error + "warning" -> Warning + "dir" -> Dir + "dirxml" -> Dirxml + "table" -> Table + "trace" -> Trace + "clear" -> Clear + "startGroup" -> StartGroup + "startGroupCollapsed" -> StartGroupCollapsed + "endGroup" -> EndGroup + "assert" -> Assert + "profile" -> Profile + "profileEnd" -> ProfileEnd + "count" -> Count + "timeEnd" -> TimeEnd + _ -> Log -- impossible diff --git a/src/Playwright/Data.js b/src/Playwright/Data.js index 5f0b07b..6bb6801 100644 --- a/src/Playwright/Data.js +++ b/src/Playwright/Data.js @@ -1,5 +1,9 @@ /* global require exports */ -import { chromium as pwChromium, firefox as pwFirefox, webkit as pwWebkit } from 'playwright'; +import { + chromium as pwChromium, + firefox as pwFirefox, + webkit as pwWebkit, +} from "playwright"; export const png = "png"; export const jpg = "jpg"; diff --git a/src/Playwright/Data.purs b/src/Playwright/Data.purs index 1d51267..b2ef124 100644 --- a/src/Playwright/Data.purs +++ b/src/Playwright/Data.purs @@ -1,8 +1,6 @@ module Playwright.Data where import Prelude -import Untagged.TypeCheck (class HasRuntimeType) -import Foreign (Foreign) foreign import data BrowserType :: Type foreign import data Browser :: Type @@ -29,11 +27,13 @@ foreign import png :: ScreenshotType foreign import jpg :: ScreenshotType newtype Selector = Selector String + derive newtype instance eqSelector :: Eq Selector derive newtype instance showSelector :: Show Selector derive newtype instance ordSelector :: Ord Selector newtype URL = URL String + derive newtype instance eqURL :: Eq URL derive newtype instance showURL :: Show URL derive newtype instance ordURL :: Ord URL diff --git a/src/Playwright/Dialog.purs b/src/Playwright/Dialog.purs index db7a509..befb0f8 100644 --- a/src/Playwright/Dialog.purs +++ b/src/Playwright/Dialog.purs @@ -23,10 +23,10 @@ data DialogType = Alert | Beforeunload | Confirm | Prompt type' :: Dialog -> Effect DialogType type' = map convert <<< type'' where - type'' = effCall "type" \_ -> type'' - convert = case _ of - "alert" -> Alert - "beforeunload" -> Beforeunload - "confirm" -> Confirm - "prompt" -> Prompt - _ -> Alert -- impossible + type'' = effCall "type" \_ -> type'' + convert = case _ of + "alert" -> Alert + "beforeunload" -> Beforeunload + "confirm" -> Confirm + "prompt" -> Prompt + _ -> Alert -- impossible diff --git a/src/Playwright/Download.js b/src/Playwright/Download.js index 480286e..c5708e4 100644 --- a/src/Playwright/Download.js +++ b/src/Playwright/Download.js @@ -1,10 +1,10 @@ /* global exports */ -export const createReadStream_ = Nothing => Just => Download => () => - Download.createReadStream().then(result => { +export const createReadStream_ = (Nothing) => (Just) => (Download) => () => + Download.createReadStream().then((result) => { if (result === null) { - return Nothing + return Nothing; } else { - return Just(result) + return Just(result); } - }) + }); diff --git a/src/Playwright/Download.purs b/src/Playwright/Download.purs index e57b9bd..53d42dc 100644 --- a/src/Playwright/Download.purs +++ b/src/Playwright/Download.purs @@ -1,13 +1,12 @@ module Playwright.Download - ( createReadStream - , suggestedFilename - , saveAs - , path - , url - , failure - , delete - ) -where + ( createReadStream + , suggestedFilename + , saveAs + , path + , url + , failure + , delete + ) where import Control.Promise (Promise, toAffE) import Data.Maybe (Maybe(..)) diff --git a/src/Playwright/Event.js b/src/Playwright/Event.js index 23f1828..0149e6e 100644 --- a/src/Playwright/Event.js +++ b/src/Playwright/Event.js @@ -2,6 +2,6 @@ export const onForeign = (obj) => (eventName) => (effCallback) => () => { obj.on(eventName, (argument) => { - effCallback(argument)() - }) -} + effCallback(argument)(); + }); +}; diff --git a/src/Playwright/Event.purs b/src/Playwright/Event.purs index b3e1a91..8d0cb4a 100644 --- a/src/Playwright/Event.purs +++ b/src/Playwright/Event.purs @@ -1,5 +1,4 @@ -module Playwright.Event -where +module Playwright.Event where import Type.Proxy (Proxy(..)) import Effect (Effect) @@ -8,122 +7,177 @@ import Playwright.Data (Browser, BrowserContext, ConsoleMessage) import Playwright.Data as Data import Effect.Exception (Error) +class Event :: forall k. k -> Constraint class Event e where getEventName :: Proxy e -> String +class OnEvent :: forall k1 k2 k3. k1 -> k2 -> k3 -> Constraint class Event e <= OnEvent x e a | x e -> a -- | Our own `Proxy` for event names. +data EventName :: forall k. k -> Type data EventName a = EventName foreign import data Close :: Type -instance eventClose :: Event Close where getEventName _ = "close" + +instance eventClose :: Event Close where + getEventName _ = "close" + instance eventPageClose :: OnEvent Data.Page Close Unit instance eventBrowserContextClose :: OnEvent BrowserContext Close Unit instance eventBrowserClose :: OnEvent Browser Close Unit instance eventWorkerClose :: OnEvent Worker Close Unit + close :: EventName Close close = EventName foreign import data Console :: Type -instance eventConsole :: Event Console where getEventName _ = "console" + +instance eventConsole :: Event Console where + getEventName _ = "console" + instance eventPageConsole :: OnEvent Data.Page Console ConsoleMessage + console :: EventName Console console = EventName foreign import data Crash :: Type -instance eventCrash :: Event Crash where getEventName _ = "crash" + +instance eventCrash :: Event Crash where + getEventName _ = "crash" + instance eventPageCrash :: OnEvent Data.Page Crash Unit + crash :: EventName Crash crash = EventName foreign import data Dialog :: Type -instance eventDialog :: Event Dialog where getEventName _ = "dialog" + +instance eventDialog :: Event Dialog where + getEventName _ = "dialog" + instance eventPageDialog :: OnEvent Data.Page Dialog Data.Dialog + dialog :: EventName Dialog dialog = EventName foreign import data DomContentLoaded :: Type + instance eventDomContentLoaded :: Event DomContentLoaded where getEventName _ = "domcontentloaded" + instance eventPageDomContentLoaded :: OnEvent Data.Page DomContentLoaded Unit + domcontentloaded :: EventName DomContentLoaded domcontentloaded = EventName foreign import data Download :: Type + instance eventDownload :: Event Download where getEventName _ = "download" + instance eventPageDownload :: OnEvent Data.Page Download Data.Download + download :: EventName Download download = EventName foreign import data FileChooser :: Type + instance eventFileChooser :: Event FileChooser where getEventName _ = "filechooser" + instance eventPageFileChooser :: OnEvent Data.Page FileChooser Data.FileChooser + filechooser :: EventName FileChooser filechooser = EventName foreign import data PageError :: Type -instance eventPageError :: Event PageError where getEventName _ = "pageerror" + +instance eventPageError :: Event PageError where + getEventName _ = "pageerror" + instance eventPagePageError :: OnEvent Data.Page PageError Error + pageerror :: EventName PageError pageerror = EventName foreign import data Popup :: Type -instance eventPopup :: Event Popup where getEventName _ = "popup" + +instance eventPopup :: Event Popup where + getEventName _ = "popup" + instance eventPagePopup :: OnEvent Data.Page Popup Page + popup :: EventName Popup popup = EventName foreign import data Request :: Type -instance eventRequest :: Event Request where getEventName _ = "request" + +instance eventRequest :: Event Request where + getEventName _ = "request" + instance eventPageRequest :: OnEvent Data.Page Request Data.Request + request :: EventName Request request = EventName foreign import data RequestFailed :: Type + instance eventRequestFailed :: Event RequestFailed where getEventName _ = "requestfailed" + instance eventPageRequestFailed :: OnEvent Data.Page RequestFailed Data.Request + requestfailed :: EventName RequestFailed requestfailed = EventName foreign import data RequestFinished :: Type + instance eventRequestFinished :: Event RequestFinished where getEventName _ = "requestfinished" + instance eventPageRequestFinished :: OnEvent Data.Page RequestFinished Data.Request + requestfinished :: EventName RequestFinished requestfinished = EventName foreign import data Response :: Type + instance eventResponse :: Event Response where getEventName _ = "response" + instance eventPageResponse :: OnEvent Data.Page Response Data.Response + response :: EventName Response response = EventName foreign import data Worker :: Type + instance eventWorker :: Event Worker where getEventName _ = "worker" + instance eventPageWorker :: OnEvent Data.Page Worker Data.Worker + worker :: EventName Worker worker = EventName foreign import data Page :: Type + instance eventPage :: Event Page where getEventName _ = "page" + instance eventPagePage :: OnEvent BrowserContext Page Data.Page + page :: EventName Page page = EventName on :: forall x e a r - . OnEvent x e a + . OnEvent x e a => EventName e -> x -> (a -> Effect r) -> Effect Unit -on event obj callback = onForeign obj (getEventName (Proxy :: Proxy e)) callback +on _ obj callback = onForeign obj (getEventName (Proxy :: Proxy e)) callback foreign import onForeign :: forall x a r. x -> String -> (a -> Effect r) -> Effect Unit diff --git a/src/Playwright/FileChooser.purs b/src/Playwright/FileChooser.purs index 9d96d8b..ee75775 100644 --- a/src/Playwright/FileChooser.purs +++ b/src/Playwright/FileChooser.purs @@ -21,19 +21,21 @@ page = effCall "page" \_ -> page setFiles :: forall o f - . Castable o SetFilesOptions + . Castable o SetFilesOptions => Castable f - ( String - |+| Array String - |+| { name :: String - , mimeType :: String - , buffer :: Buffer - } - |+| Array { name :: String + ( String + |+| Array String + |+| + { name :: String , mimeType :: String , buffer :: Buffer } - ) + |+| Array + { name :: String + , mimeType :: String + , buffer :: Buffer + } + ) => FileChooser -> f -> o diff --git a/src/Playwright/Internal.js b/src/Playwright/Internal.js index df0f500..34920d9 100644 --- a/src/Playwright/Internal.js +++ b/src/Playwright/Internal.js @@ -18,34 +18,34 @@ * * effectfulGetter('close', 0, identity); */ -function effectfulGetter (property, argsCount, effectRunnerWrapper) { - function consume(arg, args, counter) { - const argsNew = [ ...args, arg ]; +function effectfulGetter(property, argsCount, effectRunnerWrapper) { + function consume(arg, args, counter) { + const argsNew = [...args, arg]; - if (counter === 0) { - const [ object, ...rest ] = argsNew; + if (counter === 0) { + const [object, ...rest] = argsNew; - return effectRunnerWrapper(() => object[property].apply(object, rest)) - } else { - return (a) => consume(a, argsNew, counter - 1) - } + return effectRunnerWrapper(() => object[property].apply(object, rest)); + } else { + return (a) => consume(a, argsNew, counter - 1); } + } - return (object) => consume(object, [], argsCount) + return (object) => consume(object, [], argsCount); } -function identity (x) { +function identity(x) { return x; } export function unsafeEffCall(method) { - return argsCount => effectfulGetter(method, argsCount, identity); + return (argsCount) => effectfulGetter(method, argsCount, identity); } export function unsafeAffCall(toAffE) { - return method => argsCount => effectfulGetter(method, argsCount, toAffE); + return (method) => (argsCount) => effectfulGetter(method, argsCount, toAffE); } export function effProp(prop) { - return object => () => object[prop]; -} \ No newline at end of file + return (object) => () => object[prop]; +} diff --git a/src/Playwright/Internal.purs b/src/Playwright/Internal.purs index 5bec03c..44bb905 100644 --- a/src/Playwright/Internal.purs +++ b/src/Playwright/Internal.purs @@ -1,18 +1,18 @@ module Playwright.Internal - ( class NumberOfArgs - , numberOfArgs - , effCall - , effProp - , affCall - ) - where + ( class NumberOfArgs + , numberOfArgs + , effCall + , effProp + , affCall + ) where -import Type.Proxy -import Prelude -import Effect -import Effect.Aff -import Control.Promise +import Type.Proxy (Proxy(..)) +import Prelude ((+), (-)) +import Effect (Effect) +import Effect.Aff (Aff) +import Control.Promise (Promise, toAffE) +class NumberOfArgs :: forall k. k -> Constraint class NumberOfArgs x where numberOfArgs :: Proxy x -> Int @@ -25,18 +25,18 @@ else instance numberOfArgsFunction0 :: NumberOfArgs a where countArgs :: forall a. NumberOfArgs a => (forall x. x -> a) -> Int countArgs f = numberOfArgs (proxyOf f) - 2 where - proxyOf :: forall a. a -> Proxy a - proxyOf _ = Proxy :: Proxy a + proxyOf :: forall b. b -> Proxy b + proxyOf _ = Proxy :: Proxy b foreign import unsafeEffCall :: forall r - . String + . String -> Int -> r foreign import unsafeAffCall :: forall r - . (forall a. Effect (Promise a) -> Aff a) + . (forall a. Effect (Promise a) -> Aff a) -> String -> Int -> r diff --git a/src/Playwright/JSHandle.js b/src/Playwright/JSHandle.js index 6661f4a..b2fbcce 100644 --- a/src/Playwright/JSHandle.js +++ b/src/Playwright/JSHandle.js @@ -1,11 +1,12 @@ /* global exports */ export function getProperties_(insert) { - return emptyMap => jsHandle => () => jsHandle.getProperties().then(props => { + return (emptyMap) => (jsHandle) => () => + jsHandle.getProperties().then((props) => { let acc = emptyMap; - props.entries().forEach(pair => { - acc = insert(pair[0])(pair[1])(acc); + props.entries().forEach((pair) => { + acc = insert(pair[0])(pair[1])(acc); }); return acc; - }); + }); } diff --git a/src/Playwright/Keyboard.purs b/src/Playwright/Keyboard.purs index 1351b1c..8dd909e 100644 --- a/src/Playwright/Keyboard.purs +++ b/src/Playwright/Keyboard.purs @@ -1,12 +1,11 @@ module Playwright.Keyboard where -import Prelude -import Playwright.Internal (effCall, affCall) +import Prelude (Unit) +import Playwright.Internal (affCall) import Playwright.Data (Keyboard) import Playwright.Options (KeyboardPressOptions) import Effect.Aff (Aff) -import Control.Promise (toAffE) -import Untagged.Castable (class Castable, cast) +import Untagged.Castable (class Castable) type Key = String @@ -20,15 +19,21 @@ insertText = press :: forall o - . Castable o KeyboardPressOptions - => Keyboard -> Key -> o -> Aff Unit + . Castable o KeyboardPressOptions + => Keyboard + -> Key + -> o + -> Aff Unit press = affCall "press" \_ -> press type' :: forall o - . Castable o KeyboardPressOptions - => Keyboard -> String -> o -> Aff Unit + . Castable o KeyboardPressOptions + => Keyboard + -> String + -> o + -> Aff Unit type' = affCall "type" \_ -> type' diff --git a/src/Playwright/Mouse.purs b/src/Playwright/Mouse.purs index d5d8d69..fa1b407 100644 --- a/src/Playwright/Mouse.purs +++ b/src/Playwright/Mouse.purs @@ -1,12 +1,11 @@ module Playwright.Mouse where -import Effect.Aff -import Playwright.Data -import Playwright.Internal -import Playwright.Options -import Prelude +import Effect.Aff (Aff) +import Playwright.Data (Mouse) +import Playwright.Internal (affCall) +import Playwright.Options (MouseClickOptions, MouseDblClickOptions, MouseMoveOptions, MouseUpDownOptions) +import Prelude (Unit) import Untagged.Castable (class Castable) -import Untagged.Union click :: Mouse @@ -26,7 +25,7 @@ dblclick = affCall "dblclick" \_ -> dblclick down :: forall o - . Castable o MouseUpDownOptions + . Castable o MouseUpDownOptions => Mouse -> o -> Aff Unit @@ -34,7 +33,7 @@ down = affCall "down" \_ -> down move :: forall o - . Castable o MouseMoveOptions + . Castable o MouseMoveOptions => Mouse -> o -> Aff Unit @@ -42,7 +41,7 @@ move = affCall "move" \_ -> move up :: forall o - . Castable o MouseUpDownOptions + . Castable o MouseUpDownOptions => Mouse -> o -> Aff Unit diff --git a/src/Playwright/Options.purs b/src/Playwright/Options.purs index 918997a..0715b38 100644 --- a/src/Playwright/Options.purs +++ b/src/Playwright/Options.purs @@ -3,7 +3,7 @@ module Playwright.Options where import Playwright.Data import Data.String.Regex (Regex) -import Data.Time.Duration (Milliseconds(..)) +import Data.Time.Duration (Milliseconds) import Foreign (Foreign) import Foreign.Object (Object) import Literals.Null (Null) @@ -25,22 +25,22 @@ type FillOptions = } type LaunchOptions = - { headless :: Opt Boolean - , executablePath :: Opt String - , args :: Opt String + { headless :: Opt Boolean + , executablePath :: Opt String + , args :: Opt String , ignoreDefaultArgs :: Opt (Array String) - , proxy :: Opt ProxyOptions - , downloadsPath :: Opt String - , chromiumSandbox :: Opt Boolean - , firefoxUserPrefs :: Opt Foreign - , handleSIGINT :: Opt Boolean - , handleSIGTERM :: Opt Boolean - , handleSIGHUP :: Opt Boolean - , timeout :: Opt Milliseconds - , env :: Opt (Object String) - , devtools :: Opt Boolean - , slowMo :: Opt Number - , storageState :: Opt { cookies :: Array Cookie } + , proxy :: Opt ProxyOptions + , downloadsPath :: Opt String + , chromiumSandbox :: Opt Boolean + , firefoxUserPrefs :: Opt Foreign + , handleSIGINT :: Opt Boolean + , handleSIGTERM :: Opt Boolean + , handleSIGHUP :: Opt Boolean + , timeout :: Opt Milliseconds + , env :: Opt (Object String) + , devtools :: Opt Boolean + , slowMo :: Opt Number + , storageState :: Opt { cookies :: Array Cookie } } type ConnectOptions = @@ -49,43 +49,46 @@ type ConnectOptions = , timeout :: Opt Number } +type ConnectOverCDPOptions = + { timeout :: UndefinedOr Number } + type ProxyOptions = - { server :: Opt String - , bypass :: Opt String + { server :: Opt String + , bypass :: Opt String , username :: Opt String , password :: Opt String } type ScreenshotOptions = - { path :: Opt String - , "type" :: Opt ScreenshotType - , quality :: Opt Number + { path :: Opt String + , "type" :: Opt ScreenshotType + , quality :: Opt Number , omitBackground :: Opt Boolean - , timeout :: Opt Milliseconds + , timeout :: Opt Milliseconds } type GotoOptions = - { timeout :: Opt Milliseconds + { timeout :: Opt Milliseconds , waitUntil :: Opt WaitUntil - , referer :: Opt String + , referer :: Opt String } type NewpageOptions = - { acceptDownloads :: Opt Boolean + { acceptDownloads :: Opt Boolean , ignoreHTTPSErrors :: Opt Boolean - , bypassCSP :: Opt Boolean - , viewport :: Opt (Null |+| { width :: Int, height :: Int }) + , bypassCSP :: Opt Boolean + , viewport :: Opt (Null |+| { width :: Int, height :: Int }) } type GoOptions = - { timeout :: Opt Milliseconds + { timeout :: Opt Milliseconds , waitUntil :: Opt WaitUntil } type HoverOptions = { position :: Opt Position , modifier :: Opt (Array Modifier) - , force :: Opt Boolean + , force :: Opt Boolean } type InnerHTMLOptions = @@ -106,29 +109,29 @@ type AddInitScriptOptions = type Position = { x :: Int, y :: Int } type ClickOptions = - { button :: Opt MouseButton - , clickCount :: Opt Int - , delay :: Opt Int - , position :: Opt Position - , modifiers :: Opt (Array Modifier) - , force :: Opt Boolean + { button :: Opt MouseButton + , clickCount :: Opt Int + , delay :: Opt Int + , position :: Opt Position + , modifiers :: Opt (Array Modifier) + , force :: Opt Boolean , noWaitAfter :: Opt Boolean - , timeout :: Opt Milliseconds + , timeout :: Opt Milliseconds } type MouseClickOptions = - { button :: Opt MouseButton + { button :: Opt MouseButton , clickCount :: Opt Int - , delay :: Opt Int + , delay :: Opt Int } type MouseDblClickOptions = - { button :: Opt MouseButton - , delay :: Opt Int + { button :: Opt MouseButton + , delay :: Opt Int } type MouseUpDownOptions = - { button :: Opt MouseButton + { button :: Opt MouseButton , clickCount :: Opt Int } @@ -137,8 +140,8 @@ type MouseMoveOptions = } type WaitForNavigationOptions = - { timeout :: Opt Milliseconds - , url :: Opt (String |+| Regex |+| URL -> Boolean) + { timeout :: Opt Milliseconds + , url :: Opt (String |+| Regex |+| URL -> Boolean) , waitUntil :: Opt WaitUntil } @@ -151,7 +154,7 @@ type WaitForResponseOptions = } type WaitForSelectorOptions = - { state :: Opt ElementState + { state :: Opt ElementState , timeout :: Opt Milliseconds } @@ -165,29 +168,29 @@ type WaitForLoadStateOptions = } type Margin = - { top :: Opt (String |+| Number) - , right :: Opt (String |+| Number) + { top :: Opt (String |+| Number) + , right :: Opt (String |+| Number) , bottom :: Opt (String |+| Number) - , left :: Opt (String |+| Number) + , left :: Opt (String |+| Number) } type PdfOptions = - { path :: String - , scale :: Opt Number + { path :: String + , scale :: Opt Number , displayHeaderFooter :: Opt Boolean - , headerTemplate :: Opt String - , footerTemplate :: Opt String - , printBackground :: Opt Boolean - , landscape :: Opt Boolean - , pageRanges :: Opt String - , format :: Opt String - , width :: Opt (String |+| Number) - , height :: Opt (String |+| Number) - , margin :: Opt Margin - , preferCSSPageSize :: Opt Boolean + , headerTemplate :: Opt String + , footerTemplate :: Opt String + , printBackground :: Opt Boolean + , landscape :: Opt Boolean + , pageRanges :: Opt String + , format :: Opt String + , width :: Opt (String |+| Number) + , height :: Opt (String |+| Number) + , margin :: Opt Margin + , preferCSSPageSize :: Opt Boolean } type SetFilesOptions = { noWaitAfter :: Opt Boolean - , timeout :: Opt Milliseconds + , timeout :: Opt Milliseconds } diff --git a/src/Playwright/Response.js b/src/Playwright/Response.js index 7a3d455..127a304 100644 --- a/src/Playwright/Response.js +++ b/src/Playwright/Response.js @@ -1,10 +1,10 @@ /* global exports */ -export const finished_ = Nothing => Just => Response => () => +export const finished_ = (Nothing) => (Just) => (Response) => () => Response.finished().then((result) => { if (result === null) { - return Nothing + return Nothing; } else { - return Just(result) + return Just(result); } - }) + }); diff --git a/src/Playwright/Response.purs b/src/Playwright/Response.purs index cf3ab32..bdc6b91 100644 --- a/src/Playwright/Response.purs +++ b/src/Playwright/Response.purs @@ -1,17 +1,16 @@ module Playwright.Response - ( body - , finished - , frame - , headers - , json - , ok - , request - , status - , statusText - , text - , url - ) -where + ( body + , finished + , frame + , headers + , json + , ok + , request + , status + , statusText + , text + , url + ) where import Control.Promise (Promise, toAffE) import Data.Argonaut.Core (Json) diff --git a/test/Main.purs b/test/Main.purs index b7118ee..fefdea1 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -13,14 +13,14 @@ import Foreign as Foreign import Node.Encoding as Encoding import Node.FS.Aff as FS import Node.Stream as Stream -import Playwright +import Playwright (Selector(..), URL(..), chromium, click, close, dblclick, evaluate, exposeBinding, isClosed, launch, mainFrame, name, screenshot, textContent, url, version, waitForFunction, waitForSelector, waitForTimeout) import Node.EventEmitter (on_) import Playwright.ConsoleMessage as ConsoleMessage import Playwright.Dialog as Dialog import Playwright.Download as Download import Playwright.Event (on) import Playwright.Event as Event -import Prelude +import Prelude (Unit, bind, discard, pure, void, (#), ($), (/=), (<$>), (<<<), (<>), (=<<), (==)) import Test.Unit (suite, test) import Test.Unit.Assert as Assert import Test.Unit.Main (runTest) @@ -34,8 +34,8 @@ static file = main :: Effect Unit main = runTest do let - hello = static "hello.html" - index = static "index.html" + hello = static "hello.html" + index = static "index.html" suite "browser" do test "launch, close" do browser <- launch chromium {} @@ -98,8 +98,7 @@ main = runTest do ref <- liftEffect $ Ref.new Nothing frgnRef <- liftEffect $ Ref.new Nothing exposeBinding page "hi_ffi" - ( - \({frame}) frgn -> do + ( \({ frame }) frgn -> do url <- liftEffect $ url frame liftEffect do Console.log "hi" @@ -111,8 +110,9 @@ main = runTest do mbUrl <- liftEffect $ Ref.read ref mbForeign <- liftEffect $ Ref.read frgnRef Assert.equal (Just hello) mbUrl - Assert.assert "exposeBinding is not able to accept an argument" $ - pure (pure 12) == (runExcept <<< Foreign.readInt <$> mbForeign) + Assert.assert "exposeBinding is not able to accept an argument" + $ pure (pure 12) + == (runExcept <<< Foreign.readInt <$> mbForeign) suite "events" do test "console" do withBrowserPage hello diff --git a/test/TestUtils.js b/test/TestUtils.js index 9887aa4..baadbf2 100644 --- a/test/TestUtils.js +++ b/test/TestUtils.js @@ -2,4 +2,4 @@ export const cwd = process.cwd(); -export const isNull = sth => sth === null; +export const isNull = (sth) => sth === null; diff --git a/test/TestUtils.purs b/test/TestUtils.purs index 8e07275..a6a1250 100644 --- a/test/TestUtils.purs +++ b/test/TestUtils.purs @@ -1,12 +1,11 @@ module TestUtils - ( assertForeignTrue - , withBrowser - , withBrowserPage - , testClickEvent - , cwd - , isNull - ) -where + ( assertForeignTrue + , withBrowser + , withBrowserPage + , testClickEvent + , cwd + , isNull + ) where import Test.Unit.Assert as Assert import Foreign (Foreign, readBoolean) @@ -26,8 +25,8 @@ assertForeignTrue value = do withBrowser :: forall a. (Browser -> Aff a) -> Aff a withBrowser = withResource acquire release where - acquire = launch chromium {} - release = close + acquire = launch chromium {} + release = close withBrowserPage :: forall a. URL -> (Page -> Aff a) -> Aff a withBrowserPage url action = do