Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reproduces future value cast issue for scala 3 #1168

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package test.issues.ticket_906

import sangria.macros.derive._
import sangria.schema._

import scala.concurrent.Future

object Issue906Context {

@GraphQLName("SampleCaseClass")
@GraphQLDescription("A sample case class")
final case class SampleCaseClass(
name: String
) {
@GraphQLField
@GraphQLName("myString")
def graphqlMyString: String = "Hello World"

@GraphQLField
@GraphQLName("myFutureString")
def graphqlMyFutureString: Future[String] = Future.successful("Hello World")

}

object SampleCaseClass {
val sample: SampleCaseClass = SampleCaseClass("My test")
}

trait MyRepository {
def getSampleCaseClass: SampleCaseClass
}

object MyRepository {
def sample: MyRepository = new MyRepository {
override def getSampleCaseClass: SampleCaseClass = SampleCaseClass.sample
}
}

object MySample {
val schema: Schema[MyRepository, Unit] = {

implicit val graphqlSampleCaseClass: ObjectType[MyRepository, SampleCaseClass] =
deriveObjectType[MyRepository, SampleCaseClass](
// it works when adding the fields here but not when using annotations (scala 3)
// AddFields(
// Field(
// "myString",
// StringType,
// Some("A simple string"),
// resolve = _.value.graphqlMyString
// ),
// Field(
// "myFutureString",
// StringType,
// Some("A simple string"),
// resolve = ctx => ctx.value.graphqlMyFutureString
// )
// )
)

val queries: ObjectType[MyRepository, Unit] = ObjectType(
"Query",
fields(
Field(
"mySample",
graphqlSampleCaseClass,
Some("test"),
arguments = Nil,
resolve = (ctx: Context[MyRepository, Unit]) => SampleCaseClass.sample
)
)
)

Schema(
query = queries,
mutation = None,
additionalTypes = Nil
)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package test.issues.ticket_906

import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import sangria.execution.Executor
import sangria.parser.QueryParser
import sangria.util._

import scala.concurrent.ExecutionContext.Implicits.global

import Issue906Context._

final class Issue906Spec extends AnyWordSpec with Matchers with FutureResultSupport {

"Derivation" should {
"Support Future values" in {

val query = QueryParser
.parse(
s"""
query SomeTest {
mySample {
myFutureString
}
}
"""
)
.fold(throw _, identity)

Executor.execute(MySample.schema, query, MyRepository.sample).await should be(
Map(
"data" -> Map(
"mySample" -> Map(
"myFutureString" -> "Hello World"
)
)
)
)

}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package test.util

import sangria.execution.{ErrorWithResolver, QueryAnalysisError}
import sangria.marshalling.ResultMarshallerForType

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.language.postfixOps

trait FutureResultSupport {
implicit class FutureResult[T](f: Future[T]) {
def await = Await.result(f, 10 seconds)
def await(duration: Duration) = Await.result(f, duration)

def awaitAndRecoverQueryAnalysis(implicit m: ResultMarshallerForType[T]): T =
Await.result(recoverQueryAnalysis, 10 seconds)

def recoverQueryAnalysis(implicit m: ResultMarshallerForType[T]): Future[T] = f.recover {
case analysisError: QueryAnalysisError =>
analysisError.resolveError(m.marshaller).asInstanceOf[T]
}

def awaitAndRecoverQueryAnalysisScala(implicit ev: T =:= Any) =
Await.result(recoverQueryAnalysisScala, 10 seconds)

def recoverQueryAnalysisScala(implicit ev: T =:= Any) = f.recover {
case analysisError: ErrorWithResolver => analysisError.resolveError
}
}

object sync {
val executionContext = ExecutionContext.fromExecutor(new java.util.concurrent.Executor {
def execute(command: Runnable) = command.run()
})
}
}
Loading