Gren Effectful Test Runner
Run Gren integration tests that depend on the actual results of tasks.
See the full API on the package site.
Quick Start
Create a directory for your tests and initialize a gren program targeting node:
mkdir tests
cd tests
gren init --platform=node
Install the necessary packages:
gren package install gren-lang/test
gren package install blaix/gren-effectful-tests-node
Create a src/Main.gren
with your tests.
See the examples below or the working example in the repo
for how to do that.
Then compile and run your tests:
gren make src/Main.gren
node app
Examples
This package provides wrappers for the normal gren-lang/test functions, so you have access to the full gren test API.
Basic test
The basic functions you'll need to write a test that waits for a task are run and await
In the body of the await callback, you can construct a test using any of the functions in the gren-lang/test package.
import Expect
import Test exposing (test)
import Test.Runner.Effectful exposing (run, await)
import Time
main =
run <|
await Time.now "the current time" <| \now ->
test "is not Jan 1, 1970" <| \_ ->
Expect.notEqual (Time.millisToPosix 0) now
Errors
If you try to await a task that fails, the test run will fail.
If you want to explicitly test the failure condition, use awaitError:
import Expect
import Test exposing (test)
import Test.Runner.Effectful exposing (run, awaitError)
main =
run <|
awaitError (Task.fail "oopsy") "task that I expect to fail" <| \error ->
test "is an oopsy" <| \_ ->
Expect.equal "oopsy" error
Running multiple tests
You can run an array of effectful tests with join:
import Expect
import Test exposing (test)
import Test.Runner.Effectful exposing (run, await, join)
import Time
main =
run <|
join
[ await Time.now "the current time" <| \now ->
test "is not Jan 1, 1970" <| \_ ->
Expect.notEqual (Time.millisToPosix 0) now
, await (Task.succeed "hey") "my other task" <| \val ->
test "is the expected value" <| \_ ->
Expect.equal "hey" val
]
You can also include arrays of non-effectful tests with functions from the core test package like concat and describe:
import Expect
import Test exposing (describe, test)
import Test.Runner.Effectful exposing (run, await)
main =
run <|
await (Task.succeed "hello") "my task" <| \resolved ->
describe "tests for my task"
[ test "resolves to hello" <| \_ ->
Expect.equal "hello" resolved
, test "is not goodbye" <| \_ ->
Expect.notEqual "goodbye" resolved
]
Node Environment and Subsystems
If your tasks need access to Node.Environment or subsystem permissions you can use init and thenRun:
import Bytes
import Expect
import FileSystem
import Test exposing (test)
import Test.Runner.Effectful exposing (init, thenRun, join, await)
main =
init <| \env ->
-- Initialize subsystems here:
Init.await FileSystem.initialize <| \fsPerm->
Init.await ChildProcess.initialize <| \processPerm ->
-- Then run your test suite like normal here:
thenRun env <|
join
[ await (readTestFile fsPerm) "reading test.txt" <| \contents ->
test "resolves to contents of file" <| \_ ->
Expect.equal "some text\n" content
, await (catTestFile processPerm) "cat test.txt" <| \contents ->
test "also resolves to contents of file" <| \_ ->
Expect.equal "some text\n" content
]
readTestFile : FileSystem.Permission -> Task FileSystem.Error (Maybe String)
readTestFile permission =
"./test.txt"
|> Path.fromPosixString
|> FileSystem.readFile permission
|> Task.map Bytes.toString
catTestFile : ChildProcess.Permission -> Task ChildProcess.FailedRun ChildProcess.SuccessfulRun
catTestFile permission =
ChildProcess.run permission "cat" [ "test.txt" ] ChildProcess.defaultRunOptions
|> Task.map .stdout
|> Task.map Bytes.toString
Contact
Found a problem? Need some help? You can open an issue, find me on mastodon, or on the Gren Discord.