From e9c90d0a96ac6da8e2f6909484d51c2c852c8e5c Mon Sep 17 00:00:00 2001 From: Rory Campbell Date: Thu, 14 Sep 2023 14:35:25 +0100 Subject: [PATCH] move codegen tests --- .github/workflows/ci.yml | 2 + .../schema/test/Data/GraphQL/ParseFull0.purs | 163 +++++++ .../schema/test/Data/GraphQL/ParseFull1.purs | 92 ++++ .../schema/test/Data/GraphQL/ParseFull2.purs | 358 ++++++++++++++++ .../schema/test/Data/GraphQL/ParseFull3.purs | 70 +++ .../test/Data/GraphQL/ParseSadistic0.purs | 19 + .../test/Data/GraphQL/ParseSadistic1.purs | 145 +++++++ .../schema/test/Data/GraphQL/ParseSimple.purs | 126 ++++++ .../Data/GraphQL/RetrieveStringTypes.purs | 403 ++++++++++++++++++ package.json | 3 +- 10 files changed, 1380 insertions(+), 1 deletion(-) create mode 100644 codegen/schema/test/Data/GraphQL/ParseFull0.purs create mode 100644 codegen/schema/test/Data/GraphQL/ParseFull1.purs create mode 100644 codegen/schema/test/Data/GraphQL/ParseFull2.purs create mode 100644 codegen/schema/test/Data/GraphQL/ParseFull3.purs create mode 100644 codegen/schema/test/Data/GraphQL/ParseSadistic0.purs create mode 100644 codegen/schema/test/Data/GraphQL/ParseSadistic1.purs create mode 100644 codegen/schema/test/Data/GraphQL/ParseSimple.purs create mode 100644 codegen/schema/test/Data/GraphQL/RetrieveStringTypes.purs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 177d3bf0..a2611f0d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,8 @@ jobs: path: | .spago output + codegen/schema/.spago + codegen/schema/output examples/1-simple/.spago examples/1-simple/output examples/2-codegen/.spago diff --git a/codegen/schema/test/Data/GraphQL/ParseFull0.purs b/codegen/schema/test/Data/GraphQL/ParseFull0.purs new file mode 100644 index 00000000..eb589b69 --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/ParseFull0.purs @@ -0,0 +1,163 @@ +module Test.Data.GraphQL.ParseFull0 where + +import Prelude + +import Data.Either (either) +import Data.GraphQL.AST as AST +import Data.GraphQL.Parser as GP +import Data.Lens (class Wander) +import Data.Lens as L +import Data.Lens.Index as LI +import Data.Lens.Record as LR +import Data.List (List, length) +import Data.Maybe (Maybe(..), maybe) +import Data.Profunctor.Choice (class Choice) +import Type.Proxy (Proxy(..)) +import Data.Tuple (uncurry) +import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Effect.Exception (throw) +import Test.Spec (Spec, before, describe, it) +import Test.Spec.Assertions (shouldEqual, fail) +import Parsing (runParser) + +parseDocument ∷ String → Aff (AST.Document) +parseDocument t = liftEffect (either (throw <<< show) pure (runParser t GP.document)) + +schema = + """type Tweet { + id: ID! + # The tweet text. No more than 140 characters! + body: String + # When the tweet was published + date: Date + # Who published the tweet + Author: User + # Views, retweets, likes, etc + Stats: Stat +} + +type User { + id: ID! + username: String + first_name: String + last_name: String + full_name: String + name: String @deprecated + avatar_url: Url +} + +type Stat { + views: Int + likes: Int + retweets: Int + responses: Int +} + +type Notification { + id: ID + date: Date + type: String +} + +type Meta { + count: Int +} + +scalar Url +scalar Date + +type Query { + Tweet(id: ID!): Tweet + Tweets(limit: Int, skip: Int, sort_field: String, sort_order: String): [Tweet] + TweetsMeta: Meta + User(id: ID!): User + Notifications(limit: Int): [Notification] + NotificationsMeta: Meta +} + +type Mutation { + createTweet ( + body: String + ): Tweet + deleteTweet(id: ID!): Tweet + markTweetRead(id: ID!): Boolean +}""" ∷ + String + +lensToTweetObjectTypeDefinition ∷ ∀ m. Choice m ⇒ Wander m ⇒ m AST.ObjectTypeDefinition AST.ObjectTypeDefinition → m AST.Document AST.Document +lensToTweetObjectTypeDefinition = + ( uncurry L.prism' AST._Document + <<< LI.ix 0 + <<< uncurry L.prism' AST._Definition_TypeSystemDefinition + <<< uncurry L.prism' AST._TypeSystemDefinition_TypeDefinition + <<< uncurry L.prism' AST._TypeDefinition_ObjectTypeDefinition + ) + +getTweetName ∷ AST.Document → Maybe String +getTweetName = + L.preview + $ ( lensToTweetObjectTypeDefinition + <<< uncurry L.prism' AST._ObjectTypeDefinition + <<< LR.prop (Proxy ∷ Proxy "name") + ) + +getTweetFieldDefinitionList ∷ AST.Document → Maybe (List AST.FieldDefinition) +getTweetFieldDefinitionList = + L.preview + $ ( lensToTweetObjectTypeDefinition + <<< uncurry L.prism' AST._ObjectTypeDefinition + <<< LR.prop (Proxy ∷ Proxy "fieldsDefinition") + <<< L._Just + <<< uncurry L.prism' AST._FieldsDefinition + ) + +getTweetIdArgName ∷ AST.Document → Maybe String +getTweetIdArgName = + L.preview + $ ( lensToTweetObjectTypeDefinition + <<< uncurry L.prism' AST._ObjectTypeDefinition + <<< LR.prop (Proxy ∷ Proxy "fieldsDefinition") + <<< L._Just + <<< uncurry L.prism' AST._FieldsDefinition + <<< LI.ix 0 + <<< uncurry L.prism' AST._FieldDefinition + <<< LR.prop (Proxy ∷ Proxy "name") + ) + +lensToUserObjectTypeDefinition ∷ ∀ m. Choice m ⇒ Wander m ⇒ m AST.ObjectTypeDefinition AST.ObjectTypeDefinition → m AST.Document AST.Document +lensToUserObjectTypeDefinition = + ( uncurry L.prism' AST._Document + <<< LI.ix 1 + <<< uncurry L.prism' AST._Definition_TypeSystemDefinition + <<< uncurry L.prism' AST._TypeSystemDefinition_TypeDefinition + <<< uncurry L.prism' AST._TypeDefinition_ObjectTypeDefinition + ) + +getUserFieldDefinitionList ∷ AST.Document → Maybe (List AST.FieldDefinition) +getUserFieldDefinitionList = + L.preview + $ ( lensToUserObjectTypeDefinition + <<< uncurry L.prism' AST._ObjectTypeDefinition + <<< LR.prop (Proxy ∷ Proxy "fieldsDefinition") + <<< L._Just + <<< uncurry L.prism' AST._FieldsDefinition + ) + +spec ∷ Spec Unit +spec = + describe "test full doc" do + before (parseDocument schema) + $ do + it "should parse name of Tweet correctly" \doc → do + getTweetName doc `shouldEqual` Just "Tweet" + it "should have the right number of definitions in the Tweet type" \doc → do + let + fieldlist = getTweetFieldDefinitionList doc + maybe (fail "List should not be empty") (shouldEqual 5 <<< length) fieldlist + it "should parse name of Tweet.id correctly" \doc → do + getTweetIdArgName doc `shouldEqual` Just "id" + it "should have the right number of definitions in the User type" \doc → do + let + fieldlist = getUserFieldDefinitionList doc + maybe (fail "List should not be empty") (shouldEqual 7 <<< length) fieldlist diff --git a/codegen/schema/test/Data/GraphQL/ParseFull1.purs b/codegen/schema/test/Data/GraphQL/ParseFull1.purs new file mode 100644 index 00000000..16965f27 --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/ParseFull1.purs @@ -0,0 +1,92 @@ +module Data.GraphQL.ParseFull1.Test where + +import Prelude + +import Data.Either (either) +import Data.GraphQL.AST (ObjectValue(..)) +import Data.GraphQL.AST as AST +import Data.GraphQL.Parser as GP +import Data.Lens (class Wander, _Just) +import Data.Lens as L +import Data.Lens.Index as LI +import Data.Lens.Record as LR +import Data.List (singleton) +import Data.Maybe (Maybe(..)) +import Data.Profunctor.Choice (class Choice) +import Type.Proxy (Proxy(..)) +import Data.Tuple (uncurry) +import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Effect.Exception (throw) +import Test.Spec (Spec, before, describe, it) +import Test.Spec.Assertions (shouldEqual) +import Parsing (runParser) + +parseDocument ∷ String → Aff (AST.Document) +parseDocument t = liftEffect (either (throw <<< show) pure (runParser t GP.document)) + +query = + """query($id: ID!) { + id + user(id: $id, name: { equals: "bob" }, foo: "bar") { + name + } + } + +mutation MyMutation { + id # then an inline fragment + ... on User { + friends { + count + } + } +} + +# tah dah! +""" ∷ + String + +lensToQueryDefinition ∷ ∀ m. Choice m ⇒ Wander m ⇒ m AST.OperationDefinition AST.OperationDefinition → m AST.Document AST.Document +lensToQueryDefinition = + ( uncurry L.prism' AST._Document + <<< LI.ix 0 + <<< uncurry L.prism' AST._Definition_ExecutableDefinition + <<< uncurry L.prism' AST._ExecutableDefinition_OperationDefinition + ) + +getFirstQueryVarDef ∷ AST.Document → Maybe AST.VariableDefinition +getFirstQueryVarDef = + L.preview + $ ( lensToQueryDefinition + <<< uncurry L.prism' AST._OperationDefinition_OperationType + <<< LR.prop (Proxy ∷ Proxy "variableDefinitions") + <<< L._Just + <<< uncurry L.prism' AST._VariableDefinitions + <<< LI.ix 0 + ) + +getNameDef ∷ AST.Document → Maybe AST.Argument +getNameDef = + L.preview + $ ( lensToQueryDefinition + <<< uncurry L.prism' AST._OperationDefinition_OperationType + <<< LR.prop (Proxy ∷ Proxy "selectionSet") + <<< uncurry L.prism' AST._SelectionSet + <<< LI.ix 1 + <<< uncurry L.prism' AST._Selection_Field + <<< uncurry L.prism' AST._Field + <<< LR.prop (Proxy ∷ Proxy "arguments") + <<< _Just + <<< uncurry L.prism' AST._Arguments + <<< LI.ix 1 + ) + +spec ∷ Spec Unit +spec = + describe "test full query" do + before (parseDocument query) + $ do + it "should parse $id:ID!" \doc → do + getFirstQueryVarDef doc `shouldEqual` (Just $ AST.VariableDefinition { variable: AST.Variable "id", type: AST.Type_NonNullType (AST.NonNullType_NamedType $ AST.NamedType "ID"), defaultValue: Nothing }) + it "should parse name:{equals:\"bob\"}" \doc → do + getNameDef doc `shouldEqual` (Just $ AST.Argument { name: "name", value: AST.Value_ObjectValue $ ObjectValue (singleton (AST.Argument { name: "equals", value: AST.Value_StringValue $ AST.StringValue "bob" })) }) diff --git a/codegen/schema/test/Data/GraphQL/ParseFull2.purs b/codegen/schema/test/Data/GraphQL/ParseFull2.purs new file mode 100644 index 00000000..37f3411a --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/ParseFull2.purs @@ -0,0 +1,358 @@ +module Test.Data.GraphQL.ParseFull2 where + +import Prelude +import Data.Either (either) +import Data.GraphQL.AST as AST +import Data.GraphQL.Parser as GP +import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Effect.Exception (throw) +import Test.Spec (SpecT, before, describe, it) +import Parsing (runParser) + +parseDocument ∷ String → Aff (AST.Document) +parseDocument t = liftEffect (either (throw <<< show) pure (runParser t GP.document)) + +-- uses a more full featured schema +-- in this case, the publically available code sandbox schema +query = + """ +schema { + query: RootQueryType + mutation: RootMutationType + subscription: RootSubscriptionType +} + +enum Authorization { + COMMENT + NONE + OWNER + READ + WRITE_CODE + WRITE_PROJECT +} + +type Bookmarked { + entity: BookmarkEntity + isBookmarked: Boolean +} + +union BookmarkEntity = Team | User + +input CodeReference { + anchor: Int! + code: String! + head: Int! + lastUpdatedAt: String! + path: String! +} + +type CodeReferenceMetadata { + anchor: Int! + code: String! + head: Int! + path: String! + sandboxId: String! +} + +type Collaborator { + authorization: Authorization! + id: ID! + lastSeenAt: DateTime + sandbox: Sandbox! + user: User! + warning: String +} + +type Collection { + id: ID + path: String! + sandboxes: [Sandbox!]! + team: Team + teamId: ID + user: User +} + +type Comment { + comments: [Comment!]! + content: String + id: ID! + insertedAt: NaiveDateTime! + isRead: Boolean! + isResolved: Boolean! + parentComment: Comment + references: [Reference!]! + replyCount: Int! + sandbox: Sandbox! + updatedAt: NaiveDateTime! + user: User! +} + +type CurrentUser { + bookmarkedTemplates: [Template!]! + collection(path: String!, teamId: ID): Collection + collections(teamId: ID): [Collection!]! + email: String! + firstName: String + id: ID! + lastName: String + notifications(limit: Int, orderBy: OrderBy, type: [String]): [Notification] + recentlyUsedTemplates: [Template!]! + sandboxes(limit: Int, orderBy: OrderBy, showDeleted: Boolean): [Sandbox!]! + team(id: ID!): Team + teams: [Team!]! + templates(showAll: Boolean, teamId: ID): [Template!]! + username: String! +} + +scalar DateTime + +enum Direction { + ASC + DESC +} + +type Git { + branch: String + commitSha: String + id: ID + path: String + repo: String + username: String +} + +type Invitation { + authorization: Authorization! + email: String + id: ID + sandbox: Sandbox! + token: String! +} + +scalar NaiveDateTime + +type Notification { + archived: Boolean! + data: String! + id: ID! + insertedAt: NaiveDateTime! + read: Boolean! + type: String! +} + +input OrderBy { + direction: Direction! + field: String! +} + +type Reference { + id: ID! + metadata: ReferenceMetadata! + resource: String! + type: String! +} + +union ReferenceMetadata = CodeReferenceMetadata + +type RootMutationType { + updateComment(commentId: ID!, content: String, sandboxId: ID!): Comment! + + archiveAllNotifications: User! + + markNotificationAsRead(notificationId: ID!): Notification! + + removeFromTeam(teamId: ID!, userId: ID!): Team! + + deleteSandboxes(sandboxIds: [ID!]!): [Sandbox!]! + + deleteCollection(path: String!, teamId: ID): [Collection!]! + + bookmarkTemplate(teamId: ID, templateId: ID!): Template + + setTeamName(name: String!, teamId: ID!): Team! + + acceptTeamInvitation(teamId: ID!): Team! + + setTeamDescription(description: String!, teamId: ID!): Team! + renameSandbox(id: ID!, title: String!): Sandbox! + unresolveComment(commentId: ID!, sandboxId: ID!): Comment! + resolveComment(commentId: ID!, sandboxId: ID!): Comment! + revokeSandboxInvitation(invitationId: ID!, sandboxId: ID!): Invitation! + + deleteComment(commentId: ID!, sandboxId: ID!): Comment! + createSandboxInvitation( + authorization: Authorization! + email: String! + sandboxId: ID! + ): Invitation! + + leaveTeam(teamId: ID!): String! + createComment( + codeReference: CodeReference + content: String! + id: ID + parentCommentId: ID + sandboxId: ID! + ): Comment! + + clearNotificationCount: User! + + addToCollection( + collectionPath: String! + sandboxIds: [ID]! + teamId: ID + ): Collection! + + addCollaborator( + authorization: Authorization! + sandboxId: ID! + username: String! + ): Collaborator! + changeSandboxInvitationAuthorization( + authorization: Authorization! + invitationId: ID! + sandboxId: ID! + ): Invitation! + setSandboxesPrivacy(privacy: Int, sandboxIds: [ID!]!): [Sandbox!]! + + markAllNotificationsAsRead: User! + + redeemTeamInviteToken(inviteToken: String!): Team! + + unmakeSandboxesTemplates(sandboxIds: [ID!]!): [Template!]! + + revokeTeamInvitation(teamId: ID!, userId: ID!): Team! + + createCollection(path: String!, teamId: ID): Collection! + + createTeam(name: String!): Team! + + makeSandboxesTemplates(sandboxIds: [ID!]!): [Template!]! + + renameCollection( + newPath: String! + newTeamId: ID + path: String! + teamId: ID + ): [Collection!]! + + changeCollaboratorAuthorization( + authorization: Authorization! + sandboxId: ID! + username: String! + ): Collaborator! + + inviteToTeamViaEmail(email: String!, teamId: ID!): String! + + unbookmarkTemplate(teamId: ID, templateId: ID!): Template + + archiveNotification(notificationId: ID!): Notification! + redeemSandboxInvitation(invitationToken: String!, sandboxId: ID!): Invitation! + permanentlyDeleteSandboxes(sandboxIds: [ID!]!): [Sandbox!]! + + inviteToTeam(teamId: ID!, username: String!): Team! + + rejectTeamInvitation(teamId: ID!): String! + + removeCollaborator(sandboxId: ID!, username: String!): Collaborator! +} + +type RootQueryType { + me: CurrentUser + + sandbox(sandboxId: ID!): Sandbox + + teamByToken(inviteToken: String!): Team +} + +type RootSubscriptionType { + collaboratorAdded(sandboxId: ID!): Collaborator! + collaboratorChanged(sandboxId: ID!): Collaborator! + collaboratorRemoved(sandboxId: ID!): Collaborator! + commentAdded(sandboxId: ID!): Comment! + commentChanged(sandboxId: ID!): Comment! + commentRemoved(sandboxId: ID!): Comment! + invitationChanged(sandboxId: ID!): Invitation! + invitationCreated(sandboxId: ID!): Invitation! + invitationRemoved(sandboxId: ID!): Invitation! + sandboxChanged(sandboxId: ID!): Sandbox! +} + +type Sandbox { + alias: String + author: User + authorization: Authorization! + collaborators: [Collaborator!]! + collection: Collection + comment(commentId: ID!): Comment + comments: [Comment!]! + + customTemplate: Template + description: String + forkCount: Int! + forkedTemplate: Template + + git: Git + id: ID! + insertedAt: String! + invitations: [Invitation!]! + likeCount: Int! + privacy: Int! + removedAt: String + screenshotOutdated: Boolean! + screenshotUrl: String + source: Source! + title: String + updatedAt: String! + viewCount: Int! +} + +type Source { + id: ID + template: String +} + +type Team { + bookmarkedTemplates: [Template!]! + collections: [Collection!]! + creatorId: ID + description: String + id: ID! + inviteToken: String! + invitees: [User!]! + name: String! + templates: [Template!]! + users: [User!]! +} + +type Template { + bookmarked: [Bookmarked] + color: String + description: String + iconUrl: String + id: ID + insertedAt: String + published: Boolean + sandbox: Sandbox + title: String + updatedAt: String +} + +type User { + avatarUrl: String! + firstName: String + id: ID! + lastName: String + name: String + username: String! +} +""" ∷ + String + +testCS ∷ ∀ m. Monad m ⇒ SpecT Aff Unit m Unit +testCS = + describe "test cs query" do + before (parseDocument query) + $ do + it "should parse" \_ → do + pure unit diff --git a/codegen/schema/test/Data/GraphQL/ParseFull3.purs b/codegen/schema/test/Data/GraphQL/ParseFull3.purs new file mode 100644 index 00000000..97d5d745 --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/ParseFull3.purs @@ -0,0 +1,70 @@ +module Test.Data.GraphQL.ParseFull3 where + +import Prelude +import Data.Either (either) +import Data.GraphQL.AST as AST +import Data.GraphQL.Parser as GP +import Data.Lens (class Wander, Prism', _2, _Just, preview, prism', toListOf, traversed) +import Data.Lens.Common (simple) +import Data.Lens.Iso.Newtype (_Newtype) +import Data.Lens.Record (prop) +import Data.List (List(..), length, (:)) +import Data.Maybe (Maybe(..)) +import Data.Profunctor.Choice (class Choice) +import Type.Proxy (Proxy(..)) +import Data.Tuple (Tuple(..), uncurry) +import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Effect.Exception (throw) +import Node.Encoding (Encoding(..)) +import Node.FS.Sync (readTextFile) +import Test.Spec (SpecT, before, describe, it) +import Test.Spec.Assertions (shouldEqual) +import Parsing (runParser) + +parseDocument :: String -> Aff AST.Document +parseDocument t = do + rtf <- liftEffect $ readTextFile UTF8 t + liftEffect (either (throw <<< show) pure (runParser rtf GP.document)) + +lensToObjectDefinitions ∷ ∀ m. Choice m ⇒ Wander m ⇒ m AST.ObjectTypeDefinition AST.ObjectTypeDefinition → m AST.Document AST.Document +lensToObjectDefinitions = + ( uncurry prism' AST._Document + <<< traversed + <<< uncurry prism' AST._Definition_TypeSystemDefinition + <<< uncurry prism' AST._TypeSystemDefinition_TypeDefinition + <<< uncurry prism' AST._TypeDefinition_ObjectTypeDefinition + ) + +peel :: forall a. Prism' (List a) (Tuple a (List a)) +peel = + prism' (\(Tuple f s) -> (Cons f s)) + ( \l -> case l of + Nil -> Nothing + (Cons a b) -> Just $ Tuple a b + ) + +testSwapi ∷ ∀ m. Monad m ⇒ SpecT Aff Unit m Unit +testSwapi = + describe "test swapi" do + before (parseDocument "schemas/swapi.graphql") + $ do + -- 52 was confirmed by a quick n' dirty parsing of the document in python + it "should get 52 type definitions" \doc → do + (length (toListOf lensToObjectDefinitions doc)) `shouldEqual` 52 + it "should hvae a type Film that implements an interface called Node" \doc → do + preview + ( simple _Newtype + <<< peel + <<< _2 + <<< traversed + <<< uncurry prism' AST._Definition_TypeSystemDefinition + <<< uncurry prism' AST._TypeSystemDefinition_TypeDefinition + <<< uncurry prism' AST._TypeDefinition_ObjectTypeDefinition + <<< simple _Newtype + <<< (prop (Proxy :: Proxy "implementsInterfaces")) + <<< _Just + ) + doc + `shouldEqual` + Just (AST.ImplementsInterfaces (AST.NamedType "Node" : Nil)) diff --git a/codegen/schema/test/Data/GraphQL/ParseSadistic0.purs b/codegen/schema/test/Data/GraphQL/ParseSadistic0.purs new file mode 100644 index 00000000..ad397ee1 --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/ParseSadistic0.purs @@ -0,0 +1,19 @@ +module Test.Data.GraphQL.ParseSadistic0 where + +import Prelude + +import Data.Either (either) +import Data.GraphQL.Parser as GP +import Test.Spec (Spec, describe, it) +import Test.Spec.Assertions (shouldEqual, fail) +import Parsing (runParser) + +query = + """{ Z999999 : Z999 @Z99 ( Z9999999 : "뾞" Z9 : "펕ㅻ" Z9__ : $Z9999 ) @Z ( Z9 : true Z9999999 : null Z999 : $Z99999 Z99 : null Z9999999 : [ false null "㋶ꔠ艄翗" ] ) @Z9 ( Z999 : { Z9 : false Z9 : { Z9999 : null Z9999 : 233568 } Z999_9 : null Z999 : null Z9999 : true Z999 : false } ) @Z9 @Z99999 ( Z99 : 0.4079264874606982 Z9999999 : "" Z99 : $Z999999 Z9 : [ null 0.28475046823022443 ] Z9999 : { Z9 : "Z9" Z9 : 865238 Z999999 : "Z9999" Z99999 : "Z99" Z9 : 0.20705605773583802 } Z9999 : null ) @Z99999 ( Z9999999 : { Z9 : [ "" [ -679623 $Z ] { Z : null } "" ] Z9 : [ 0.972630813239436 ] } Z999 : -136147 Z9999999 : "嵉즹篙릏" Z9999 : 0.2963733232097576 Z99 : { Z9 : "晃캂ㄼ踛" Z : null Z : [ ] Z : -903096 Z99999 : 0.8035609935426903 } ) @_9 { Z99999 ( ) { Z9_9 : Z999 ( Z9999 : null Z9 : "㔉揆" Z999 : "" Z9 : $Z ) { Z99 : Z9 { } ... Z @Z99 @Z ( Z9 : true ) } ... { Z99 ( Z : null ) @Z99 ( Z9 : [ ] ) { } } ... on Z999 { ... Z99 } ... Z @Z99 ( Z99 : false Z99 : "" Z9 : null ) } Z9 : Z ( Z99 : "Z" Z99 : "Z" Z999_99 : null Z9 : false Z999 : -847508 Z999999 : false ) ... on Z999999 @Z99999 { ... on Z9 { Z99 ( Z99 : "Z" ) @Z @Z9 ( ) } ... Z9999 } } ... on Z99999 { ... Z99 @Z999 ( Z : 0.575622919749293 Z : null Z99 : { Z9999 : false Z99 : 0.43402963291575647 } Z9 : "Z" ) @Z999999 ( Z999 : 165296 Z99999 : true Z999 : "Z_99" Z9 : 0.9520399700626917 Z9999 : "서" ) @Z @Z9999 @Z9999 ( Z99 : "" Z99 : null Z99999 : [ { } 0.18022870699885707 true ] ) ... on Z @Z999999 @Z ( Z99 : "氭蓵臨" Z9 : "Z999" Z9999 : false Z999 : null ) @Z9999 ( Z99999 : [ "Z9" ] Z999999 : [ 0.23149938286817603 $Z99 [ "" null ] 0.21311289361357358 ] Z9999 : "Z" Z9 : $Z999 Z_99 : [ -793239 "Z" ] ) { Z : Z9 ( Z99 : "Z99" Z99 : null Z9999 : null ) @Z99_9 @Z99 ( Z999 : $Z99 Z : { Z9 : [ ] } Z99_9 : 0.41953172274843403 Z9999 : "Z9" ) { ... Z99 @Z9 ( ) Z9 : Z ( Z9 : 0.836182736715387 ) { } } } Z9999 @Z99999 ( Z999 : "Z9" Z99 : "Z9999" Z99999 : { Z999 : $Z9 Z9999 : "읒" Z9 : true Z9 : [ ] } Z : null Z99999 : $Z_99 ) @Z9 Z : Z ( Z99999 : { Z9999 : "᫃" Z : true Z : null } Z9 : true ) @Z99999 ( Z999999 : true Z : { Z : null Z9 : true Z999 : -969889 Z9 : $Z99 } Z9999 : { } _999 : "Z9" Z9 : { } Z99 : [ { Z9 : { } Z99 : [ ] } { } $Z ] ) { } ... on Z999999 @Z9 ( Z9 : $Z9999 Z_9 : [ true null ] Z9999 : "姖\\29" Z999 : "Z9999" ) @Z999 ( Z : 0.46380479469141217 Z99 : { Z : 166956 Z9 : null } Z99999 : { Z9 : null Z_999 : [ false ] Z : null } ) @Z999 ( Z9999 : "" Z999999 : "Z999" Z99 : { } ) @Z_99999 ( Z99 : $Z99 Z999 : 0.4802650699765724 ) @Z999 ( Z : { } Z9 : 514626 Z99999 : 0.10744267660539722 Z999 : null ) { } ... Z999 } ... Z9999999_ @_999999 @Z9 ( Z99999 : 0.9729139124848479 Z999999 : { Z9_99 : -631801 Z99 : [ ] Z999 : [ 0.6842147087139145 ] Z999999 : { Z9 : [ ] Z999 : { Z99 : null Z99 : "" } Z9999 : 0.5500629849499384 _99 : 0.17829077931972723 } Z999 : 0.41082164990288284 } Z99 : null ) @Z ( ) @Z999999 ( ) @Z9999999 ( Z999 : $Z999 Z : $Z9999 Z99999999 : 0.6118729406091724 Z99 : null Z : true Z : "Z999" ) @Z99 ( Z99 : "㵀ꔱ瞎뎔" Z9999999 : null ) ... Z9 @Z9 @Z99999 ( Z99999999 : null Z99 : { } Z999 : null Z : true ) @Z9 ( Z : true Z99 : "Z" Z9999 : 0.2192597427495102 Z9 : "Z999999" Z99999999 : 428559 Z99999 : false Z : 0.8863087859406642 Z : null ) @Z999999 ( Z : [ { _99 : [ ] Z9 : null } ] ) @Z99999999 @Z9999 @Z9999 ( Z9 : [ false 0.5977931714606439 ] Z999999 : 0.8410291014430249 Z : 869668 Z : [ "㙈齆" null 0.720802083947138 { Z_9 : "Z" } [ 483499 0.31544311219614146 ] ] Z999 : 755759 Z : false Z99999 : $Z Z : "�尓෪" ) ... @Z @Z9 ( Z99 : null Z9999999 : { } Z99999 : "慒╏" Z_ : "㠁䢦唕ﱗ" ) @_9999 ( Z9999 : "�ꚳⷚ" Z9999 : { Z999 : false Z999999 : null Z99 : null } ) @Z99999999 ( Z : $Z9 Z : "蚦喙脝⯞Ꟍ" Z9999999 : null Z : [ [ 0.8266237912823556 0.07284331837335756 ] true ] Z : "≴્" ) @Z99 ( Z99 : $Z Z99 : "䤷䞣" ) @Z99999999 { ... @Z9 ( ) { ... on Z99 @Z99 ( Z9999 : "Z99" ) { ... on Z99 { } ... on Z { } } ... Z ... on Z99 @Z9999 ( ) @Z9999 ( Z9999 : -498148 Z9999 : "" Z9 : $Z9 Z99 : $Z99 ) { Z9 : Z { } } } Z @Z99999 ( Z9_ : "Z999" Z999 : 0.31384074935402756 Z9999 : false Z999 : { Z9999 : "" Z99 : true Z99 : false Z : null } Z : -390163 ) @Z9 @Z9999 { ... Z9 @Z9999 ( Z_99 : null Z999 : "鹖뇈" ) @Z9 ( Z9999 : -528751 Z99 : { Z9 : 933454 Z9 : true } ) } ... on Z999 @Z99999 ( Z99999 : "Z999" Z9999 : "㾠摙㖚" Z999999 : "᭾髜믬ࠑ" Z999999 : 0.6020648617307026 Z99 : { Z : { Z9 : true Z9 : null } Z999 : 684254 Z99 : true } Z99 : { Z999 : { Z9 : -34080 Z9 : [ ] } Z : { Z9 : true Z99 : [ ] } Z9 : [ 0.6264860819217218 ] } ) @Z ( ) { } ... on Z9 @Z9 ( ) @Z99999 ( ) @Z ( ) { ... Z9999 ... @Z999 ( Z9999 : "馧ꦕ" ) @Z { ... on Z { } } Z99 : Z @Z99 ( Z999_ : { Z9 : { } Z9 : "Z" } Z : $Z ) @Z999 ( Z9999 : 0.1402587514092488 Z9999 : true Z9 : $Z99 Z99 : false ) @Z9999 ( Z9999 : $Z99 Z999 : 0.4145121771909819 ) @Z9 ( ) { Z99 : Z9 ( Z9 : $Z ) { } ... { } } } ... Z9999 @Z99 @Z99 ( ) } }""" ∷ + String + +spec ∷ Spec Unit +spec = + describe "test complicated query 0" do + it "should parse" do + either (\s -> fail $ "Bad :: " <> (show s)) (\_ -> 1 `shouldEqual` 1) $ runParser query GP.selectionSet diff --git a/codegen/schema/test/Data/GraphQL/ParseSadistic1.purs b/codegen/schema/test/Data/GraphQL/ParseSadistic1.purs new file mode 100644 index 00000000..b039213e --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/ParseSadistic1.purs @@ -0,0 +1,145 @@ +module Test.Data.GraphQL.ParseSadistic1 where + +import Prelude +import Data.Either (either) +import Data.GraphQL.Parser as GP +import Test.Spec (Spec, describe, it) +import Test.Spec.Assertions (shouldEqual, fail) +import Parsing (runParser) + +query = + """subscription Z9 + @Z999999 ( Z999 : null Z9999999 : [ -316139 "Z99" "훞穼邏" ] Z : "썽싸䍵궝쁀둞㰰霽" Z99 : "Z99" Z99999 : [ null "Z99" ] Z999999 : 0.6970254749511487 Z999999 : "Z" Z999999_99_ : "襱" ) + @Z99999999 + @Z ( Z999 : { Z99999 : -94473 Z99999_99 : "䄀" Z : 0.9285909761342178 Z9999 : { Z99 : null Z99 : "ᯇ" Z999999 : null Z99 : 0.6531501722769579 } Z9 : 0.31265580342740557 Z99999 : "Z9" Z : [ { Z9999 : { Z99 : -904667 } Z9 : "Z9" Z999 : "Z" } { Z99 : { } Z99 : "Z" Z9999 : true Z9999 : [ ] } [ ] ] } Z9999999 : -546049 Z999999999 : 0.7844195267113017 Z99 : 0.957635213601233 Z : { Z99999 : "Z9" Z : true } Z99999 : true ) + @Z999999999 ( Z999_ : -365466 Z9999 : false Z9 : null ) + @Z ( Z9_ : $Z Z9999999999 : false Z9999 : { Z999999 : 0.8104727113668214 Z99 : $Z999 Z : "" Z99 : [ 539745 0.6616102953728337 "Z9" 0.6331723838267719 ] Z99999999 : "Z9" Z999999 : $Z99 Z9999_999 : 0.8580171735296106 Z99999 : 0.7592082097005137 } ) + { + ... on Z9999999 @Z_99 @Z99999 @Z9999 ( ) { + Z9999 ( + Z999 : "Z" Z9 : 0.10320645854957702 Z9_ : false Z9 : [ [ ] 860094 $Z9 709381 ] Z99_ : false Z : 731488 + ) + @Z999 + @Z999 ( Z999 : false Z999 : [ [ true ] [ ] ] ) + @Z99_99 + @Z999999 ( Z999999 : { } ) + @Z9 ( Z99 : null _999 : null Z999999 : "Z999" Z9999 : -596390 Z : { Z9 : "Z99" } ) + @Z999 { + Z9999 : Z9 + @Z ( ) + @Z99 ( ) + @Z99 ( Z9 : 0.7338208252255902 Z : "Z99" Z9999 : -188362 Z : { Z99 : $Z Z : { } } ) + @Z99 ( Z9 : "졁" ) + } + ... on Z99 @Z99 ( Z : true Z99 : null Z999 : "Z" Z : false Z99 : false Z999_ : "Z9999" ) @Z9 ( Z9999 : $Z9999 Z99 : true ) { + Z : Z9 ( ) + @Z9999 { } + Z : Z9999 @Z9999 ( Z999 : { Z9 : "" } ) @Z99 ( ) @Z99 { + Z : Z ( Z9 : -258508 ) @Z99 ( Z9 : "Z" ) @Z99 ( Z99 : "Z" Z : "" ) + } + ... on Z { + ... Z9 @Z ( ) @Z99 + } + } + Z99999 : Z99999 ( Z9999 : -143301 Z : 0.22076653699426285 _999999 : [ "覐" 0.6037301070074226 "퐢᛽" ] ) + @Z + @Z99 ( Z999999 : { Z999 : "弿" Z99 : $Z99 } Z9999 : "21" Z9 : false ) + @Z999 ( Z99 : [ $Z99 { } ] Z9 : { Z999 : { } } Z : false Z99999 : 0.2387966086337327 ) { + ... on Z9999 @Z9 @Z99 { + ... on Z { } + ... on Z99 { } + } + ... Z9999 + Z9 : Z99 ( Z9999 : null Z : null Z : $Z99 ) @Z ( Z9 : null Z9999 : [ ] Z : [ ] Z999 : "㞱" ) { + Z9 : Z9 ( Z : [ ] Z9 : -632631 ) + ... on Z99 @Z99 ( ) { } + } + } + Z : Z999999 ( Z999999 : { Z9 : { Z : 860237 Z9 : null } Z : { Z99 : $Z } Z9999 : $Z99 Z99 : 225060 } Z : "啂" Z_9_ : null Z9 : 0.14897621010848144 Z999 : 0.1890953291156773 Z99 : 0.8565692956822781 ) { + ... @Z9 ( Z9 : $Z9 Z : "Z9" Z9 : $Z9 ) { } + } + Z : Z99999 ( Z99_9 : [ [ null ] -367293 true ] Z99 : [ ] ) @Z9 ( ) @Z9 @Z9999 ( ) @Z99 ( Z9999 : 0.2680879115444086 Z9999 : "" Z99999 : $Z999 Z99999 : "敿䧢" Z9 : null ) @Z999 ( ) @Z99 { } + } + ... Z + ... on Z @Z99999999 ( Z : 941586 Z99 : "煤玗娍嵡" Z999999 : "੸귬ᎋ喚" Z999 : [ { } ] Z9999999_ : -482652 _999 : false ) @Z999999 ( Z : [ "Z99" { Z9999 : 192167 Z9 : 0.18517909254188608 } null "菈諛氰㬾" null ] _999 : "Z99" Z99999 : "䦶녟" Z9 : [ null false null 931529 ] Z : $Z9999 Z99999999 : "Z999" Z99 : $Z9999 ) @Z9999999 ( Z99999 : 0.6006248381923068 Z99999999 : 521547 Z9_ : $Z999 Z9999999 : 0.29000867264811353 Z9999_ : $Z9 Z9 : $Z Z9999 : $Z99999 ) @Z9999999 @Z99 ( Z_999 : 0.12508951179920208 Z9 : 754981 Z99999 : [ "" null ] Z99 : [ "Z" ] Z9 : -566495 Z99999 : false Z99 : $Z999999 ) @Z99 ( Z : 0.9038422549626987 Z999999 : "Z999" ) @Z999999 { + ... Z99999 @Z999999 ( Z9 : null Z99 : $Z9999 Z99999 : { Z9 : true Z999 : null Z : true } Z : [ true "Z" $Z "Z99" ] Z999 : null ) @Z999999 @Z99 ( Z99 : null Z99 : 307247 ) @Z9999 ( Z9999 : [ ] Z9 : { Z : $Z Z9999 : 0.6548896765591994 Z : 0.5681797385067585 } ) @Z99_ ( Z99_ : 0.9858854231358903 Z999999 : 0.7869455887875266 Z99 : -543541 Z99999 : "惘⋶" Z999999 : $Z9 Z99999 : true ) @Z999 + Z9 : Z99 + ... on Z999999 @Z999 @_ ( Z999 : null Z999999 : { } Z99 : "ڲ傚" ) @Z9999 ( Z9999 : $Z99 Z9999 : null _999999 : $Z Z9999 : 0.962995012273544 ) @Z @Z @Z99 ( Z999 : $Z999 ) { + ... @Z9 ( Z9 : -162027 Z : 87117 ) @Z9999 @Z9999 { + ... on Z9 @_ ( Z99 : null ) { } + } + ... on Z99 @Z9999 @Z99 ( Z9_ : { Z : false Z9 : "Z" } _99 : { Z : true } Z : "⥾" ) @Z9 ( Z9999 : 0.12686475046298687 Z9 : { } Z9 : -403741 Z99 : "Z" ) @Z9 { } + } + ... Z999999 + ... on Z999 @Z9999 ( Z99999 : null Z99999 : "Z9" Z9999 : { } Z99999 : 364895 Z9999 : 0.6416477098323627 _ : 688494 ) @Z999 ( Z999 : null Z99 : "_9999" Z9 : null Z9999 : true ) @Z999 ( ) @Z9 { + ... Z9 + ... Z999 + Z9999 : Z ( Z9999 : "Z9" Z_999 : $Z9 Z99 : { } ) @Z999 ( Z999 : $Z9 ) @Z_999 ( Z99 : false Z99 : true Z9999 : 0.09627152983856925 ) + } + ... on _99999 @Z999 ( Z999 : true Z9 : "Z99" Z9 : true ) @Z99999 ( Z999999 : $Z Z999 : "Z9999" Z999999 : $Z Z99999 : -840413 ) { + ... on Z99 @Z9999 @Z99 ( Z9 : -708802 Z999 : [ "_" null ] ) { } + ... on Z9 @Z9999 @Z ( Z : "Z" ) { + ... Z @Z99 ( Z : null ) } + ... on Z99 @Z9 ( Z9 : { } ) @Z999_ ( Z99 : "" Z9999 : null ) { + ... Z @Z ( ) @Z + ... on Z { } + } + ... Z999 @Z999 ( Z9 : { } _99 : $Z9 ) @Z99 ( Z999 : "Z" Z999 : -500999 Z : "" Z9999 : null ) @Z99 ( ) + } + } + Z : Z99999 ( Z9_9999 : "Z999999" Z9 : $Z Z999 : 0.11665303731181334 Z9999_99 : "Z99999" Z99 : -750338 ) { + ... { + Z9999 : Z { + Z99 : Z9 ( ) { } + } + ... _99 @Z @Z ( _99 : 0.6718788862563105 Z999 : $Z9 Z99 : 0.7575586655910865 ) + } Z9999 : Z999999 ( ) { + ... Z999 @Z9999 ( Z9999 : $Z99 Z99 : true Z9 : 0.48285015229268474 ) @Z999 ( Z9999 : "Z9" Z9999 : { } Z9999 : "暣灱" ) + ... on Z9999 { + ... Z9 @Z9 ( ) + } + ... Z9 @Z999 ( Z99 : "Z9" Z : "Z" Z : null ) @Z ( ) @Z99 @Z9999 ( Z9999 : $Z ) + Z999 : Z9 ( Z999 : null Z9999 : -628795 ) @Z9 ( Z9 : "Z9" Z99 : 0.4020341697158451 Z9999 : 0.5898340868716286 Z : 619530 ) @Z99 @Z99 ( Z : "Z99" Z999 : true ) { + ... Z9 @Z99 ( Z : $Z ) + } + } + ... Z99999 @Z999999 ( Z9 : $Z99 Z : "" ) @Z999 ( Z99 : "癚觤乕" Z999 : "Z9999" Z9_99 : -639389 Z9 : 0.27601521661319545 Z99999 : [ $Z9 ] Z9999 : true ) @Z999 ( Z99999 : 205214 Z : { Z999 : $Z9 Z99 : "Z99" Z9_ : [ ] Z9 : false } Z : $Z99 Z9999 : null Z9999 : { } ) @Z999 @Z999999 ( Z9 : $Z99 Z999 : "Z999" Z9 : 474893 Z999 : false Z999 : $Z99 Z999 : [ [ ] [ "" 944657 ] false ] ) + Z9999 : Z999999 @Z99 ( Z99 : false ) { + Z99 : _9999 ( Z999 : "Z9" _ : "Z9" Z9 : 0.9802215378639388 Z99 : $Z99 ) @Z9999 ( ) @Z9 ( Z9999 : [ true "" ] ) @Z9999 @Z99 ( Z : { Z : null Z : $Z } ) { + ... Z9 @Z99 ( Z : [ ] Z99 : [ ] ) + } + ... Z9999 @Z ( Z9 : null Z : "Z99" Z9 : "ဴ" Z : true ) @Z999 ( Z : "Z" Z : [ true ] Z : 613573 Z9999 : -34473 ) + ... on Z99 @Z @Z9 ( Z : { Z99 : null Z9 : "" } Z_999 : { Z99 : null } Z : $Z Z9999 : { } ) @Z99 ( Z9999 : "" ) { + ... Z9 @Z99 ( Z9 : [ ] ) + } + } + Z99999 : Z999 ( ) @Z9 ( Z999 : "㟸ꔨ䧋" Z99 : 0.9806272187180013 Z99 : false Z999 : [ { Z99 : "Z" Z : [ ] } { } "㙂" [ false ] ] Z99999 : "仜⵺뱲" Z999999 : [ ] ) @Z9999 ( Z9 : null Z999999 : false Z99 : 0.8655353728055653 ) @Z999999 ( Z999999 : null Z999999 : null Z99999 : [ ] ) @Z ( Z99 : 939841 Z99999 : [ ] Z99999 : "暂ཱ�ᓠ" Z999999 : "痱⤶" Z99999 : { _999 : 0.9324696031084608 } ) @Z9999 ( ) Z9 : Z9 ( Z9999 : [ "Z9" "Z99" $Z $Z9 ] Z999999 : null ) @Z9999 ( Z9999 : { Z999 : false Z999 : true Z999 : [ null ] } Z99 : false Z9 : "朐" ) @Z9999 @_9999 ( Z : 710058 Z9999 : [ false ] Z99999 : "" Z99 : 25160 Z999999 : null ) @Z9 ( Z999 : $Z_9 Z999999 : { Z9999 : "Z" Z999 : $Z Z999 : $Z99 Z : "Z9" } Z99 : "Z99" ) } Z9999 : Z99999 ( Z999999 : null ) { + ... on Z99999 { + ... Z99 @Z ( Z999 : "ࣝ蠡" _ : "Z9" Z : { Z9 : -17117 Z9 : false } ) @Z9 @Z9 ( ) + } + ... on Z9 { } + ... on Z9 @Z ( Z9999 : { Z9 : $Z9 Z9 : $Z99 } Z : 0.19616120271205958 Z999 : 451109 Z_9999 : [ { Z9 : 0.5548451382456557 Z : false } "Z9" null "뫦혳" ] Z9 : "Z99" ) { + ... Z9 + ... { } + ... Z9999 @Z9999 + } + } + ... on Z9 @Z999 ( Z : null Z99999 : false Z99 : 0.003580871505467627 Z9999 : false Z9999999 : 0.8289355653472876 ) { + Z99 ( _9 : { Z : "Z" Z9999 : { Z99 : 26392 } Z9999 : 0.769245373443349 Z999 : null } Z999999 : [ $Z99 "갡" true $Z9 ] Z9 : 0.6299138104682387 ) + ... Z99999 @Z9 ( Z99999 : "" ) @Z999999 ( Z999 : "Z9999" Z999999 : 0.3073853930958479 Z999 : false Z99 : false ) @Z99999 ( ) @Z9 ( ) @Z99 ( Z999 : { Z9 : { Z : 554038 } Z999 : false Z999 : "ᒷ夓" } Z : $Z9 ) + ... Z @Z99 @Z99_ ( Z : -539668 ) @Z9999 ( Z99999 : "Z99" Z99999 : false Z : "ᣂ呾ꌹ⩖" Z : { Z99 : "Z9" Z9 : "Z99" Z9 : false Z9 : 886547 } ) @Z99999 + ... on Z99999 { + ... on Z99 { } + Z : Z99_9 + } + ... Z999 @Z9 @Z ( ) @Z ( _99999 : null Z999 : $Z99 ) @Z999 ( Z999 : -562940 ) + ... Z99 @Z ( Z999999 : "另" Z9 : [ false ] _9999 : 0.31369374055121735 Z9 : -848840 Z9999 : false ) @Z9 ( Z99 : "牀⹌" Z999999 : "좯" Z9 : "" ) + } + }""" ∷ + String + +spec ∷ Spec Unit +spec = + describe "test complicated query 1" do + it "should parse" do + either (\s -> fail $ "Bad :: " <> (show s)) (\_ -> 1 `shouldEqual` 1) $ runParser query GP.operationDefinition diff --git a/codegen/schema/test/Data/GraphQL/ParseSimple.purs b/codegen/schema/test/Data/GraphQL/ParseSimple.purs new file mode 100644 index 00000000..81b670c0 --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/ParseSimple.purs @@ -0,0 +1,126 @@ +module Test.Data.GraphQL.ParseSimple where + +import Prelude + +import Control.Monad.Error.Class (class MonadThrow) +import Data.Either (either) +import Data.GraphQL.AST as AST +import Data.GraphQL.Parser as GP +import Data.List (List(..), singleton, (:)) +import Data.Maybe (Maybe(..)) +import Data.String.CodeUnits (fromCharArray) +import Effect.Exception (Error) +import Test.Spec (Spec, describe, it) +import Test.Spec.Assertions (shouldEqual, fail) +import Parsing (runParser, Parser) + +parseSuccess ∷ ∀ t m. MonadThrow Error m ⇒ Show t ⇒ Eq t ⇒ Parser String t → String → t → m Unit +parseSuccess parser toparse tocomp = either (fail <<< show) (shouldEqual tocomp) (runParser toparse parser) + +spec ∷ Spec Unit +spec = + describe "test parser" do + describe "test tokens" do + it "should correctly parse comments" do + parseSuccess GP.comment "# abc" unit + parseSuccess GP.comment "#" unit + it "should correctly parse variables" do + parseSuccess GP.variable "$_x" (AST.Variable "_x") + it "should correctly parse integers" do + parseSuccess GP.intValue "42" (AST.IntValue 42) + parseSuccess GP.intValue "-42" (AST.IntValue (negate 42)) + it "should correctly parse numbers" do + parseSuccess GP.floatValue "3.1416" (AST.FloatValue 3.1416) + parseSuccess GP.floatValue "-0.1416e+3" (AST.FloatValue $ negate 0.1416e+3) + it "should correctly parse booleans" do + parseSuccess GP.booleanValue "true" (AST.BooleanValue true) + parseSuccess GP.booleanValue "false" (AST.BooleanValue false) + it "should correctly parse null" do + parseSuccess GP.nullValue "null" (AST.NullValue) + it "should correctly parse strings" do + parseSuccess GP.stringValue (fromCharArray [ '"', 'a', 'b', '\\', 'n', 'q', '"' ]) (AST.StringValue "ab\nq") + parseSuccess GP.stringValue (fromCharArray [ '"', 'a', 'b', '\\', 'u', '0', '0', '2', '1', 'q', '"' ]) (AST.StringValue "ab!q") + parseSuccess GP.stringValue (fromCharArray [ '"', '"', '"', 'a', 'b', '\\', 'n', 'q', '"', '"', '"' ]) (AST.StringValue """ab\nq""") + it "should correctly parse lists" do + parseSuccess (GP.listValue GP.value) "[]" (AST.ListValue (Nil)) + parseSuccess (GP.listValue GP.value) "[1]" (AST.ListValue (AST.Value_IntValue (AST.IntValue 1) : Nil)) + parseSuccess (GP.listValue GP.value) "[\n\n#hello\n\n]" (AST.ListValue (Nil)) + parseSuccess (GP.listValue GP.value) "[1 2]" (AST.ListValue (AST.Value_IntValue (AST.IntValue 1) : AST.Value_IntValue (AST.IntValue 2) : Nil)) + parseSuccess (GP.listValue GP.value) "[1 2 ]" (AST.ListValue (AST.Value_IntValue (AST.IntValue 1) : AST.Value_IntValue (AST.IntValue 2) : Nil)) + parseSuccess (GP.listValue GP.value) "[\t\t1 2 \t,, \"3\" ]" (AST.ListValue (AST.Value_IntValue (AST.IntValue 1) : AST.Value_IntValue (AST.IntValue 2) : AST.Value_StringValue (AST.StringValue "3") : Nil)) + parseSuccess (GP.listValue GP.value) "[1 2 \"3\"]" (AST.ListValue (AST.Value_IntValue (AST.IntValue 1) : AST.Value_IntValue (AST.IntValue 2) : AST.Value_StringValue (AST.StringValue "3") : Nil)) + it "should correctly parse objects" do + parseSuccess (GP.objectValue GP.value) "{}" (AST.ObjectValue (Nil)) + parseSuccess (GP.objectValue GP.value) "{foo: 1}" (AST.ObjectValue (AST.Argument { name: "foo", value: (AST.Value_IntValue $ AST.IntValue 1) } : Nil)) + parseSuccess (GP.objectValue GP.value) "{foo: $bar}" (AST.ObjectValue (AST.Argument { name: "foo", value: (AST.Value_Variable $ AST.Variable "bar") } : Nil)) + parseSuccess (GP.objectValue GP.value) "{foo: BAR}" (AST.ObjectValue (AST.Argument { name: "foo", value: (AST.Value_EnumValue $ AST.EnumValue "BAR") } : Nil)) + parseSuccess (GP.objectValue GP.value) "{foo: BAR, baz: \"hello\"}" (AST.ObjectValue (AST.Argument { name: "foo", value: (AST.Value_EnumValue $ AST.EnumValue "BAR") } : AST.Argument { name: "baz", value: (AST.Value_StringValue $ AST.StringValue "hello") } : Nil)) + parseSuccess (GP.objectValue GP.value) "{foo: BAR baz: \"hello\" \t}" (AST.ObjectValue (AST.Argument { name: "foo", value: (AST.Value_EnumValue $ AST.EnumValue "BAR") } : AST.Argument { name: "baz", value: (AST.Value_StringValue $ AST.StringValue "hello") } : Nil)) + describe "test field" do + it "should correctly parse simple field" do + parseSuccess (GP.field GP.selectionSet) "foo" (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) + parseSuccess (GP.field GP.selectionSet) "bar: foo" (AST.Field { alias: Just "bar", name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) + parseSuccess (GP.field GP.selectionSet) "bar:foo" (AST.Field { alias: Just "bar", name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) + parseSuccess (GP.field GP.selectionSet) "bar\t#\n:foo" (AST.Field { alias: Just "bar", name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) + describe "test selectionSet" do + it "should correctly parse selectionSet" do + parseSuccess GP.selectionSet "{ \n#sel\nfoo }" (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) : Nil)) + parseSuccess (GP.selection GP.selectionSet) "foo" (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) + parseSuccess GP.selectionSet "{foo}" (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) : Nil)) + parseSuccess GP.selectionSet "{ foo { foo {foo}#hello\n} }" (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Just (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Just (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) : Nil)) }) : Nil)) }) : Nil)) + parseSuccess GP.selectionSet "{ foo { foo {foo},,,#hello\n} }" (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Just (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Just (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) : Nil)) }) : Nil)) }) : Nil)) + parseSuccess GP.selectionSet "{foo { foo { foo } } }" (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Just (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Just (AST.SelectionSet (AST.Selection_Field (AST.Field { alias: Nothing, name: "foo", arguments: Nothing, directives: Nothing, selectionSet: Nothing }) : Nil)) }) : Nil)) }) : Nil)) + describe "test fieldDefinition" do + it "should parse a non-null field definition" do + parseSuccess GP.fieldDefinition "id: ID!" (AST.FieldDefinition { description: Nothing, name: "id", argumentsDefinition: Nothing, type: (AST.Type_NonNullType (AST.NonNullType_NamedType (AST.NamedType "ID"))), directives: Nothing }) + describe "test type" do + it "should parse a nullable type" do + parseSuccess GP._type "ID" (AST.Type_NamedType (AST.NamedType "ID")) + describe "test variable definition" do + it "should parse a variable definition" do + parseSuccess GP.variableDefinition "$id:ID!" (AST.VariableDefinition { variable: AST.Variable "id", type: AST.Type_NonNullType (AST.NonNullType_NamedType $ AST.NamedType "ID"), defaultValue: Nothing }) + describe "test list parser" do + it "should parse lists correctly" do + parseSuccess (GP.listish "{" "}" GP.name) "{id user }" $ ("id" : "user" : Nil) + describe "test parse an alias correclty" do + it "should parse a simple alias correctly" do + parseSuccess GP.alias "z3 :" "z3" + parseSuccess (GP.field GP.selectionSet) "z9: Z" $ AST.Field { alias: Just "z9", name: "Z", arguments: Nothing, directives: Nothing, selectionSet: Nothing } + parseSuccess (GP.selection GP.selectionSet) "z9: Z" (AST.Selection_Field (AST.Field { alias: Just "z9", name: "Z", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) + parseSuccess GP.selectionSet "{ z9: Z }" $ AST.SelectionSet (singleton (AST.Selection_Field (AST.Field { alias: Just "z9", name: "Z", arguments: Nothing, directives: Nothing, selectionSet: Nothing }))) + describe "should parse selection set correctly" do + it "should parse a selection set with multiple values" do + --parseSuccess GP.selectionSet "{ id user }" $ AST.SelectionSet ((AST.Selection_Field (AST.Field { alias: Nothing, name: "id", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) : (AST.Selection_Field (AST.Field { alias: Nothing, name: "user", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) : Nil) + ------------------------------------- + ----------- issue is that it is parsing the ignoreMe as part of the field + ----------- as it moves through + parseSuccess (GP._listish (GP.field GP.selectionSet)) "id user" $ (((AST.Field { alias: Nothing, name: "id", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) : ((AST.Field { alias: Nothing, name: "user", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) : Nil) + --parseSuccess (GP._listish (GP.selection GP.selectionSet)) "id user" $ ((AST.Selection_Field (AST.Field { alias: Nothing, name: "id", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) : (AST.Selection_Field (AST.Field { alias: Nothing, name: "user", arguments: Nothing, directives: Nothing, selectionSet: Nothing })) : Nil) + it "should parse a selection set with alias multiple values" do + parseSuccess GP.selectionSet "{ id {} a: user {} }" $ AST.SelectionSet ((AST.Selection_Field (AST.Field { alias: Nothing, name: "id", arguments: Nothing, directives: Nothing, selectionSet: Just $ AST.SelectionSet Nil })) : (AST.Selection_Field (AST.Field { alias: Just "a", name: "user", arguments: Nothing, directives: Nothing, selectionSet: Just $ AST.SelectionSet Nil })) : Nil) + describe "schema definition" do + it "should parse schema definition correctly" do + parseSuccess GP.typeSystemDefinition "schema { query: A\nmutation: B }" $ AST.TypeSystemDefinition_SchemaDefinition (AST.SchemaDefinition { directives: Nothing, rootOperationTypeDefinition: ((AST.RootOperationTypeDefinition { namedType: (AST.NamedType "A"), operationType: AST.Query }) : (AST.RootOperationTypeDefinition { namedType: (AST.NamedType "B"), operationType: AST.Mutation }) : Nil) }) + it "should parse schema definition when is document" do + parseSuccess GP.document " schema { query: A\nmutation: B }" $ AST.Document (AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_SchemaDefinition (AST.SchemaDefinition { directives: Nothing, rootOperationTypeDefinition: ((AST.RootOperationTypeDefinition { namedType: (AST.NamedType "A"), operationType: AST.Query }) : (AST.RootOperationTypeDefinition { namedType: (AST.NamedType "B"), operationType: AST.Mutation }) : Nil) })) : Nil) + describe "union definition" do + it "should parse union definition correctly" do + parseSuccess GP.unionTypeDefinition "union Foo = A | B" (AST.UnionTypeDefinition { description: Nothing, directives: Nothing, name: "Foo", unionMemberTypes: (Just (AST.UnionMemberTypes ((AST.NamedType "A") : (AST.NamedType "B") : Nil))) }) + it "should parse schunionema definition when is document" do + parseSuccess GP.document "union Foo = A | B \nunion Foo = A | B\nunion Foo = A | B" (AST.Document ((AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_TypeDefinition (AST.TypeDefinition_UnionTypeDefinition (AST.UnionTypeDefinition { description: Nothing, directives: Nothing, name: "Foo", unionMemberTypes: (Just (AST.UnionMemberTypes ((AST.NamedType "A") : (AST.NamedType "B") : Nil))) })))) : (AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_TypeDefinition (AST.TypeDefinition_UnionTypeDefinition (AST.UnionTypeDefinition { description: Nothing, directives: Nothing, name: "Foo", unionMemberTypes: (Just (AST.UnionMemberTypes ((AST.NamedType "A") : (AST.NamedType "B") : Nil))) })))) : (AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_TypeDefinition (AST.TypeDefinition_UnionTypeDefinition (AST.UnionTypeDefinition { description: Nothing, directives: Nothing, name: "Foo", unionMemberTypes: (Just (AST.UnionMemberTypes ((AST.NamedType "A") : (AST.NamedType "B") : Nil))) })))) : Nil)) + it "should parse union definition when is document and there is whitespace" do + parseSuccess GP.document " union Foo = A | B \nunion Foo = A | B\nunion Foo = A | B" (AST.Document ((AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_TypeDefinition (AST.TypeDefinition_UnionTypeDefinition (AST.UnionTypeDefinition { description: Nothing, directives: Nothing, name: "Foo", unionMemberTypes: (Just (AST.UnionMemberTypes ((AST.NamedType "A") : (AST.NamedType "B") : Nil))) })))) : (AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_TypeDefinition (AST.TypeDefinition_UnionTypeDefinition (AST.UnionTypeDefinition { description: Nothing, directives: Nothing, name: "Foo", unionMemberTypes: (Just (AST.UnionMemberTypes ((AST.NamedType "A") : (AST.NamedType "B") : Nil))) })))) : (AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_TypeDefinition (AST.TypeDefinition_UnionTypeDefinition (AST.UnionTypeDefinition { description: Nothing, directives: Nothing, name: "Foo", unionMemberTypes: (Just (AST.UnionMemberTypes ((AST.NamedType "A") : (AST.NamedType "B") : Nil))) })))) : Nil)) + describe "directive definition" do + it "should parse directive definition correctly" do + parseSuccess GP.directiveDefinition "directive @cacheControl(maxAge: Int, scope: CacheControlScope) on FIELD_DEFINITION | OBJECT | INTERFACE" (AST.DirectiveDefinition { argumentsDefinition: (Just (AST.ArgumentsDefinition ((AST.InputValueDefinition { defaultValue: Nothing, description: Nothing, directives: Nothing, name: "maxAge", type: (AST.Type_NamedType (AST.NamedType "Int")) }) : (AST.InputValueDefinition { defaultValue: Nothing, description: Nothing, directives: Nothing, name: "scope", type: (AST.Type_NamedType (AST.NamedType "CacheControlScope")) }) : Nil))), description: Nothing, directiveLocations: (AST.DirectiveLocations ((AST.DirectiveLocation_TypeSystemDirectiveLocation AST.FIELD_DEFINITION) : (AST.DirectiveLocation_TypeSystemDirectiveLocation AST.OBJECT) : (AST.DirectiveLocation_TypeSystemDirectiveLocation AST.INTERFACE) : Nil)), name: "cacheControl" }) + it "should parse directive definition followed by enum correctly" do + ( parseSuccess GP.document + """directive @cacheControl(maxAge: Int, scope: CacheControlScope) on FIELD_DEFINITION | OBJECT | INTERFACE + +enum CacheControlScope { + PUBLIC + PRIVATE +} +""" + (AST.Document ((AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_DirectiveDefinition (AST.DirectiveDefinition { argumentsDefinition: (Just (AST.ArgumentsDefinition ((AST.InputValueDefinition { defaultValue: Nothing, description: Nothing, directives: Nothing, name: "maxAge", type: (AST.Type_NamedType (AST.NamedType "Int")) }) : (AST.InputValueDefinition { defaultValue: Nothing, description: Nothing, directives: Nothing, name: "scope", type: (AST.Type_NamedType (AST.NamedType "CacheControlScope")) }) : Nil))), description: Nothing, directiveLocations: (AST.DirectiveLocations ((AST.DirectiveLocation_TypeSystemDirectiveLocation AST.FIELD_DEFINITION) : (AST.DirectiveLocation_TypeSystemDirectiveLocation AST.OBJECT) : (AST.DirectiveLocation_TypeSystemDirectiveLocation AST.INTERFACE) : Nil)), name: "cacheControl" })) : (AST.Definition_TypeSystemDefinition (AST.TypeSystemDefinition_TypeDefinition (AST.TypeDefinition_EnumTypeDefinition (AST.EnumTypeDefinition { description: Nothing, directives: Nothing, enumValuesDefinition: (Just (AST.EnumValuesDefinition ((AST.EnumValueDefinition { description: Nothing, directives: Nothing, enumValue: (AST.EnumValue "PUBLIC") }) : (AST.EnumValueDefinition { description: Nothing, directives: Nothing, enumValue: (AST.EnumValue "PRIVATE") }) : Nil))), name: "CacheControlScope" })))) : Nil))) + ) diff --git a/codegen/schema/test/Data/GraphQL/RetrieveStringTypes.purs b/codegen/schema/test/Data/GraphQL/RetrieveStringTypes.purs new file mode 100644 index 00000000..b5b187c0 --- /dev/null +++ b/codegen/schema/test/Data/GraphQL/RetrieveStringTypes.purs @@ -0,0 +1,403 @@ +module Test.Data.GraphQL.RetrieveStringTypes where + +import Prelude + +import Data.Either (either) +import Data.GraphQL.AST as AST +import Data.GraphQL.Parser as GP +import Data.Lens as L +import Data.Lens.Record as LR +import Data.List (List) +import Data.Set as Set +import Type.Proxy (Proxy(..)) +import Data.Tuple (uncurry) +import Effect.Aff (Aff) +import Effect.Class (liftEffect) +import Effect.Exception (throw) +import Test.Spec (Spec, before, describe, it) +import Test.Spec.Assertions (shouldEqual) +import Parsing (runParser) + +parseDocument ∷ String → Aff (AST.Document) +parseDocument t = liftEffect (either (throw <<< show) pure (runParser t GP.document)) + +-- uses a more full featured schema +-- in this case, the publically available code sandbox schema +query = + """ +schema { + query: RootQueryType + mutation: RootMutationType + subscription: RootSubscriptionType +} + +enum Authorization { + COMMENT + NONE + OWNER + READ + WRITE_CODE + WRITE_PROJECT +} + +type Bookmarked { + entity: BookmarkEntity + isBookmarked: Boolean +} + +union BookmarkEntity = Team | User + +input CodeReference { + anchor: Int! + code: String! + head: Int! + lastUpdatedAt: String! + path: String! +} + +type CodeReferenceMetadata { + anchor: Int! + code: String! + head: Int! + path: String! + sandboxId: String! +} + +type Collaborator { + authorization: Authorization! + id: ID! + lastSeenAt: DateTime + sandbox: Sandbox! + user: User! + warning: String +} + +type Collection { + id: ID + path: String! + sandboxes: [Sandbox!]! + team: Team + teamId: ID + user: User +} + +type Comment { + comments: [Comment!]! + content: String + id: ID! + insertedAt: NaiveDateTime! + isRead: Boolean! + isResolved: Boolean! + parentComment: Comment + references: [Reference!]! + replyCount: Int! + sandbox: Sandbox! + updatedAt: NaiveDateTime! + user: User! +} + +type CurrentUser { + bookmarkedTemplates: [Template!]! + collection(path: String!, teamId: ID): Collection + collections(teamId: ID): [Collection!]! + email: String! + firstName: String + id: ID! + lastName: String + notifications(limit: Int, orderBy: OrderBy, type: [String]): [Notification] + recentlyUsedTemplates: [Template!]! + sandboxes(limit: Int, orderBy: OrderBy, showDeleted: Boolean): [Sandbox!]! + team(id: ID!): Team + teams: [Team!]! + templates(showAll: Boolean, teamId: ID): [Template!]! + username: String! +} + +scalar DateTime + +enum Direction { + ASC + DESC +} + +type Git { + branch: String + commitSha: String + id: ID + path: String + repo: String + username: String +} + +type Invitation { + authorization: Authorization! + email: String + id: ID + sandbox: Sandbox! + token: String! +} + +scalar NaiveDateTime + +type Notification { + archived: Boolean! + data: String! + id: ID! + insertedAt: NaiveDateTime! + read: Boolean! + type: String! +} + +input OrderBy { + direction: Direction! + field: String! +} + +type Reference { + id: ID! + metadata: ReferenceMetadata! + resource: String! + type: String! +} + +union ReferenceMetadata = CodeReferenceMetadata + +type RootMutationType { + updateComment(commentId: ID!, content: String, sandboxId: ID!): Comment! + + archiveAllNotifications: User! + + markNotificationAsRead(notificationId: ID!): Notification! + + removeFromTeam(teamId: ID!, userId: ID!): Team! + + deleteSandboxes(sandboxIds: [ID!]!): [Sandbox!]! + + deleteCollection(path: String!, teamId: ID): [Collection!]! + + bookmarkTemplate(teamId: ID, templateId: ID!): Template + + setTeamName(name: String!, teamId: ID!): Team! + + acceptTeamInvitation(teamId: ID!): Team! + + setTeamDescription(description: String!, teamId: ID!): Team! + renameSandbox(id: ID!, title: String!): Sandbox! + unresolveComment(commentId: ID!, sandboxId: ID!): Comment! + resolveComment(commentId: ID!, sandboxId: ID!): Comment! + revokeSandboxInvitation(invitationId: ID!, sandboxId: ID!): Invitation! + + deleteComment(commentId: ID!, sandboxId: ID!): Comment! + createSandboxInvitation( + authorization: Authorization! + email: String! + sandboxId: ID! + ): Invitation! + + leaveTeam(teamId: ID!): String! + createComment( + codeReference: CodeReference + content: String! + id: ID + parentCommentId: ID + sandboxId: ID! + ): Comment! + + clearNotificationCount: User! + + addToCollection( + collectionPath: String! + sandboxIds: [ID]! + teamId: ID + ): Collection! + + addCollaborator( + authorization: Authorization! + sandboxId: ID! + username: String! + ): Collaborator! + changeSandboxInvitationAuthorization( + authorization: Authorization! + invitationId: ID! + sandboxId: ID! + ): Invitation! + setSandboxesPrivacy(privacy: Int, sandboxIds: [ID!]!): [Sandbox!]! + + markAllNotificationsAsRead: User! + + redeemTeamInviteToken(inviteToken: String!): Team! + + unmakeSandboxesTemplates(sandboxIds: [ID!]!): [Template!]! + + revokeTeamInvitation(teamId: ID!, userId: ID!): Team! + + createCollection(path: String!, teamId: ID): Collection! + + createTeam(name: String!): Team! + + makeSandboxesTemplates(sandboxIds: [ID!]!): [Template!]! + + renameCollection( + newPath: String! + newTeamId: ID + path: String! + teamId: ID + ): [Collection!]! + + changeCollaboratorAuthorization( + authorization: Authorization! + sandboxId: ID! + username: String! + ): Collaborator! + + inviteToTeamViaEmail(email: String!, teamId: ID!): String! + + unbookmarkTemplate(teamId: ID, templateId: ID!): Template + + archiveNotification(notificationId: ID!): Notification! + redeemSandboxInvitation(invitationToken: String!, sandboxId: ID!): Invitation! + permanentlyDeleteSandboxes(sandboxIds: [ID!]!): [Sandbox!]! + + inviteToTeam(teamId: ID!, username: String!): Team! + + rejectTeamInvitation(teamId: ID!): String! + + removeCollaborator(sandboxId: ID!, username: String!): Collaborator! +} + +type RootQueryType { + me: CurrentUser + + sandbox(sandboxId: ID!): Sandbox + + teamByToken(inviteToken: String!): Team +} + +type RootSubscriptionType { + collaboratorAdded(sandboxId: ID!): Collaborator! + collaboratorChanged(sandboxId: ID!): Collaborator! + collaboratorRemoved(sandboxId: ID!): Collaborator! + commentAdded(sandboxId: ID!): Comment! + commentChanged(sandboxId: ID!): Comment! + commentRemoved(sandboxId: ID!): Comment! + invitationChanged(sandboxId: ID!): Invitation! + invitationCreated(sandboxId: ID!): Invitation! + invitationRemoved(sandboxId: ID!): Invitation! + sandboxChanged(sandboxId: ID!): Sandbox! +} + +type Sandbox { + alias: String + author: User + authorization: Authorization! + collaborators: [Collaborator!]! + collection: Collection + comment(commentId: ID!): Comment + comments: [Comment!]! + + customTemplate: Template + description: String + forkCount: Int! + forkedTemplate: Template + + git: Git + id: ID! + insertedAt: String! + invitations: [Invitation!]! + likeCount: Int! + privacy: Int! + removedAt: String + screenshotOutdated: Boolean! + screenshotUrl: String + source: Source! + title: String + updatedAt: String! + viewCount: Int! +} + +type Source { + id: ID + template: String +} + +type Team { + bookmarkedTemplates: [Template!]! + collections: [Collection!]! + creatorId: ID + description: String + id: ID! + inviteToken: String! + invitees: [User!]! + name: String! + templates: [Template!]! + users: [User!]! +} + +type Template { + bookmarked: [Bookmarked] + color: String + description: String + iconUrl: String + id: ID + insertedAt: String + published: Boolean + sandbox: Sandbox + title: String + updatedAt: String +} + +type User { + avatarUrl: String! + firstName: String + id: ID! + lastName: String + name: String + username: String! +} +""" ∷ + String + +getFieldNamesFromDocument ∷ AST.Document → List String +getFieldNamesFromDocument = + L.toListOf $ uncurry L.prism' AST._Document + <<< L.traversed + <<< uncurry L.prism' AST._Definition_TypeSystemDefinition + <<< uncurry L.prism' AST._TypeSystemDefinition_TypeDefinition + <<< uncurry L.prism' AST._TypeDefinition_ObjectTypeDefinition + <<< uncurry L.prism' AST._ObjectTypeDefinition + <<< LR.prop (Proxy :: Proxy "fieldsDefinition") + <<< L._Just + <<< uncurry L.prism' AST._FieldsDefinition + <<< L.traversed + <<< uncurry L.prism' AST._FieldDefinition + <<< L.filtered + ( \fd -> + fd.type == (AST.Type_NamedType $ AST.NamedType "String") + || fd.type + == ( AST.Type_NonNullType + (AST.NonNullType_NamedType (AST.NamedType "String")) + ) + ) + <<< LR.prop (Proxy :: Proxy "name") + +spec ∷ Spec Unit +spec = + describe "test string type retriever" do + before (parseDocument query) + $ do + it "should retrieve only string types" \doc → do + Set.subset + (Set.fromFoldable [ "username", "name" ]) + (Set.fromFoldable $ getFieldNamesFromDocument doc) + `shouldEqual` + true + Set.subset + (Set.fromFoldable [ "username", "fhufweuifhwe" ]) + (Set.fromFoldable $ getFieldNamesFromDocument doc) + `shouldEqual` + false + Set.subset + (Set.fromFoldable [ "username", "published" ]) + (Set.fromFoldable $ getFieldNamesFromDocument doc) + `shouldEqual` + false diff --git a/package.json b/package.json index 54288de3..7a2dfd2a 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "test": "test" }, "scripts": { - "test": "spago test --no-install && node ./run-example-tests", + "test": "spago test --no-install && npm run test-codegen && node ./run-example-tests", + "test-codegen": "cd codegen/schema && spago test", "should-fail-tests": "node ./run-should-fail-tests", "bundle": "cd codegen/schema && spago bundle-module -m GraphQL.Client.CodeGen.Js -t '../../gen-schema-bundled.mjs'", "patch": "npm run bundle && gcam 'update bundle' --allow-empty && npm version patch && npm publish && pulp publish",