duckling/Duckling/Testing/Types.hs
Ziyang Liu a3b35880e5 Change value in Entity to typed value instead of JSON
Summary:
Modified `Entity` to use the new `ResolvedVal` data type. Other changes follow naturally. Related issues: https://github.com/facebook/duckling/issues/121 and https://github.com/facebook/duckling/issues/172

Now one can pattern match on the output value, for instance:

```
{-# LANGUAGE GADTs #-}

import Data.Text
import Duckling.Core
import Duckling.Testing.Types
import qualified Duckling.PhoneNumber.Types as PN

parsePhoneNumber :: Text -> Text
parsePhoneNumber input =
  case value entity of
    (RVal PhoneNumber (PN.PhoneNumberValue v)) -> v
    where
    (entity:_) = parse input testContext testOptions [This PhoneNumber]
```

Reviewed By: patapizza

Differential Revision: D7502020

fbshipit-source-id: 76ba7b315cfd0d2c61ff95c855b7c95efc0a401c
2018-04-20 14:18:47 -07:00

88 lines
2.4 KiB
Haskell

-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree. An additional grant
-- of patent rights can be found in the PATENTS file in the same directory.
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE TupleSections #-}
module Duckling.Testing.Types
( Corpus
, Datetime
, Example
, NegativeCorpus
, TestPredicate
, dt
, examples
, examplesCustom
, parserCheck
, refTime
, simpleCheck
, testContext
, testOptions
, withLocale
, zTime
) where
import Data.Aeson (toJSON, ToJSON, Value)
import Data.Fixed (Pico)
import Data.Text (Text)
import Prelude
import qualified Data.Time as Time
import Duckling.Core
import Duckling.Resolve
import Duckling.Types
type TestPredicate = Context -> ResolvedToken -> Bool
type Example = (Text, TestPredicate)
type Corpus = (Context, Options, [Example])
type NegativeCorpus = (Context, Options, [Text])
examplesCustom :: TestPredicate -> [Text] -> [Example]
examplesCustom check = map (, check)
simpleCheck :: ToJSON a => a -> TestPredicate
simpleCheck json _ Resolved{rval = RVal _ v} = toJSON json == toJSON v
parserCheck :: Eq a => a -> (Value -> Maybe a) -> TestPredicate
parserCheck expected parse _ Resolved{rval = RVal _ v} =
maybe False (expected ==) $ parse (toJSON v)
examples :: ToJSON a => a -> [Text] -> [Example]
examples output = examplesCustom (simpleCheck output)
type Datetime = (Integer, Int, Int, Int, Int, Pico)
dt :: Datetime -> Time.UTCTime
dt (year, month, days, hours, minutes, seconds) = Time.UTCTime day diffTime
where
day = Time.fromGregorian year month days
diffTime = Time.timeOfDayToTime $ Time.TimeOfDay hours minutes seconds
zTime :: Datetime -> Int -> Time.ZonedTime
zTime datetime offset = fromUTC (dt datetime) $ Time.hoursToTimeZone offset
refTime :: Datetime -> Int -> DucklingTime
refTime datetime offset = fromZonedTime $ zTime datetime offset
-- Tuesday Feb 12, 2013 at 4:30am is the "now" for the tests
testContext :: Context
testContext = Context
{ locale = makeLocale EN Nothing
, referenceTime = refTime (2013, 2, 12, 4, 30, 0) (-2)
}
testOptions :: Options
testOptions = Options
{ withLatent = False
}
withLocale :: (Context, Options, [a]) -> Locale -> [a]
-> (Context, Options, [a])
withLocale (langContext, options, langXs) locale localeXs
= (langContext {locale = locale}, options, langXs ++ localeXs)