Write unit test for validation result

I’m doing the exercises in chapter 7 of the purescript book being revised, and, at the same time, attempting to add unit tests to validate the solution.

The exercise is the 1st one in this group to validate a field using a regex. My solution is:

validateAddressRegex :: Address -> Semigroup.V Errors Address
validateAddressRegex a =
  address <$> (nonEmpty "Street" a.street *> pure a.street)
    <*> (nonEmpty "City" a.city *> pure a.city)
    <*> (matches "State" stateAbbreviationRegex a.state *> pure a.state)

stateAbbreviationRegex :: Regex
stateAbbreviationRegex =
  unsafePartial case regex "^[A-Za-z]{2}$" noFlags of
    Right r -> r

which works fine.

My problem is: how do I write a unit test for it? Here are the two categories of validation response:

Passing:

> validateAddressRegex (address "22 Fake St" "Fake City" "CA" )
pure ({ city: "Fake City", state: "CA", street: "22 Fake St" })

Failing:

> validateAddressRegex (address "22 Fake St" "Fake City" "CAA" )
invalid (["Field 'State' did not match the required format"])

I’m finding I’m flailing with this trying to test it: I presume the unit test should look similar to the following:

main :: Effect Unit
main =
  runTest do
    suite "Exercise Group 2" do
      suite "Regex validator for state code to be two alphabetic chars" do
        test "OK"
          $ Assert.equal
          $ pure { city: "street: "22 Fake St", Fake City", state: "CA" }
          $ validateAddressRegex (address "22 Fake St" "Fake City" "CA" )
        test "Fails validation"
          $ Assert.equal
          $ invalid (["Field 'State' did not match the required format"])
          $ validateAddressRegex (address "22 Fake St" "Fake City" "CAA" )

I get the following compile error on the first validateAddressRegex line:

  Could not match type
                        
    Function            
      { city :: String  
      , state :: String 
      , street :: String
      }                 
                        
  with type
       
    Aff
       

while trying to match type t0 -> Aff Unit
  with type Aff Unit
while checking that expression (apply equal) ((apply (pure { street: ...         
                                                           , city: ...           
                                                           , state: ...          
                                                           }                     
                                                     )                           
                                              )                                  
                                              (validateAddressRegex ((...) "CA"))
                                             )                                   
  has type Aff Unit
in value declaration main

where t0 is an unknown type

Can anyone help me get this unit test to properly check a validation response?

It really depends on which testing package you’re using, but I’m going to guess that you need to do something like this:

test "OK" do
  Assert.equal x y

You’re just missing some parens around the first argument.

So change:

test "OK"
  $ Assert.equal
  $ pure { street: "22 Fake St", city: "Fake City", state: "CA" }
  $ validateAddressRegex (address "22 Fake St" "Fake City" "CA")

to:

test "OK"
  $ Assert.equal
      (pure { street: "22 Fake St", city: "Fake City", state: "CA" })
  $ validateAddressRegex (address "22 Fake St" "Fake City" "CA")

But I’d write it like this:

test "OK" do
  let
    addr = address "22 Fake St" "Fake City" "CA"
  Assert.equal
    (pure addr)
    $ validateAddressRegex addr
1 Like

@milesfrain Thank you! Parenthesis did fix it; don’t know why I couldn’t spot that.

@paulyoung Thanks for reply. @milesfrain has the solution below; I missed the parenthesis.

Here’s the complete set of unit tests I was able to complete after Miles’ help:

      suite "Regex validator for state code to be two alphabetic chars" do
        test "Passes validation" do
          let
            addr = address "22 Fake St" "Fake City" "CA"
          Assert.equal (pure addr)
            $ validateAddressRegex addr
        suite "Fails validation" do
          let
            fail = Semigroup.invalid ([ "Field 'State' did not match the required format" ])
          test "Too few letters"
            $ Assert.equal fail
            $ validateAddressRegex (address "22 Fake St" "Fake City" "C")
          test "Too many letters"
            $ Assert.equal fail
            $ validateAddressRegex (address "22 Fake St" "Fake City" "CAA")
          test "Contains non-letters"
            $ Assert.equal fail
            $ validateAddressRegex (address "22 Fake St" "Fake City" "C3")
          test "Not all caps"
            $ Assert.equal fail
            $ validateAddressRegex (address "22 Fake St" "Fake City" "Ca")

So in order to “learn something”, I played with do and indentation and found the following work using one of the fail assertions:

No do:

          test "Not all caps"
            $ Assert.equal fail
            $ validateAddressRegex (address "22 Fake St" "Fake City" "CAA")

Use do:

          test "Not all caps" do
            Assert.equal fail
              $ validateAddressRegex (address "22 Fake St" "Fake City" "Ca")

Finally starting to make sense.