~jan0sch/smederee

Showing details for patch f84160f508d04211cfafcca776f98da63f76ace1.
2024-07-22 (Mon), 7:51 AM - Jens Grassel - f84160f508d04211cfafcca776f98da63f76ace1

chore: migrate test to ScalaCheckEffect

Summary of changes
1 files modified with 368 lines added and 400 lines removed
  • modules/hub/src/test/scala/de/smederee/hub/DoobieAuthenticationRepositoryTest.scala with 368 added and 400 removed lines
diff -rN -u old-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieAuthenticationRepositoryTest.scala new-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieAuthenticationRepositoryTest.scala
--- old-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieAuthenticationRepositoryTest.scala	2025-01-11 03:19:29.853485109 +0000
+++ new-smederee/modules/hub/src/test/scala/de/smederee/hub/DoobieAuthenticationRepositoryTest.scala	2025-01-11 03:19:29.857485118 +0000
@@ -6,15 +6,20 @@
 
 package de.smederee.hub
 
+import cats.data.NonEmptyList
 import cats.effect.*
 import cats.syntax.all.*
 import de.smederee.TestTags.*
-import de.smederee.hub.Generators.*
+import de.smederee.hub.Generators.given
 import de.smederee.security.*
 import doobie.*
 import org.flywaydb.core.Flyway
 
