packages feed

convex-schema-parser-0.1.4.0: test/UnificationTest.hs

{-# LANGUAGE OverloadedStrings #-}

module UnificationTest (tests) where

import qualified Convex.Action.Parser as Action
import qualified Convex.Parser as Parser
import qualified Convex.Schema.Parser as Schema
import Test.HUnit

testUnifyWithTableDoc :: Test
testUnifyWithTableDoc = "unifies function return with table doc" ~: TestCase $ do
  let schemaContent =
        unlines
          [ "import { defineSchema, defineTable } from \"convex/server\";",
            "import { v } from \"convex/values\";",
            "",
            "export default defineSchema({",
            "  users: defineTable({",
            "    name: v.string(),",
            "    email: v.string()",
            "  })",
            "});"
          ]
  let apiFileContent =
        unlines
          [ "declare const fullApi: ApiFromModules<{",
            "  \"myActions\": typeof myActions;",
            "}>;"
          ]
  let actionContent =
        unlines
          [ "export declare const getUser: import(\"convex/server\").RegisteredQuery<\"public\", {}, Promise<{ _id: import(\"convex/values\").GenericId<\"users\">; _creationTime: number; name: string; email: string; }>>;"
          ]
  let actionContents = [("myActions", actionContent)]

  result <- Parser.parseProjectFromContents schemaContent apiFileContent actionContents
  case result of
    Left err -> assertFailure ("Parser failed: " ++ show err)
    Right project ->
      let expected =
            [ Action.ConvexFunction
                { Action.funcName = "getUser",
                  Action.funcPath = "myActions",
                  Action.funcType = Action.Query,
                  Action.funcArgs = [],
                  Action.funcReturn = Schema.VReference "UsersDoc"
                }
            ]
       in Parser.ppFunctions project @?= expected

testUnifyWithNestedObject :: Test
testUnifyWithNestedObject = "unifies function return with nested object" ~: TestCase $ do
  let schemaContent =
        unlines
          [ "import { defineSchema, defineTable } from \"convex/server\";",
            "import { v } from \"convex/values\";",
            "",
            "export default defineSchema({",
            "  users: defineTable({",
            "    name: v.string(),",
            "    profile: v.object({",
            "      image: v.string()",
            "    })",
            "  })",
            "});"
          ]
  let apiFileContent =
        unlines
          [ "declare const fullApi: ApiFromModules<{",
            "  \"myActions\": typeof myActions;",
            "}>;"
          ]
  let actionContent =
        unlines
          [ "export declare const getUser: import(\"convex/server\").RegisteredQuery<\"public\", {}, Promise<{ _id: import(\"convex/values\").GenericId<\"users\">; _creationTime: number; name: string; profile: { image: string; }; }>>;"
          ]
  let actionContents = [("myActions", actionContent)]

  result <- Parser.parseProjectFromContents schemaContent apiFileContent actionContents
  case result of
    Left err -> assertFailure ("Parser failed: " ++ show err)
    Right project ->
      let expected =
            [ Action.ConvexFunction
                { Action.funcName = "getUser",
                  Action.funcPath = "myActions",
                  Action.funcType = Action.Query,
                  Action.funcArgs = [],
                  Action.funcReturn = Schema.VReference "UsersDoc"
                }
            ]
       in Parser.ppFunctions project @?= expected

testUnifyWithArrayOfDocs :: Test
testUnifyWithArrayOfDocs = "unifies function returning an array of docs" ~: TestCase $ do
  let schemaContent =
        unlines
          [ "import { defineSchema, defineTable } from \"convex/server\";",
            "import { v } from \"convex/values\";",
            "",
            "export default defineSchema({",
            "  users: defineTable({",
            "    name: v.string(),",
            "    email: v.string()",
            "  })",
            "});"
          ]
  let apiFileContent =
        unlines
          [ "declare const fullApi: ApiFromModules<{",
            "  \"myActions\": typeof myActions;",
            "}>;"
          ]
  let actionContent =
        unlines
          [ "export declare const listUsers: import(\"convex/server\").RegisteredQuery<\"public\", {}, Promise<{",
            "  _id: import(\"convex/values\").GenericId<\"users\">;",
            "  _creationTime: number;",
            "  name: string;",
            "  email: string;",
            "}[]>>;"
          ]
  let actionContents = [("myActions", actionContent)]

  result <- Parser.parseProjectFromContents schemaContent apiFileContent actionContents
  case result of
    Left err -> assertFailure ("Parser failed: " ++ show err)
    Right project ->
      let expected =
            [ Action.ConvexFunction
                { Action.funcName = "listUsers",
                  Action.funcPath = "myActions",
                  Action.funcType = Action.Query,
                  Action.funcArgs = [],
                  Action.funcReturn = Schema.VArray (Schema.VReference "UsersDoc")
                }
            ]
       in Parser.ppFunctions project @?= expected

testUnifyWithDeeplyNestedObject :: Test
testUnifyWithDeeplyNestedObject = "unifies function return with deeply nested object" ~: TestCase $ do
  let schemaContent =
        unlines
          [ "import { defineSchema, defineTable } from \"convex/server\";",
            "import { v } from \"convex/values\";",
            "",
            "export default defineSchema({",
            "  users: defineTable({",
            "    name: v.string(),",
            "    profile: v.object({",
            "      image: v.string(),",
            "      details: v.object({",
            "        bio: v.string()",
            "      })",
            "    })",
            "  })",
            "});"
          ]
  let apiFileContent =
        unlines
          [ "declare const fullApi: ApiFromModules<{",
            "  \"myActions\": typeof myActions;",
            "}>;"
          ]
  let actionContent =
        unlines
          [ "export declare const getUser: import(\"convex/server\").RegisteredQuery<\"public\", {}, Promise<{ _id: import(\"convex/values\").GenericId<\"users\">; _creationTime: number; name: string; profile: { image: string; details: { bio: string; } }; }>>;"
          ]
  let actionContents = [("myActions", actionContent)]

  result <- Parser.parseProjectFromContents schemaContent apiFileContent actionContents
  case result of
    Left err -> assertFailure ("Parser failed: " ++ show err)
    Right project ->
      let expected =
            [ Action.ConvexFunction
                { Action.funcName = "getUser",
                  Action.funcPath = "myActions",
                  Action.funcType = Action.Query,
                  Action.funcArgs = [],
                  Action.funcReturn = Schema.VReference "UsersDoc"
                }
            ]
       in Parser.ppFunctions project @?= expected

tests :: Test
tests =
  "Unification"
    ~: test
      [ testUnifyWithTableDoc,
        testUnifyWithNestedObject,
        testUnifyWithArrayOfDocs,
        testUnifyWithDeeplyNestedObject,
        testUnifyWithShuffledFields
      ]

testUnifyWithShuffledFields :: Test
testUnifyWithShuffledFields = "unifies function return with shuffled fields" ~: TestCase $ do
  let schemaContent =
        unlines
          [ "import { defineSchema, defineTable } from \"convex/server\";",
            "import { v } from \"convex/values\";",
            "",
            "export default defineSchema({",
            "  users: defineTable({",
            "    name: v.string(),",
            "    email: v.string()",
            "  })",
            "});"
          ]
  let apiFileContent =
        unlines
          [ "declare const fullApi: ApiFromModules<{",
            "  \"myActions\": typeof myActions;",
            "}>;"
          ]
  let actionContent =
        unlines
          -- Note the shuffled fields: email, name instead of name, email
          [ "export declare const getUser: import(\"convex/server\").RegisteredQuery<\"public\", {}, Promise<{ _id: import(\"convex/values\").GenericId<\"users\">; _creationTime: number; email: string; name: string; }>>;"
          ]
  let actionContents = [("myActions", actionContent)]

  result <- Parser.parseProjectFromContents schemaContent apiFileContent actionContents
  case result of
    Left err -> assertFailure ("Parser failed: " ++ show err)
    Right project ->
      let expected =
            [ Action.ConvexFunction
                { Action.funcName = "getUser",
                  Action.funcPath = "myActions",
                  Action.funcType = Action.Query,
                  Action.funcArgs = [],
                  Action.funcReturn = Schema.VReference "UsersDoc"
                }
            ]
       in Parser.ppFunctions project @?= expected