packages feed

nri-redis-0.4.1.1: test/Spec/Redis/Script.hs

{-# LANGUAGE QuasiQuotes #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Spec.Redis.Script (tests) where

import qualified Data.Bifunctor
import Data.Either (Either (..))
import qualified Expect
import Redis.Script
import qualified Test
import qualified Text.Megaparsec as P

tests :: Test.Test
tests =
  Test.describe
    "Redis.Script"
    [ Test.describe "parser" parserTests,
      Test.describe "th tests" thTests
    ]

parserTests :: List Test.Test
parserTests =
  [ Test.test "1 word" <| \_ ->
      P.runParser parser "" "Jabuticaba"
        |> Expect.equal (Right [ScriptText "Jabuticaba"]),
    Test.test "3 words" <| \_ ->
      P.runParser parser "" "Picolé de Jabuticaba"
        |> Expect.equal (Right [ScriptText "Picolé de Jabuticaba"]),
    Test.test "1 value" <| \_ ->
      P.runParser parser "" "${value}"
        |> Expect.equal (Right [ScriptVariable "value"]),
    Test.test "function application" <| \_ ->
      P.runParser parser "" "${func arg1 arg2}"
        |> Expect.equal (Right [ScriptVariable "func arg1 arg2"]),
    Test.test "text and variables" <| \_ ->
      P.runParser parser "" "some text ${value} some more text ${ anotherValue }"
        |> Expect.equal
          ( Right
              [ ScriptText "some text ",
                ScriptVariable "value",
                ScriptText " some more text ",
                ScriptVariable "anotherValue"
              ]
          ),
    Test.test "ERROR: empty" <| \_ -> do
      P.runParser parser "" ""
        |> Data.Bifunctor.first P.errorBundlePretty
        |> Expect.equal
          ( Left
              "1:1:\n\
              \  |\n\
              \1 | <empty line>\n\
              \  | ^\n\
              \unexpected end of input\n\
              \expecting \"${\" or some plain text\n\
              \"
          ),
    Test.test "ERROR: empty variable" <| \_ -> do
      P.runParser parser "" "${}"
        |> Data.Bifunctor.first P.errorBundlePretty
        |> Expect.equal
          ( Left
              "1:3:\n\
              \  |\n\
              \1 | ${}\n\
              \  |   ^\n\
              \unexpected '}'\n\
              \expecting anything but '$', '{' or '}' (no records, sorry) or white space\n\
              \"
          ),
    Test.test "ERROR: nested ${}" <| \_ -> do
      P.runParser parser "" "asdasd ${ ${ value } }"
        |> Data.Bifunctor.first P.errorBundlePretty
        |> Expect.equal
          ( Left
              "1:11:\n\
              \  |\n\
              \1 | asdasd ${ ${ value } }\n\
              \  |           ^\n\
              \unexpected '$'\n\
              \expecting anything but '$', '{' or '}' (no records, sorry) or white space\n\
              \"
          ),
    Test.test "ERROR: misplaced ${ inside ${}" <| \_ -> do
      P.runParser parser "" "${ v$alue }"
        |> Data.Bifunctor.first P.errorBundlePretty
        |> Expect.equal
          ( Left
              "1:5:\n\
              \  |\n\
              \1 | ${ v$alue }\n\
              \  |     ^\n\
              \unexpected '$'\n\
              \expecting '}' or anything but '$', '{' or '}' (no records, sorry)\n\
              \"
          ),
    Test.test "ERROR: misplaced { inside ${}" <| \_ -> do
      P.runParser parser "" "${ v{alue }"
        |> Data.Bifunctor.first P.errorBundlePretty
        |> Expect.equal
          ( Left
              "1:5:\n\
              \  |\n\
              \1 | ${ v{alue }\n\
              \  |     ^\n\
              \unexpected '{'\n\
              \expecting '}' or anything but '$', '{' or '}' (no records, sorry)\n\
              \"
          )
  ]

thTests :: List Test.Test
thTests =
  [ Test.test "just text" <| \_ ->
      [script|some text|]
        |> Expect.equal
          ( Script
              { luaScript = "some text",
                quasiQuotedString = "some text",
                keys = [],
                arguments = Log.mkSecret []
              }
          ),
    Test.test "one key argument" <| \_ ->
      [script|${Key "hi"}|]
        |> Expect.equal
          ( Script
              { luaScript = "KEYS[1]",
                quasiQuotedString = "${Key \"hi\"}",
                keys = ["hi"],
                arguments = Log.mkSecret []
              }
          ),
    Test.test "one literal argument" <| \_ ->
      [script|${Literal "hi"}|]
        |> Expect.equal
          ( Script
              { luaScript = "ARGV[1]",
                quasiQuotedString = "${Literal \"hi\"}",
                keys = [],
                arguments = Log.mkSecret ["hi"]
              }
          ),
    Test.test "one key one literal argument" <| \_ ->
      [script|${Key "a key"} ${Literal "a literal"}|]
        |> Expect.equal
          ( Script
              { luaScript = "KEYS[1] ARGV[1]",
                quasiQuotedString = "${Key \"a key\"} ${Literal \"a literal\"}",
                keys = ["a key"],
                arguments = Log.mkSecret ["a literal"]
              }
          ),
    Test.test "multiple keys and literals" <| \_ ->
      [script|${Key "key1"} ${Key "key2"} ${Key "key3"} ${Literal "literal1"} ${Literal "literal2"} ${Literal "literal3"}|]
        |> Expect.equal
          ( Script
              { luaScript = "KEYS[1] KEYS[2] KEYS[3] ARGV[1] ARGV[2] ARGV[3]",
                quasiQuotedString = "${Key \"key1\"} ${Key \"key2\"} ${Key \"key3\"} ${Literal \"literal1\"} ${Literal \"literal2\"} ${Literal \"literal3\"}",
                keys = ["key1", "key2", "key3"],
                arguments = Log.mkSecret ["literal1", "literal2", "literal3"]
              }
          ),
    Test.test "fails on type-checking when not given Key or Literal" <| \_ ->
      [script|${False}|]
        |> arguments
        |> Log.unSecret
        |> Expect.equal ["this would have been a type-checking error"]
  ]

-- This instance is picked when none of the instances in src/Redis/Script.hs work..
-- proving in real code we would have a type-checking error.
instance {-# INCOHERENT #-} HasScriptParam Bool where
  getScriptParam _ = Literal "this would have been a type-checking error"