Flatten packages
Remove modules prefix
This commit is contained in:
@@ -0,0 +1 @@
|
||||
package be.simplenotes.domain
|
||||
@@ -0,0 +1,51 @@
|
||||
package be.simplenotes.domain.security
|
||||
|
||||
import be.simplenotes.config.JwtConfig
|
||||
import be.simplenotes.domain.usecases.users.login.Token
|
||||
import be.simplenotes.types.LoggedInUser
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import com.natpryce.hamkrest.absent
|
||||
import com.natpryce.hamkrest.assertion.assertThat
|
||||
import com.natpryce.hamkrest.equalTo
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.stream.Stream
|
||||
|
||||
internal class LoggedInUserExtractorTest {
|
||||
private val jwtConfig = JwtConfig("a secret", 1, TimeUnit.HOURS)
|
||||
private val simpleJwt = SimpleJwt(jwtConfig)
|
||||
private val jwtPayloadExtractor = JwtPayloadExtractor(simpleJwt)
|
||||
|
||||
private fun createToken(username: String? = null, id: Int? = null, secret: String = jwtConfig.secret): Token {
|
||||
val algo = Algorithm.HMAC256(secret)
|
||||
return JWT.create().apply {
|
||||
username?.let { withClaim(usernameField, it) }
|
||||
id?.let { withClaim(userIdField, it) }
|
||||
}.sign(algo)
|
||||
}
|
||||
|
||||
@Suppress("Unused")
|
||||
private fun invalidTokens() = Stream.of(
|
||||
createToken(id = 1),
|
||||
createToken(username = "user"),
|
||||
createToken(),
|
||||
createToken(username = "user", id = 1, secret = "not the correct secret"),
|
||||
createToken(username = "user", id = 1) + "\"efesfsef",
|
||||
"something that is not even a token"
|
||||
)
|
||||
|
||||
@ParameterizedTest(name = "[{index}] token `{0}` should be invalid")
|
||||
@MethodSource("invalidTokens")
|
||||
fun `parse invalid tokens`(token: String) {
|
||||
assertThat(jwtPayloadExtractor(token), absent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `parse valid token`() {
|
||||
val token = createToken(username = "someone", id = 1)
|
||||
assertThat(jwtPayloadExtractor(token), equalTo(LoggedInUser(1, "someone")))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package be.simplenotes.domain.testutils
|
||||
|
||||
import arrow.core.Either
|
||||
import com.natpryce.hamkrest.MatchResult
|
||||
import com.natpryce.hamkrest.Matcher
|
||||
|
||||
fun isLeft() = object : Matcher<Either<*, *>> {
|
||||
override val description: String
|
||||
get() = "is Either.Left<>"
|
||||
|
||||
override fun invoke(actual: Either<*, *>) = when {
|
||||
actual.isLeft() -> MatchResult.Match
|
||||
else -> MatchResult.Mismatch("is Either.Right<>")
|
||||
}
|
||||
}
|
||||
|
||||
fun isRight() = object : Matcher<Either<*, *>> {
|
||||
override val description: String
|
||||
get() = "is Either.Right<>"
|
||||
|
||||
override fun invoke(actual: Either<*, *>) = when (actual) {
|
||||
is Either.Right -> MatchResult.Match
|
||||
is Either.Left -> {
|
||||
val valueA = actual.a
|
||||
MatchResult.Mismatch("is Either.Left<${if (valueA == null) "Null" else valueA::class.simpleName}>")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified A> isLeftOfType() = object : Matcher<Either<*, *>> {
|
||||
override val description: String
|
||||
get() = "is Either.Left<${A::class.qualifiedName}>"
|
||||
|
||||
override fun invoke(actual: Either<*, *>) = when (actual) {
|
||||
is Either.Right -> MatchResult.Mismatch("was Either.Right<>")
|
||||
is Either.Left -> {
|
||||
val valueA = actual.a
|
||||
if (valueA is A) MatchResult.Match
|
||||
else MatchResult.Mismatch("was Left<${if (valueA == null) "Null" else valueA::class.simpleName}>")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package be.simplenotes.domain.usecases.search
|
||||
|
||||
import be.simplenotes.search.SearchTerms
|
||||
import com.natpryce.hamkrest.assertion.assertThat
|
||||
import com.natpryce.hamkrest.equalTo
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import java.util.stream.Stream
|
||||
|
||||
internal class SearchTermsParserKtTest {
|
||||
|
||||
private fun createResult(
|
||||
input: String,
|
||||
title: String? = null,
|
||||
tag: String? = null,
|
||||
content: String? = null,
|
||||
all: String? = null,
|
||||
): Pair<String, SearchTerms> = input to SearchTerms(title, tag, content, all)
|
||||
|
||||
@Suppress("Unused")
|
||||
private fun results() = Stream.of(
|
||||
createResult("title:'example'", title = "example"),
|
||||
createResult("title:'example with words'", title = "example with words"),
|
||||
createResult("title:'example with words'", title = "example with words"),
|
||||
createResult("""title:"double quotes"""", title = "double quotes"),
|
||||
createResult("title:'example' something else", title = "example", all = "something else"),
|
||||
createResult("tag:'example'", tag = "example"),
|
||||
createResult("tag:'example' title:'other'", title = "other", tag = "example"),
|
||||
createResult("blah blah tag:'example' title:'other'", title = "other", tag = "example", all = "blah blah"),
|
||||
createResult("tag:'example' middle title:'other'", title = "other", tag = "example", all = "middle"),
|
||||
createResult("tag:'example' title:'other' end", title = "other", tag = "example", all = "end"),
|
||||
createResult(
|
||||
"tag:'example abc' title:'other with words' this is the end ",
|
||||
title = "other with words",
|
||||
tag = "example abc",
|
||||
all = "this is the end"
|
||||
),
|
||||
)
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("results")
|
||||
fun `valid search parser`(case: Pair<String, SearchTerms>) {
|
||||
assertThat(parseSearchTerms(case.first), equalTo(case.second))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package be.simplenotes.domain.usecases.users.login
|
||||
|
||||
import be.simplenotes.config.JwtConfig
|
||||
import be.simplenotes.domain.security.BcryptPasswordHash
|
||||
import be.simplenotes.domain.security.SimpleJwt
|
||||
import be.simplenotes.domain.testutils.isLeftOfType
|
||||
import be.simplenotes.domain.testutils.isRight
|
||||
import be.simplenotes.persistance.repositories.UserRepository
|
||||
import be.simplenotes.types.PersistedUser
|
||||
import com.natpryce.hamkrest.assertion.assertThat
|
||||
import io.mockk.*
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
internal class LoginUseCaseImplTest {
|
||||
// region setup
|
||||
private val mockUserRepository = mockk<UserRepository>()
|
||||
private val passwordHash = BcryptPasswordHash(test = true)
|
||||
private val jwtConfig = JwtConfig("a secret", 1, TimeUnit.HOURS)
|
||||
private val simpleJwt = SimpleJwt(jwtConfig)
|
||||
private val loginUseCase = LoginUseCaseImpl(mockUserRepository, passwordHash, simpleJwt)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(mockUserRepository)
|
||||
}
|
||||
// endregion
|
||||
|
||||
@Test
|
||||
fun `Login should fail with invalid form`() {
|
||||
val form = LoginForm("", "a")
|
||||
assertThat(loginUseCase.login(form), isLeftOfType<InvalidLoginForm>())
|
||||
verify { mockUserRepository wasNot called }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Login should fail with non existing user`() {
|
||||
val form = LoginForm("someusername", "somepassword")
|
||||
every { mockUserRepository.find(form.username!!) } returns null
|
||||
assertThat(loginUseCase.login(form), isLeftOfType<Unregistered>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Login should fail with wrong password`() {
|
||||
val form = LoginForm("someusername", "wrongpassword")
|
||||
|
||||
every { mockUserRepository.find(form.username!!) } returns
|
||||
PersistedUser(form.username!!, passwordHash.crypt("right password"), 1)
|
||||
|
||||
assertThat(loginUseCase.login(form), isLeftOfType<WrongPassword>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Login should succeed with existing user and correct password`() {
|
||||
val loginForm = LoginForm("someusername", "somepassword")
|
||||
|
||||
every { mockUserRepository.find(loginForm.username!!) } returns
|
||||
PersistedUser(loginForm.username!!, passwordHash.crypt(loginForm.password!!), 1)
|
||||
|
||||
val res = loginUseCase.login(loginForm)
|
||||
assertThat(res, isRight())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package be.simplenotes.domain.usecases.users.register
|
||||
|
||||
import be.simplenotes.domain.security.BcryptPasswordHash
|
||||
import be.simplenotes.domain.testutils.isLeftOfType
|
||||
import be.simplenotes.domain.testutils.isRight
|
||||
import be.simplenotes.persistance.repositories.UserRepository
|
||||
import be.simplenotes.persistance.transactions.TransactionService
|
||||
import be.simplenotes.types.PersistedUser
|
||||
import com.natpryce.hamkrest.assertion.assertThat
|
||||
import com.natpryce.hamkrest.equalTo
|
||||
import io.mockk.*
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
internal class RegisterUseCaseImplTest {
|
||||
|
||||
// region setup
|
||||
private val mockUserRepository = mockk<UserRepository>()
|
||||
private val passwordHash = BcryptPasswordHash(test = true)
|
||||
private val noopTransactionService = object : TransactionService {
|
||||
override fun <T> use(block: () -> T) = block()
|
||||
}
|
||||
private val registerUseCase = RegisterUseCaseImpl(mockUserRepository, passwordHash, noopTransactionService)
|
||||
|
||||
@BeforeEach
|
||||
fun resetMocks() {
|
||||
clearMocks(mockUserRepository)
|
||||
}
|
||||
// endregion
|
||||
|
||||
@Test
|
||||
fun `register should fail with invalid form`() {
|
||||
val form = RegisterForm("", "a".repeat(10))
|
||||
assertThat(registerUseCase.register(form), isLeftOfType<InvalidRegisterForm>())
|
||||
verify { mockUserRepository wasNot called }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Register should fail with existing username`() {
|
||||
val form = RegisterForm("someuser", "somepassword")
|
||||
every { mockUserRepository.exists(form.username!!) } returns true
|
||||
assertThat(registerUseCase.register(form), isLeftOfType<UserExists>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Register should succeed with new user`() {
|
||||
val form = RegisterForm("someuser", "somepassword")
|
||||
every { mockUserRepository.exists(form.username!!) } returns false
|
||||
every { mockUserRepository.create(any()) } returns PersistedUser(form.username!!, form.password!!, 1)
|
||||
val res = registerUseCase.register(form)
|
||||
assertThat(res, isRight())
|
||||
res.map { assertThat(it.username, equalTo(form.username)) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package be.simplenotes.domain.validation
|
||||
|
||||
import be.simplenotes.domain.testutils.isLeftOfType
|
||||
import be.simplenotes.domain.testutils.isRight
|
||||
import be.simplenotes.domain.usecases.users.login.InvalidLoginForm
|
||||
import be.simplenotes.domain.usecases.users.login.LoginForm
|
||||
import be.simplenotes.domain.usecases.users.register.RegisterForm
|
||||
import com.natpryce.hamkrest.assertion.assertThat
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import java.util.stream.Stream
|
||||
|
||||
internal class UserValidationsTest {
|
||||
|
||||
@Nested
|
||||
inner class Login {
|
||||
|
||||
@Suppress("Unused")
|
||||
fun invalidLoginForms(): Stream<LoginForm> = Stream.of(
|
||||
LoginForm(username = null, password = null),
|
||||
LoginForm(username = "", password = ""),
|
||||
LoginForm(username = "a", password = "aaaa"),
|
||||
LoginForm(username = "a".repeat(51), password = "a".repeat(8)),
|
||||
LoginForm(username = "a".repeat(10), password = "a".repeat(7))
|
||||
)
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidLoginForms")
|
||||
fun `validate invalid logins`(form: LoginForm) {
|
||||
assertThat(UserValidations.validateLogin(form), isLeftOfType<InvalidLoginForm>())
|
||||
}
|
||||
|
||||
@Suppress("Unused")
|
||||
fun validLoginForms(): Stream<LoginForm> = Stream.of(
|
||||
LoginForm(username = "a".repeat(50), password = "a".repeat(72)),
|
||||
LoginForm(username = "a".repeat(3), password = "a".repeat(8))
|
||||
)
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("validLoginForms")
|
||||
fun `validate valid logins`(form: LoginForm) {
|
||||
assertThat(UserValidations.validateLogin(form), isRight())
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class Register {
|
||||
|
||||
@Suppress("Unused")
|
||||
fun invalidRegisterForms(): Stream<RegisterForm> = Stream.of(
|
||||
RegisterForm(username = null, password = null),
|
||||
RegisterForm(username = "", password = ""),
|
||||
RegisterForm(username = "a", password = "aaaa"),
|
||||
RegisterForm(username = "a".repeat(51), password = "a".repeat(8)),
|
||||
RegisterForm(username = "a".repeat(10), password = "a".repeat(7))
|
||||
)
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidRegisterForms")
|
||||
fun `validate invalid register`(form: LoginForm) {
|
||||
assertThat(UserValidations.validateLogin(form), isLeftOfType<InvalidLoginForm>())
|
||||
}
|
||||
|
||||
@Suppress("Unused")
|
||||
fun validRegisterForms(): Stream<RegisterForm> = Stream.of(
|
||||
RegisterForm(username = "a".repeat(50), password = "a".repeat(72)),
|
||||
RegisterForm(username = "a".repeat(3), password = "a".repeat(8))
|
||||
)
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("validRegisterForms")
|
||||
fun `validate valid register`(form: LoginForm) {
|
||||
assertThat(UserValidations.validateLogin(form), isRight())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user