packages feed

ziptastic-core-0.2.0.0: test/Spec.hs

{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}

module Main (main) where

import           Control.Monad
import           Data.Aeson (decodeStrict')
import qualified Data.ISO3166_CountryCodes as CC
import           Data.Monoid
import           Data.Text (Text)
import           Data.Text.Encoding (encodeUtf8)
import           Test.Hspec
import           Data.String.Here (here, iTrim)
import           Data.Time.Zones.All as TZ

import           Ziptastic.Core


main :: IO ()
main = hspec spec

spec :: Spec
spec = describe "JSON decoding LocaleInfo" $ do
  let parseTemplate :: Maybe (Text, Text) -> Maybe LocaleInfo
      parseTemplate = decodeStrict' . encodeUtf8 . exampleJsonTemplate

  it "accepts the standard example" $
     parseTemplate Nothing `shouldBe` Just exampleLocaleInfo

  it "nullifies coordinates if any related fields are null" $
    forM_ [ ("geohash", quoted ""), ("geohash", "null")
          , ("latitude", "null"), ("longitude", "null") ] $ \(field, val) ->
      parseTemplate (Just (field, val)) `shouldBe` Just exampleLocaleInfo{localeCoords = Nothing}

  it "accepts empty time zone" $
    forM_ [quoted "", "null"] $ \val ->
      parseTemplate (Just ("timezone", val))
        `shouldBe` Just exampleLocaleInfo{localeTimeZone = Nothing}

  it "does not accept invalid time zone" $
    parseTemplate (Just ("timezone", "blah")) `shouldBe` Nothing

  it "does not accept invalid country code" $
    parseTemplate (Just ("country", "zz")) `shouldBe` Nothing

  it "does not accept empty postal code" $
    parseTemplate (Just ("postal_code", quoted "")) `shouldBe` Nothing


exampleJsonTemplate :: Maybe (Text, Text) -> Text
exampleJsonTemplate fieldOverride = [iTrim|
    {
      ${f "city" $ quoted "Owosso"},
      ${f "geohash" $ quoted "dpshsfsytw8k"},
      ${f "country" $ quoted "US"},
      ${f "county" $ quoted "Shiawassee"},
      ${f "state" $ quoted "Michigan"},
      ${f "state_short" $ quoted "MI"},
      ${f "postal_code" $ quoted "48867"},
      ${f "latitude" "42.9934"},
      ${f "longitude" "-84.1595"},
      ${f "timezone" $ quoted "America/Detroit"}
    }
  |] :: Text
  where
    f :: Text -> Text -> Text
    f field defaultVal = quoted field <> ": " <> case fieldOverride of
      Nothing -> defaultVal
      Just (key, val) -> if field == key then val else defaultVal

quoted :: Text -> Text
quoted x = "\"" <> x <> "\""

exampleLocaleInfo :: LocaleInfo
exampleLocaleInfo = LocaleInfo
  { localeCity         = Just "Owosso"
  , localeCountry      = CC.US
  , localeCounty       = Just "Shiawassee"
  , localeRegionFull   = Just "Michigan"
  , localeRegionAbbrev = Just "MI"
  , localePostalCode   = "48867"
  , localeCoords       = Just LocaleCoords
      { coordsLatitude  = 42.9934
      , coordsLongitude = (-84.1595)
      , coordsGeohash   = "dpshsfsytw8k"
      }
  , localeTimeZone   = Just TZ.America__Detroit
  }