packages feed

fluent-1.0.0: test/FunctionSpec.hs

module FunctionSpec (spec) where

import Data.Either.Extra (maybeToEither)
import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as HashMap
import Data.Maybe (listToMaybe)
import Language.Fluent.Pattern qualified as Pattern
import Prelude

spec :: Spec
spec = do
    it "returns the first of its positional arguments" $
        translate
            "foo"
            ("a", "Foo" :: Text)
            ("b", "Bar" :: Text)
            (WithFunction "FIRST" first)
            [fluent|foo = { FIRST($a, $b) }|]
            `shouldBe` Right "Foo"
    it "is called with a named argument" $
        translate
            "foo"
            (WithFunction "PICK" pick)
            [fluent|foo = { PICK(which: "Bar") }|]
            `shouldBe` Right "Bar"
    it "is called with a named argument that is a number" $
        translate
            "foo"
            (WithFunction "PICK" pick)
            [fluent|foo = { PICK(which: 3) }|]
            `shouldBe` Right "3"
    it "is called with no arguments at all" $
        translate
            "foo"
            (WithFunction "GREET" greet)
            [fluent|foo = A{ GREET() }B|]
            `shouldBe` Right "AHelloB"
    it "is the selector of a select expression" $
        translate
            "foo"
            (WithFunction "PICK" pick)
            [fluent|
              foo = { PICK(which: "a") ->
                  [a] A
                 *[b] B
                }
            |]
            `shouldBe` Right "A"
    it "is called with a message reference" $
        translate
            "foo"
            (WithFunction "FIRST" first)
            [fluent|
              bar = Bar
              foo = { FIRST(bar) }
            |]
            `shouldBe` Right "Bar"
    it "is called with a message of more than one part" $
        translate
            "foo"
            (WithFunction "FIRST" first)
            [fluent|
              bar = B{ "a" }r
              foo = { FIRST(bar) }
            |]
            `shouldBe` Right "Bar"
    it "returns a variable, which a variant key still matches" $
        translate
            "foo"
            ("arg", "a" :: Text)
            (WithFunction "FIRST" first)
            [fluent|
              foo = { FIRST($arg) ->
                  [a] A
                 *[b] B
                }
            |]
            `shouldBe` Right "A"
    it "returns a message, which a variant key still matches" $
        translate
            "foo"
            (WithFunction "FIRST" first)
            [fluent|
              bar = a
              foo = { FIRST(bar) ->
                  [a] A
                 *[b] B
                }
            |]
            `shouldBe` Right "A"
    it "returns a message of more than one part, which cannot be a selector" $
        translate
            "foo"
            (WithFunction "FIRST" first)
            [fluent|
              bar = a{ "b" }
              foo = { FIRST(bar) ->
                  [ab] AB
                 *[c] C
                }
            |]
            `shouldBe` Left "Selector is not a number or identifier"
    it "is missing" $
        translate "foo" [fluent|foo = { MISSING() }|]
            `shouldBe` Left "Function not found: \"MISSING\""
    it "returns the reason it fails" $
        translate
            "foo"
            (WithFunction "FAIL" refuse)
            [fluent|foo = { FAIL() }|]
            `shouldBe` Left "this function always fails"

first :: [Pattern] -> HashMap Identifier SomeValue -> Either String Pattern
first values _ = maybeToEither "no argument" $ listToMaybe values

greet :: [Pattern] -> HashMap Identifier SomeValue -> Either String Pattern
greet _ _ = Right "Hello"

pick :: [Pattern] -> HashMap Identifier SomeValue -> Either String Pattern
pick _ named =
    Pattern.fromValue <$> maybeToEither "no argument named which" (HashMap.lookup "which" named)

refuse :: [Pattern] -> HashMap Identifier SomeValue -> Either String Pattern
refuse _ _ = Left "this function always fails"