forked from tpolecat/doobie
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Checker.scala
80 lines (74 loc) · 2.4 KB
/
Checker.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// Copyright (c) 2013-2020 Rob Norris and Contributors
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT
package doobie.weaver
import cats.effect.kernel.Sync
import cats.syntax.functor.*
import doobie.Query
import doobie.Query0
import doobie.Transactor
import doobie.syntax.connectionio.*
import doobie.util.Colors
import doobie.util.testing.AnalysisArgs
import doobie.util.testing.Analyzable
import doobie.util.testing.analyze
import doobie.util.testing.formatReport
import org.tpolecat.typename.TypeName
import org.tpolecat.typename.typeName
import weaver.Expectations
import weaver.Expectations.Helpers.*
import weaver.SourceLocation
/**
* Module with a mix-in trait for specifications that enables checking of doobie
* `Query` and `Update` values.
*
* {{{
* object ExampleSuite extends IOSuite with IOChecker {
*
* override type Res = Transactor[IO]
* override def sharedResource: Resource[IO, Res] =
* // The transactor to use for the tests.
* Resource.pure(Transactor.fromDriverManager[IO](...))
*
* // Now just mention the queries. Arguments are not used.
* test("findByNameAndAge") { implicit transactor => check(MyDaoModule.findByNameAndAge(null, 0)) }
* test("allWoozles") { implicit transactor => check(MyDaoModule.allWoozles) }
*
* }
* }}}
*/
trait Checker[M[_]] {
def check[A: Analyzable](a: A)(implicit M: Sync[M], pos: SourceLocation, transactor: Transactor[M]): M[Expectations] =
checkImpl(Analyzable.unpack(a))
def checkOutput[A: TypeName](q: Query0[A])(implicit
M: Sync[M],
pos: SourceLocation,
transactor: Transactor[M],
): M[Expectations] =
checkImpl(AnalysisArgs(
s"Query0[${typeName[A]}]",
q.pos,
q.sql,
q.outputAnalysis,
))
def checkOutput[A: TypeName, B: TypeName](q: Query[A, B])(implicit
M: Sync[M],
pos: SourceLocation,
transactor: Transactor[M],
): M[Expectations] =
checkImpl(AnalysisArgs(
s"Query[${typeName[A]}, ${typeName[B]}]",
q.pos,
q.sql,
q.outputAnalysis,
))
private def checkImpl(args: AnalysisArgs)(implicit M: Sync[M], pos: SourceLocation, transactor: Transactor[M]) = {
analyze(args).transact(transactor).map { report =>
if (!report.succeeded)
failure(formatReport(args, report, Colors.Ansi)
.padLeft(" ")
.toString)
else success
}
}
}