Making test assertions on variant types

Does anyone have a preferred way to making assertions on a variant type? For example something like this:

type httpResponse<'a> =
  | Success('a)
  | Conflict(string)
  | NotFound(string)
  | UnAuthorized(string)


let response = await someTestApi()

// expect(response)->toBe(Success(_))
// expect(response)->toBe(NotFound(_))

So far, I’ve been manually pattern matching and throwing errors:

switch response {
| Success(_) => ()
| err => failwith("Expected 'success'")
}

But the output is unfavorable when a test fails and not easy to debug

1 Like

toBe checks the reference equality, why don’t you use toEqual or toStrictEqual instead?

I use GitHub - DZakh/rescript-ava: 🪲 ReScript bindings for Ava. Any other test library will work

1 Like

I can feel your pain. I need something like Rust’s matches! macro to assert with a pattern.

1 Like

An equivalent PPX macro may be required, but it’s not that complicated if it generates a framework-specific codes.

Oh yeah, toEqual works when you’re asserting a specific value expect(res)->toEqual(Success(5))

I think I chose a poor example, but I meant asserting that the res is of type success, without caring what the actual payload is. A better example would be something like a state machine

type multistep =
  | Part1({..})
  | Cancelled
  | Part2({..})
  | Part3({..})

let workflow = Part1({..})
let nextState = applySomeTransition(workflow, data)

expect(nextState)->toBeTypeOf(Part2)

Where I’m just asserting that it transitioned properly, but I don’t care what the actual inner object is

I was browsing the forums and saw another discussion on where someone with a similar issue created an “enum” function

let enum = ms =>
  switch ms {
  | Part1(_) => #Part1
  | Cancelled => #Cancelled
  | Part2(_) => #Part2
  | Part3(_) => #Part3
  }

This is probably the route I’ll choose, it’s minimal maintanance and the jest failures will also be able to differentiate got vs expected

enum(workflow)->expect->toBe(#Part2)
3 Likes