git.iko.soy/rowtype-yoga/purescript-lunapark
on main help sign in
19 files changed+2611−607
since splitsnapshots
unifiedsplit
.github/workflows/ci.yml+37 .gitignore+1−2 .travis.yml−15 README.md+23−20 bower.json−36 package.json−17 spago.lock+1712 spago.yaml+41 src/Lunapark.purs+8−5 src/Lunapark/API.purs+232−180 src/Lunapark/ActionF.purs+19−20 src/Lunapark/Endpoint.purs+20−12 src/Lunapark/Error.purs+36−120 src/Lunapark/LunaparkF.purs+58−58 src/Lunapark/Types.purs+106−112 src/Lunapark/UnicodeCharacters.purs+177 src/Lunapark/Utils.purs+12−10 src/Lunapark/WebDriverError.purs+117 test/Test/Main.purs+12
.github/workflows/ci.ymlnew file+37
@@ -0,0 +1,37 @@
1+name: CI
2+
3+on:
4+ push:
5+ branches: [master, main]
6+ pull_request:
7+ branches: [master, main]
8+
9+jobs:
10+ build:
11+ runs-on: ubuntu-latest
12+ steps:
13+ - uses: actions/checkout@v4
14+
15+ - name: Set up a PureScript toolchain
16+ uses: purescript-contrib/setup-purescript@main
17+ with:
18+ purescript: "latest"
19+ purs-tidy: "latest"
20+ spago: "unstable"
21+
22+ - name: Cache PureScript dependencies
23+ uses: actions/cache@v4
24+ with:
25+ key: ${{ runner.os }}-spago-${{ hashFiles('**/spago.lock') }}
26+ path: |
27+ .spago
28+ output
29+
30+ - name: Build source
31+ run: spago build --censor-stats --strict --pedantic-packages
32+
33+ - name: Run tests
34+ run: spago test --offline --censor-stats --strict --pedantic-packages -- --censor-codes=UserDefinedWarning
35+
36+ - name: Verify formatting
37+ run: purs-tidy check src test
.gitignore+1−2
@@ -1,8 +1,7 @@
11/.*
22!/.gitignore
3−!/.travis.yml
3+!/.github
44/bower_components/
55/node_modules/
66/output/
7−/example/dist/test.js
87package-lock.json
.travis.ymldeleted−15
@@ -1,15 +0,0 @@
1−language: node_js
2−dist: trusty
3−sudo: required
4−node_js: stable
5−install:
6− - npm install
7− - npm install -g bower
8− - bower install --production
9−script:
10− - npm run -s build
11−after_success:
12−- >-
13− test $TRAVIS_TAG &&
14− echo $GITHUB_TOKEN | pulp login &&
15− echo y | pulp publish --no-push
README.md+23−20
@@ -1,11 +1,13 @@
11# purescript-lunapark
22
33[![Latest release](http://img.shields.io/github/release/slamdata/purescript-lunapark.svg)](https://github.com/slamdata/purescript-lunapark/releases)
4−[![Build status](https://travis-ci.org/slamdata/purescript-lunapark.svg?branch=master)](https://travis-ci.org/slamdata/purescript-lunapark)
4+![Build Status](https://github.com/slamdata/purescript-lunapark/actions/workflows/ci.yml/badge.svg)
55
66## Disclaimer
77
8−+ This is WIP: some things weren't implemented, some might have bugs. Filling issues and prs are welcomed!
8+Webdriver/JsonWire bindings for PureScript
9+
10+- This is WIP: some things weren't implemented, some might have bugs. Filling issues and prs are welcomed!
911
1012## Purescript W3C webdriver protocol bindings
1113
@@ -14,20 +16,20 @@ won't involve any JavaScript dependencies.
1416
1517## Architecture
1618
17−+ There is a module that encodes any possible error returned by Selenium.
18−+ Low-level API uses `purescript-argonaut`'s `Json` type and `purescript-affjax`s helper functions (`get`, `post` etc)
19−+ Endpoints are constructed using `Endpoint@Lunapark.Endpoint` type. This module also provides helper functions
20−returning `Aff _ (Either Error Json)`
21−+ Types of requests and resposes live in `Lunapark.Types` module.
22−+ High-level API uses `purescript-run`. There are several functors, but the main two are: `LunaparkF` and `ActionF`.
23−This functor embed in `Run` encode almost all posible interactions with w3c/selenium server.
24−+ At first `ActionF` functor (that is a functor that encodes all posible actions like click, hover) is interpreted to
25−`LunaparkF`, then `LunaparkF` is interpreted into `Run` with `EXCEPT` and `AFF|EFF` effects.
26−+ `Lunapark` is facade library on top of api, functors and error.
27−+ Capabilities are represented via gradually typed datastructure `Array Capability`. `init` function takes a record
28−`{ alwaysMatch: Array Capability, firstMatch: Array (Array Capability) }`. `firstMatch` must have at least on array.
29−+ To construct interpreter you need call `init@Lunapark.API`. The result would be `Aff _ (Either Error Interpreter)`,
30−where `Interpreter` is function taking `Lunapark` monad and unwrapping it into `Run` with `EXCEPT` and `AFF|EFF`. E.g.
19+- There is a module that encodes any possible error returned by Selenium.
20+- Low-level API uses `purescript-argonaut`'s `Json` type and `purescript-affjax`s helper functions (`get`, `post` etc)
21+- Endpoints are constructed using `Endpoint@Lunapark.Endpoint` type. This module also provides helper functions
22+ returning `Aff (Either Error Json)`
23+- Types of requests and resposes live in `Lunapark.Types` module.
24+- High-level API uses `purescript-run`. There are several functors, but the main two are: `LunaparkF` and `ActionF`.
25+ This functor embed in `Run` encode almost all posible interactions with w3c/selenium server.
26+- At first `ActionF` functor (that is a functor that encodes all posible actions like click, hover) is interpreted to
27+ `LunaparkF`, then `LunaparkF` is interpreted into `Run` with `EXCEPT` and `AFF|EFF` effects.
28+- `Lunapark` is facade library on top of api, functors and error.
29+- Capabilities are represented via gradually typed datastructure `Array Capability`. `init` function takes a record
30+ `{ alwaysMatch: Array Capability, firstMatch: Array (Array Capability) }`. `firstMatch` must have at least on array.
31+- To construct interpreter you need call `init@Lunapark.API`. The result would be `Aff (Either Error Interpreter)`,
32+ where `Interpreter` is function taking `Lunapark` monad and unwrapping it into `Run` with `EXCEPT` and `AFF|EFF`. E.g.
3133
3234```purescript
3335main = launchAff do
@@ -47,7 +49,8 @@ main = launchAff do
4749 sendKeys "secret"
4850 sendKeys "\\xE007"
4951```
50−+ The interpreter takes care about implemented and non-implemented features of particular driver. E.g. if driver supports
51−`GET@/session/:sessionId/timeouts` via W3C standard it will use it otherwise the interpreter makes it a chain call of
52−JsonWire commands. The same works for actions: they are interpreted into either `POST@/session/:sessionId/action` or
53−chains of JsonWire commands.
52+
53+- The interpreter takes care about implemented and non-implemented features of particular driver. E.g. if driver supports
54+ `GET@/session/:sessionId/timeouts` via W3C standard it will use it otherwise the interpreter makes it a chain call of
55+ JsonWire commands. The same works for actions: they are interpreted into either `POST@/session/:sessionId/action` or
56+ chains of JsonWire commands.
bower.jsondeleted−36
@@ -1,36 +0,0 @@
1−{
2− "name": "purescript-lunapark",
3− "homepage": "https://github.com/slamdata/purescript-lunapark",
4− "authors": [
5− "Maxim Zimaliev <zimaliev@gmail.com>"
6− ],
7− "description": "Webdriver/JsonWire bindings for PureScript",
8− "license": "Apache-2.0",
9− "keywords": [
10− "purescript",
11− "selenium",
12− "webdriver",
13− "jsonwire"
14− ],
15− "repository": {
16− "type": "git",
17− "url": "git://github.com/slamdata/purescript-lunapark.git"
18− },
19− "ignore": [
20− "**/*.",
21− "node_modules",
22− "bower_components",
23− "output",
24− "test",
25− "vendor"
26− ],
27− "dependencies": {
28− "purescript-affjax": "^9.0.0",
29− "purescript-argonaut-codecs": "^6.0.0",
30− "purescript-argonaut-core": "^5.0.0",
31− "purescript-css": "^4.0.0",
32− "purescript-node-fs-aff": "^6.0.0",
33− "purescript-run": "^3.0.0",
34− "purescript-xpath": "cryogenian/purescript-xpath#compiler/0.12"
35− }
36−}
package.jsondeleted−17
@@ -1,17 +0,0 @@
1−{
2− "name": "purescript-lunapark",
3− "private": true,
4− "scripts": {
5− "build": "pulp build -- --strict --stash",
6− "build:non-strict": "pulp build",
7− "ide": "purs ide server"
8− },
9− "license": "Apache-2.0",
10− "dependencies": {
11− "chromedriver": "^2.37.0",
12− "pulp": "^12.2.0",
13− "purescript": "^0.12.3",
14− "purescript-psa": "^0.7.3",
15− "xhr2": "^0.1.4"
16− }
17−}
spago.locknew file+1712
@@ -0,0 +1,1712 @@
1+{
2+ "workspace": {
3+ "packages": {
4+ "lunapark": {
5+ "path": "./",
6+ "core": {
7+ "dependencies": [
8+ "aff",
9+ "affjax",
10+ "affjax-node",
11+ "argonaut-codecs",
12+ "argonaut-core",
13+ "arrays",
14+ "bifunctors",
15+ "control",
16+ "css",
17+ "datetime",
18+ "effect",
19+ "either",
20+ "foldable-traversable",
21+ "foreign-object",
22+ "lists",
23+ "maybe",
24+ "newtype",
25+ "node-buffer",
26+ "node-fs",
27+ "node-path",
28+ "ordered-collections",
29+ "prelude",
30+ "refs",
31+ "run",
32+ "strings",
33+ "tailrec",
34+ "tuples",
35+ "typelevel-prelude",
36+ "unsafe-coerce",
37+ "variant"
38+ ],
39+ "build_plan": [
40+ "aff",
41+ "affjax",
42+ "affjax-node",
43+ "argonaut-codecs",
44+ "argonaut-core",
45+ "arraybuffer-types",
46+ "arrays",
47+ "bifunctors",
48+ "catenable-lists",
49+ "colors",
50+ "console",
51+ "const",
52+ "contravariant",
53+ "control",
54+ "css",
55+ "datetime",
56+ "distributive",
57+ "effect",
58+ "either",
59+ "enums",
60+ "exceptions",
61+ "exists",
62+ "foldable-traversable",
63+ "foreign",
64+ "foreign-object",
65+ "form-urlencoded",
66+ "free",
67+ "functions",
68+ "functors",
69+ "gen",
70+ "http-methods",
71+ "identity",
72+ "integers",
73+ "invariant",
74+ "js-date",
75+ "js-uri",
76+ "lazy",
77+ "lcg",
78+ "lists",
79+ "maybe",
80+ "media-types",
81+ "newtype",
82+ "node-buffer",
83+ "node-event-emitter",
84+ "node-fs",
85+ "node-path",
86+ "node-streams",
87+ "nonempty",
88+ "now",
89+ "nullable",
90+ "numbers",
91+ "ordered-collections",
92+ "orders",
93+ "parallel",
94+ "partial",
95+ "prelude",
96+ "profunctor",
97+ "quickcheck",
98+ "quickcheck-laws",
99+ "random",
100+ "record",
101+ "refs",
102+ "run",
103+ "safe-coerce",
104+ "st",
105+ "strings",
106+ "tailrec",
107+ "these",
108+ "transformers",
109+ "tuples",
110+ "type-equality",
111+ "typelevel-prelude",
112+ "unfoldable",
113+ "unsafe-coerce",
114+ "variant",
115+ "web-dom",
116+ "web-events",
117+ "web-file",
118+ "web-html",
119+ "web-storage",
120+ "web-xhr"
121+ ]
122+ },
123+ "test": {
124+ "dependencies": [
125+ "console"
126+ ],
127+ "build_plan": [
128+ "console",
129+ "effect",
130+ "prelude"
131+ ]
132+ }
133+ }
134+ },
135+ "package_set": {
136+ "address": {
137+ "registry": "60.4.0"
138+ },
139+ "compiler": ">=0.15.15 <0.16.0",
140+ "content": {
141+ "abc-parser": "2.0.1",
142+ "ace": "9.1.0",
143+ "address-rfc2821": "0.1.1",
144+ "aff": "8.0.0",
145+ "aff-bus": "6.0.0",
146+ "aff-coroutines": "9.0.0",
147+ "aff-promise": "4.0.0",
148+ "aff-retry": "2.0.0",
149+ "affjax": "13.0.0",
150+ "affjax-node": "1.0.0",
151+ "affjax-web": "1.0.0",
152+ "ansi": "7.0.0",
153+ "apexcharts": "0.5.0",
154+ "applicative-phases": "1.0.0",
155+ "argonaut": "9.0.0",
156+ "argonaut-aeson-generic": "0.4.1",
157+ "argonaut-codecs": "9.1.0",
158+ "argonaut-core": "7.0.0",
159+ "argonaut-generic": "8.0.0",
160+ "argonaut-traversals": "10.0.0",
161+ "argparse-basic": "2.0.0",
162+ "array-builder": "0.1.2",
163+ "array-search": "0.6.0",
164+ "arraybuffer": "13.2.0",
165+ "arraybuffer-builder": "3.1.0",
166+ "arraybuffer-types": "3.0.2",
167+ "arrays": "7.3.0",
168+ "arrays-extra": "0.6.1",
169+ "arrays-zipper": "2.0.1",
170+ "ask": "1.0.0",
171+ "assert": "6.0.0",
172+ "assert-multiple": "0.4.0",
173+ "avar": "5.0.0",
174+ "b64": "0.0.8",
175+ "barbies": "1.0.1",
176+ "barlow-lens": "0.9.0",
177+ "bifunctors": "6.0.0",
178+ "bigints": "7.0.1",
179+ "bolson": "0.3.9",
180+ "bookhound": "0.1.7",
181+ "bower-json": "3.0.0",
182+ "call-by-name": "4.0.1",
183+ "canvas": "6.0.0",
184+ "canvas-action": "9.0.0",
185+ "cartesian": "1.0.6",
186+ "catenable-lists": "7.0.0",
187+ "cbor-stream": "1.3.0",
188+ "chameleon": "1.0.0",
189+ "chameleon-halogen": "1.0.3",
190+ "chameleon-react-basic": "1.1.0",
191+ "chameleon-styled": "2.5.0",
192+ "chameleon-transformers": "1.0.0",
193+ "channel": "1.0.0",
194+ "checked-exceptions": "3.1.1",
195+ "choku": "1.0.1",
196+ "classless": "0.1.1",
197+ "classless-arbitrary": "0.1.1",
198+ "classless-decode-json": "0.1.1",
199+ "classless-encode-json": "0.1.3",
200+ "classnames": "2.0.0",
201+ "codec": "6.1.0",
202+ "codec-argonaut": "10.0.0",
203+ "codec-json": "2.0.0",
204+ "colors": "7.0.1",
205+ "concur-core": "0.5.0",
206+ "concur-react": "0.5.0",
207+ "concurrent-queues": "3.0.0",
208+ "console": "6.1.0",
209+ "const": "6.0.0",
210+ "contravariant": "6.0.0",
211+ "control": "6.0.0",
212+ "convertable-options": "1.0.0",
213+ "coroutines": "7.0.0",
214+ "css": "6.0.0",
215+ "css-frameworks": "1.0.1",
216+ "csv-stream": "2.3.0",
217+ "data-mvc": "0.0.2",
218+ "datetime": "6.1.0",
219+ "datetime-parsing": "0.2.0",
220+ "debounce": "0.1.0",
221+ "debug": "6.0.2",
222+ "decimals": "7.1.0",
223+ "default-values": "1.0.1",
224+ "deku": "0.9.23",
225+ "deno": "0.0.5",
226+ "dissect": "1.0.0",
227+ "distributive": "6.0.0",
228+ "dom-filereader": "7.0.0",
229+ "dom-indexed": "12.0.0",
230+ "dom-simple": "0.4.0",
231+ "dotenv": "4.0.3",
232+ "droplet": "0.6.0",
233+ "dts": "1.0.0",
234+ "dual-numbers": "1.0.3",
235+ "dynamic-buffer": "3.0.1",
236+ "echarts-simple": "0.0.1",
237+ "effect": "4.0.0",
238+ "either": "6.1.0",
239+ "elmish": "0.13.0",
240+ "elmish-enzyme": "0.1.1",
241+ "elmish-hooks": "0.10.3",
242+ "elmish-html": "0.9.0",
243+ "elmish-testing-library": "0.3.2",
244+ "email-validate": "7.0.0",
245+ "encoding": "0.0.9",
246+ "enums": "6.0.1",
247+ "env-names": "0.4.0",
248+ "error": "2.0.0",
249+ "eta-conversion": "0.3.2",
250+ "exceptions": "6.1.0",
251+ "exists": "6.0.0",
252+ "exitcodes": "4.0.0",
253+ "expect-inferred": "3.0.0",
254+ "ezfetch": "1.0.0",
255+ "fahrtwind": "2.0.0",
256+ "fallback": "0.1.0",
257+ "fast-vect": "1.2.0",
258+ "fetch": "4.1.0",
259+ "fetch-argonaut": "1.0.1",
260+ "fetch-core": "5.1.0",
261+ "fetch-yoga-json": "1.1.0",
262+ "ffi-simple": "0.5.1",
263+ "fft-js": "0.1.0",
264+ "filterable": "5.0.0",
265+ "fix-functor": "0.1.0",
266+ "fixed-points": "7.0.0",
267+ "fixed-precision": "5.0.0",
268+ "flame": "1.3.0",
269+ "float32": "2.0.0",
270+ "fmt": "0.2.1",
271+ "foldable-traversable": "6.0.0",
272+ "foldable-traversable-extra": "0.0.6",
273+ "foreign": "7.0.0",
274+ "foreign-object": "4.1.0",
275+ "foreign-readwrite": "3.4.0",
276+ "forgetmenot": "0.1.0",
277+ "fork": "6.0.0",
278+ "form-urlencoded": "7.0.0",
279+ "formatters": "7.0.0",
280+ "framer-motion": "1.0.1",
281+ "free": "7.1.0",
282+ "freeap": "7.0.0",
283+ "freer-free": "0.0.1",
284+ "freet": "7.0.0",
285+ "functions": "6.0.0",
286+ "functor1": "3.0.0",
287+ "functors": "5.0.0",
288+ "fuzzy": "0.4.0",
289+ "gen": "4.0.0",
290+ "generate-values": "1.0.1",
291+ "generic-router": "0.0.1",
292+ "geojson": "0.0.5",
293+ "geometria": "2.2.0",
294+ "gojs": "0.1.1",
295+ "grain": "3.0.0",
296+ "grain-router": "3.0.0",
297+ "grain-virtualized": "3.0.0",
298+ "graphs": "8.1.0",
299+ "group": "4.1.1",
300+ "halogen": "7.0.0",
301+ "halogen-bootstrap5": "5.3.2",
302+ "halogen-canvas": "1.0.0",
303+ "halogen-css": "10.0.0",
304+ "halogen-echarts-simple": "0.0.4",
305+ "halogen-formless": "4.0.3",
306+ "halogen-helix": "1.0.1",
307+ "halogen-hooks": "0.6.3",
308+ "halogen-hooks-extra": "0.9.0",
309+ "halogen-infinite-scroll": "1.1.0",
310+ "halogen-store": "0.5.4",
311+ "halogen-storybook": "2.0.0",
312+ "halogen-subscriptions": "2.0.0",
313+ "halogen-svg-elems": "8.0.0",
314+ "halogen-typewriter": "1.0.4",
315+ "halogen-vdom": "8.0.0",
316+ "halogen-vdom-string-renderer": "0.5.0",
317+ "halogen-xterm": "2.0.0",
318+ "heckin": "2.0.1",
319+ "heterogeneous": "0.6.0",
320+ "homogeneous": "0.4.0",
321+ "http-methods": "6.0.0",
322+ "httpurple": "4.0.0",
323+ "huffman": "0.4.0",
324+ "humdrum": "0.0.1",
325+ "hyrule": "2.3.8",
326+ "identity": "6.0.0",
327+ "identy": "4.0.1",
328+ "indexed-db": "1.0.0",
329+ "indexed-monad": "3.0.0",
330+ "int64": "3.0.0",
331+ "integers": "6.0.0",
332+ "interpolate": "5.0.2",
333+ "intersection-observer": "1.0.1",
334+ "invariant": "6.0.0",
335+ "jarilo": "1.0.1",
336+ "jelly": "0.10.0",
337+ "jelly-router": "0.3.0",
338+ "jelly-signal": "0.4.0",
339+ "jest": "1.0.0",
340+ "js-abort-controller": "1.0.0",
341+ "js-bigints": "2.2.1",
342+ "js-date": "8.0.0",
343+ "js-fetch": "0.2.1",
344+ "js-fileio": "3.0.0",
345+ "js-intl": "1.0.4",
346+ "js-iterators": "0.1.1",
347+ "js-maps": "0.1.2",
348+ "js-promise": "1.0.0",
349+ "js-promise-aff": "1.0.0",
350+ "js-timers": "6.1.0",
351+ "js-uri": "3.1.0",
352+ "json": "1.1.0",
353+ "json-codecs": "5.0.0",
354+ "justifill": "0.5.0",
355+ "jwt": "0.0.9",
356+ "labeled-data": "0.2.0",
357+ "language-cst-parser": "0.14.0",
358+ "lazy": "6.0.0",
359+ "lazy-joe": "1.0.0",
360+ "lcg": "4.0.0",
361+ "leibniz": "5.0.0",
362+ "leveldb": "1.0.1",
363+ "liminal": "1.0.1",
364+ "linalg": "6.0.0",
365+ "lists": "7.0.0",
366+ "literals": "1.0.2",
367+ "logging": "3.0.0",
368+ "logging-journald": "0.4.0",
369+ "lumi-components": "18.0.0",
370+ "machines": "7.0.0",
371+ "maps-eager": "0.5.0",
372+ "marionette": "1.0.0",
373+ "marionette-react-basic-hooks": "0.1.1",
374+ "marked": "0.1.0",
375+ "matrices": "5.0.1",
376+ "matryoshka": "1.0.0",
377+ "maybe": "6.0.0",
378+ "media-types": "6.0.0",
379+ "meowclient": "1.0.0",
380+ "midi": "4.0.0",
381+ "milkis": "9.0.0",
382+ "minibench": "4.0.1",
383+ "mmorph": "7.0.0",
384+ "monad-control": "5.0.0",
385+ "monad-logger": "1.3.1",
386+ "monad-loops": "0.5.0",
387+ "monad-unlift": "1.0.1",
388+ "monoid-extras": "0.0.1",
389+ "monoidal": "0.16.0",
390+ "morello": "0.4.0",
391+ "mote": "3.0.0",
392+ "motsunabe": "2.0.0",
393+ "mvc": "0.0.1",
394+ "mysql": "6.0.1",
395+ "n3": "0.1.0",
396+ "nano-id": "1.1.0",
397+ "nanoid": "0.1.0",
398+ "naturals": "3.0.0",
399+ "nested-functor": "0.2.1",
400+ "newtype": "5.0.0",
401+ "nextjs": "0.1.1",
402+ "nextui": "0.2.0",
403+ "node-buffer": "9.0.0",
404+ "node-child-process": "11.1.0",
405+ "node-event-emitter": "3.0.0",
406+ "node-execa": "5.0.0",
407+ "node-fs": "9.2.0",
408+ "node-glob-basic": "1.3.0",
409+ "node-http": "9.1.0",
410+ "node-http2": "1.1.1",
411+ "node-human-signals": "1.0.0",
412+ "node-net": "5.1.0",
413+ "node-os": "5.1.0",
414+ "node-path": "5.0.0",
415+ "node-process": "11.2.0",
416+ "node-readline": "8.1.1",
417+ "node-sqlite3": "8.0.0",
418+ "node-stream-pipes": "2.1.6",
419+ "node-streams": "9.0.0",
420+ "node-tls": "0.3.1",
421+ "node-url": "7.0.1",
422+ "node-zlib": "0.4.0",
423+ "nonempty": "7.0.0",
424+ "now": "6.0.0",
425+ "npm-package-json": "2.0.0",
426+ "nullable": "6.0.0",
427+ "numberfield": "0.2.2",
428+ "numbers": "9.0.1",
429+ "oak": "3.1.1",
430+ "oak-debug": "1.2.2",
431+ "object-maps": "0.3.0",
432+ "ocarina": "1.5.4",
433+ "oooooooooorrrrrrrmm-lib": "0.0.1",
434+ "open-colors-scales-and-schemes": "1.0.0",
435+ "open-folds": "6.4.0",
436+ "open-foreign-generic": "11.0.3",
437+ "open-memoize": "6.2.0",
438+ "open-mkdirp-aff": "1.2.0",
439+ "open-pairing": "6.2.0",
440+ "open-smolder": "12.0.2",
441+ "options": "7.0.0",
442+ "optparse": "5.0.1",
443+ "ordered-collections": "3.2.0",
444+ "ordered-set": "0.4.0",
445+ "orders": "6.0.0",
446+ "owoify": "1.2.0",
447+ "pairs": "9.0.1",
448+ "parallel": "7.0.0",
449+ "parsing": "10.2.0",
450+ "parsing-dataview": "3.2.4",
451+ "partial": "4.0.0",
452+ "pathy": "9.0.0",
453+ "pha": "0.13.0",
454+ "phaser": "0.7.0",
455+ "phylio": "1.1.2",
456+ "pipes": "8.0.0",
457+ "pirates-charm": "0.0.1",
458+ "pmock": "0.9.0",
459+ "point-free": "1.0.0",
460+ "pointed-list": "0.5.1",
461+ "polymorphic-vectors": "4.0.0",
462+ "posix-types": "6.0.0",
463+ "postgresql": "2.0.19",
464+ "precise": "6.0.0",
465+ "precise-datetime": "7.0.0",
466+ "prelude": "6.0.1",
467+ "prettier-printer": "3.0.0",
468+ "priority-queue": "0.1.2",
469+ "profunctor": "6.0.1",
470+ "profunctor-lenses": "8.0.0",
471+ "protobuf": "4.3.0",
472+ "psa-utils": "8.0.0",
473+ "psci-support": "6.0.0",
474+ "punycode": "1.0.0",
475+ "qualified-do": "2.2.0",
476+ "quantities": "12.2.0",
477+ "quickcheck": "8.0.1",
478+ "quickcheck-combinators": "0.1.3",
479+ "quickcheck-laws": "7.0.0",
480+ "quickcheck-utf8": "0.0.0",
481+ "random": "6.0.0",
482+ "rationals": "6.0.0",
483+ "rdf": "0.1.0",
484+ "react": "11.0.0",
485+ "react-aria": "0.2.0",
486+ "react-basic": "17.0.0",
487+ "react-basic-classic": "3.0.0",
488+ "react-basic-dnd": "10.1.0",
489+ "react-basic-dom": "6.1.0",
490+ "react-basic-dom-beta": "0.1.1",
491+ "react-basic-emotion": "7.1.0",
492+ "react-basic-hooks": "8.2.0",
493+ "react-basic-storybook": "2.0.0",
494+ "react-dom": "8.0.0",
495+ "react-halo": "3.0.0",
496+ "react-icons": "1.1.5",
497+ "react-markdown": "0.1.0",
498+ "react-testing-library": "4.0.1",
499+ "react-virtuoso": "1.0.0",
500+ "reactix": "0.6.1",
501+ "read": "1.0.1",
502+ "recharts": "1.1.0",
503+ "record": "4.0.0",
504+ "record-extra": "5.0.1",
505+ "record-ptional-fields": "0.1.2",
506+ "record-studio": "1.0.4",
507+ "refs": "6.0.0",
508+ "remotedata": "5.0.1",
509+ "repr": "0.5.0",
510+ "resize-observer": "1.0.0",
511+ "resource": "2.0.1",
512+ "resourcet": "1.0.0",
513+ "result": "1.0.3",
514+ "return": "0.2.0",
515+ "ring-modules": "5.0.1",
516+ "rito": "0.3.4",
517+ "roman": "0.4.0",
518+ "rough-notation": "1.0.2",
519+ "routing": "11.0.0",
520+ "routing-duplex": "0.7.0",
521+ "run": "5.0.0",
522+ "safe-coerce": "2.0.0",
523+ "safely": "4.0.1",
524+ "school-of-music": "1.3.0",
525+ "selection-foldable": "0.2.0",
526+ "selective-functors": "1.0.1",
527+ "semirings": "7.0.0",
528+ "signal": "13.0.0",
529+ "simple-emitter": "3.0.1",
530+ "simple-i18n": "2.0.1",
531+ "simple-json": "9.0.0",
532+ "simple-json-generics": "0.2.1",
533+ "simple-ulid": "3.0.0",
534+ "sized-matrices": "1.0.0",
535+ "sized-vectors": "5.0.2",
536+ "slug": "3.1.0",
537+ "small-ffi": "4.0.1",
538+ "soundfonts": "4.1.0",
539+ "sparse-matrices": "2.0.1",
540+ "sparse-polynomials": "3.0.1",
541+ "spec": "8.1.0",
542+ "spec-discovery": "8.4.0",
543+ "spec-mocha": "5.1.1",
544+ "spec-node": "0.0.2",
545+ "spec-quickcheck": "5.0.2",
546+ "spec-reporter-xunit": "0.7.1",
547+ "splitmix": "2.1.0",
548+ "ssrs": "1.0.0",
549+ "st": "6.2.0",
550+ "statistics": "0.3.2",
551+ "strictlypositiveint": "1.0.1",
552+ "string-parsers": "8.0.0",
553+ "strings": "6.0.1",
554+ "strings-extra": "4.0.0",
555+ "stringutils": "0.0.12",
556+ "substitute": "0.2.3",
557+ "supply": "0.2.0",
558+ "svg-parser": "3.0.0",
559+ "systemd-journald": "0.3.0",
560+ "tagged": "4.0.2",
561+ "tailrec": "6.1.0",
562+ "tecton": "0.2.1",
563+ "tecton-halogen": "0.2.0",
564+ "test-unit": "17.0.0",
565+ "thermite": "6.3.1",
566+ "thermite-dom": "0.3.1",
567+ "these": "6.0.0",
568+ "threading": "0.0.3",
569+ "tldr": "0.0.0",
570+ "toestand": "0.9.0",
571+ "transformation-matrix": "1.0.1",
572+ "transformers": "6.1.0",
573+ "tree-rose": "4.0.2",
574+ "ts-bridge": "4.0.0",
575+ "tuples": "7.0.0",
576+ "two-or-more": "1.0.0",
577+ "type-equality": "4.0.1",
578+ "typedenv": "2.0.1",
579+ "typelevel": "6.0.0",
580+ "typelevel-lists": "2.1.0",
581+ "typelevel-peano": "1.0.1",
582+ "typelevel-prelude": "7.0.0",
583+ "typelevel-regex": "0.0.3",
584+ "typelevel-rows": "0.1.0",
585+ "typisch": "0.4.0",
586+ "uint": "7.0.0",
587+ "ulid": "3.0.1",
588+ "uncurried-transformers": "1.1.0",
589+ "undefined": "2.0.0",
590+ "undefined-is-not-a-problem": "1.1.0",
591+ "unfoldable": "6.0.0",
592+ "unicode": "6.0.0",
593+ "unique": "0.6.1",
594+ "unlift": "1.0.1",
595+ "unordered-collections": "3.1.0",
596+ "unsafe-coerce": "6.0.0",
597+ "unsafe-reference": "5.0.0",
598+ "untagged-to-tagged": "0.1.4",
599+ "untagged-union": "1.0.0",
600+ "uri": "9.0.0",
601+ "url-immutable": "1.0.0",
602+ "uuid": "9.0.0",
603+ "uuidv4": "1.0.0",
604+ "validation": "6.0.0",
605+ "variant": "8.0.0",
606+ "variant-encodings": "2.0.0",
607+ "vectorfield": "1.0.1",
608+ "vectors": "2.1.0",
609+ "versions": "7.0.0",
610+ "visx": "0.0.2",
611+ "web-clipboard": "6.0.0",
612+ "web-cssom": "2.0.0",
613+ "web-cssom-view": "0.1.0",
614+ "web-dom": "6.0.0",
615+ "web-dom-parser": "8.0.0",
616+ "web-dom-xpath": "3.0.0",
617+ "web-encoding": "3.0.0",
618+ "web-events": "4.0.0",
619+ "web-fetch": "4.0.1",
620+ "web-file": "4.0.0",
621+ "web-geometry": "0.1.0",
622+ "web-html": "4.1.0",
623+ "web-pointerevents": "2.0.0",
624+ "web-proletarian": "1.0.0",
625+ "web-promise": "3.2.0",
626+ "web-resize-observer": "2.1.0",
627+ "web-router": "1.0.0",
628+ "web-socket": "4.0.0",
629+ "web-storage": "5.0.0",
630+ "web-streams": "4.0.0",
631+ "web-touchevents": "4.0.0",
632+ "web-uievents": "5.0.0",
633+ "web-url": "2.0.0",
634+ "web-workers": "1.1.0",
635+ "web-xhr": "5.0.1",
636+ "webextension-polyfill": "0.1.0",
637+ "webgpu": "0.0.1",
638+ "which": "2.0.0",
639+ "xterm": "1.0.0",
640+ "yoga-fetch": "1.0.1",
641+ "yoga-json": "5.1.0",
642+ "yoga-om": "0.1.0",
643+ "yoga-postgres": "6.0.0",
644+ "yoga-tree": "1.0.0",
645+ "z3": "0.0.2",
646+ "zipperarray": "2.0.0"
647+ }
648+ },
649+ "extra_packages": {}
650+ },
651+ "packages": {
652+ "aff": {
653+ "type": "registry",
654+ "version": "8.0.0",
655+ "integrity": "sha256-5MmdI4+0RHBtSBy+YlU3/Cq4R5W2ih3OaRedJIrVHdk=",
656+ "dependencies": [
657+ "bifunctors",
658+ "control",
659+ "datetime",
660+ "effect",
661+ "either",
662+ "exceptions",
663+ "foldable-traversable",
664+ "functions",
665+ "maybe",
666+ "newtype",
667+ "parallel",
668+ "prelude",
669+ "refs",
670+ "tailrec",
671+ "transformers",
672+ "unsafe-coerce"
673+ ]
674+ },
675+ "affjax": {
676+ "type": "registry",
677+ "version": "13.0.0",
678+ "integrity": "sha256-blYfaoW4FYIrIdvmT4sB7nN7BathFaEfZuiVLPmHJOo=",
679+ "dependencies": [
680+ "aff",
681+ "argonaut-core",
682+ "arraybuffer-types",
683+ "foreign",
684+ "form-urlencoded",
685+ "http-methods",
686+ "integers",
687+ "media-types",
688+ "nullable",
689+ "refs",
690+ "unsafe-coerce",
691+ "web-xhr"
692+ ]
693+ },
694+ "affjax-node": {
695+ "type": "registry",
696+ "version": "1.0.0",
697+ "integrity": "sha256-NcmRTXJxJzgHuKoLh+36yA8UejkfouYcX3uevT+Trjc=",
698+ "dependencies": [
699+ "aff",
700+ "affjax",
701+ "either",
702+ "maybe",
703+ "prelude"
704+ ]
705+ },
706+ "argonaut-codecs": {
707+ "type": "registry",
708+ "version": "9.1.0",
709+ "integrity": "sha256-N6efXByUeg848ompEqJfVvZuZPfdRYDGlTDFn0G0Oh8=",
710+ "dependencies": [
711+ "argonaut-core",
712+ "arrays",
713+ "effect",
714+ "foreign-object",
715+ "identity",
716+ "integers",
717+ "maybe",
718+ "nonempty",
719+ "ordered-collections",
720+ "prelude",
721+ "record"
722+ ]
723+ },
724+ "argonaut-core": {
725+ "type": "registry",
726+ "version": "7.0.0",
727+ "integrity": "sha256-RC82GfAjItydxrO24cdX373KHVZiLqybu19b5X8u7B4=",
728+ "dependencies": [
729+ "arrays",
730+ "control",
731+ "either",
732+ "foreign-object",
733+ "functions",
734+ "gen",
735+ "maybe",
736+ "nonempty",
737+ "prelude",
738+ "strings",
739+ "tailrec"
740+ ]
741+ },
742+ "arraybuffer-types": {
743+ "type": "registry",
744+ "version": "3.0.2",
745+ "integrity": "sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA=",
746+ "dependencies": []
747+ },
748+ "arrays": {
749+ "type": "registry",
750+ "version": "7.3.0",
751+ "integrity": "sha256-tmcklBlc/muUtUfr9RapdCPwnlQeB3aSrC4dK85gQlc=",
752+ "dependencies": [
753+ "bifunctors",
754+ "control",
755+ "foldable-traversable",
756+ "functions",
757+ "maybe",
758+ "nonempty",
759+ "partial",
760+ "prelude",
761+ "safe-coerce",
762+ "st",
763+ "tailrec",
764+ "tuples",
765+ "unfoldable",
766+ "unsafe-coerce"
767+ ]
768+ },
769+ "bifunctors": {
770+ "type": "registry",
771+ "version": "6.0.0",
772+ "integrity": "sha256-/gZwC9YhNxZNQpnHa5BIYerCGM2jeX9ukZiEvYxm5Nw=",
773+ "dependencies": [
774+ "const",
775+ "either",
776+ "newtype",
777+ "prelude",
778+ "tuples"
779+ ]
780+ },
781+ "catenable-lists": {
782+ "type": "registry",
783+ "version": "7.0.0",
784+ "integrity": "sha256-76vYENhwF4BWTBsjeLuErCH2jqVT4M3R1HX+4RwSftA=",
785+ "dependencies": [
786+ "control",
787+ "foldable-traversable",
788+ "lists",
789+ "maybe",
790+ "prelude",
791+ "tuples",
792+ "unfoldable"
793+ ]
794+ },
795+ "colors": {
796+ "type": "registry",
797+ "version": "7.0.1",
798+ "integrity": "sha256-udlg/y2PFsHYli8Tgz8BQGGrOjyGo0BcJj36IfgYADs=",
799+ "dependencies": [
800+ "arrays",
801+ "integers",
802+ "lists",
803+ "numbers",
804+ "partial",
805+ "strings"
806+ ]
807+ },
808+ "console": {
809+ "type": "registry",
810+ "version": "6.1.0",
811+ "integrity": "sha256-CxmAzjgyuGDmt9FZW51VhV6rBPwR6o0YeKUzA9rSzcM=",
812+ "dependencies": [
813+ "effect",
814+ "prelude"
815+ ]
816+ },
817+ "const": {
818+ "type": "registry",
819+ "version": "6.0.0",
820+ "integrity": "sha256-tNrxDW8D8H4jdHE2HiPzpLy08zkzJMmGHdRqt5BQuTc=",
821+ "dependencies": [
822+ "invariant",
823+ "newtype",
824+ "prelude"
825+ ]
826+ },
827+ "contravariant": {
828+ "type": "registry",
829+ "version": "6.0.0",
830+ "integrity": "sha256-TP+ooAp3vvmdjfQsQJSichF5B4BPDHp3wAJoWchip6c=",
831+ "dependencies": [
832+ "const",
833+ "either",
834+ "newtype",
835+ "prelude",
836+ "tuples"
837+ ]
838+ },
839+ "control": {
840+ "type": "registry",
841+ "version": "6.0.0",
842+ "integrity": "sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk=",
843+ "dependencies": [
844+ "newtype",
845+ "prelude"
846+ ]
847+ },
848+ "css": {
849+ "type": "registry",
850+ "version": "6.0.0",
851+ "integrity": "sha256-zfSHxgiU4rSWuVxMjSKKh+s7j433wxmsr+CqI6hm9s4=",
852+ "dependencies": [
853+ "colors",
854+ "console",
855+ "effect",
856+ "nonempty",
857+ "profunctor",
858+ "strings",
859+ "these",
860+ "transformers"
861+ ]
862+ },
863+ "datetime": {
864+ "type": "registry",
865+ "version": "6.1.0",
866+ "integrity": "sha256-g/5X5BBegQWLpI9IWD+sY6mcaYpzzlW5lz5NBzaMtyI=",
867+ "dependencies": [
868+ "bifunctors",
869+ "control",
870+ "either",
871+ "enums",
872+ "foldable-traversable",
873+ "functions",
874+ "gen",
875+ "integers",
876+ "lists",
877+ "maybe",
878+ "newtype",
879+ "numbers",
880+ "ordered-collections",
881+ "partial",
882+ "prelude",
883+ "tuples"
884+ ]
885+ },
886+ "distributive": {
887+ "type": "registry",
888+ "version": "6.0.0",
889+ "integrity": "sha256-HTDdmEnzigMl+02SJB88j+gAXDx9VKsbvR4MJGDPbOQ=",
890+ "dependencies": [
891+ "identity",
892+ "newtype",
893+ "prelude",
894+ "tuples",
895+ "type-equality"
896+ ]
897+ },
898+ "effect": {
899+ "type": "registry",
900+ "version": "4.0.0",
901+ "integrity": "sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M=",
902+ "dependencies": [
903+ "prelude"
904+ ]
905+ },
906+ "either": {
907+ "type": "registry",
908+ "version": "6.1.0",
909+ "integrity": "sha256-6hgTPisnMWVwQivOu2PKYcH8uqjEOOqDyaDQVUchTpY=",
910+ "dependencies": [
911+ "control",
912+ "invariant",
913+ "maybe",
914+ "prelude"
915+ ]
916+ },
917+ "enums": {
918+ "type": "registry",
919+ "version": "6.0.1",
920+ "integrity": "sha256-HWaD73JFLorc4A6trKIRUeDMdzE+GpkJaEOM1nTNkC8=",
921+ "dependencies": [
922+ "control",
923+ "either",
924+ "gen",
925+ "maybe",
926+ "newtype",
927+ "nonempty",
928+ "partial",
929+ "prelude",
930+ "tuples",
931+ "unfoldable"
932+ ]
933+ },
934+ "exceptions": {
935+ "type": "registry",
936+ "version": "6.1.0",
937+ "integrity": "sha256-K0T89IHtF3vBY7eSAO7eDOqSb2J9kZGAcDN5+IKsF8E=",
938+ "dependencies": [
939+ "effect",
940+ "either",
941+ "maybe",
942+ "prelude"
943+ ]
944+ },
945+ "exists": {
946+ "type": "registry",
947+ "version": "6.0.0",
948+ "integrity": "sha256-A0JQHpTfo1dNOj9U5/Fd3xndlRSE0g2IQWOGor2yXn8=",
949+ "dependencies": [
950+ "unsafe-coerce"
951+ ]
952+ },
953+ "foldable-traversable": {
954+ "type": "registry",
955+ "version": "6.0.0",
956+ "integrity": "sha256-fLeqRYM4jUrZD5H4WqcwUgzU7XfYkzO4zhgtNc3jcWM=",
957+ "dependencies": [
958+ "bifunctors",
959+ "const",
960+ "control",
961+ "either",
962+ "functors",
963+ "identity",
964+ "maybe",
965+ "newtype",
966+ "orders",
967+ "prelude",
968+ "tuples"
969+ ]
970+ },
971+ "foreign": {
972+ "type": "registry",
973+ "version": "7.0.0",
974+ "integrity": "sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA=",
975+ "dependencies": [
976+ "either",
977+ "functions",
978+ "identity",
979+ "integers",
980+ "lists",
981+ "maybe",
982+ "prelude",
983+ "strings",
984+ "transformers"
985+ ]
986+ },
987+ "foreign-object": {
988+ "type": "registry",
989+ "version": "4.1.0",
990+ "integrity": "sha256-q24okj6mT+yGHYQ+ei/pYPj5ih6sTbu7eDv/WU56JVo=",
991+ "dependencies": [
992+ "arrays",
993+ "foldable-traversable",
994+ "functions",
995+ "gen",
996+ "lists",
997+ "maybe",
998+ "prelude",
999+ "st",
1000+ "tailrec",
1001+ "tuples",
1002+ "typelevel-prelude",
1003+ "unfoldable"
1004+ ]
1005+ },
1006+ "form-urlencoded": {
1007+ "type": "registry",
1008+ "version": "7.0.0",
1009+ "integrity": "sha256-WUzk8DTjrbPVHKZ5w7XpPBO6ci6xFhvYguHp6RvX+18=",
1010+ "dependencies": [
1011+ "foldable-traversable",
1012+ "js-uri",
1013+ "maybe",
1014+ "newtype",
1015+ "prelude",
1016+ "strings",
1017+ "tuples"
1018+ ]
1019+ },
1020+ "free": {
1021+ "type": "registry",
1022+ "version": "7.1.0",
1023+ "integrity": "sha256-JAumgEsGSzJCNLD8AaFvuX7CpqS5yruCngi6yI7+V5k=",
1024+ "dependencies": [
1025+ "catenable-lists",
1026+ "control",
1027+ "distributive",
1028+ "either",
1029+ "exists",
1030+ "foldable-traversable",
1031+ "invariant",
1032+ "lazy",
1033+ "maybe",
1034+ "prelude",
1035+ "tailrec",
1036+ "transformers",
1037+ "tuples",
1038+ "unsafe-coerce"
1039+ ]
1040+ },
1041+ "functions": {
1042+ "type": "registry",
1043+ "version": "6.0.0",
1044+ "integrity": "sha256-adMyJNEnhGde2unHHAP79gPtlNjNqzgLB8arEOn9hLI=",
1045+ "dependencies": [
1046+ "prelude"
1047+ ]
1048+ },
1049+ "functors": {
1050+ "type": "registry",
1051+ "version": "5.0.0",
1052+ "integrity": "sha256-zfPWWYisbD84MqwpJSZFlvM6v86McM68ob8p9s27ywU=",
1053+ "dependencies": [
1054+ "bifunctors",
1055+ "const",
1056+ "contravariant",
1057+ "control",
1058+ "distributive",
1059+ "either",
1060+ "invariant",
1061+ "maybe",
1062+ "newtype",
1063+ "prelude",
1064+ "profunctor",
1065+ "tuples",
1066+ "unsafe-coerce"
1067+ ]
1068+ },
1069+ "gen": {
1070+ "type": "registry",
1071+ "version": "4.0.0",
1072+ "integrity": "sha256-f7yzAXWwr+xnaqEOcvyO3ezKdoes8+WXWdXIHDBCAPI=",
1073+ "dependencies": [
1074+ "either",
1075+ "foldable-traversable",
1076+ "identity",
1077+ "maybe",
1078+ "newtype",
1079+ "nonempty",
1080+ "prelude",
1081+ "tailrec",
1082+ "tuples",
1083+ "unfoldable"
1084+ ]
1085+ },
1086+ "http-methods": {
1087+ "type": "registry",
1088+ "version": "6.0.0",
1089+ "integrity": "sha256-Orr7rbDGcp7qoqmUMXPRMjBx+C4jqOQcFe9+gE3nMgU=",
1090+ "dependencies": [
1091+ "either",
1092+ "prelude",
1093+ "strings"
1094+ ]
1095+ },
1096+ "identity": {
1097+ "type": "registry",
1098+ "version": "6.0.0",
1099+ "integrity": "sha256-4wY0XZbAksjY6UAg99WkuKyJlQlWAfTi2ssadH0wVMY=",
1100+ "dependencies": [
1101+ "control",
1102+ "invariant",
1103+ "newtype",
1104+ "prelude"
1105+ ]
1106+ },
1107+ "integers": {
1108+ "type": "registry",
1109+ "version": "6.0.0",
1110+ "integrity": "sha256-sf+sK26R1hzwl3NhXR7WAu9zCDjQnfoXwcyGoseX158=",
1111+ "dependencies": [
1112+ "maybe",
1113+ "numbers",
1114+ "prelude"
1115+ ]
1116+ },
1117+ "invariant": {
1118+ "type": "registry",
1119+ "version": "6.0.0",
1120+ "integrity": "sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo=",
1121+ "dependencies": [
1122+ "control",
1123+ "prelude"
1124+ ]
1125+ },
1126+ "js-date": {
1127+ "type": "registry",
1128+ "version": "8.0.0",
1129+ "integrity": "sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo=",
1130+ "dependencies": [
1131+ "datetime",
1132+ "effect",
1133+ "exceptions",
1134+ "foreign",
1135+ "integers",
1136+ "now"
1137+ ]
1138+ },
1139+ "js-uri": {
1140+ "type": "registry",
1141+ "version": "3.1.0",
1142+ "integrity": "sha256-3p0ynHveCJmC2CXze+eMBdW/2l5e953Q8XMAKz+jxUo=",
1143+ "dependencies": [
1144+ "functions",
1145+ "maybe"
1146+ ]
1147+ },
1148+ "lazy": {
1149+ "type": "registry",
1150+ "version": "6.0.0",
1151+ "integrity": "sha256-lMsfFOnlqfe4KzRRiW8ot5ge6HtcU3Eyh2XkXcP5IgU=",
1152+ "dependencies": [
1153+ "control",
1154+ "foldable-traversable",
1155+ "invariant",
1156+ "prelude"
1157+ ]
1158+ },
1159+ "lcg": {
1160+ "type": "registry",
1161+ "version": "4.0.0",
1162+ "integrity": "sha256-h7ME5cthLfbgJOJdsZcSfFpwXsx4rf8YmhebU+3iSYg=",
1163+ "dependencies": [
1164+ "effect",
1165+ "integers",
1166+ "maybe",
1167+ "partial",
1168+ "prelude",
1169+ "random"
1170+ ]
1171+ },
1172+ "lists": {
1173+ "type": "registry",
1174+ "version": "7.0.0",
1175+ "integrity": "sha256-EKF15qYqucuXP2lT/xPxhqy58f0FFT6KHdIB/yBOayI=",
1176+ "dependencies": [
1177+ "bifunctors",
1178+ "control",
1179+ "foldable-traversable",
1180+ "lazy",
1181+ "maybe",
1182+ "newtype",
1183+ "nonempty",
1184+ "partial",
1185+ "prelude",
1186+ "tailrec",
1187+ "tuples",
1188+ "unfoldable"
1189+ ]
1190+ },
1191+ "maybe": {
1192+ "type": "registry",
1193+ "version": "6.0.0",
1194+ "integrity": "sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q=",
1195+ "dependencies": [
1196+ "control",
1197+ "invariant",
1198+ "newtype",
1199+ "prelude"
1200+ ]
1201+ },
1202+ "media-types": {
1203+ "type": "registry",
1204+ "version": "6.0.0",
1205+ "integrity": "sha256-n/4FoGBasbVSYscGVRSyBunQ6CZbL3jsYL+Lp01mc9k=",
1206+ "dependencies": [
1207+ "newtype",
1208+ "prelude"
1209+ ]
1210+ },
1211+ "newtype": {
1212+ "type": "registry",
1213+ "version": "5.0.0",
1214+ "integrity": "sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw=",
1215+ "dependencies": [
1216+ "prelude",
1217+ "safe-coerce"
1218+ ]
1219+ },
1220+ "node-buffer": {
1221+ "type": "registry",
1222+ "version": "9.0.0",
1223+ "integrity": "sha256-PWE2DJ5ruBLCmeA/fUiuySEFmUJ/VuRfyrnCuVZBlu4=",
1224+ "dependencies": [
1225+ "arraybuffer-types",
1226+ "effect",
1227+ "maybe",
1228+ "nullable",
1229+ "st",
1230+ "unsafe-coerce"
1231+ ]
1232+ },
1233+ "node-event-emitter": {
1234+ "type": "registry",
1235+ "version": "3.0.0",
1236+ "integrity": "sha256-Qw0MjsT4xRH2j2i4K8JmRjcMKnH5z1Cw39t00q4LE4w=",
1237+ "dependencies": [
1238+ "effect",
1239+ "either",
1240+ "functions",
1241+ "maybe",
1242+ "nullable",
1243+ "prelude",
1244+ "unsafe-coerce"
1245+ ]
1246+ },
1247+ "node-fs": {
1248+ "type": "registry",
1249+ "version": "9.2.0",
1250+ "integrity": "sha256-Sg0vkXycEzkEerX6hLccz21Ygd9w1+QSk1thotRZPGI=",
1251+ "dependencies": [
1252+ "datetime",
1253+ "effect",
1254+ "either",
1255+ "enums",
1256+ "exceptions",
1257+ "functions",
1258+ "integers",
1259+ "js-date",
1260+ "maybe",
1261+ "node-buffer",
1262+ "node-path",
1263+ "node-streams",
1264+ "nullable",
1265+ "partial",
1266+ "prelude",
1267+ "strings",
1268+ "unsafe-coerce"
1269+ ]
1270+ },
1271+ "node-path": {
1272+ "type": "registry",
1273+ "version": "5.0.0",
1274+ "integrity": "sha256-pd82nQ+2l5UThzaxPdKttgDt7xlsgIDLpPG0yxDEdyE=",
1275+ "dependencies": [
1276+ "effect"
1277+ ]
1278+ },
1279+ "node-streams": {
1280+ "type": "registry",
1281+ "version": "9.0.0",
1282+ "integrity": "sha256-2n6dq7YWleTDmD1Kur/ul7Cn08IvWrScgPf+0PgX2TQ=",
1283+ "dependencies": [
1284+ "aff",
1285+ "effect",
1286+ "either",
1287+ "exceptions",
1288+ "node-buffer",
1289+ "node-event-emitter",
1290+ "nullable",
1291+ "prelude"
1292+ ]
1293+ },
1294+ "nonempty": {
1295+ "type": "registry",
1296+ "version": "7.0.0",
1297+ "integrity": "sha256-54ablJZUHGvvlTJzi3oXyPCuvY6zsrWJuH/dMJ/MFLs=",
1298+ "dependencies": [
1299+ "control",
1300+ "foldable-traversable",
1301+ "maybe",
1302+ "prelude",
1303+ "tuples",
1304+ "unfoldable"
1305+ ]
1306+ },
1307+ "now": {
1308+ "type": "registry",
1309+ "version": "6.0.0",
1310+ "integrity": "sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY=",
1311+ "dependencies": [
1312+ "datetime",
1313+ "effect"
1314+ ]
1315+ },
1316+ "nullable": {
1317+ "type": "registry",
1318+ "version": "6.0.0",
1319+ "integrity": "sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o=",
1320+ "dependencies": [
1321+ "effect",
1322+ "functions",
1323+ "maybe"
1324+ ]
1325+ },
1326+ "numbers": {
1327+ "type": "registry",
1328+ "version": "9.0.1",
1329+ "integrity": "sha256-/9M6aeMDBdB4cwYDeJvLFprAHZ49EbtKQLIJsneXLIk=",
1330+ "dependencies": [
1331+ "functions",
1332+ "maybe"
1333+ ]
1334+ },
1335+ "ordered-collections": {
1336+ "type": "registry",
1337+ "version": "3.2.0",
1338+ "integrity": "sha256-o9jqsj5rpJmMdoe/zyufWHFjYYFTTsJpgcuCnqCO6PM=",
1339+ "dependencies": [
1340+ "arrays",
1341+ "foldable-traversable",
1342+ "gen",
1343+ "lists",
1344+ "maybe",
1345+ "partial",
1346+ "prelude",
1347+ "st",
1348+ "tailrec",
1349+ "tuples",
1350+ "unfoldable"
1351+ ]
1352+ },
1353+ "orders": {
1354+ "type": "registry",
1355+ "version": "6.0.0",
1356+ "integrity": "sha256-nBA0g3/ai0euH8q9pSbGqk53W2q6agm/dECZTHcoink=",
1357+ "dependencies": [
1358+ "newtype",
1359+ "prelude"
1360+ ]
1361+ },
1362+ "parallel": {
1363+ "type": "registry",
1364+ "version": "7.0.0",
1365+ "integrity": "sha256-gUC9i4Txnx9K9RcMLsjujbwZz6BB1bnE2MLvw4GIw5o=",
1366+ "dependencies": [
1367+ "control",
1368+ "effect",
1369+ "either",
1370+ "foldable-traversable",
1371+ "functors",
1372+ "maybe",
1373+ "newtype",
1374+ "prelude",
1375+ "profunctor",
1376+ "refs",
1377+ "transformers"
1378+ ]
1379+ },
1380+ "partial": {
1381+ "type": "registry",
1382+ "version": "4.0.0",
1383+ "integrity": "sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4=",
1384+ "dependencies": []
1385+ },
1386+ "prelude": {
1387+ "type": "registry",
1388+ "version": "6.0.1",
1389+ "integrity": "sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0=",
1390+ "dependencies": []
1391+ },
1392+ "profunctor": {
1393+ "type": "registry",
1394+ "version": "6.0.1",
1395+ "integrity": "sha256-E58hSYdJvF2Qjf9dnWLPlJKh2Z2fLfFLkQoYi16vsFk=",
1396+ "dependencies": [
1397+ "control",
1398+ "distributive",
1399+ "either",
1400+ "exists",
1401+ "invariant",
1402+ "newtype",
1403+ "prelude",
1404+ "tuples"
1405+ ]
1406+ },
1407+ "quickcheck": {
1408+ "type": "registry",
1409+ "version": "8.0.1",
1410+ "integrity": "sha256-ZvpccKQCvgslTXZCNmpYW4bUsFzhZd/kQUr2WmxFTGY=",
1411+ "dependencies": [
1412+ "arrays",
1413+ "console",
1414+ "control",
1415+ "effect",
1416+ "either",
1417+ "enums",
1418+ "exceptions",
1419+ "foldable-traversable",
1420+ "gen",
1421+ "identity",
1422+ "integers",
1423+ "lazy",
1424+ "lcg",
1425+ "lists",
1426+ "maybe",
1427+ "newtype",
1428+ "nonempty",
1429+ "numbers",
1430+ "partial",
1431+ "prelude",
1432+ "record",
1433+ "st",
1434+ "strings",
1435+ "tailrec",
1436+ "transformers",
1437+ "tuples",
1438+ "unfoldable"
1439+ ]
1440+ },
1441+ "quickcheck-laws": {
1442+ "type": "registry",
1443+ "version": "7.0.0",
1444+ "integrity": "sha256-rnzVTiDnymzYkvnhI8EvPwrmO8LgcTnrMTuiI172Tkc=",
1445+ "dependencies": [
1446+ "enums",
1447+ "quickcheck"
1448+ ]
1449+ },
1450+ "random": {
1451+ "type": "registry",
1452+ "version": "6.0.0",
1453+ "integrity": "sha256-CJ611a35MPCE7XQMp0rdC6MCn76znlhisiCRgboAG+Q=",
1454+ "dependencies": [
1455+ "effect",
1456+ "integers"
1457+ ]
1458+ },
1459+ "record": {
1460+ "type": "registry",
1461+ "version": "4.0.0",
1462+ "integrity": "sha256-Za5U85bTRJEfGK5Sk4hM41oXy84YQI0I8TL3WUn1Qzg=",
1463+ "dependencies": [
1464+ "functions",
1465+ "prelude",
1466+ "unsafe-coerce"
1467+ ]
1468+ },
1469+ "refs": {
1470+ "type": "registry",
1471+ "version": "6.0.0",
1472+ "integrity": "sha256-Vgwne7jIbD3ZMoLNNETLT8Litw6lIYo3MfYNdtYWj9s=",
1473+ "dependencies": [
1474+ "effect",
1475+ "prelude"
1476+ ]
1477+ },
1478+ "run": {
1479+ "type": "registry",
1480+ "version": "5.0.0",
1481+ "integrity": "sha256-uCCGBqPXOSTnQoVzQUoCcEYyGvi+dWZp+lLsxtNG6+U=",
1482+ "dependencies": [
1483+ "aff",
1484+ "effect",
1485+ "either",
1486+ "free",
1487+ "maybe",
1488+ "newtype",
1489+ "prelude",
1490+ "profunctor",
1491+ "tailrec",
1492+ "tuples",
1493+ "type-equality",
1494+ "typelevel-prelude",
1495+ "unsafe-coerce",
1496+ "variant"
1497+ ]
1498+ },
1499+ "safe-coerce": {
1500+ "type": "registry",
1501+ "version": "2.0.0",
1502+ "integrity": "sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU=",
1503+ "dependencies": [
1504+ "unsafe-coerce"
1505+ ]
1506+ },
1507+ "st": {
1508+ "type": "registry",
1509+ "version": "6.2.0",
1510+ "integrity": "sha256-z9X0WsOUlPwNx9GlCC+YccCyz8MejC8Wb0C4+9fiBRY=",
1511+ "dependencies": [
1512+ "partial",
1513+ "prelude",
1514+ "tailrec",
1515+ "unsafe-coerce"
1516+ ]
1517+ },
1518+ "strings": {
1519+ "type": "registry",
1520+ "version": "6.0.1",
1521+ "integrity": "sha256-WssD3DbX4OPzxSdjvRMX0yvc9+pS7n5gyPv5I2Trb7k=",
1522+ "dependencies": [
1523+ "arrays",
1524+ "control",
1525+ "either",
1526+ "enums",
1527+ "foldable-traversable",
1528+ "gen",
1529+ "integers",
1530+ "maybe",
1531+ "newtype",
1532+ "nonempty",
1533+ "partial",
1534+ "prelude",
1535+ "tailrec",
1536+ "tuples",
1537+ "unfoldable",
1538+ "unsafe-coerce"
1539+ ]
1540+ },
1541+ "tailrec": {
1542+ "type": "registry",
1543+ "version": "6.1.0",
1544+ "integrity": "sha256-Xx19ECVDRrDWpz9D2GxQHHV89vd61dnXxQm0IcYQHGk=",
1545+ "dependencies": [
1546+ "bifunctors",
1547+ "effect",
1548+ "either",
1549+ "identity",
1550+ "maybe",
1551+ "partial",
1552+ "prelude",
1553+ "refs"
1554+ ]
1555+ },
1556+ "these": {
1557+ "type": "registry",
1558+ "version": "6.0.0",
1559+ "integrity": "sha256-6poQvFzGw7Ir9mTDEbFV9N6+cUeSHe0FdzTR2ZK1o6g=",
1560+ "dependencies": [
1561+ "arrays",
1562+ "gen",
1563+ "lists",
1564+ "quickcheck",
1565+ "quickcheck-laws",
1566+ "tuples"
1567+ ]
1568+ },
1569+ "transformers": {
1570+ "type": "registry",
1571+ "version": "6.1.0",
1572+ "integrity": "sha256-3Bm+Z6tsC/paG888XkywDngJ2JMos+JfOhRlkVfb7gI=",
1573+ "dependencies": [
1574+ "control",
1575+ "distributive",
1576+ "effect",
1577+ "either",
1578+ "exceptions",
1579+ "foldable-traversable",
1580+ "identity",
1581+ "lazy",
1582+ "maybe",
1583+ "newtype",
1584+ "prelude",
1585+ "st",
1586+ "tailrec",
1587+ "tuples",
1588+ "unfoldable"
1589+ ]
1590+ },
1591+ "tuples": {
1592+ "type": "registry",
1593+ "version": "7.0.0",
1594+ "integrity": "sha256-1rXgTomes9105BjgXqIw0FL6Fz1lqqUTLWOumhWec1M=",
1595+ "dependencies": [
1596+ "control",
1597+ "invariant",
1598+ "prelude"
1599+ ]
1600+ },
1601+ "type-equality": {
1602+ "type": "registry",
1603+ "version": "4.0.1",
1604+ "integrity": "sha256-Hs9D6Y71zFi/b+qu5NSbuadUQXe5iv5iWx0226vOHUw=",
1605+ "dependencies": []
1606+ },
1607+ "typelevel-prelude": {
1608+ "type": "registry",
1609+ "version": "7.0.0",
1610+ "integrity": "sha256-uFF2ph+vHcQpfPuPf2a3ukJDFmLhApmkpTMviHIWgJM=",
1611+ "dependencies": [
1612+ "prelude",
1613+ "type-equality"
1614+ ]
1615+ },
1616+ "unfoldable": {
1617+ "type": "registry",
1618+ "version": "6.0.0",
1619+ "integrity": "sha256-JtikvJdktRap7vr/K4ITlxUX1QexpnqBq0G/InLr6eg=",
1620+ "dependencies": [
1621+ "foldable-traversable",
1622+ "maybe",
1623+ "partial",
1624+ "prelude",
1625+ "tuples"
1626+ ]
1627+ },
1628+ "unsafe-coerce": {
1629+ "type": "registry",
1630+ "version": "6.0.0",
1631+ "integrity": "sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0=",
1632+ "dependencies": []
1633+ },
1634+ "variant": {
1635+ "type": "registry",
1636+ "version": "8.0.0",
1637+ "integrity": "sha256-SR//zQDg2dnbB8ZHslcxieUkCeNlbMToapvmh9onTtw=",
1638+ "dependencies": [
1639+ "enums",
1640+ "lists",
1641+ "maybe",
1642+ "partial",
1643+ "prelude",
1644+ "record",
1645+ "tuples",
1646+ "unsafe-coerce"
1647+ ]
1648+ },
1649+ "web-dom": {
1650+ "type": "registry",
1651+ "version": "6.0.0",
1652+ "integrity": "sha256-1kSKWFDI4LupdmpjK01b1MMxDFW7jvatEgPgVmCmSBQ=",
1653+ "dependencies": [
1654+ "web-events"
1655+ ]
1656+ },
1657+ "web-events": {
1658+ "type": "registry",
1659+ "version": "4.0.0",
1660+ "integrity": "sha256-YDt8b6u1tzGtnWyNRodne57iO8FNSGPaTCVzBUyUn4k=",
1661+ "dependencies": [
1662+ "datetime",
1663+ "enums",
1664+ "foreign",
1665+ "nullable"
1666+ ]
1667+ },
1668+ "web-file": {
1669+ "type": "registry",
1670+ "version": "4.0.0",
1671+ "integrity": "sha256-1h5jPBkvjY71jLEdwVadXCx86/2inNoMBO//Rd3eCSU=",
1672+ "dependencies": [
1673+ "foreign",
1674+ "media-types",
1675+ "web-dom"
1676+ ]
1677+ },
1678+ "web-html": {
1679+ "type": "registry",
1680+ "version": "4.1.0",
1681+ "integrity": "sha256-ByqS/h1/yG+hjCOnOQp7L1QpIWzQENNKB1kaHtpEhlE=",
1682+ "dependencies": [
1683+ "js-date",
1684+ "web-dom",
1685+ "web-file",
1686+ "web-storage"
1687+ ]
1688+ },
1689+ "web-storage": {
1690+ "type": "registry",
1691+ "version": "5.0.0",
1692+ "integrity": "sha256-q+6lxcnfWxus0/nDeFVtF1V+tLehZvvXQ0cduYPLksY=",
1693+ "dependencies": [
1694+ "nullable",
1695+ "web-events"
1696+ ]
1697+ },
1698+ "web-xhr": {
1699+ "type": "registry",
1700+ "version": "5.0.1",
1701+ "integrity": "sha256-3dbIPVG66S+hPrgEVnpD78hrGjE7qlBbsReWOz89Ios=",
1702+ "dependencies": [
1703+ "arraybuffer-types",
1704+ "datetime",
1705+ "http-methods",
1706+ "web-dom",
1707+ "web-file",
1708+ "web-html"
1709+ ]
1710+ }
1711+ }
1712+}
spago.yamlnew file+41
@@ -0,0 +1,41 @@
1+package:
2+ name: lunapark
3+ dependencies:
4+ - aff: ">=8.0.0 <9.0.0"
5+ - affjax: ">=13.0.0 <14.0.0"
6+ - affjax-node: ">=1.0.0 <2.0.0"
7+ - argonaut-codecs: ">=9.1.0 <10.0.0"
8+ - argonaut-core: ">=7.0.0 <8.0.0"
9+ - arrays: ">=7.3.0 <8.0.0"
10+ - bifunctors: ">=6.0.0 <7.0.0"
11+ - control: ">=6.0.0 <7.0.0"
12+ - css: ">=6.0.0 <7.0.0"
13+ - datetime: ">=6.1.0 <7.0.0"
14+ - effect: ">=4.0.0 <5.0.0"
15+ - either: ">=6.1.0 <7.0.0"
16+ - foldable-traversable: ">=6.0.0 <7.0.0"
17+ - foreign-object: ">=4.1.0 <5.0.0"
18+ - lists: ">=7.0.0 <8.0.0"
19+ - maybe: ">=6.0.0 <7.0.0"
20+ - newtype: ">=5.0.0 <6.0.0"
21+ - node-buffer: ">=9.0.0 <10.0.0"
22+ - node-fs: ">=9.2.0 <10.0.0"
23+ - node-path: ">=5.0.0 <6.0.0"
24+ - ordered-collections: ">=3.2.0 <4.0.0"
25+ - prelude: ">=6.0.1 <7.0.0"
26+ - refs: ">=6.0.0 <7.0.0"
27+ - run: ">=5.0.0 <6.0.0"
28+ - strings: ">=6.0.1 <7.0.0"
29+ - tailrec: ">=6.1.0 <7.0.0"
30+ - tuples: ">=7.0.0 <8.0.0"
31+ - typelevel-prelude: ">=7.0.0 <8.0.0"
32+ - unsafe-coerce: ">=6.0.0 <7.0.0"
33+ - variant: ">=8.0.0 <9.0.0"
34+ test:
35+ main: Test.Main
36+ dependencies:
37+ - console
38+workspace:
39+ packageSet:
40+ registry: 60.4.0
41+ extraPackages: {}
src/Lunapark.purs+8−5
@@ -3,10 +3,13 @@ module Lunapark
33 , module Lunapark.Error
44 , module Lunapark.ActionF
55 , module Lunapark.LunaparkF
6+ , module Lunapark.WebDriverError
7+ , module Lunapark.Types
68 ) where
79
8−
9−import Lunapark.API (Interpreter(..), runInterpreter, BaseRun, HandleLunaparkInput, Lunapark, handleLunapark, init, interpret, interpretW3CActions, jsonWireActions, runLunapark, runLunaparkActions, w3cActions)
10−import Lunapark.Error (Error, ErrorType(..), fromJson, fromStringCode, toStringCode, unknownError)
11−import Lunapark.ActionF (ActionF(..), LUNAPARK_ACTIONS, TouchF(..), WithAction, _lunaparkActions, buttonDown, buttonUp, click, doubleClick, doubleTap, flick, liftAction, longTap, moveTo, pause, scroll, sendKeys, tap, touchDown, touchUp)
12−import Lunapark.LunaparkF (ElementF(..), LUNAPARK, LunaparkF(..), WithLunapark, _lunapark, acceptAlert, addCookie, back, childElement, childElements, clearElement, clickElement, closeWindow, deleteAllCookies, deleteCookie, dismissAlert, elementScreenshot, executeScript, executeScriptAsync, findElement, findElements, forward, fullscreenWindow, getAlertText, getAllCookies, getAttribute, getCookie, getCss, getProperty, getRectangle, getTagName, getText, getTimeouts, getTitle, getUrl, getWindowHandle, getWindowHandles, getWindowRectangle, go, isDisplayed, isEnabled, isSelected, liftLunapark, maximizeWindow, minimizeWindow, performActions, quit, refresh, releaseActions, screenshot, sendAlertText, sendKeysElement, setTimeouts, setWindowRectangle, status, submitElement, switchToFrame, switchToParentFrame, switchToWindow)
10+import Lunapark.API (Lunapark, Interpreter(..), runInterpreter, BASE_EFFECTS, HandleLunaparkInput, handleLunapark, init, interpret, interpretW3CActions, jsonWireActions, runLunapark, runLunaparkActions, w3cActions)
11+import Lunapark.Error (Error(..), CachingError(..), printError)
12+import Lunapark.ActionF (ActionF(..), LUNAPARK_ACTIONS, TouchF(..), _lunaparkActions, buttonDown, buttonUp, click, doubleClick, doubleTap, flick, liftAction, longTap, moveTo, pause, scroll, sendKeys, tap, touchDown, touchUp)
13+import Lunapark.LunaparkF (ElementF(..), LUNAPARK, LunaparkF(..), _lunapark, acceptAlert, addCookie, back, childElement, childElements, clearElement, clickElement, closeWindow, deleteAllCookies, deleteCookie, dismissAlert, elementScreenshot, executeScript, executeScriptAsync, findElement, findElements, forward, fullscreenWindow, getAlertText, getAllCookies, getAttribute, getCookie, getCss, getProperty, getRectangle, getTagName, getText, getTimeouts, getTitle, getUrl, getWindowHandle, getWindowHandles, getWindowRectangle, go, isDisplayed, isEnabled, isSelected, liftLunapark, maximizeWindow, minimizeWindow, performActions, quit, refresh, releaseActions, screenshot, sendAlertText, sendKeysElement, setTimeouts, setWindowRectangle, status, submitElement, switchToFrame, switchToParentFrame, switchToWindow)
14+import Lunapark.WebDriverError (WebDriverError, WebDriverErrorType(..), fromJson, fromStringCode, toStringCode)
15+import Lunapark.Types (SessionId(..), WindowHandle(..), FrameId(..), Element(..), CreateSessionResponse, ServerStatus, Timeouts, Rectangle, RawLocator, Locator(..), Script, Cookie, Screenshot, Button(..), PointerMoveOrigin(..), PointerMove, Action, PointerType(..), ActionSequence(..), ActionRequest, BrowserType(..), DriverPaths, PageLoad(..), UnhandledPrompt(..), Platform(..), Capability(..), CapabilitiesRequest, MoveToRequest)
src/Lunapark/API.purs+232−180
@@ -22,20 +22,25 @@ import Effect.Aff.Class (class MonadAff, liftAff)
2222import Effect.Class (liftEffect)
2323import Effect.Ref as Ref
2424import Foreign.Object as FO
25−import Lunapark.ActionF (_lunaparkActions, LUNAPARK_ACTIONS, ActionF(..), TouchF(..))
25+import Lunapark.ActionF (_lunaparkActions, ActionF(..), TouchF(..), LUNAPARK_ACTIONS)
2626import Lunapark.Endpoint as LP
2727import Lunapark.Error as LE
28−import Lunapark.LunaparkF (_lunapark, LUNAPARK, ElementF(..), LunaparkF(..), performActions, findElement)
28+import Lunapark.LunaparkF (_lunapark, ElementF(..), LunaparkF(..), LUNAPARK, performActions, findElement)
2929import Lunapark.Types as LT
30−import Lunapark.Utils (liftAndRethrow, throwLeft, catch)
30+import Lunapark.Utils (liftAndRethrow, rethrowAsJsonDecodeError, catch)
3131import Node.Buffer as B
3232import Node.FS.Aff as FS
33+import Run (Run)
3334import Run as R
3435import Run.Except (EXCEPT)
36+import Type.Row (type (+))
37+import Run.Except as RE
3538
36−newtype Interpreter r = Interpreter (Lunapark r ~> BaseRun r)
39+type Lunapark r a = Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r) a
3740
38−runInterpreter ∷ ∀ r. Interpreter r → Lunapark r ~> BaseRun r
41+newtype Interpreter r = Interpreter (Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r) ~> Run (BASE_EFFECTS r))
42+
43+runInterpreter ∷ ∀ r. Interpreter r → Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r) ~> Run (BASE_EFFECTS r)
3944runInterpreter (Interpreter f) = f
4045
4146init
@@ -54,7 +59,7 @@ init uri caps = do
5459 let
5560 sessionResponse = do
5661 sessObj ← res
57− lmap LE.unknownError $ LT.decodeCreateSessionResponse sessObj
62+ lmap LE.JsonDecodeError $ LT.decodeCreateSessionResponse sessObj
5863
5964 T.for sessionResponse \{ session, capabilities } → do
6065 timeoutsRef ←
@@ -69,8 +74,9 @@ init uri caps = do
6974 actionsEnabled ←
7075 map isRight
7176 $ liftAff
72− $ LP.post uri (LP.InSession session : LP.Actions : Nil)
73− $ LT.encodeActionRequest $ FO.singleton "action-test"
77+ $ LP.post uri (LP.InSession session : LP.Actions : Nil)
78+ $ LT.encodeActionRequest
79+ $ FO.singleton "action-test"
7480 $ LT.NoSource [ LT.pause $ Milliseconds 0.0 ]
7581
7682 let
@@ -88,24 +94,21 @@ init uri caps = do
8894interpret
8995 ∷ ∀ r
9096 . HandleLunaparkInput
91− → Lunapark r
92− ~> BaseRun r
97+ → Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r)
98+ ~> Run (BASE_EFFECTS r)
9399interpret input = runLunapark input <<< runLunaparkActions input
94100
101+type BASE_EFFECTS r = EXCEPT LE.Error + R.AFF + R.EFFECT + r
95102
96−type Lunapark r = BaseRun (lunapark ∷ LUNAPARK, lunaparkActions ∷ LUNAPARK_ACTIONS|r)
97−
98−type BaseRun r = R.Run
99− ( except ∷ EXCEPT LE.Error
100− , aff ∷ R.AFF
101− , effect ∷ R.EFFECT
102− | r)
103−
104−runLunapark ∷ ∀ r. HandleLunaparkInput → BaseRun (lunapark ∷ LUNAPARK|r) ~> BaseRun r
103+runLunapark ∷ ∀ r. HandleLunaparkInput → Run (BASE_EFFECTS + LUNAPARK + r) ~> Run (BASE_EFFECTS r)
105104runLunapark input = do
106105 R.interpretRec (R.on _lunapark (handleLunapark input) R.send)
107106
108−runLunaparkActions ∷ ∀ r. HandleLunaparkInput → Lunapark r ~> BaseRun (lunapark ∷ LUNAPARK|r)
107+runLunaparkActions
108+ ∷ ∀ r
109+ . HandleLunaparkInput
110+ → Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r)
111+ ~> Run (BASE_EFFECTS + LUNAPARK + r)
109112runLunaparkActions input
110113 | input.actionsEnabled = interpretW3CActions Nil
111114 | otherwise = R.interpretRec (R.on _lunaparkActions (jsonWireActions input) R.send)
@@ -113,8 +116,8 @@ runLunaparkActions input
113116interpretW3CActions
114117 ∷ ∀ r
115118 . List LT.ActionSequence
116− → Lunapark r
117− ~> BaseRun (lunapark ∷ LUNAPARK|r)
119+ → Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r)
120+ ~> Run (BASE_EFFECTS + LUNAPARK + r)
118121interpretW3CActions acc as = case R.peel as of
119122 Left la → case tag la of
120123 Left a → w3cActions acc interpretW3CActions a
@@ -130,55 +133,83 @@ w3cActions
130133 ∷ ∀ r a
131134 . List LT.ActionSequence
132135 → ( List LT.ActionSequence
133− → Lunapark r
134− ~> BaseRun (lunapark ∷ LUNAPARK|r)
136+ → Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r)
137+ ~> Run (BASE_EFFECTS + LUNAPARK + r)
135138 )
136− → ActionF (Lunapark r a)
137− → BaseRun (lunapark ∷ LUNAPARK|r) a
139+ → ActionF (Run (BASE_EFFECTS + LUNAPARK + LUNAPARK_ACTIONS + r) a)
140+ → Run (BASE_EFFECTS + LUNAPARK + r) a
138141w3cActions acc loop = case _ of
139142 Click btn next →
140− let seq = [ LT.pointerDown btn, LT.pointerUp btn ]
141− in loop (inMouse seq) next
143+ let
144+ seq = [ LT.pointerDown btn, LT.pointerUp btn ]
145+ in
146+ loop (inMouse seq) next
142147 ButtonDown btn next →
143− let seq = [ LT.pointerDown btn ]
144− in loop (inMouse seq) next
148+ let
149+ seq = [ LT.pointerDown btn ]
150+ in
151+ loop (inMouse seq) next
145152 ButtonUp btn next →
146− let seq = [ LT.pointerUp btn ]
147− in loop (inMouse seq) next
153+ let
154+ seq = [ LT.pointerUp btn ]
155+ in
156+ loop (inMouse seq) next
148157 DoubleClick btn next →
149− let seq = [ LT.pointerDown btn, LT.pointerUp btn, LT.pointerDown btn, LT.pointerUp btn ]
150− in loop (inMouse seq) next
158+ let
159+ seq = [ LT.pointerDown btn, LT.pointerUp btn, LT.pointerDown btn, LT.pointerUp btn ]
160+ in
161+ loop (inMouse seq) next
151162 MoveTo move next →
152− let seq = [ LT.pointerMove move ]
153− in loop (inPointer seq) next
163+ let
164+ seq = [ LT.pointerMove move ]
165+ in
166+ loop (inPointer seq) next
154167 SendKeys txt next →
155− let seq = T.foldMap (\ch → [ LT.keyDown ch, LT.keyUp ch ]) $ Str.toCharArray txt
156− in loop (inKeys seq) next
168+ let
169+ seq = T.foldMap (\ch → [ LT.keyDown ch, LT.keyUp ch ]) $ Str.toCharArray txt
170+ in
171+ loop (inKeys seq) next
157172 Pause ms next →
158− let seq = [ LT.pause ms ]
159− in loop (anywhere seq) next
173+ let
174+ seq = [ LT.pause ms ]
175+ in
176+ loop (anywhere seq) next
160177 InTouch tch → case tch of
161178 Tap next →
162− let seq = [ LT.pointerDown LT.LeftBtn, LT.pointerUp LT.LeftBtn ]
163− in loop (inTouch seq) next
179+ let
180+ seq = [ LT.pointerDown LT.LeftBtn, LT.pointerUp LT.LeftBtn ]
181+ in
182+ loop (inTouch seq) next
164183 TouchDown next →
165− let seq = [ LT.pointerDown LT.LeftBtn ]
166− in loop (inTouch seq) next
184+ let
185+ seq = [ LT.pointerDown LT.LeftBtn ]
186+ in
187+ loop (inTouch seq) next
167188 TouchUp next →
168− let seq = [ LT.pointerUp LT.LeftBtn ]
169− in loop (inTouch seq) next
189+ let
190+ seq = [ LT.pointerUp LT.LeftBtn ]
191+ in
192+ loop (inTouch seq) next
170193 LongClick next →
171− let seq = [ LT.pointerDown LT.LeftBtn, LT.pause (Milliseconds 3000.0), LT.pointerUp LT.LeftBtn ]
172− in loop (inTouch seq) next
194+ let
195+ seq = [ LT.pointerDown LT.LeftBtn, LT.pause (Milliseconds 3000.0), LT.pointerUp LT.LeftBtn ]
196+ in
197+ loop (inTouch seq) next
173198 Flick move next →
174− let seq = [ LT.pointerMove move ]
175− in loop (inTouch seq) next
199+ let
200+ seq = [ LT.pointerMove move ]
201+ in
202+ loop (inTouch seq) next
176203 Scroll move next →
177− let seq = [ LT.pointerMove move ]
178− in loop (inTouch seq) next
204+ let
205+ seq = [ LT.pointerMove move ]
206+ in
207+ loop (inTouch seq) next
179208 DoubleTap next →
180− let seq = [ LT.pointerDown LT.LeftBtn, LT.pointerUp LT.LeftBtn, LT.pointerDown LT.LeftBtn, LT.pointerUp LT.LeftBtn ]
181− in loop (inTouch seq) next
209+ let
210+ seq = [ LT.pointerDown LT.LeftBtn, LT.pointerUp LT.LeftBtn, LT.pointerDown LT.LeftBtn, LT.pointerUp LT.LeftBtn ]
211+ in
212+ loop (inTouch seq) next
182213 where
183214 unconsed = L.uncons acc
184215
@@ -219,7 +250,7 @@ type HandleLunaparkInput =
219250 , actionsEnabled ∷ Boolean
220251 }
221252
222−jsonWireActions ∷ ∀ r. HandleLunaparkInput → ActionF ~> BaseRun (lunapark ∷ LUNAPARK|r)
253+jsonWireActions ∷ ∀ r. HandleLunaparkInput → ActionF ~> Run (BASE_EFFECTS + LUNAPARK + r)
223254jsonWireActions inp = case _ of
224255 Click btn next → do
225256 _ ← post (LP.Click : Nil) (LT.encodeButton btn)
@@ -232,8 +263,8 @@ jsonWireActions inp = case _ of
232263 pure next
233264 DoubleClick btn next → do
234265 _ ← case btn of
235− LT.LeftBtn → post_ (LP.DoubleClick : Nil)
236− other → do
266+ LT.LeftBtn → post' (LP.DoubleClick : Nil)
267+ _ → do
237268 _ ← post (LP.Click : Nil) (LT.encodeButton btn)
238269 post (LP.Click : Nil) (LT.encodeButton btn)
239270 pure next
@@ -253,16 +284,16 @@ jsonWireActions inp = case _ of
253284 pure next
254285 InTouch tch → case tch of
255286 Tap next → do
256− _ ← post_ (LP.Touch : LP.Click : Nil)
287+ _ ← post' (LP.Touch : LP.Click : Nil)
257288 pure next
258289 TouchDown next → do
259− _ ← post_ (LP.Touch : LP.Down : Nil)
290+ _ ← post' (LP.Touch : LP.Down : Nil)
260291 pure next
261292 TouchUp next → do
262− _ ← post_ (LP.Touch : LP.Up : Nil)
293+ _ ← post' (LP.Touch : LP.Up : Nil)
263294 pure next
264295 LongClick next → do
265− _ ← post_ (LP.Touch : LP.LongClick : Nil)
296+ _ ← post' (LP.Touch : LP.LongClick : Nil)
266297 pure next
267298 Flick move next → do
268299 element ← case move.origin of
@@ -281,23 +312,23 @@ jsonWireActions inp = case _ of
281312 _ ← post (LP.Touch : LP.Scroll : Nil) (LT.encodeMoveToRequest req)
282313 pure next
283314 DoubleTap next → do
284− _ ← post_ (LP.Touch : LP.DoubleClick : Nil)
315+ _ ← post' (LP.Touch : LP.DoubleClick : Nil)
285316 pure next
286317 where
287318 post a b = liftAndRethrow $ LP.post inp.uri (inSession : a) b
288− post_ a = liftAndRethrow $ LP.post_ inp.uri (inSession : a)
319+ post' a = liftAndRethrow $ LP.post' inp.uri (inSession : a)
289320
290321 inSession ∷ LP.EndpointPart
291322 inSession = LP.InSession inp.session
292323
293−handleLunapark ∷ ∀ r. HandleLunaparkInput → LunaparkF ~> BaseRun r
324+handleLunapark ∷ ∀ r. HandleLunaparkInput → LunaparkF ~> Run (BASE_EFFECTS r)
294325handleLunapark inp = case _ of
295326 Quit next → do
296327 _ ← delete $ inSession : Nil
297328 pure next
298329 Status cont → do
299330 res ← get $ LP.Status : Nil
300− ss ← throwLeft $ LT.decodeServerStatus res
331+ ss ← rethrowAsJsonDecodeError $ LT.decodeServerStatus res
301332 pure $ cont ss
302333 GetTimeouts cont → do
303334 res ← R.liftEffect $ Ref.read inp.timeoutsRef
@@ -306,8 +337,7 @@ handleLunapark inp = case _ of
306337 R.liftEffect $ Ref.write ts inp.timeoutsRef
307338 tryAndCache "set timeouts"
308339 [ void $ post (inSession : LP.Timeouts : Nil) (LT.encodeTimeouts ts)
309− , do T.for_ (LT.encodeLegacyTimeouts ts) \j →
310− void $ post (inSession : LP.Timeouts : Nil) j
340+ , T.for_ (LT.encodeLegacyTimeouts ts) (post (inSession : LP.Timeouts : Nil))
311341 ]
312342 pure next
313343 GoTo uri next → do
@@ -315,31 +345,31 @@ handleLunapark inp = case _ of
315345 pure next
316346 GetUrl cont → do
317347 res ← get $ inSession : LP.Url : Nil
318− map cont $ throwLeft $ J.decodeJson res
348+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
319349 Back next → do
320− _ ← post_ (inSession : LP.Back : Nil)
350+ _ ← post' (inSession : LP.Back : Nil)
321351 pure next
322352 Forward next → do
323− _ ← post_ (inSession : LP.Forward : Nil)
353+ _ ← post' (inSession : LP.Forward : Nil)
324354 pure next
325355 Refresh next → do
326− _ ← post_ (inSession : LP.Refresh : Nil)
356+ _ ← post' (inSession : LP.Refresh : Nil)
327357 pure next
328358 GetTitle cont → do
329359 res ← get (inSession : LP.Title : Nil)
330− map cont $ throwLeft $ J.decodeJson res
360+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
331361 GetWindowHandle cont → do
332362 res ← tryAndCache "get window handle"
333363 [ get (inSession : LP.Window : Nil)
334364 , get (inSession : LP.WindowHandle : Nil)
335365 ]
336− map cont $ throwLeft $ LT.decodeWindowHandle res
366+ map cont $ rethrowAsJsonDecodeError $ LT.decodeWindowHandle res
337367 GetWindowHandles cont → do
338368 res ← tryAndCache "get window handles"
339369 [ get (inSession : LP.Window : LP.Handles : Nil)
340370 , get (inSession : LP.WindowHandles : Nil)
341371 ]
342− map cont $ throwLeft $ T.traverse LT.decodeWindowHandle =<< J.decodeJson res
372+ map cont $ rethrowAsJsonDecodeError $ T.traverse LT.decodeWindowHandle =<< J.decodeJson res
343373 CloseWindow next → do
344374 _ ← delete (inSession : LP.Window : Nil)
345375 pure next
@@ -350,33 +380,36 @@ handleLunapark inp = case _ of
350380 _ ← post (inSession : LP.Frame : Nil) (LT.encodeFrameId fid)
351381 pure next
352382 SwitchToParentFrame next → do
353− _ ← post_ (inSession : LP.Frame : LP.Parent : Nil)
383+ _ ← post' (inSession : LP.Frame : LP.Parent : Nil)
354384 pure next
355385 GetWindowRectangle cont → do
356386 res ← tryAndCache "get window rectangle"
357− [ do res ← get (inSession : LP.Window : LP.Rect : Nil)
358− throwLeft $ LT.decodeRectangle res
359− , do position ← get (inSession : LP.Window : LP.Position : Nil)
360− size ← get (inSession : LP.Window : LP.Size : Nil)
361− throwLeft $ LT.decodeRectangleLegacy { position, size }
387+ [ do
388+ res ← get (inSession : LP.Window : LP.Rect : Nil)
389+ rethrowAsJsonDecodeError $ LT.decodeRectangle res
390+ , do
391+ position ← get (inSession : LP.Window : LP.Position : Nil)
392+ size ← get (inSession : LP.Window : LP.Size : Nil)
393+ rethrowAsJsonDecodeError $ LT.decodeRectangleLegacy { position, size }
362394 ]
363395 pure $ cont res
364396 SetWindowRectangle r next → do
365397 tryAndCache "set window rectangle"
366398 [ void $ post (inSession : LP.Window : LP.Rect : Nil) (LT.encodeRectangle r)
367− , do let js = LT.encodeRectangleLegacy r
368− _ ← post (inSession : LP.Window : LP.Size : Nil) js.size
369− void $ post (inSession : LP.Window : LP.Position : Nil) js.position
399+ , do
400+ let js = LT.encodeRectangleLegacy r
401+ _ ← post (inSession : LP.Window : LP.Size : Nil) js.size
402+ void $ post (inSession : LP.Window : LP.Position : Nil) js.position
370403 ]
371404 pure next
372405 MaximizeWindow next → do
373− _ ← post_ (inSession : LP.Window : LP.Maximize : Nil)
406+ _ ← post' (inSession : LP.Window : LP.Maximize : Nil)
374407 pure next
375408 MinimizeWindow next → do
376− _ ← post_ (inSession : LP.Window : LP.Minimize : Nil)
409+ _ ← post' (inSession : LP.Window : LP.Minimize : Nil)
377410 pure next
378411 FullscreenWindow next → do
379− _ ← post_ (inSession : LP.Window : LP.Fullscreen : Nil)
412+ _ ← post' (inSession : LP.Window : LP.Fullscreen : Nil)
380413 pure next
381414 ExecuteScript script cont → do
382415 map cont $ tryAndCache "execute script"
@@ -390,10 +423,10 @@ handleLunapark inp = case _ of
390423 ]
391424 GetAllCookies cont → do
392425 res ← get (inSession : LP.Cookies : Nil)
393− map cont $ throwLeft $ T.traverse LT.decodeCookie =<< J.decodeJson res
426+ map cont $ rethrowAsJsonDecodeError $ T.traverse LT.decodeCookie =<< J.decodeJson res
394427 GetCookie name cont → do
395428 res ← get (inSession : LP.Cookie name : Nil)
396− map cont $ throwLeft $ LT.decodeCookie res
429+ map cont $ rethrowAsJsonDecodeError $ LT.decodeCookie res
397430 DeleteAllCookies next → do
398431 _ ← delete (inSession : LP.Cookies : Nil)
399432 pure next
@@ -405,14 +438,14 @@ handleLunapark inp = case _ of
405438 pure next
406439 DismissAlert next → do
407440 _ ← tryAndCache "dismiss alert"
408− [ post_ (inSession : LP.Alert : LP.Dismiss : Nil)
409− , post_ (inSession : LP.DismissAlert : Nil)
441+ [ post' (inSession : LP.Alert : LP.Dismiss : Nil)
442+ , post' (inSession : LP.DismissAlert : Nil)
410443 ]
411444 pure next
412445 AcceptAlert next → do
413446 _ ← tryAndCache "accept alert"
414− [ post_ (inSession : LP.Alert : LP.Accept : Nil)
415− , post_ (inSession : LP.AcceptAlert : Nil)
447+ [ post' (inSession : LP.Alert : LP.Accept : Nil)
448+ , post' (inSession : LP.AcceptAlert : Nil)
416449 ]
417450 pure next
418451 GetAlertText cont → do
@@ -420,7 +453,7 @@ handleLunapark inp = case _ of
420453 [ get (inSession : LP.Alert : LP.Text : Nil)
421454 , get (inSession : LP.AlertText : Nil)
422455 ]
423− map cont $ throwLeft $ J.decodeJson res
456+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
424457 SendAlertText str next → do
425458 _ ← tryAndCache "send alert text"
426459 [ post (inSession : LP.Alert : LP.Text : Nil) (LT.encodeSendKeysRequest str)
@@ -429,124 +462,143 @@ handleLunapark inp = case _ of
429462 pure next
430463 Screenshot fp next → do
431464 res ← get (inSession : LP.Screenshot : Nil)
432− screenshotPack ← throwLeft $ LT.decodeScreenshot res
465+ screenshotPack ← rethrowAsJsonDecodeError $ LT.decodeScreenshot res
433466 buffer ← R.liftEffect $ B.fromString screenshotPack.content screenshotPack.encoding
434467 R.liftAff $ FS.writeFile fp buffer
435468 pure next
436469 FindElement loc cont → do
437470 res ← post (inSession : LP.Element : Nil) (LT.encodeLocator loc)
438− map cont $ throwLeft $ LT.decodeElement res
471+ map cont $ rethrowAsJsonDecodeError $ LT.decodeElement res
439472 FindElements loc cont → do
440473 res ← post (inSession : LP.Elements : Nil) (LT.encodeLocator loc)
441− map cont $ throwLeft $ T.traverse LT.decodeElement =<< J.decodeJson res
474+ map cont $ rethrowAsJsonDecodeError $ T.traverse LT.decodeElement =<< J.decodeJson res
442475 GetActiveElement cont → do
443476 res ← get (inSession : LP.Element : LP.Active : Nil)
444− map cont $ throwLeft $ LT.decodeElement res
477+ map cont $ rethrowAsJsonDecodeError $ LT.decodeElement res
445478 PerformActions req next → do
446479 when inp.actionsEnabled
447− $ void $ post
448− (inSession : LP.Actions : Nil)
449− (LT.encodeActionRequest req)
480+ $ void
481+ $ post
482+ (inSession : LP.Actions : Nil)
483+ (LT.encodeActionRequest req)
450484 pure next
451485 ReleaseActions next → do
452486 when inp.actionsEnabled $ void $ delete (inSession : LP.Actions : Nil)
453487 pure next
454488 OnElement el elF →
455− let inElement = LP.InElement el
456− in case elF of
457− ChildElement loc cont → do
458− res ← post (inSession : inElement : LP.Element : Nil) (LT.encodeLocator loc)
459− map cont $ throwLeft $ LT.decodeElement res
460− ChildElements loc cont → do
461− res ← post (inSession : inElement : LP.Elements : Nil) (LT.encodeLocator loc)
462− map cont $ throwLeft $ T.traverse LT.decodeElement =<< J.decodeJson res
463− ScreenshotEl fp next → do
464− res ← get (inSession : inElement : LP.Screenshot : Nil)
465− screenshotPack ← throwLeft $ LT.decodeScreenshot res
466− buffer ← R.liftEffect $ B.fromString screenshotPack.content screenshotPack.encoding
467− R.liftAff $ FS.writeFile fp buffer
468− pure next
469− IsSelected cont → do
470− res ← get (inSession : inElement : LP.Selected : Nil)
471− map cont $ throwLeft $ J.decodeJson res
472− GetAttribute attr cont → do
473− res ← get (inSession : inElement : LP.Attribute attr : Nil)
474− map cont $ throwLeft $ J.decodeJson res
475− GetProperty prop cont → do
476− map cont $ get (inSession : inElement : LP.Property prop : Nil)
477− GetCss css cont → do
478− res ← get (inSession : inElement : LP.CssValue css : Nil)
479− map cont $ throwLeft $ J.decodeJson res
480− GetText cont → do
481− res ← get (inSession : inElement : LP.Text : Nil)
482− map cont $ throwLeft $ J.decodeJson res
483− GetTagName cont → do
484− res ← get (inSession : inElement : LP.Name : Nil)
485− map cont $ throwLeft $ J.decodeJson res
486− GetRectangle cont →
487− map cont $ tryAndCache "get element rectangle"
488− [ do res ← get (inSession : inElement : LP.Rect : Nil)
489− throwLeft $ LT.decodeRectangle res
490− , do position ← get (inSession : inElement : LP.Position : Nil)
491− size ← get (inSession : inElement : LP.Size : Nil)
492− throwLeft $ LT.decodeRectangleLegacy { position, size }
493− ]
494− IsEnabled cont → do
495− res ← get (inSession : inElement : LP.Enabled : Nil)
496− map cont $ throwLeft $ J.decodeJson res
497− ClickEl next → do
498− _ ← post_ (inSession : inElement : LP.Click : Nil)
499− pure next
500− ClearEl next → do
501− _ ← post_ (inSession : inElement : LP.Clear : Nil)
502− pure next
503− SendKeysEl txt next → do
504− _ ← tryAndCache "send keys chromedriver hack"
505− [ post (inSession : inElement : LP.Value : Nil) (LT.encodeSendKeysRequest txt)
506− , post (inSession : inElement : LP.Value : Nil)
507− $ J.encodeJson $ FO.singleton "value" $ Str.toCharArray txt
508− ]
509− pure next
510− IsDisplayed cont → do
511− res ← tryAndCache "is element displayed"
512− [ get (inSession : inElement : LP.Displayed : Nil)
513− , do let script =
514− { script: """var el = arguments[0]; return el.offsetHeight > 0 && el.offsetWidth > 0"""
515− , args: [ LT.encodeElement el ]
516− }
517− handleLunapark inp $ ExecuteScript script identity
518− ]
519− map cont $ throwLeft $ J.decodeJson res
520− Submit next → do
521− _ ← post_ (inSession : inElement : LP.Submit : Nil)
522− pure next
489+ let
490+ inElement = LP.InElement el
491+ in
492+ case elF of
493+ ChildElement loc cont → do
494+ res ← post (inSession : inElement : LP.Element : Nil) (LT.encodeLocator loc)
495+ map cont $ rethrowAsJsonDecodeError $ LT.decodeElement res
496+ ChildElements loc cont → do
497+ res ← post (inSession : inElement : LP.Elements : Nil) (LT.encodeLocator loc)
498+ map cont $ rethrowAsJsonDecodeError $ T.traverse LT.decodeElement =<< J.decodeJson res
499+ ScreenshotEl fp next → do
500+ res ← get (inSession : inElement : LP.Screenshot : Nil)
501+ screenshotPack ← rethrowAsJsonDecodeError $ LT.decodeScreenshot res
502+ buffer ← R.liftEffect $ B.fromString screenshotPack.content screenshotPack.encoding
503+ R.liftAff $ FS.writeFile fp buffer
504+ pure next
505+ IsSelected cont → do
506+ res ← get (inSession : inElement : LP.Selected : Nil)
507+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
508+ GetAttribute attr cont → do
509+ res ← get (inSession : inElement : LP.Attribute attr : Nil)
510+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
511+ GetProperty prop cont → do
512+ map cont $ get (inSession : inElement : LP.Property prop : Nil)
513+ GetCss css cont → do
514+ res ← get (inSession : inElement : LP.CssValue css : Nil)
515+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
516+ GetText cont → do
517+ res ← get (inSession : inElement : LP.Text : Nil)
518+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
519+ GetTagName cont → do
520+ res ← get (inSession : inElement : LP.Name : Nil)
521+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
522+ GetRectangle cont →
523+ map cont $ tryAndCache "get element rectangle"
524+ [ do
525+ res ← get (inSession : inElement : LP.Rect : Nil)
526+ rethrowAsJsonDecodeError $ LT.decodeRectangle res
527+ , do
528+ position ← get (inSession : inElement : LP.Position : Nil)
529+ size ← get (inSession : inElement : LP.Size : Nil)
530+ rethrowAsJsonDecodeError $ LT.decodeRectangleLegacy { position, size }
531+ ]
532+ IsEnabled cont → do
533+ res ← get (inSession : inElement : LP.Enabled : Nil)
534+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
535+ ClickEl next → do
536+ _ ← tryAndCache "chromedriver75 update clickElement"
537+ [ post' (inSession : inElement : LP.Click : Nil)
538+ , post (inSession : inElement : LP.Click : Nil) $ LT.encodeElement el
539+ ]
540+ pure next
541+ ClearEl next → do
542+ _ ← tryAndCache "chromedriver75 update clearElement"
543+ [ post' (inSession : inElement : LP.Clear : Nil)
544+ , post (inSession : inElement : LP.Click : Nil) $ LT.encodeElement el
545+ ]
546+ pure next
547+ SendKeysEl txt next → do
548+ _ ← tryAndCache "send keys chromedriver hack"
549+ [ post (inSession : inElement : LP.Value : Nil) (LT.encodeSendKeysRequest txt)
550+ , post (inSession : inElement : LP.Value : Nil)
551+ $ J.encodeJson
552+ $ FO.singleton "value"
553+ $ Str.toCharArray txt
554+ ]
555+ pure next
556+ IsDisplayed cont → do
557+ res ← tryAndCache "is element displayed"
558+ [ get (inSession : inElement : LP.Displayed : Nil)
559+ , do
560+ let
561+ script =
562+ { script: """var el = arguments[0]; return el.offsetHeight > 0 && el.offsetWidth > 0"""
563+ , args: [ LT.encodeElement el ]
564+ }
565+ handleLunapark inp $ ExecuteScript script identity
566+ ]
567+ map cont $ rethrowAsJsonDecodeError $ J.decodeJson res
568+ Submit next → do
569+ _ ← tryAndCache "chromedriver75 update submit form"
570+ [ post' (inSession : inElement : LP.Submit : Nil)
571+ , post (inSession : inElement : LP.Submit : Nil) $ LT.encodeElement el
572+ ]
573+ pure next
523574
524575 where
525576 delete a = liftAndRethrow $ LP.delete inp.uri a
526577 post a b = liftAndRethrow $ LP.post inp.uri a b
527578 get a = liftAndRethrow $ LP.get inp.uri a
528− post_ a = liftAndRethrow $ LP.post_ inp.uri a
579+ post' a = liftAndRethrow $ LP.post' inp.uri a
529580
530− tryAndCache ∷ ∀ a. String → Array (BaseRun r a) → BaseRun r a
581+ -- | It caches an index of an action that is valid for current webdriver implementation.
582+ -- | So you don't need to search correct one by tring them each time
583+ tryAndCache ∷ ∀ a. String → Array (Run (BASE_EFFECTS r) a) → Run (BASE_EFFECTS r) a
531584 tryAndCache key actions = do
532− let emptyCases = throwLeft $ Left $ "No valid cases for " <> key <> " caching"
533− let incorrectCache = throwLeft $ Left $ "Fallback for " <> key <> " error"
534−
535585 mp ← R.liftEffect $ Ref.read inp.requestMapRef
536586 case Map.lookup key mp of
537587 Just ix → case A.index actions ix of
538588 Just action → action
539− Nothing → incorrectCache
589+ Nothing → RE.throw $ LE.CachingError $ LE.IncorrectCache key
540590 Nothing →
541591 let
542592 go ix acc act =
543− let try' = do
544− a ← act
545− R.liftEffect $ Ref.modify_ (Map.insert key ix) inp.requestMapRef
546− pure a
547− in catch try' \_ → acc
593+ let
594+ try' = do
595+ a ← act
596+ R.liftEffect $ Ref.modify_ (Map.insert key ix) inp.requestMapRef
597+ pure a
598+ in
599+ catch try' \_ → acc
548600 in
549− FI.foldlWithIndex go emptyCases actions
601+ FI.foldlWithIndex go (RE.throw $ LE.CachingError $ LE.EmptyCases key) actions
550602
551603 inSession ∷ LP.EndpointPart
552604 inSession = LP.InSession inp.session
src/Lunapark/ActionF.purs+19−20
@@ -2,12 +2,12 @@ module Lunapark.ActionF where
22
33import Prelude
44
5−import Data.Symbol (SProxy(..))
5+import Type.Proxy (Proxy(..))
66import Data.Time.Duration (Milliseconds)
77import Lunapark.Types as LT
8+import Run (Run)
89import Run as R
910
10−
1111data ActionF a
1212 = Click LT.Button a
1313 | ButtonDown LT.Button a
@@ -30,51 +30,50 @@ data TouchF a
3030derive instance functorActionF ∷ Functor ActionF
3131derive instance functorTouchF ∷ Functor TouchF
3232
33−_lunaparkActions = SProxy ∷ SProxy "lunaparkActions"
34−type LUNAPARK_ACTIONS = R.FProxy ActionF
35−type WithAction r = R.Run (lunaparkActions ∷ LUNAPARK_ACTIONS|r) Unit
33+_lunaparkActions = Proxy ∷ Proxy "lunaparkActions"
34+type LUNAPARK_ACTIONS r = (lunaparkActions ∷ ActionF | r)
3635
37−liftAction ∷ ∀ r. ActionF Unit → WithAction r
36+liftAction ∷ ∀ r. ActionF Unit → Run (LUNAPARK_ACTIONS r) Unit
3837liftAction = R.lift _lunaparkActions
3938
40−click ∷ ∀ r. LT.Button → WithAction r
39+click ∷ ∀ r. LT.Button → Run (LUNAPARK_ACTIONS r) Unit
4140click btn = liftAction $ Click btn unit
4241
43−buttonDown ∷ ∀ r. LT.Button → WithAction r
42+buttonDown ∷ ∀ r. LT.Button → Run (LUNAPARK_ACTIONS r) Unit
4443buttonDown btn = liftAction $ ButtonDown btn unit
4544
46−buttonUp ∷ ∀ r. LT.Button → WithAction r
45+buttonUp ∷ ∀ r. LT.Button → Run (LUNAPARK_ACTIONS r) Unit
4746buttonUp btn = liftAction $ ButtonUp btn unit
4847
49−doubleClick ∷ ∀ r. LT.Button → WithAction r
48+doubleClick ∷ ∀ r. LT.Button → Run (LUNAPARK_ACTIONS r) Unit
5049doubleClick btn = liftAction $ DoubleClick btn unit
5150
52−sendKeys ∷ ∀ r. String → WithAction r
51+sendKeys ∷ ∀ r. String → Run (LUNAPARK_ACTIONS r) Unit
5352sendKeys txt = liftAction $ SendKeys txt unit
5453
55−moveTo ∷ ∀ r. LT.PointerMove → WithAction r
54+moveTo ∷ ∀ r. LT.PointerMove → Run (LUNAPARK_ACTIONS r) Unit
5655moveTo move = liftAction $ MoveTo move unit
5756
58−pause ∷ ∀ r. Milliseconds → WithAction r
57+pause ∷ ∀ r. Milliseconds → Run (LUNAPARK_ACTIONS r) Unit
5958pause ms = liftAction $ Pause ms unit
6059
61−tap ∷ ∀ r. WithAction r
60+tap ∷ ∀ r. Run (LUNAPARK_ACTIONS r) Unit
6261tap = liftAction $ InTouch $ Tap unit
6362
64−touchDown ∷ ∀ r. WithAction r
63+touchDown ∷ ∀ r. Run (LUNAPARK_ACTIONS r) Unit
6564touchDown = liftAction $ InTouch $ TouchDown unit
6665
67−touchUp ∷ ∀ r. WithAction r
66+touchUp ∷ ∀ r. Run (LUNAPARK_ACTIONS r) Unit
6867touchUp = liftAction $ InTouch $ TouchUp unit
6968
70−longTap ∷ ∀ r. WithAction r
69+longTap ∷ ∀ r. Run (LUNAPARK_ACTIONS r) Unit
7170longTap = liftAction $ InTouch $ LongClick unit
7271
73−flick ∷ ∀ r. LT.PointerMove → WithAction r
72+flick ∷ ∀ r. LT.PointerMove → Run (LUNAPARK_ACTIONS r) Unit
7473flick move = liftAction $ InTouch $ Flick move unit
7574
76−scroll ∷ ∀ r. LT.PointerMove → WithAction r
75+scroll ∷ ∀ r. LT.PointerMove → Run (LUNAPARK_ACTIONS r) Unit
7776scroll move = liftAction $ InTouch $ Scroll move unit
7877
79−doubleTap ∷ ∀ r. WithAction r
78+doubleTap ∷ ∀ r. Run (LUNAPARK_ACTIONS r) Unit
8079doubleTap = liftAction $ InTouch $ DoubleTap unit
src/Lunapark/Endpoint.purs+20−12
@@ -3,11 +3,17 @@
33-- | So, to have something like `/session/:sessId/element/:elId/doubleclick` we have
44-- | `InSession sessId : InElement elId : DoubleClick : Nil`
55-- | This is not as typesafe as it could be, but at least it saves from typos.
6−module Lunapark.Endpoint where
6+module Lunapark.Endpoint
7+ ( delete
8+ , get
9+ , post
10+ , post'
11+ , EndpointPart(..)
12+ ) where
713
814import Prelude
915
10−import Affjax as N
16+import Affjax.Node as N
1117import Affjax.RequestBody as NQ
1218import Affjax.ResponseFormat as NR
1319import Affjax.StatusCode (StatusCode(..))
@@ -23,6 +29,7 @@ import Data.Newtype (un)
2329import Effect.Aff (Aff)
2430import Lunapark.Error as LE
2531import Lunapark.Types as LT
32+import Lunapark.WebDriverError as LWE
2633
2734data EndpointPart
2835 = Session
@@ -169,23 +176,24 @@ printPart = case _ of
169176 Flick → "flick"
170177
171178handleAPIError
172− ∷ N.Response (Either N.ResponseFormatError Json)
179+ ∷ Either N.Error (N.Response Json)
173180 → Either LE.Error Json
174−handleAPIError r = case r.status of
175− StatusCode 200 → lmap LE.unknownError do
176− obj ← J.decodeJson =<< lmap N.printResponseFormatError r.body
181+handleAPIError (Left error) = Left $ LE.AffjaxError error
182+handleAPIError (Right r) = case r.status of
183+ StatusCode 200 → lmap LE.JsonDecodeError do
184+ obj ← J.decodeJson r.body
177185 obj J..: "value"
178− code →
179− Left $ either (LE.unknownError <<< N.printResponseFormatError) LE.fromJson r.body
186+ _ →
187+ Left $ either LE.JsonDecodeError LE.WebDriverError $ LWE.fromJson r.body
180188
181189get ∷ String → Endpoint → Aff (Either LE.Error Json)
182−get uri ep = map handleAPIError $ N.get NR.json (uri <> print ep)
190+get uri ep = map handleAPIError $ N.get NR.json (uri <> print ep)
183191
184192post ∷ String → Endpoint → Json → Aff (Either LE.Error Json)
185−post uri ep obj = map handleAPIError $ N.post NR.json (uri <> print ep) $ NQ.json obj
193+post uri ep obj = map handleAPIError $ N.post NR.json (uri <> print ep) $ Just (NQ.json obj)
186194
187−post_ ∷ String → Endpoint → Aff (Either LE.Error Json)
188−post_ uri ep = map handleAPIError $ N.post' NR.json (uri <> print ep) Nothing
195+post' ∷ String → Endpoint → Aff (Either LE.Error Json)
196+post' uri ep = map handleAPIError $ N.post NR.json (uri <> print ep) Nothing
189197
190198delete ∷ String → Endpoint → Aff (Either LE.Error Json)
191199delete uri ep = map handleAPIError $ N.delete NR.json (uri <> print ep)
src/Lunapark/Error.purs+36−120
@@ -1,123 +1,39 @@
11module Lunapark.Error where
22
33import Prelude
4−
5−import Data.Argonaut.Core (Json) as J
6−import Data.Argonaut.Decode.Combinators ((.:)) as J
7−import Data.Argonaut.Decode.Class (decodeJson) as J
8−import Data.Either (Either(..), either)
9−
10−data ErrorType
11− = ElementClickIntercepted
12− | ElementNotSelectable
13− | ElementNotInteractable
14− | InsecureCertificate
15− | InvalidArgument
16− | InvalidCookieDomain
17− | InvalidCoordinates
18− | InvalidElementState
19− | InvalidSelector
20− | InvalidSessionId
21− | JavaScriptError
22− | MoveTargetOutOfBounds
23− | NoSuchAlert
24− | NoSuchCookie
25− | NoSuchElement
26− | NoSuchFrame
27− | NoSuchWindow
28− | ScriptTimeout
29− | SessionNotCreated
30− | StaleElementReference
31− | Timeout
32− | UnableToSetCookie
33− | UnableToCaptureScreen
34− | UnexpectedAlertOpen
35− | UnknownCommand
36− | UnknownError
37− | UnknownMethod
38− | UnsupportedOperation
39−
40−fromStringCode ∷ String → Either String ErrorType
41−fromStringCode = case _ of
42− "element click intercepted" → Right ElementClickIntercepted
43− "element not selectable" → Right ElementNotSelectable
44− "element not interactable" → Right ElementNotInteractable
45− "insecure certificate" → Right InsecureCertificate
46− "invalid argument" → Right InvalidArgument
47− "invalid cookie domain" → Right InvalidCookieDomain
48− "invalid coordinates" → Right InvalidCoordinates
49− "invalid element state" → Right InvalidElementState
50− "invalid selector" → Right InvalidSelector
51− "invalid session id" → Right InvalidSessionId
52− "javascript error" → Right JavaScriptError
53− "move target out of bounds" → Right MoveTargetOutOfBounds
54− "no such alert" → Right NoSuchAlert
55− "no such cookie" → Right NoSuchCookie
56− "no such element" → Right NoSuchElement
57− "no such frame" → Right NoSuchFrame
58− "no such window" → Right NoSuchWindow
59− "script timeout" → Right ScriptTimeout
60− "session not created" → Right SessionNotCreated
61− "stale element reference" → Right StaleElementReference
62− "timeout" → Right Timeout
63− "unable to set cookie" → Right UnableToSetCookie
64− "unable to capture screen" → Right UnableToCaptureScreen
65− "unexpected alert open" → Right UnexpectedAlertOpen
66− "unknown command" → Right UnknownCommand
67− "unknown error" → Right UnknownError
68− "unknown method" → Right UnknownMethod
69− "unsupported operation" → Right UnsupportedOperation
70− s → Left s
71−
72−toStringCode ∷ ErrorType → String
73−toStringCode = case _ of
74− ElementClickIntercepted → "element click intercepted"
75− ElementNotSelectable → "element not selectable"
76− ElementNotInteractable → "element not interactable"
77− InsecureCertificate → "insecure certificate"
78− InvalidArgument → "invalid argument"
79− InvalidCookieDomain → "invalid cookie domain"
80− InvalidCoordinates → "invalid coordinates"
81− InvalidElementState → "invalid element state"
82− InvalidSelector → "invalid selector"
83− InvalidSessionId → "invalid session id"
84− JavaScriptError → "javascript error"
85− MoveTargetOutOfBounds → "move target out of bounds"
86− NoSuchAlert → "no such alert"
87− NoSuchCookie → "no such cookie"
88− NoSuchElement → "no such element"
89− NoSuchFrame → "no such frame"
90− NoSuchWindow → "no such window"
91− ScriptTimeout → "script timeout"
92− SessionNotCreated → "session not created"
93− StaleElementReference → "stale element reference"
94− Timeout → "timeout"
95− UnableToSetCookie → "unable to set cookie"
96− UnableToCaptureScreen → "unable to capture screen"
97− UnexpectedAlertOpen → "unexpected alert open"
98− UnknownCommand → "unknown command"
99− UnknownError → "unknown error"
100− UnknownMethod → "unknown method"
101− UnsupportedOperation → "unsupported operation"
102−
103−type Error =
104− { error ∷ ErrorType
105− , message ∷ String
106− , stacktrace ∷ String
107− }
108−
109−fromJson ∷ J.Json → Error
110−fromJson js = either unknownError identity do
111− obj ← J.decodeJson js
112− value ← obj J..: "value"
113− error ← fromStringCode =<< value J..: "error"
114− message ← value J..: "message"
115− stacktrace ← value J..: "stacktrace"
116− pure { error, message, stacktrace }
117−
118−unknownError ∷ String → Error
119−unknownError message =
120− { error: UnknownError
121− , message
122− , stacktrace: ""
123− }
4+import Affjax as N
5+import Lunapark.WebDriverError as LWE
6+import Data.Argonaut.Decode (JsonDecodeError, printJsonDecodeError) as J
7+
8+data CachingError
9+ = EmptyCases String
10+ | IncorrectCache String
11+
12+data Error
13+ = JsonDecodeError J.JsonDecodeError
14+ | WebDriverError LWE.WebDriverError
15+ | AffjaxError N.Error
16+ | CachingError CachingError
17+
18+printError ∷ Error → String
19+printError = case _ of
20+ JsonDecodeError jsonDecodeError →
21+ J.printJsonDecodeError jsonDecodeError
22+ WebDriverError webdriverError →
23+ "Response with error message:\n"
24+ <> " error type: "
25+ <> LWE.toStringCode webdriverError.error
26+ <> "\n"
27+ <> " message: "
28+ <> webdriverError.message
29+ <> "\n"
30+ <> " stacktrace: "
31+ <> webdriverError.stacktrace
32+ AffjaxError affjaxError →
33+ N.printError affjaxError
34+ CachingError cachingError →
35+ "Error during caching:\n " <> printCachingError cachingError
36+ where
37+ printCachingError = case _ of
38+ EmptyCases key → "There is no working implementation for " <> key <> " action."
39+ IncorrectCache key → "Trying another implementation for " <> key <> " action."
src/Lunapark/LunaparkF.purs+58−58
@@ -3,8 +3,9 @@ module Lunapark.LunaparkF where
33import Prelude
44
55import Data.Argonaut.Core as J
6−import Data.Symbol (SProxy(..))
6+import Type.Proxy (Proxy(..))
77import Lunapark.Types as LT
8+import Run (Run)
89import Run as R
910
1011data LunaparkF a
@@ -69,169 +70,168 @@ data ElementF a
6970derive instance functorLunaparkF ∷ Functor LunaparkF
7071derive instance functorElementF ∷ Functor ElementF
7172
72−_lunapark = SProxy ∷ SProxy "lunapark"
73−type LUNAPARK = R.FProxy LunaparkF
74−type WithLunapark r a = R.Run (lunapark ∷ LUNAPARK|r) a
73+_lunapark = Proxy ∷ Proxy "lunapark"
7574
75+type LUNAPARK r = (lunapark ∷ LunaparkF | r)
7676
77−liftLunapark ∷ ∀ a r. LunaparkF a → WithLunapark r a
77+liftLunapark ∷ ∀ a r. LunaparkF a → Run (LUNAPARK r) a
7878liftLunapark = R.lift _lunapark
7979
80−quit ∷ ∀ r. WithLunapark r Unit
80+quit ∷ ∀ r. Run (LUNAPARK r) Unit
8181quit = liftLunapark $ Quit unit
8282
83−status ∷ ∀ r. WithLunapark r LT.ServerStatus
83+status ∷ ∀ r. Run (LUNAPARK r) LT.ServerStatus
8484status = liftLunapark $ Status identity
8585
86−setTimeouts ∷ ∀ r. LT.Timeouts → WithLunapark r Unit
86+setTimeouts ∷ ∀ r. LT.Timeouts → Run (LUNAPARK r) Unit
8787setTimeouts ts = liftLunapark $ SetTimeouts ts unit
8888
89−getTimeouts ∷ ∀ r. WithLunapark r LT.Timeouts
89+getTimeouts ∷ ∀ r. Run (LUNAPARK r) LT.Timeouts
9090getTimeouts = liftLunapark $ GetTimeouts identity
9191
92−go ∷ ∀ r. String → WithLunapark r Unit
92+go ∷ ∀ r. String → Run (LUNAPARK r) Unit
9393go uri = liftLunapark $ GoTo uri unit
9494
95−getUrl ∷ ∀ r. WithLunapark r String
95+getUrl ∷ ∀ r. Run (LUNAPARK r) String
9696getUrl = liftLunapark $ GetUrl identity
9797
98−forward ∷ ∀ r. WithLunapark r Unit
98+forward ∷ ∀ r. Run (LUNAPARK r) Unit
9999forward = liftLunapark $ Forward unit
100100
101−back ∷ ∀ r. WithLunapark r Unit
101+back ∷ ∀ r. Run (LUNAPARK r) Unit
102102back = liftLunapark $ Back unit
103103
104−refresh ∷ ∀ r. WithLunapark r Unit
104+refresh ∷ ∀ r. Run (LUNAPARK r) Unit
105105refresh = liftLunapark $ Refresh unit
106106
107−getTitle ∷ ∀ r. WithLunapark r String
107+getTitle ∷ ∀ r. Run (LUNAPARK r) String
108108getTitle = liftLunapark $ GetTitle identity
109109
110−getWindowHandle ∷ ∀ r. WithLunapark r LT.WindowHandle
110+getWindowHandle ∷ ∀ r. Run (LUNAPARK r) LT.WindowHandle
111111getWindowHandle = liftLunapark $ GetWindowHandle identity
112112
113−getWindowHandles ∷ ∀ r. WithLunapark r (Array LT.WindowHandle)
113+getWindowHandles ∷ ∀ r. Run (LUNAPARK r) (Array LT.WindowHandle)
114114getWindowHandles = liftLunapark $ GetWindowHandles identity
115115
116−closeWindow ∷ ∀ r. WithLunapark r Unit
116+closeWindow ∷ ∀ r. Run (LUNAPARK r) Unit
117117closeWindow = liftLunapark $ CloseWindow unit
118118
119−switchToWindow ∷ ∀ r. LT.WindowHandle → WithLunapark r Unit
119+switchToWindow ∷ ∀ r. LT.WindowHandle → Run (LUNAPARK r) Unit
120120switchToWindow w = liftLunapark $ SwitchToWindow w unit
121121
122−switchToFrame ∷ ∀ r. LT.FrameId → WithLunapark r Unit
122+switchToFrame ∷ ∀ r. LT.FrameId → Run (LUNAPARK r) Unit
123123switchToFrame f = liftLunapark $ SwitchToFrame f unit
124124
125−switchToParentFrame ∷ ∀ r. WithLunapark r Unit
125+switchToParentFrame ∷ ∀ r. Run (LUNAPARK r) Unit
126126switchToParentFrame = liftLunapark $ SwitchToParentFrame unit
127127
128−getWindowRectangle ∷ ∀ r. WithLunapark r LT.Rectangle
128+getWindowRectangle ∷ ∀ r. Run (LUNAPARK r) LT.Rectangle
129129getWindowRectangle = liftLunapark $ GetWindowRectangle identity
130130
131−setWindowRectangle ∷ ∀ r. LT.Rectangle → WithLunapark r Unit
131+setWindowRectangle ∷ ∀ r. LT.Rectangle → Run (LUNAPARK r) Unit
132132setWindowRectangle r = liftLunapark $ SetWindowRectangle r unit
133133
134−maximizeWindow ∷ ∀ r. WithLunapark r Unit
134+maximizeWindow ∷ ∀ r. Run (LUNAPARK r) Unit
135135maximizeWindow = liftLunapark $ MaximizeWindow unit
136136
137−minimizeWindow ∷ ∀ r. WithLunapark r Unit
137+minimizeWindow ∷ ∀ r. Run (LUNAPARK r) Unit
138138minimizeWindow = liftLunapark $ MinimizeWindow unit
139139
140−fullscreenWindow ∷ ∀ r. WithLunapark r Unit
140+fullscreenWindow ∷ ∀ r. Run (LUNAPARK r) Unit
141141fullscreenWindow = liftLunapark $ FullscreenWindow unit
142142
143−executeScript ∷ ∀ r. LT.Script → WithLunapark r J.Json
143+executeScript ∷ ∀ r. LT.Script → Run (LUNAPARK r) J.Json
144144executeScript script = liftLunapark $ ExecuteScript script identity
145145
146−executeScriptAsync ∷ ∀ r. LT.Script → WithLunapark r J.Json
146+executeScriptAsync ∷ ∀ r. LT.Script → Run (LUNAPARK r) J.Json
147147executeScriptAsync script = liftLunapark $ ExecuteScriptAsync script identity
148148
149−getAllCookies ∷ ∀ r. WithLunapark r (Array LT.Cookie)
149+getAllCookies ∷ ∀ r. Run (LUNAPARK r) (Array LT.Cookie)
150150getAllCookies = liftLunapark $ GetAllCookies identity
151151
152−getCookie ∷ ∀ r. String → WithLunapark r LT.Cookie
152+getCookie ∷ ∀ r. String → Run (LUNAPARK r) LT.Cookie
153153getCookie name = liftLunapark $ GetCookie name identity
154154
155−addCookie ∷ ∀ r. LT.Cookie → WithLunapark r Unit
155+addCookie ∷ ∀ r. LT.Cookie → Run (LUNAPARK r) Unit
156156addCookie cookie = liftLunapark $ AddCookie cookie unit
157157
158−deleteCookie ∷ ∀ r. String → WithLunapark r Unit
158+deleteCookie ∷ ∀ r. String → Run (LUNAPARK r) Unit
159159deleteCookie name = liftLunapark $ DeleteCookie name unit
160160
161−deleteAllCookies ∷ ∀ r. WithLunapark r Unit
161+deleteAllCookies ∷ ∀ r. Run (LUNAPARK r) Unit
162162deleteAllCookies = liftLunapark $ DeleteAllCookies unit
163163
164−dismissAlert ∷ ∀ r. WithLunapark r Unit
164+dismissAlert ∷ ∀ r. Run (LUNAPARK r) Unit
165165dismissAlert = liftLunapark $ DismissAlert unit
166166
167−acceptAlert ∷ ∀ r. WithLunapark r Unit
167+acceptAlert ∷ ∀ r. Run (LUNAPARK r) Unit
168168acceptAlert = liftLunapark $ AcceptAlert unit
169169
170−getAlertText ∷ ∀ r. WithLunapark r String
170+getAlertText ∷ ∀ r. Run (LUNAPARK r) String
171171getAlertText = liftLunapark $ GetAlertText identity
172172
173−sendAlertText ∷ ∀ r. String → WithLunapark r Unit
173+sendAlertText ∷ ∀ r. String → Run (LUNAPARK r) Unit
174174sendAlertText txt = liftLunapark $ SendAlertText txt unit
175175
176−screenshot ∷ ∀ r. String → WithLunapark r Unit
176+screenshot ∷ ∀ r. String → Run (LUNAPARK r) Unit
177177screenshot fp = liftLunapark $ Screenshot fp unit
178178
179−elementScreenshot ∷ ∀ r. LT.Element → String → WithLunapark r Unit
179+elementScreenshot ∷ ∀ r. LT.Element → String → Run (LUNAPARK r) Unit
180180elementScreenshot el fp = liftLunapark $ OnElement el $ ScreenshotEl fp unit
181181
182−findElement ∷ ∀ r. LT.Locator → WithLunapark r LT.Element
182+findElement ∷ ∀ r. LT.Locator → Run (LUNAPARK r) LT.Element
183183findElement l = liftLunapark $ FindElement l identity
184184
185−findElements ∷ ∀ r. LT.Locator → WithLunapark r (Array LT.Element)
185+findElements ∷ ∀ r. LT.Locator → Run (LUNAPARK r) (Array LT.Element)
186186findElements l = liftLunapark $ FindElements l identity
187187
188−childElement ∷ ∀ r. LT.Element → LT.Locator → WithLunapark r LT.Element
188+childElement ∷ ∀ r. LT.Element → LT.Locator → Run (LUNAPARK r) LT.Element
189189childElement el l = liftLunapark $ OnElement el $ ChildElement l identity
190190
191−childElements ∷ ∀ r. LT.Element → LT.Locator → WithLunapark r (Array LT.Element)
191+childElements ∷ ∀ r. LT.Element → LT.Locator → Run (LUNAPARK r) (Array LT.Element)
192192childElements el l = liftLunapark $ OnElement el $ ChildElements l identity
193193
194−isSelected ∷ ∀ r. LT.Element → WithLunapark r Boolean
194+isSelected ∷ ∀ r. LT.Element → Run (LUNAPARK r) Boolean
195195isSelected el = liftLunapark $ OnElement el $ IsSelected identity
196196
197−getAttribute ∷ ∀ r. LT.Element → String → WithLunapark r String
197+getAttribute ∷ ∀ r. LT.Element → String → Run (LUNAPARK r) String
198198getAttribute el name = liftLunapark $ OnElement el $ GetAttribute name identity
199199
200−getProperty ∷ ∀ r. LT.Element → String → WithLunapark r J.Json
200+getProperty ∷ ∀ r. LT.Element → String → Run (LUNAPARK r) J.Json
201201getProperty el name = liftLunapark $ OnElement el $ GetProperty name identity
202202
203−getCss ∷ ∀ r. LT.Element → String → WithLunapark r String
203+getCss ∷ ∀ r. LT.Element → String → Run (LUNAPARK r) String
204204getCss el name = liftLunapark $ OnElement el $ GetCss name identity
205205
206−getText ∷ ∀ r. LT.Element → WithLunapark r String
206+getText ∷ ∀ r. LT.Element → Run (LUNAPARK r) String
207207getText el = liftLunapark $ OnElement el $ GetText identity
208208
209−getTagName ∷ ∀ r. LT.Element → WithLunapark r String
209+getTagName ∷ ∀ r. LT.Element → Run (LUNAPARK r) String
210210getTagName el = liftLunapark $ OnElement el $ GetTagName identity
211211
212−getRectangle ∷ ∀ r. LT.Element → WithLunapark r LT.Rectangle
212+getRectangle ∷ ∀ r. LT.Element → Run (LUNAPARK r) LT.Rectangle
213213getRectangle el = liftLunapark $ OnElement el $ GetRectangle identity
214214
215−isEnabled ∷ ∀ r. LT.Element → WithLunapark r Boolean
215+isEnabled ∷ ∀ r. LT.Element → Run (LUNAPARK r) Boolean
216216isEnabled el = liftLunapark $ OnElement el $ IsEnabled identity
217217
218−clickElement ∷ ∀ r. LT.Element → WithLunapark r Unit
218+clickElement ∷ ∀ r. LT.Element → Run (LUNAPARK r) Unit
219219clickElement el = liftLunapark $ OnElement el $ ClickEl unit
220220
221−clearElement ∷ ∀ r. LT.Element → WithLunapark r Unit
221+clearElement ∷ ∀ r. LT.Element → Run (LUNAPARK r) Unit
222222clearElement el = liftLunapark $ OnElement el $ ClearEl unit
223223
224−sendKeysElement ∷ ∀ r. LT.Element → String → WithLunapark r Unit
224+sendKeysElement ∷ ∀ r. LT.Element → String → Run (LUNAPARK r) Unit
225225sendKeysElement el txt = liftLunapark $ OnElement el $ SendKeysEl txt unit
226226
227−isDisplayed ∷ ∀ r. LT.Element → WithLunapark r Boolean
227+isDisplayed ∷ ∀ r. LT.Element → Run (LUNAPARK r) Boolean
228228isDisplayed el = liftLunapark $ OnElement el $ IsDisplayed identity
229229
230−submitElement ∷ ∀ r. LT.Element → WithLunapark r Unit
230+submitElement ∷ ∀ r. LT.Element → Run (LUNAPARK r) Unit
231231submitElement el = liftLunapark $ OnElement el $ Submit unit
232232
233−performActions ∷ ∀ r. LT.ActionRequest → WithLunapark r Unit
233+performActions ∷ ∀ r. LT.ActionRequest → Run (LUNAPARK r) Unit
234234performActions req = liftLunapark $ PerformActions req unit
235235
236−releaseActions ∷ ∀ r. WithLunapark r Unit
236+releaseActions ∷ ∀ r. Run (LUNAPARK r) Unit
237237releaseActions = liftLunapark $ ReleaseActions unit
src/Lunapark/Types.purs+106−112
@@ -1,15 +1,14 @@
11-- | This module contains types for requests and response.
2−-- | Most of them are records with `α → Json` and `Json → Either String α` functions
2+-- | Most of them are records with `α → J.Json` and `J.Json → Either J.JsonDecodeError α` functions
33-- | not newtypes with `Encode|DecodeJson` instances.
44module Lunapark.Types where
55
66import Prelude
77
8−import CSS.Render as CSSR
9−import CSS.Selector as CSS
8+import CSS as CSS
109import Control.Alt ((<|>))
11−import Data.Argonaut.Core (Json)
12−import Data.Argonaut.Core (Json, jsonEmptyObject, jsonNull) as J
10+import Data.Argonaut.Core (Json, jsonEmptyObject, jsonNull, fromString) as J
11+import Data.Argonaut.Decode (JsonDecodeError(..)) as J
1312import Data.Argonaut.Decode.Class (decodeJson) as J
1413import Data.Argonaut.Decode.Combinators ((.:))
1514import Data.Argonaut.Encode.Class (class EncodeJson, encodeJson) as J
@@ -20,13 +19,11 @@ import Data.Map as Map
2019import Data.Maybe (Maybe(..))
2120import Data.Newtype (class Newtype, un)
2221import Data.String as Str
23−import Data.Symbol (SProxy(..))
22+import Type.Proxy (Proxy(..))
2423import Data.Time.Duration (Milliseconds(..))
2524import Data.Traversable as F
2625import Data.Tuple (Tuple(..))
2726import Data.Variant as V
28−import Data.XPath.AST as XA
29−import Data.XPath.Printer (printSelector)
3027import Foreign.Object as FO
3128import Node.Encoding as NE
3229import Node.Path (FilePath)
@@ -57,25 +54,25 @@ derive instance newtypeElement ∷ Newtype Element _
5754derive newtype instance eqElement ∷ Eq Element
5855derive newtype instance ordElement ∷ Ord Element
5956
60−decodeElement ∷ Json → Either String Element
57+decodeElement ∷ J.Json → Either J.JsonDecodeError Element
6158decodeElement = J.decodeJson >=> \obj →
6259 map Element $ obj .: "element-6066-11e4-a52e-4f735466cecf" <|> obj .: "ELEMENT"
6360
64−encodeElement ∷ Element → Json
61+encodeElement ∷ Element → J.Json
6562encodeElement (Element eid) = J.encodeJson $ FO.fromFoldable
6663 [ Tuple "element-6066-11e4-a52e-4f735466cecf" eid
6764 , Tuple "ELEMENT" eid
6865 ]
6966
70−decodeSessionId ∷ Json → Either String SessionId
67+decodeSessionId ∷ J.Json → Either J.JsonDecodeError SessionId
7168decodeSessionId = map SessionId <<< J.decodeJson
7269
7370type CreateSessionResponse =
74− { session ∷ SessionId
75− , capabilities ∷ Array Capability
76− }
71+ { session ∷ SessionId
72+ , capabilities ∷ Array Capability
73+ }
7774
78−decodeCreateSessionResponse ∷ Json → Either String CreateSessionResponse
75+decodeCreateSessionResponse ∷ J.Json → Either J.JsonDecodeError CreateSessionResponse
7976decodeCreateSessionResponse = J.decodeJson >=> \obj → do
8077 session ← decodeSessionId =<< obj .: "sessionId"
8178 capabilities ← decodeCapabilities =<< obj .: "capabilities"
@@ -86,7 +83,7 @@ type ServerStatus =
8683 , message ∷ String
8784 }
8885
89−decodeServerStatus ∷ Json → Either String ServerStatus
86+decodeServerStatus ∷ J.Json → Either J.JsonDecodeError ServerStatus
9087decodeServerStatus = J.decodeJson >=> \obj → { ready: _, message: _ } <$> obj .: "ready" <*> obj .: "message"
9188
9289type Timeouts =
@@ -95,37 +92,37 @@ type Timeouts =
9592 , implicit ∷ Milliseconds
9693 }
9794
98−decodeTimeouts ∷ Json → Either String Timeouts
95+decodeTimeouts ∷ J.Json → Either J.JsonDecodeError Timeouts
9996decodeTimeouts = J.decodeJson >=> \obj → do
10097 script ← map Milliseconds $ obj .: "script"
10198 pageLoad ← map Milliseconds $ obj .: "pageLoad"
10299 implicit ← map Milliseconds $ obj .: "implicit"
103100 pure { script, pageLoad, implicit }
104101
105−encodeTimeouts ∷ Timeouts → Json
102+encodeTimeouts ∷ Timeouts → J.Json
106103encodeTimeouts r = J.encodeJson $ FO.fromFoldable
107104 [ Tuple "script" (un Milliseconds r.script)
108105 , Tuple "pageLoad" (un Milliseconds r.pageLoad)
109106 , Tuple "implicit" (un Milliseconds r.implicit)
110107 ]
111108
112−encodeLegacyTimeouts ∷ Timeouts → Array Json
109+encodeLegacyTimeouts ∷ Timeouts → Array J.Json
113110encodeLegacyTimeouts r =
114111 [ J.encodeJson $ FO.singleton "script" $ un Milliseconds r.script
115112 , J.encodeJson $ FO.singleton "implicit" $ un Milliseconds r.implicit
116113 , J.encodeJson $ FO.singleton "page load" $ un Milliseconds r.pageLoad
117114 ]
118115
119−encodeGoRequest ∷ String → Json
116+encodeGoRequest ∷ String → J.Json
120117encodeGoRequest url = J.encodeJson $ FO.fromFoldable [ Tuple "url" url ]
121118
122−decodeWindowHandle ∷ Json → Either String WindowHandle
119+decodeWindowHandle ∷ J.Json → Either J.JsonDecodeError WindowHandle
123120decodeWindowHandle = map WindowHandle <<< J.decodeJson
124121
125−encodeSwitchToWindowRequest ∷ WindowHandle → Json
122+encodeSwitchToWindowRequest ∷ WindowHandle → J.Json
126123encodeSwitchToWindowRequest w = J.encodeJson $ FO.fromFoldable [ Tuple "handle" $ un WindowHandle w ]
127124
128−encodeFrameId ∷ FrameId → Json
125+encodeFrameId ∷ FrameId → J.Json
129126encodeFrameId fid = J.encodeJson $ FO.fromFoldable [ Tuple "id" encoded ]
130127 where
131128 encoded = case fid of
@@ -140,7 +137,7 @@ type Rectangle =
140137 , y ∷ Int
141138 }
142139
143−decodeRectangle ∷ Json → Either String Rectangle
140+decodeRectangle ∷ J.Json → Either J.JsonDecodeError Rectangle
144141decodeRectangle = J.decodeJson >=> \obj → do
145142 width ← obj .: "width"
146143 height ← obj .: "height"
@@ -148,7 +145,7 @@ decodeRectangle = J.decodeJson >=> \obj → do
148145 y ← obj .: "y"
149146 pure { width, height, x, y }
150147
151−decodeRectangleLegacy ∷ { size ∷ Json, position ∷ Json } → Either String Rectangle
148+decodeRectangleLegacy ∷ { size ∷ J.Json, position ∷ J.Json } → Either J.JsonDecodeError Rectangle
152149decodeRectangleLegacy { size, position } = do
153150 sobj ← J.decodeJson size
154151 pobj ← J.decodeJson position
@@ -158,13 +155,13 @@ decodeRectangleLegacy { size, position } = do
158155 height ← sobj .: "height"
159156 pure { width, height, x, y }
160157
161−encodeRectangleLegacy ∷ Rectangle → { size ∷ Json, position ∷ Json }
158+encodeRectangleLegacy ∷ Rectangle → { size ∷ J.Json, position ∷ J.Json }
162159encodeRectangleLegacy r =
163160 { size: J.encodeJson $ FO.fromFoldable [ Tuple "width" r.width, Tuple "height" r.height ]
164161 , position: J.encodeJson $ FO.fromFoldable [ Tuple "x" r.x, Tuple "y" r.y ]
165162 }
166163
167−encodeRectangle ∷ Rectangle → Json
164+encodeRectangle ∷ Rectangle → J.Json
168165encodeRectangle r = J.encodeJson $ FO.fromFoldable
169166 [ Tuple "width" r.width
170167 , Tuple "height" r.height
@@ -174,7 +171,7 @@ encodeRectangle r = J.encodeJson $ FO.fromFoldable
174171
175172data Locator
176173 = ByCss CSS.Selector
177− | ByXPath XA.Selector
174+ | ByXPath String
178175 | ByTagName String
179176 | ByLinkText String
180177 | ByPartialLinkText String
@@ -185,15 +182,15 @@ type RawLocator =
185182 , value ∷ String
186183 }
187184
188−encodeLocator ∷ Locator → Json
185+encodeLocator ∷ Locator → J.Json
189186encodeLocator l = J.encodeJson $ FO.fromFoldable case l of
190187 ByCss sel →
191188 [ Tuple "using" "css selector"
192− , Tuple "value" $ CSSR.selector sel
189+ , Tuple "value" $ CSS.selector sel
193190 ]
194− ByXPath sel →
191+ ByXPath expr →
195192 [ Tuple "using" "xpath"
196− , Tuple "value" $ printSelector sel
193+ , Tuple "value" expr
197194 ]
198195 ByLinkText sel →
199196 [ Tuple "using" "link text"
@@ -212,15 +209,15 @@ encodeLocator l = J.encodeJson $ FO.fromFoldable case l of
212209 , Tuple "value" r.value
213210 ]
214211
215−encodeSendKeysRequest ∷ String → Json
212+encodeSendKeysRequest ∷ String → J.Json
216213encodeSendKeysRequest txt = J.encodeJson $ FO.fromFoldable [ Tuple "text" txt ]
217214
218215type Script =
219216 { script ∷ String
220− , args ∷ Array Json
217+ , args ∷ Array J.Json
221218 }
222219
223−encodeScript ∷ Script → Json
220+encodeScript ∷ Script → J.Json
224221encodeScript r = J.encodeJson $ FO.fromFoldable
225222 [ Tuple "script" $ J.encodeJson r.script
226223 , Tuple "args" $ J.encodeJson r.args
@@ -236,23 +233,24 @@ type Cookie =
236233 , expiry ∷ Maybe Int
237234 }
238235
239−encodeCookie ∷ Cookie → Json
236+encodeCookie ∷ Cookie → J.Json
240237encodeCookie r = J.encodeJson $ FO.fromFoldable
241238 [ Tuple "cookie" $ FO.fromFoldable
242− $ [ Tuple "name" $ J.encodeJson r.name
243− , Tuple "value" $ J.encodeJson r.value
244− ]
245− <> maybeToAOfPair "path" r.path
246− <> maybeToAOfPair "domain" r.domain
247− <> maybeToAOfPair "secure" r.secure
248− <> maybeToAOfPair "httpOnly" r.httpOnly
249− <> maybeToAOfPair "expiry" r.expiry
239+ $
240+ [ Tuple "name" $ J.encodeJson r.name
241+ , Tuple "value" $ J.encodeJson r.value
242+ ]
243+ <> maybeToAOfPair "path" r.path
244+ <> maybeToAOfPair "domain" r.domain
245+ <> maybeToAOfPair "secure" r.secure
246+ <> maybeToAOfPair "httpOnly" r.httpOnly
247+ <> maybeToAOfPair "expiry" r.expiry
250248 ]
251249 where
252250 maybeToAOfPair ∷ ∀ a. J.EncodeJson a ⇒ String → Maybe a → Array (Tuple String J.Json)
253251 maybeToAOfPair key mb = F.foldMap (A.singleton <<< Tuple key <<< J.encodeJson) mb
254252
255−decodeCookie ∷ Json → Either String Cookie
253+decodeCookie ∷ J.Json → Either J.JsonDecodeError Cookie
256254decodeCookie = J.decodeJson >=> \obj → do
257255 name ← obj .: "name"
258256 value ← obj .: "value"
@@ -274,19 +272,18 @@ decodeCookie = J.decodeJson >=> \obj → do
274272 maybify ∷ ∀ a b. Either a b → Either a (Maybe b)
275273 maybify e = map Just e <|> Right Nothing
276274
277−
278275type Screenshot =
279276 { content ∷ String
280277 , encoding ∷ NE.Encoding
281278 }
282279
283−decodeScreenshot ∷ Json → Either String Screenshot
280+decodeScreenshot ∷ J.Json → Either J.JsonDecodeError Screenshot
284281decodeScreenshot j =
285282 { content: _, encoding: NE.Base64 } <$> J.decodeJson j
286283
287284data Button = LeftBtn | MiddleBtn | RightBtn
288285
289−encodeButton ∷ Button → Json
286+encodeButton ∷ Button → J.Json
290287encodeButton = J.encodeJson <<< case _ of
291288 LeftBtn → 0
292289 MiddleBtn → 1
@@ -297,7 +294,7 @@ data PointerMoveOrigin
297294 | FromPointer
298295 | FromElement Element
299296
300−encodeOrigin ∷ PointerMoveOrigin → Json
297+encodeOrigin ∷ PointerMoveOrigin → J.Json
301298encodeOrigin = case _ of
302299 FromViewport → J.encodeJson "viewport"
303300 FromPointer → J.encodeJson "pointer"
@@ -310,7 +307,7 @@ type PointerMove =
310307 , y ∷ Int
311308 }
312309
313−encodePointerMove ∷ PointerMove → FO.Object Json
310+encodePointerMove ∷ PointerMove → FO.Object J.Json
314311encodePointerMove r = FO.fromFoldable
315312 [ Tuple "x" $ J.encodeJson r.x
316313 , Tuple "y" $ J.encodeJson r.y
@@ -318,7 +315,6 @@ encodePointerMove r = FO.fromFoldable
318315 , Tuple "origin" $ encodeOrigin r.origin
319316 ]
320317
321−
322318type Action = V.Variant
323319 ( pause ∷ Milliseconds
324320 , keyDown ∷ Char
@@ -328,56 +324,55 @@ type Action = V.Variant
328324 , pointerMove ∷ PointerMove
329325 )
330326
331−pause ∷ ∀ r a. a → V.Variant (pause ∷ a|r)
332−pause = V.inj (SProxy ∷ SProxy "pause")
327+pause ∷ ∀ r a. a → V.Variant (pause ∷ a | r)
328+pause = V.inj (Proxy ∷ Proxy "pause")
333329
334−keyDown ∷ ∀ r a. a → V.Variant (keyDown ∷ a|r)
335−keyDown = V.inj (SProxy ∷ SProxy "keyDown")
330+keyDown ∷ ∀ r a. a → V.Variant (keyDown ∷ a | r)
331+keyDown = V.inj (Proxy ∷ Proxy "keyDown")
336332
337−keyUp ∷ ∀ r a. a → V.Variant (keyUp ∷ a|r)
338−keyUp = V.inj (SProxy ∷ SProxy "keyUp")
333+keyUp ∷ ∀ r a. a → V.Variant (keyUp ∷ a | r)
334+keyUp = V.inj (Proxy ∷ Proxy "keyUp")
339335
340−pointerUp ∷ ∀ r a. a → V.Variant (pointerUp ∷ a|r)
341−pointerUp = V.inj (SProxy ∷ SProxy "pointerUp")
336+pointerUp ∷ ∀ r a. a → V.Variant (pointerUp ∷ a | r)
337+pointerUp = V.inj (Proxy ∷ Proxy "pointerUp")
342338
343−pointerDown ∷ ∀ r a. a → V.Variant (pointerDown ∷ a|r)
344−pointerDown = V.inj (SProxy ∷ SProxy "pointerDown")
339+pointerDown ∷ ∀ r a. a → V.Variant (pointerDown ∷ a | r)
340+pointerDown = V.inj (Proxy ∷ Proxy "pointerDown")
345341
346−pointerMove ∷ ∀ r a. a → V.Variant (pointerMove ∷ a|r)
347−pointerMove = V.inj (SProxy ∷ SProxy "pointerMove")
342+pointerMove ∷ ∀ r a. a → V.Variant (pointerMove ∷ a | r)
343+pointerMove = V.inj (Proxy ∷ Proxy "pointerMove")
348344
349−encodeAction ∷ Action → Json
345+encodeAction ∷ Action → J.Json
350346encodeAction = V.match
351347 { pause: \ms →
352− J.encodeJson $ FO.fromFoldable
353− [ Tuple "duration" $ J.encodeJson $ un Milliseconds ms
354− , Tuple "type" $ J.encodeJson "pause"
355− ]
348+ J.encodeJson $ FO.fromFoldable
349+ [ Tuple "duration" $ J.encodeJson $ un Milliseconds ms
350+ , Tuple "type" $ J.encodeJson "pause"
351+ ]
356352 , keyDown: \ch →
357− J.encodeJson $ FO.fromFoldable
358− [ Tuple "value" $ J.encodeJson ch
359− , Tuple "type" $ J.encodeJson "keyDown"
360− ]
353+ J.encodeJson $ FO.fromFoldable
354+ [ Tuple "value" $ J.encodeJson ch
355+ , Tuple "type" $ J.encodeJson "keyDown"
356+ ]
361357 , keyUp: \ch →
362− J.encodeJson $ FO.fromFoldable
363− [ Tuple "value" $ J.encodeJson ch
364− , Tuple "type" $ J.encodeJson "keyUp"
365− ]
358+ J.encodeJson $ FO.fromFoldable
359+ [ Tuple "value" $ J.encodeJson ch
360+ , Tuple "type" $ J.encodeJson "keyUp"
361+ ]
366362 , pointerUp: \btn →
367− J.encodeJson $ FO.fromFoldable
368− [ Tuple "button" $ encodeButton btn
369− , Tuple "type" $ J.encodeJson "pointerUp"
370− ]
363+ J.encodeJson $ FO.fromFoldable
364+ [ Tuple "button" $ encodeButton btn
365+ , Tuple "type" $ J.encodeJson "pointerUp"
366+ ]
371367 , pointerDown: \btn →
372− J.encodeJson $ FO.fromFoldable
373− [ Tuple "button" $ encodeButton btn
374− , Tuple "type" $ J.encodeJson "pointerDown"
375− ]
368+ J.encodeJson $ FO.fromFoldable
369+ [ Tuple "button" $ encodeButton btn
370+ , Tuple "type" $ J.encodeJson "pointerDown"
371+ ]
376372 , pointerMove: \pm →
377− J.encodeJson $ FO.insert "type" (J.encodeJson "pointerMove") $ encodePointerMove pm
373+ J.encodeJson $ FO.insert "type" (J.encodeJson "pointerMove") $ encodePointerMove pm
378374 }
379375
380−
381376data PointerType = Mouse | Pen | Touch
382377
383378printPointerType ∷ PointerType → String
@@ -397,17 +392,17 @@ data ActionSequence
397392-- Right, this is not an `Array` but `StrMap` because all `ActionSequence`s are tagged with unique id's
398393type ActionRequest = FO.Object ActionSequence
399394
400−encodeActionRequest ∷ ActionRequest → Json
395+encodeActionRequest ∷ ActionRequest → J.Json
401396encodeActionRequest sm = J.encodeJson $ FO.singleton "actions" $ map encodePair arrayOfPairs
402397 where
403398 arrayOfPairs ∷ Array (Tuple String ActionSequence)
404399 arrayOfPairs = FO.toUnfoldable sm
405400
406− encodePair ∷ Tuple String ActionSequence → Json
401+ encodePair ∷ Tuple String ActionSequence → J.Json
407402 encodePair (Tuple identifier sequence) =
408403 J.encodeJson $ FO.insert "id" (J.encodeJson identifier) $ encodeSequence sequence
409404
410− encodeSequence ∷ ActionSequence → FO.Object Json
405+ encodeSequence ∷ ActionSequence → FO.Object J.Json
411406 encodeSequence = case _ of
412407 NoSource as → FO.fromFoldable
413408 [ Tuple "type" $ J.encodeJson "none"
@@ -465,10 +460,9 @@ data Capability
465460 | PageLoadStrategy PageLoad
466461 | DesiredTimeouts Timeouts
467462 | UnhandledPromptBehavior UnhandledPrompt
468− | CustomCapability String Json
469−
463+ | CustomCapability String J.Json
470464
471−encodeCapability ∷ Capability → Tuple String Json
465+encodeCapability ∷ Capability → Tuple String J.Json
472466encodeCapability = case _ of
473467 BrowserName bn → Tuple "browserName" $ J.encodeJson case bn of
474468 MSEdge → "MicrosoftEdge"
@@ -491,50 +485,50 @@ encodeCapability = case _ of
491485 Dismiss → "dismiss"
492486 CustomCapability k v → Tuple k v
493487
494−encodeCapabilities ∷ ∀ f. F.Foldable f ⇒ f Capability → Json
488+encodeCapabilities ∷ ∀ f. F.Foldable f ⇒ f Capability → J.Json
495489encodeCapabilities = F.foldl (\b a → J.extend (encodeCapability a) b) J.jsonEmptyObject
496490
497−decodeCapabilities ∷ Json → Either String (Array Capability)
491+decodeCapabilities ∷ J.Json → Either J.JsonDecodeError (Array Capability)
498492decodeCapabilities = J.decodeJson >=> \obj →
499493 F.for (FO.toUnfoldable obj) \l@(Tuple key val) →
500494 decodeCapability l <|> Right (CustomCapability key val)
501495 where
502− decodeCapability ∷ Tuple String Json → Either String Capability
496+ decodeCapability ∷ Tuple String J.Json → Either J.JsonDecodeError Capability
503497 decodeCapability (Tuple key val) = case key of
504− "browserName" → BrowserName <$> decodeBrowserName val
498+ "browserName" → BrowserName <$> decodeBrowserType val
505499 "browserVersion" → BrowserVersion <$> J.decodeJson val
506500 "acceptInsecureCerts" → AcceptInsecureCerts <$> J.decodeJson val
507− "pageLoadStrategy" → PageLoadStrategy <$> decodePageLoadStrategy val
501+ "pageLoadStrategy" → PageLoadStrategy <$> decodePageLoad val
508502 "timeouts" → DesiredTimeouts <$> decodeTimeouts val
509− "unhandledPromptBehaviour" → UnhandledPromptBehavior <$> decodePrompt val
510− _ → Left "unhandled"
503+ "unhandledPromptBehaviour" → UnhandledPromptBehavior <$> decodeUnhandledPrompt val
504+ other → Left $ J.Named "Capability" $ J.UnexpectedValue (J.fromString other)
511505
512− decodeBrowserName ∷ Json → Either String BrowserType
513− decodeBrowserName = J.decodeJson >=> \str → case Str.toLower str of
506+ decodeBrowserType ∷ J.Json → Either J.JsonDecodeError BrowserType
507+ decodeBrowserType = J.decodeJson >=> \str → case Str.toLower str of
514508 "microsoftedge" → Right MSEdge
515509 "chrome" → Right Chrome
516510 "firefox" → Right Firefox
517− _ → Left "unhandled"
511+ other → Left $ J.Named "BrowserType" $ J.UnexpectedValue (J.fromString other)
518512
519− decodePageLoadStrategy ∷ Json → Either String PageLoad
520− decodePageLoadStrategy = J.decodeJson >=> \str → case Str.toLower str of
513+ decodePageLoad ∷ J.Json → Either J.JsonDecodeError PageLoad
514+ decodePageLoad = J.decodeJson >=> \str → case Str.toLower str of
521515 "none" → Right Immediate
522516 "normal" → Right Normal
523517 "eager" → Right Eager
524− _ → Left "unhandled"
518+ other → Left $ J.Named "PageLoad" $ J.UnexpectedValue (J.fromString other)
525519
526− decodePrompt ∷ Json → Either String UnhandledPrompt
527− decodePrompt = J.decodeJson >=> \str → case Str.toLower str of
520+ decodeUnhandledPrompt ∷ J.Json → Either J.JsonDecodeError UnhandledPrompt
521+ decodeUnhandledPrompt = J.decodeJson >=> \str → case Str.toLower str of
528522 "accept" → Right Accept
529523 "dismiss" → Right Dismiss
530− _ → Left "unhandled"
524+ other → Left $ J.Named "UnhandledPrompt" $ J.UnexpectedValue (J.fromString other)
531525
532526type CapabilitiesRequest =
533527 { alwaysMatch ∷ Array Capability
534528 , firstMatch ∷ Array (Array Capability)
535529 }
536530
537−encodeCapabilitiesRequest ∷ CapabilitiesRequest → Json
531+encodeCapabilitiesRequest ∷ CapabilitiesRequest → J.Json
538532encodeCapabilitiesRequest r = J.encodeJson $ FO.singleton "capabilities" $ FO.fromFoldable
539533 [ Tuple "alwaysMatch" $ encodeCapabilities r.alwaysMatch
540534 , Tuple "firstMatch" $ J.encodeJson $ map encodeCapabilities r.firstMatch
@@ -546,11 +540,11 @@ type MoveToRequest =
546540 , yoffset ∷ Int
547541 }
548542
549−encodeMoveToRequest ∷ MoveToRequest → Json
543+encodeMoveToRequest ∷ MoveToRequest → J.Json
550544encodeMoveToRequest r = J.encodeJson $ FO.fromFoldable
551545 [ Tuple "element" $ case r.element of
552− Nothing → J.jsonNull
553− Just el → J.encodeJson $ un Element el
546+ Nothing → J.jsonNull
547+ Just el → J.encodeJson $ un Element el
554548 , Tuple "xoffset" $ J.encodeJson r.xoffset
555549 , Tuple "yoffset" $ J.encodeJson r.yoffset
556550 ]
src/Lunapark/UnicodeCharacters.pursnew file+177
@@ -0,0 +1,177 @@
1+module Lunapark.UnicodeCharacters where
2+
3+-- copied from https://github.com/webdriverio/webdriverio/blob/13d3a3419b951803c5e7a5db53e48764ca58f371/packages/webdriverio/src/constants.js#L315
4+
5+unidentified ∷ Char
6+unidentified = '\xE000'
7+
8+cancel ∷ Char
9+cancel = '\xE001'
10+
11+help ∷ Char
12+help = '\xE002'
13+
14+backspace ∷ Char
15+backspace = '\xE003'
16+
17+tab ∷ Char
18+tab = '\xE004'
19+
20+clear ∷ Char
21+clear = '\xE005'
22+
23+return ∷ Char
24+return = '\xE006'
25+
26+enter ∷ Char
27+enter = '\xE007'
28+
29+shift ∷ Char
30+shift = '\xE008'
31+
32+controlLeft ∷ Char
33+controlLeft = '\xE009'
34+
35+controlRight ∷ Char
36+controlRight = '\xE051'
37+
38+alt ∷ Char
39+alt = '\xE00A'
40+
41+pause ∷ Char
42+pause = '\xE00B'
43+
44+escape ∷ Char
45+escape = '\xE00C'
46+
47+space ∷ Char
48+space = '\xE00D'
49+
50+pageUp ∷ Char
51+pageUp = '\xE00E'
52+
53+pageDown ∷ Char
54+pageDown = '\xE00F'
55+
56+end ∷ Char
57+end = '\xE010'
58+
59+home ∷ Char
60+home = '\xE011'
61+
62+arrowLeft ∷ Char
63+arrowLeft = '\xE012'
64+
65+arrowUp ∷ Char
66+arrowUp = '\xE013'
67+
68+arrowRight ∷ Char
69+arrowRight = '\xE014'
70+
71+arrowDown ∷ Char
72+arrowDown = '\xE015'
73+
74+insert ∷ Char
75+insert = '\xE016'
76+
77+delete ∷ Char
78+delete = '\xE017'
79+
80+semicolon ∷ Char
81+semicolon = '\xE018'
82+
83+equals ∷ Char
84+equals = '\xE019'
85+
86+numpad0 ∷ Char
87+numpad0 = '\xE01A'
88+
89+numpad1 ∷ Char
90+numpad1 = '\xE01B'
91+
92+numpad2 ∷ Char
93+numpad2 = '\xE01C'
94+
95+numpad3 ∷ Char
96+numpad3 = '\xE01D'
97+
98+numpad4 ∷ Char
99+numpad4 = '\xE01E'
100+
101+numpad5 ∷ Char
102+numpad5 = '\xE01F'
103+
104+numpad6 ∷ Char
105+numpad6 = '\xE020'
106+
107+numpad7 ∷ Char
108+numpad7 = '\xE021'
109+
110+numpad8 ∷ Char
111+numpad8 = '\xE022'
112+
113+numpad9 ∷ Char
114+numpad9 = '\xE023'
115+
116+multiply ∷ Char
117+multiply = '\xE024'
118+
119+add ∷ Char
120+add = '\xE025'
121+
122+separator ∷ Char
123+separator = '\xE026'
124+
125+subtract ∷ Char
126+subtract = '\xE027'
127+
128+decimal ∷ Char
129+decimal = '\xE028'
130+
131+divide ∷ Char
132+divide = '\xE029'
133+
134+f1 ∷ Char
135+f1 = '\xE031'
136+
137+f2 ∷ Char
138+f2 = '\xE032'
139+
140+f3 ∷ Char
141+f3 = '\xE033'
142+
143+f4 ∷ Char
144+f4 = '\xE034'
145+
146+f5 ∷ Char
147+f5 = '\xE035'
148+
149+f6 ∷ Char
150+f6 = '\xE036'
151+
152+f7 ∷ Char
153+f7 = '\xE037'
154+
155+f8 ∷ Char
156+f8 = '\xE038'
157+
158+f9 ∷ Char
159+f9 = '\xE039'
160+
161+f10 ∷ Char
162+f10 = '\xE03A'
163+
164+f11 ∷ Char
165+f11 = '\xE03B'
166+
167+f12 ∷ Char
168+f12 = '\xE03C'
169+
170+command ∷ Char
171+command = '\xE03D'
172+
173+meta ∷ Char
174+meta = '\xE03D'
175+
176+zenkakuHankaku ∷ Char
177+zenkakuHankaku = '\xE040'
src/Lunapark/Utils.purs+12−10
@@ -2,33 +2,35 @@ module Lunapark.Utils where
22
33import Prelude
44
5−import Effect.Aff (Aff)
5+import Data.Argonaut.Decode (JsonDecodeError) as J
66import Data.Bifunctor (lmap)
77import Data.Either (Either)
8+import Effect.Aff (Aff)
89import Lunapark.Error as LE
910import Run as R
1011import Run.Except as RE
12+import Type.Row (type (+))
1113import Unsafe.Coerce (unsafeCoerce)
1214
1315liftAndRethrow
1416 ∷ ∀ r ε ω
1517 . Aff (Either ε ω)
16− → R.Run (aff ∷ R.AFF, except ∷ RE.EXCEPT ε|r) ω
18+ → R.Run (R.AFF + RE.EXCEPT ε + r) ω
1719liftAndRethrow a = do
1820 res ← R.liftAff a
1921 RE.rethrow res
2022
21−throwLeft
23+rethrowAsJsonDecodeError
2224 ∷ ∀ r
23− . Either String
24− ~> R.Run (except ∷ RE.EXCEPT LE.Error|r)
25−throwLeft =
26− RE.rethrow <<< lmap LE.unknownError
25+ . Either J.JsonDecodeError
26+ ~> R.Run (RE.EXCEPT LE.Error + r)
27+rethrowAsJsonDecodeError =
28+ RE.rethrow <<< lmap LE.JsonDecodeError
2729
2830-- Safe, since we actually want handler and result have same rows not, remove except
2931catch
3032 ∷ ∀ e r a
31− . R.Run (except ∷ RE.EXCEPT e|r) a
32− → (e → R.Run (except ∷ RE.EXCEPT e|r) a)
33− → R.Run (except ∷ RE.EXCEPT e|r) a
33+ . R.Run (RE.EXCEPT e + r) a
34+ → (e → R.Run (RE.EXCEPT e + r) a)
35+ → R.Run (RE.EXCEPT e + r) a
3436catch = unsafeCoerce $ flip RE.catch
src/Lunapark/WebDriverError.pursnew file+117
@@ -0,0 +1,117 @@
1+module Lunapark.WebDriverError where
2+
3+import Prelude
4+
5+import Data.Argonaut.Core (Json, fromString) as J
6+import Data.Argonaut.Decode (JsonDecodeError(..)) as J
7+import Data.Argonaut.Decode.Combinators ((.:)) as J
8+import Data.Argonaut.Decode.Class (decodeJson) as J
9+import Data.Either (Either(..))
10+
11+data WebDriverErrorType
12+ = ElementClickIntercepted
13+ | ElementNotSelectable
14+ | ElementNotInteractable
15+ | InsecureCertificate
16+ | InvalidArgument
17+ | InvalidCookieDomain
18+ | InvalidCoordinates
19+ | InvalidElementState
20+ | InvalidSelector
21+ | InvalidSessionId
22+ | JavaScriptError
23+ | MoveTargetOutOfBounds
24+ | NoSuchAlert
25+ | NoSuchCookie
26+ | NoSuchElement
27+ | NoSuchFrame
28+ | NoSuchWindow
29+ | ScriptTimeout
30+ | SessionNotCreated
31+ | StaleElementReference
32+ | Timeout
33+ | UnableToSetCookie
34+ | UnableToCaptureScreen
35+ | UnexpectedAlertOpen
36+ | UnknownCommand
37+ | UnknownError
38+ | UnknownMethod
39+ | UnsupportedOperation
40+
41+fromStringCode ∷ String → Either J.JsonDecodeError WebDriverErrorType
42+fromStringCode = case _ of
43+ "element click intercepted" → Right ElementClickIntercepted
44+ "element not selectable" → Right ElementNotSelectable
45+ "element not interactable" → Right ElementNotInteractable
46+ "insecure certificate" → Right InsecureCertificate
47+ "invalid argument" → Right InvalidArgument
48+ "invalid cookie domain" → Right InvalidCookieDomain
49+ "invalid coordinates" → Right InvalidCoordinates
50+ "invalid element state" → Right InvalidElementState
51+ "invalid selector" → Right InvalidSelector
52+ "invalid session id" → Right InvalidSessionId
53+ "javascript error" → Right JavaScriptError
54+ "move target out of bounds" → Right MoveTargetOutOfBounds
55+ "no such alert" → Right NoSuchAlert
56+ "no such cookie" → Right NoSuchCookie
57+ "no such element" → Right NoSuchElement
58+ "no such frame" → Right NoSuchFrame
59+ "no such window" → Right NoSuchWindow
60+ "script timeout" → Right ScriptTimeout
61+ "session not created" → Right SessionNotCreated
62+ "stale element reference" → Right StaleElementReference
63+ "timeout" → Right Timeout
64+ "unable to set cookie" → Right UnableToSetCookie
65+ "unable to capture screen" → Right UnableToCaptureScreen
66+ "unexpected alert open" → Right UnexpectedAlertOpen
67+ "unknown command" → Right UnknownCommand
68+ "unknown error" → Right UnknownError
69+ "unknown method" → Right UnknownMethod
70+ "unsupported operation" → Right UnsupportedOperation
71+ s → Left $ J.Named "WebDriverErrorType" $ J.UnexpectedValue $ J.fromString s
72+
73+toStringCode ∷ WebDriverErrorType → String
74+toStringCode = case _ of
75+ ElementClickIntercepted → "element click intercepted"
76+ ElementNotSelectable → "element not selectable"
77+ ElementNotInteractable → "element not interactable"
78+ InsecureCertificate → "insecure certificate"
79+ InvalidArgument → "invalid argument"
80+ InvalidCookieDomain → "invalid cookie domain"
81+ InvalidCoordinates → "invalid coordinates"
82+ InvalidElementState → "invalid element state"
83+ InvalidSelector → "invalid selector"
84+ InvalidSessionId → "invalid session id"
85+ JavaScriptError → "javascript error"
86+ MoveTargetOutOfBounds → "move target out of bounds"
87+ NoSuchAlert → "no such alert"
88+ NoSuchCookie → "no such cookie"
89+ NoSuchElement → "no such element"
90+ NoSuchFrame → "no such frame"
91+ NoSuchWindow → "no such window"
92+ ScriptTimeout → "script timeout"
93+ SessionNotCreated → "session not created"
94+ StaleElementReference → "stale element reference"
95+ Timeout → "timeout"
96+ UnableToSetCookie → "unable to set cookie"
97+ UnableToCaptureScreen → "unable to capture screen"
98+ UnexpectedAlertOpen → "unexpected alert open"
99+ UnknownCommand → "unknown command"
100+ UnknownError → "unknown error"
101+ UnknownMethod → "unknown method"
102+ UnsupportedOperation → "unsupported operation"
103+
104+type WebDriverError =
105+ { error ∷ WebDriverErrorType
106+ , message ∷ String
107+ , stacktrace ∷ String
108+ }
109+
110+fromJson ∷ J.Json → Either J.JsonDecodeError WebDriverError
111+fromJson js = do
112+ obj ← J.decodeJson js
113+ value ← obj J..: "value"
114+ error ← fromStringCode =<< value J..: "error"
115+ message ← value J..: "message"
116+ stacktrace ← value J..: "stacktrace"
117+ pure { error, message, stacktrace }
test/Test/Main.pursnew file+12
@@ -0,0 +1,12 @@
1+module Test.Main where
2+
3+import Prelude
4+
5+import Effect (Effect)
6+import Effect.Class.Console (log)
7+
8+main :: Effect Unit
9+main = do
10+ log "🍕"
11+ log "You should add some tests."
12+