+import org.scalacheck.effect.PropF
+
 final class DoobieAuthenticationRepositoryTest extends BaseSpec {
+    override def scalaCheckTestParameters = super.scalaCheckTestParameters.withMinSuccessfulTests(1)
+
     override def beforeEach(context: BeforeEach): Unit = {
         val dbConfig = configuration.database
         val flyway: Flyway =
@@ -33,480 +38,443 @@
     }
 
     test("allAccounts must return all accounts from the database".tag(NeedsDatabase)) {
-        genValidAccounts.sample match {
-            case Some(accounts) =>
-                val expected = accounts.map(_.copy(language = None))
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- accounts.traverse(account =>
-                        createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    )
-                    result <- repo.allAccounts().compile.toList
-                } yield result
-                test.map { result =>
-                    assertEquals(result.size, expected.size)
-                    assertEquals(result, expected.sortBy(_.name))
-                }
-            case _ => fail("Could not generate data samples!")
+        PropF.forAllF { (accounts: NonEmptyList[Account]) =>
+            val expected = accounts.toList.map(_.copy(language = None))
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- accounts.traverse(account =>
+                    createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                )
+                result <- repo.allAccounts().compile.toList
+            } yield result
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assertEquals(result.size, expected.size)
+                assertEquals(result, expected.sortBy(_.name))
+            }
         }
     }
 
     test("createUserSession must create the user session".tag(NeedsDatabase)) {
-        (genValidSession.sample, genValidAccount.sample) match {
-            case (Some(s), Some(account)) =>
-                val session  = s.copy(uid = account.uid)
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    w <- repo.createUserSession(session)
-                    o <- repo.findUserSession(session.id)
-                } yield (w, o)
-                test.map { result =>
-                    val (written, maybeSession) = result
-                    assert(written === 1, "Creating user session must modify one database row!")
-                    assert(clue(maybeSession) === clue(Option(session)))
-                }
-            case _ => fail("Could not generate data samples!")
+        PropF.forAllF { (s: Session, account: Account) =>
+            val session  = s.copy(uid = account.uid)
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                w <- repo.createUserSession(session)
+                o <- repo.findUserSession(session.id)
+            } yield (w, o)
+            test.start.flatMap(_.joinWithNever).map { result =>
+                val (written, maybeSession) = result
+                assert(written === 1, "Creating user session must modify one database row!")
+                assert(clue(maybeSession) === clue(Option(session)))
+            }
         }
     }
 
     test("createUserSession must fail if the user does not exist".tag(NeedsDatabase)) {
-        genValidSession.sample match {
-            case Some(session) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- repo.createUserSession(session)
-                    _ <- repo.findUserSession(session.id)
-                } yield ()
-                test.attempt.map(result => assert(result.isLeft))
-            case _ => fail("Could not generate data samples!")
+        PropF.forAllF { (session: Session) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- repo.createUserSession(session)
+                _ <- repo.findUserSession(session.id)
+            } yield ()
+            test.attempt.map(result => assert(result.isLeft))
         }
     }
 
     test("deleteAllUserSessions must delete all sessions of the user".tag(NeedsDatabase)) {
-        (genValidSessions.sample, genValidAccount.sample) match {
-            case (Some(generatedSessions), Some(account)) =>
-                val sessions = generatedSessions.map(_.copy(uid = account.uid))
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _             <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    _             <- sessions.traverse(createUserSession)
-                    deleted       <- repo.deleteAllUserSessions(account.uid)
-                    foundSessions <- sessions.traverse(s => repo.findUserSession(s.id))
-                } yield (deleted, foundSessions)
-                test.map { result =>
-                    val (deleted, foundSessions) = result
-                    assertEquals(deleted, sessions.size, "Number of deleted sessions differs from number of sessions!")
-                    assert(foundSessions.flatten.isEmpty, "Not all sessions were deleted!")
-                }
-            case _ => fail("Could not generate data samples!")
+        PropF.forAllF { (generatedSessions: NonEmptyList[Session], account: Account) =>
+            val sessions = generatedSessions.toList.map(_.copy(uid = account.uid))
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _             <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                _             <- sessions.traverse(createUserSession)
+                deleted       <- repo.deleteAllUserSessions(account.uid)
+                foundSessions <- sessions.traverse(s => repo.findUserSession(s.id))
+            } yield (deleted, foundSessions)
+            test.start.flatMap(_.joinWithNever).map { result =>
+                val (deleted, foundSessions) = result
+                assertEquals(deleted, sessions.size, "Number of deleted sessions differs from number of sessions!")
+                assert(foundSessions.flatten.isEmpty, "Not all sessions were deleted!")
+            }
         }
     }
 
     test("deleteUserSession must delete the session".tag(NeedsDatabase)) {
-        (genValidSession.sample, genValidAccount.sample) match {
-            case (Some(s), Some(account)) =>
-                val session  = s.copy(uid = account.uid)
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _       <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    _       <- createUserSession(session)
-                    before  <- repo.findUserSession(session.id)
-                    deleted <- repo.deleteUserSession(session.id)
-                    after   <- repo.findUserSession(session.id)
-                } yield (before, deleted, after)
-                test.map { result =>
-                    val (before, deleted, after) = result
-                    assert(before.nonEmpty, "Session must exist before deleting it!")
-                    assert(deleted === 1, "Deletion must affect one database row!")
-                    assert(after.isEmpty, "Session must not exist after deletion!")
-                }
-            case _ => fail("Could not generate data samples!")
+        PropF.forAllF { (s: Session, account: Account) =>
+            val session  = s.copy(uid = account.uid)
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _       <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                _       <- createUserSession(session)
+                before  <- repo.findUserSession(session.id)
+                deleted <- repo.deleteUserSession(session.id)
+                after   <- repo.findUserSession(session.id)
+            } yield (before, deleted, after)
+            test.start.flatMap(_.joinWithNever).map { result =>
+                val (before, deleted, after) = result
+                assert(before.nonEmpty, "Session must exist before deleting it!")
+                assert(deleted === 1, "Deletion must affect one database row!")
+                assert(after.isEmpty, "Session must not exist after deletion!")
+            }
         }
     }
 
     test("findAccount must return an existing account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    o <- repo.findAccount(account.uid)
-                } yield o
-                test.map { result =>
-                    assert(result === Option(account))
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                o <- repo.findAccount(account.uid)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result === Option(account))
+            }
         }
     }
 
     test("findAccount must not return a locked account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(
-                        account,
-                        PasswordHash("I am not a password hash!"),
-                        Option(UnlockToken.generate),
-                        None
-                    )
-                    o <- repo.findAccount(account.uid)
-                } yield o
-                test.map { result =>
-                    assert(result.isEmpty, "The function must not return locked accounts!")
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(
+                    account,
+                    PasswordHash("I am not a password hash!"),
+                    Option(UnlockToken.generate),
+                    None
+                )
+                o <- repo.findAccount(account.uid)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result.isEmpty, "The function must not return locked accounts!")
+            }
         }
     }
 
     test("findAccountByEmail must return an existing account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    o <- repo.findAccountByEmail(account.email)
-                } yield o
-                test.map { result =>
-                    assert(result === Option(account))
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                o <- repo.findAccountByEmail(account.email)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result === Option(account))
+            }
         }
     }
 
     test("findAccountByEmail must not return a locked account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(
-                        account,
-                        PasswordHash("I am not a password hash!"),
-                        Option(UnlockToken.generate),
-                        None
-                    )
-                    o <- repo.findAccountByEmail(account.email)
-                } yield o
-                test.map { result =>
-                    assert(result.isEmpty, "The function must not return locked accounts!")
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(
+                    account,
+                    PasswordHash("I am not a password hash!"),
+                    Option(UnlockToken.generate),
+                    None
+                )
+                o <- repo.findAccountByEmail(account.email)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result.isEmpty, "The function must not return locked accounts!")
+            }
         }
     }
 
     test("findAccountByName must return an existing account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    o <- repo.findAccountByName(account.name)
-                } yield o
-                test.map { result =>
-                    assert(result === Option(account))
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                o <- repo.findAccountByName(account.name)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result === Option(account))
+            }
         }
     }
 
     test("findAccountByName must not return a locked account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(
-                        account,
-                        PasswordHash("I am not a password hash!"),
-                        Option(UnlockToken.generate),
-                        None
-                    )
-                    o <- repo.findAccountByName(account.name)
-                } yield o
-                test.map { result =>
-                    assert(result.isEmpty, "The function must not return locked accounts!")
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(
+                    account,
+                    PasswordHash("I am not a password hash!"),
+                    Option(UnlockToken.generate),
+                    None
+                )
+                o <- repo.findAccountByName(account.name)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result.isEmpty, "The function must not return locked accounts!")
+            }
         }
     }
 
     test("findLockedAccount must return a locked account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo  = new DoobieAuthenticationRepository[IO](tx)
-                val token = UnlockToken.generate
-                val test = for {
-                    _ <- createAccount(account, PasswordHash("I am not a password hash!"), Option(token), None)
-                    o <- repo.findLockedAccount(account.name)(token.some)
-                } yield o
-                test.map { result =>
-                    assert(result === Option(account))
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo  = new DoobieAuthenticationRepository[IO](tx)
+            val token = UnlockToken.generate
+            val test = for {
+                _ <- createAccount(account, PasswordHash("I am not a password hash!"), Option(token), None)
+                o <- repo.findLockedAccount(account.name)(token.some)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result === Option(account))
+            }
         }
     }
 
     test("findLockedAccount must return a locked account if no token is given".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo  = new DoobieAuthenticationRepository[IO](tx)
-                val token = UnlockToken.generate
-                val test = for {
-                    _ <- createAccount(account, PasswordHash("I am not a password hash!"), Option(token), None)
-                    o <- repo.findLockedAccount(account.name)(None)
-                } yield o
-                test.map { result =>
-                    assert(result === Option(account))
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo  = new DoobieAuthenticationRepository[IO](tx)
+            val token = UnlockToken.generate
+            val test = for {
+                _ <- createAccount(account, PasswordHash("I am not a password hash!"), Option(token), None)
+                o <- repo.findLockedAccount(account.name)(None)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result === Option(account))
+            }
         }
     }
 
     test("findPasswordHashAndAttempts must return correct values".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo     = new DoobieAuthenticationRepository[IO](tx)
-                val attempts = scala.util.Random.nextInt(128)
-                val hash     = PasswordHash("Yet another weak password!")
-                val test = for {
-                    _ <- createAccount(account, hash, None, Option(attempts))
-                    o <- repo.findPasswordHashAndAttempts(account.uid)
-                } yield o
-                test.map { result =>
-                    result match {
-                        case Some((readHash, readAttempts)) =>
-                            assert(readHash === hash)
-                            assert(readAttempts === attempts)
-                        case _ => fail("Unexpected result from database!")
-                    }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo     = new DoobieAuthenticationRepository[IO](tx)
+            val attempts = scala.util.Random.nextInt(128)
+            val hash     = PasswordHash("Yet another weak password!")
+            val test = for {
+                _ <- createAccount(account, hash, None, Option(attempts))
+                o <- repo.findPasswordHashAndAttempts(account.uid)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                result match {
+                    case Some((readHash, readAttempts)) =>
+                        assert(readHash === hash)
+                        assert(readAttempts === attempts)
+                    case _ => fail("Unexpected result from database!")
                 }
+            }
         }
     }
 
     test("findPasswordHashAndAttempts must not return values for locked accounts".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo     = new DoobieAuthenticationRepository[IO](tx)
-                val attempts = scala.util.Random.nextInt(128)
-                val hash     = PasswordHash("Yet another weak password!")
-                val test = for {
-                    _ <- createAccount(account, hash, Option(UnlockToken.generate), Option(attempts))
-                    o <- repo.findPasswordHashAndAttempts(account.uid)
-                } yield o
-                test.map { result =>
-                    assert(result.isEmpty, "The function must not return locked accounts!")
-                }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo     = new DoobieAuthenticationRepository[IO](tx)
+            val attempts = scala.util.Random.nextInt(128)
+            val hash     = PasswordHash("Yet another weak password!")
+            val test = for {
+                _ <- createAccount(account, hash, Option(UnlockToken.generate), Option(attempts))
+                o <- repo.findPasswordHashAndAttempts(account.uid)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { result =>
+                assert(result.isEmpty, "The function must not return locked accounts!")
+            }
         }
     }
 
     test("findUserSession must find an existing session".tag(NeedsDatabase)) {
-        (genValidSession.sample, genValidAccount.sample) match {
-            case (Some(s), Some(account)) =>
-                val session  = s.copy(uid = account.uid)
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo = new DoobieAuthenticationRepository[IO](tx)
-                val test = for {
-                    _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    _ <- createUserSession(session)
-                    o <- repo.findUserSession(session.id)
-                } yield o
-                test.map { maybeSession =>
-                    assert(clue(maybeSession) === clue(Option(session)))
-                }
-            case _ => fail("Could not generate data samples!")
+        PropF.forAllF { (s: Session, account: Account) =>
+            val session  = s.copy(uid = account.uid)
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo = new DoobieAuthenticationRepository[IO](tx)
+            val test = for {
+                _ <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                _ <- createUserSession(session)
+                o <- repo.findUserSession(session.id)
+            } yield o
+            test.start.flatMap(_.joinWithNever).map { maybeSession =>
+                assert(clue(maybeSession) === clue(Option(session)))
+            }
         }
     }
 
     test("incrementFailedAttempts must increment failed attempts by 1".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo     = new DoobieAuthenticationRepository[IO](tx)
-                val attempts = scala.util.Random.nextInt(128)
-                val hash     = PasswordHash("Yet another weak password!")
-                val test = for {
-                    _      <- createAccount(account, hash, None, Option(attempts))
-                    before <- repo.findPasswordHashAndAttempts(account.uid)
-                    _      <- repo.incrementFailedAttempts(account.uid)
-                    after  <- repo.findPasswordHashAndAttempts(account.uid)
-                } yield (before, after)
-                test.map { result =>
-                    result match {
-                        case (Some((_, before)), Some((_, after))) =>
-                            assert(after - before === 1, "Attempts must be incremented by one!")
-                        case _ => fail("Unexpected result from database!")
-                    }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo     = new DoobieAuthenticationRepository[IO](tx)
+            val attempts = scala.util.Random.nextInt(128)
+            val hash     = PasswordHash("Yet another weak password!")
+            val test = for {
+                _      <- createAccount(account, hash, None, Option(attempts))
+                before <- repo.findPasswordHashAndAttempts(account.uid)
+                _      <- repo.incrementFailedAttempts(account.uid)
+                after  <- repo.findPasswordHashAndAttempts(account.uid)
+            } yield (before, after)
+            test.start.flatMap(_.joinWithNever).map { result =>
+                result match {
+                    case (Some((_, before)), Some((_, after))) =>
+                        assert(after - before === 1, "Attempts must be incremented by one!")
+                    case _ => fail("Unexpected result from database!")
                 }
+            }
         }
     }
 
     test("lockAccount must lock an account".tag(NeedsDatabase)) {
-        genValidAccount.sample match {
-            case None => fail("Could not generate data samples!")
-            case Some(account) =>
-                val dbConfig = configuration.database
-                val tx = Transactor.fromDriverManager[IO](
-                    driver = dbConfig.driver,
-                    url = dbConfig.url,
-                    user = dbConfig.user,
-                    password = dbConfig.pass,
-                    logHandler = None
-                )
-                val repo  = new DoobieAuthenticationRepository[IO](tx)
-                val token = UnlockToken.generate
-                val test = for {
-                    _      <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
-                    before <- repo.findAccount(account.uid)
-                    _      <- repo.lockAccount(account.uid)(Option(token))
-                    after  <- repo.findAccount(account.uid)
-                    locked <- repo.findLockedAccount(account.name)(token.some)
-                } yield (before, after, locked)
-                test.map { result =>
-                    result match {
-                        case (Some(before), after, Some(locked)) =>
-                            assert(after.isEmpty)
-                            assert(before === locked)
-                        case _ => fail("Unexpected result from database!")
-                    }
+        PropF.forAllF { (account: Account) =>
+            val dbConfig = configuration.database
+            val tx = Transactor.fromDriverManager[IO](
+                driver = dbConfig.driver,
+                url = dbConfig.url,
+                user = dbConfig.user,
+                password = dbConfig.pass,
+                logHandler = None
+            )
+            val repo  = new DoobieAuthenticationRepository[IO](tx)
+            val token = UnlockToken.generate
+            val test = for {
+                _      <- createAccount(account, PasswordHash("I am not a password hash!"), None, None)
+                before <- repo.findAccount(account.uid)
+                _      <- repo.lockAccount(account.uid)(Option(token))
+                after  <- repo.findAccount(account.uid)
+                locked <- repo.findLockedAccount(account.name)(token.some)
+            } yield (before, after, locked)
+            test.start.flatMap(_.joinWithNever).map { result =>
+                result match {
+                    case (Some(before), after, Some(locked)) =>
+                        assert(after.isEmpty)
+                        assert(before === locked)
+                    case _ => fail("Unexpected result from database!")
                 }
+            }
         }
     }
-
 }