module THSpec where import Composite.CoRecord (Field, field) import Composite.Record ((:->)(Val), Rec(RNil), Record, pattern (:*:), rlens) import Composite.TH import Control.Lens (preview, review, view) import Test.Hspec (Spec, describe, it, shouldBe) -- test that withLensesAndProxies works in the simple case withLensesAndProxies [d| type FConcrete = "foo" :-> Int |] -- test that withLensesAndProxies ignores non-conformant shapes (without :->) in the declaration withLensesAndProxies [d| type ConcreteRec = '[FConcrete] type FConcreteRec = "foo" :-> Record ConcreteRec |] -- test that withLensesAndProxies works with parameterized fields (and unrelated types) withLensesAndProxies [d| type FParameterized a = "foo" :-> a type ParameterizedRec a = '[FParameterized a] type FParameterizedRec a = "foo" :-> Record (ParameterizedRec a) |] -- test that withOpticsAndProxies works in the simple case withOpticsAndProxies [d| type FOptical = "foo" :-> Int |] thSuite :: Spec thSuite = do describe "withLensesAndProxies" $ do it "works for simple fields" $ do let r :: Record '[FConcrete] r = 123 :*: RNil view fConcrete r `shouldBe` 123 view (rlens fConcrete_) r `shouldBe` 123 it "works for declaration blocks with non-fields in them" $ do let r :: Record ConcreteRec r = 123 :*: RNil r2 :: Record '[FConcreteRec] r2 = r :*: RNil view ( fConcreteRec . fConcrete) r2 `shouldBe` 123 view (rlens fConcreteRec_ . fConcrete) r2 `shouldBe` 123 it "works with parameterized fields" $ do let ra :: Record '[FParameterized Int] ra = 123 :*: RNil ra2 :: Record '[FParameterizedRec Int] ra2 = ra :*: RNil rb :: Record '[FParameterized Bool] rb = True :*: RNil rb2 :: Record '[FParameterizedRec Bool] rb2 = rb :*: RNil view ( (fParameterized @Int )) ra `shouldBe` 123 view ( rlens (fParameterized_ @Int )) ra `shouldBe` 123 view ( (fParameterized @Bool)) rb `shouldBe` True view ( rlens (fParameterized_ @Bool)) rb `shouldBe` True view ( (fParameterizedRec @Int ). (fParameterized @Int )) ra2 `shouldBe` 123 view (rlens (fParameterizedRec_ @Int ). (fParameterized @Int )) ra2 `shouldBe` 123 view ( (fParameterizedRec @Bool). (fParameterized @Bool)) rb2 `shouldBe` True view (rlens (fParameterizedRec_ @Bool). (fParameterized @Bool)) rb2 `shouldBe` True describe "withOpticsAndProxies" $ do it "works for simple fields" $ do let f :: Field '[FOptical] f = field (Val 123 :: FOptical) preview _FOptical f `shouldBe` Just 123 review _FOptical 123 `shouldBe` f