Skip to content

Commit

Permalink
LoneAnonymousOperation rule implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
OlegIlyenko committed Aug 7, 2015
1 parent d751be4 commit cf23a34
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/main/scala/sangria/validation/Violation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,6 @@ case class FieldsConflictViolation(outputName: String, reason: Either[String, Ve
}
}

case class AnonOperationNotAloneViolation(sourceMapper: Option[SourceMapper], positions: List[Position]) extends AstNodeViolation {
lazy val errorMessage = s"This anonymous operation must be the only defined operation.$astLocation"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package sangria.validation.rules

import sangria.ast
import sangria.ast.AstVisitorCommand._
import sangria.validation._

import scala.language.postfixOps

/**
* Lone anonymous operation
*
* A GraphQL document is only valid if when it contains an anonymous operation
* (the query short-hand) that it contains only that one operation definition.
*/
class LoneAnonymousOperation extends ValidationRule {
override def visitor(ctx: ValidationContext) = new AstValidatingVisitor {
var operationCount = 0

override val onEnter: ValidationVisit = {
case ast.Document(definitions, _, _) =>
operationCount = definitions.count(_.isInstanceOf[ast.OperationDefinition])
Right(Continue)
case op: ast.OperationDefinition =>
if (op.name.isEmpty && operationCount > 1)
Left(Vector(AnonOperationNotAloneViolation(ctx.sourceMapper, op.position.toList)))
else
Right(Continue)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package sangria.validation.rules

import org.scalatest.WordSpec
import sangria.util.{Pos, ValidationSupport}

class LoneAnonymousOperationSpec extends WordSpec with ValidationSupport {

override val defaultRule = Some(new LoneAnonymousOperation)

"Validate: Anonymous operation must be alone" should {
"no operations" in expectPasses(
"""
fragment fragA on Type {
field
}
""")

"one anon operation" in expectPasses(
"""
{
field
}
""")

"multiple named operations" in expectPasses(
"""
query Foo {
field
}
query Bar {
field
}
""")

"anon operation with fragment" in expectPasses(
"""
{
...Foo
}
fragment Foo on Type {
field
}
""")

"multiple anon operations" in expectFails(
"""
{
fieldA
}
{
fieldB
}
""",
List(
"This anonymous operation must be the only defined operation." -> Some(Pos(2, 9)),
"This anonymous operation must be the only defined operation." -> Some(Pos(5, 9))
))

"anon operation with another operation" in expectFails(
"""
{
fieldA
}
mutation Foo {
fieldB
}
""",
List(
"This anonymous operation must be the only defined operation." -> Some(Pos(2, 9))
))
}
}

0 comments on commit cf23a34

Please sign in to comment.