icepeak-0.7.1.0: tests/StoreSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module StoreSpec (spec) where
import Data.Aeson (Value (..))
import Test.Hspec (Spec, describe, it, shouldBe)
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck.Instances ()
import qualified Data.HashMap.Strict as HashMap
import OrphanInstances ()
import Store (Modification (..))
import qualified Store
spec :: Spec
spec = do
describe "Store.insert" $ do
it "creates an object when putting 'x' into Null" $
let
before = Null
after = Object $ HashMap.singleton "x" (String "Robert")
in
Store.insert ["x"] (String "Robert") before `shouldBe` after
it "overwrites a key when putting 'x' into {'x': ...}" $
let
before = Object $ HashMap.singleton "x" (String "Arian")
after = Object $ HashMap.singleton "x" (String "Robert")
in
Store.insert ["x"] (String "Robert") before `shouldBe` after
it "adds a key when putting 'x' into {'y': ...}" $
let
before = Object $ HashMap.singleton "y" (String "Arian")
after = Object $ HashMap.fromList [("x", String "Robert"), ("y", String "Arian")]
in
Store.insert ["x"] (String "Robert") before `shouldBe` after
it "creates a nested object when putting 'x/y' into Null" $
let
before = Null
after = Object $ HashMap.singleton "x" $ Object $ HashMap.singleton "y" "Stefan"
in
Store.insert ["x", "y"] (String "Stefan") before `shouldBe` after
it "updates a nested object when putting 'x/y' into {'x': {'y': ...}}" $
let
before = Object $ HashMap.singleton "x" $ Object $ HashMap.singleton "y" "Radek"
after = Object $ HashMap.singleton "x" $ Object $ HashMap.singleton "y" "Stefan"
in
Store.insert ["x", "y"] (String "Stefan") before `shouldBe` after
it "adds a nested key when putting 'x/y' into {'x': {'y': ...}, 'z': ...}" $
let
before = Object $ HashMap.fromList [("x", Object $ HashMap.singleton "y" "Nuno"), ("z", Null)]
after = Object $ HashMap.fromList [("x", Object $ HashMap.singleton "y" "Stefan"), ("z", Null)]
in
Store.insert ["x", "y"] (String "Stefan") before `shouldBe` after
describe "Store" $ do
prop "returns None after (lookup . delete . insert) in Null" $ \ path value ->
let
lkupDelIns = Store.lookup path . Store.delete path . Store.insert path value
in
if path == []
then lkupDelIns Null `shouldBe` (Just Null)
else lkupDelIns Null `shouldBe` Nothing
prop "returns None after (lookup . delete . insert) in anything" $ \ path value before ->
let
lkupDelIns = Store.lookup path . Store.delete path . Store.insert path value
in
if path == []
then lkupDelIns before `shouldBe` (Just Null)
else lkupDelIns before `shouldBe` Nothing
describe "Store.applyModification" $ do
it "creates an object when putting 'x' into Null" $
let
put = Put ["x"] (String "Robert")
before = Null
after = Object $ HashMap.singleton "x" (String "Robert")
in
Store.applyModification put before `shouldBe` after
it "overwrites a key when putting 'x' into {'x': ...}" $
let
put = Put ["x"] (String "Robert")
before = Object $ HashMap.singleton "x" (String "Arian")
after = Object $ HashMap.singleton "x" (String "Robert")
in
Store.applyModification put before `shouldBe` after
it "adds a key when putting 'x' into {'y': ...}" $
let
put = Put ["x"] (String "Robert")
before = Object $ HashMap.singleton "y" (String "Arian")
after = Object $ HashMap.fromList [("x", String "Robert"), ("y", String "Arian")]
in
Store.applyModification put before `shouldBe` after
it "creates a nested object when putting 'x/y' into Null" $
let
put = Put ["x", "y"] (String "Stefan")
before = Null
after = Object $ HashMap.singleton "x" $ Object $ HashMap.singleton "y" "Stefan"
in
Store.applyModification put before `shouldBe` after
it "updates a nested object when putting 'x/y' into {'x': {'y': ...}}" $
let
put = Put ["x", "y"] (String "Stefan")
before = Object $ HashMap.singleton "x" $ Object $ HashMap.singleton "y" "Radek"
after = Object $ HashMap.singleton "x" $ Object $ HashMap.singleton "y" "Stefan"
in
Store.applyModification put before `shouldBe` after
it "adds a nested key when putting 'x/y' into {'x': {'y': ...}, 'z': ...}" $
let
put = Put ["x", "y"] (String "Stefan")
before = Object $ HashMap.fromList [("x", Object $ HashMap.singleton "y" "Nuno"), ("z", Null)]
after = Object $ HashMap.fromList [("x", Object $ HashMap.singleton "y" "Stefan"), ("z", Null)]
in
Store.applyModification put before `shouldBe` after
prop "is idempotent" $ \op value ->
let apply = Store.applyModification op
in apply value == apply (apply value)