Skip to content
Merged
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
Expand Up @@ -12,11 +12,18 @@ import dev.appoutlet.some.android.resolver.SizeResolver
import dev.appoutlet.some.android.resolver.UriResolver
import dev.appoutlet.some.android.resolver.UserHandleResolver
import dev.appoutlet.some.android.resolver.compose.AnnotatedStringResolver
import dev.appoutlet.some.android.resolver.compose.DpResolver
import dev.appoutlet.some.android.resolver.compose.IntOffsetResolver
import dev.appoutlet.some.android.resolver.compose.IntSizeResolver
import dev.appoutlet.some.android.resolver.compose.OffsetResolver
import dev.appoutlet.some.android.resolver.compose.SpResolver
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverProvider
import dev.appoutlet.some.core.StrategyProvider
import kotlin.random.Random
import dev.appoutlet.some.android.resolver.compose.ColorResolver as ComposeColorResolver
import dev.appoutlet.some.android.resolver.compose.RectResolver as ComposeRectResolver
import dev.appoutlet.some.android.resolver.compose.SizeResolver as ComposeSizeResolver

/**
* Contributes Android-specific resolvers discovered through `ServiceLoader`.
Expand All @@ -35,19 +42,26 @@ class AndroidResolverProvider : ResolverProvider {
random: Random
): List<Resolver> {
return listOf(
UriResolver(strategyProvider, random),
BundleResolver(random),
RectResolver(random),
RectFResolver(random),
PointResolver(random),
ColorResolver(random),
PairResolver(random),
PointFResolver(random),
SizeResolver(random),
PointResolver(random),
RectFResolver(random),
RectResolver(random),
SizeFResolver(random),
PairResolver(random),
SizeResolver(random),
UriResolver(strategyProvider, random),
UserHandleResolver(random),
ColorResolver(random),
AnnotatedStringResolver(random),
ComposeColorResolver(strategyProvider, random),
DpResolver(random),
IntOffsetResolver(random),
IntSizeResolver(random),
OffsetResolver(random),
ComposeRectResolver(random),
ComposeSizeResolver(random),
SpResolver(random),
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.unit.Dp
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverChain
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

private const val MAX_DP = 1000f

/**
* Resolves [Dp] types with randomized float values.
*
* @param random Random source used when generating values.
*/
class DpResolver(
private val random: Random
) : Resolver {
override fun canResolve(type: KType): Boolean = type == typeOf<Dp>()

override fun resolve(type: KType, chain: ResolverChain): Any {
return Dp(random.nextFloat() * MAX_DP)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.unit.IntOffset
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverChain
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

private const val COORDINATE_BOUND = 1000

/**
* Resolves [IntOffset] types with randomized integer coordinates.
*
* @param random Random source used when generating coordinates.
*/
class IntOffsetResolver(
private val random: Random
) : Resolver {
override fun canResolve(type: KType): Boolean = type == typeOf<IntOffset>()

override fun resolve(type: KType, chain: ResolverChain): Any {
val x = random.nextInt(-COORDINATE_BOUND, COORDINATE_BOUND)
val y = random.nextInt(-COORDINATE_BOUND, COORDINATE_BOUND)
return IntOffset(x, y)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.unit.IntSize
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverChain
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

private const val MAX_DIMENSION = 1000

/**
* Resolves [IntSize] types with randomized positive integer dimensions.
*
* @param random Random source used when generating dimensions.
*/
class IntSizeResolver(
private val random: Random
) : Resolver {
override fun canResolve(type: KType): Boolean = type == typeOf<IntSize>()

override fun resolve(type: KType, chain: ResolverChain): Any {
val width = random.nextInt(1, MAX_DIMENSION)
val height = random.nextInt(1, MAX_DIMENSION)
return IntSize(width, height)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.geometry.Offset
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverChain
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

private const val COORDINATE_BOUND = 1000f

/**
* Resolves [Offset] types with randomized float coordinates.
*
* @param random Random source used when generating coordinates.
*/
class OffsetResolver(
private val random: Random
) : Resolver {
override fun canResolve(type: KType): Boolean = type == typeOf<Offset>()

override fun resolve(type: KType, chain: ResolverChain): Any {
val x = (random.nextFloat() * 2 - 1) * COORDINATE_BOUND
val y = (random.nextFloat() * 2 - 1) * COORDINATE_BOUND
return Offset(x, y)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.geometry.Rect
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverChain
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

private const val COORDINATE_BOUND = 1000f

/**
* Resolves [Rect] types with randomized float bounds.
*
* Generated rectangles always satisfy `left < right` and `top < bottom`.
*
* @param random Random source used when generating coordinates.
*/
class RectResolver(
private val random: Random
) : Resolver {
override fun canResolve(type: KType): Boolean = type == typeOf<Rect>()

override fun resolve(type: KType, chain: ResolverChain): Any {
val left = (random.nextFloat() * 2 - 1) * COORDINATE_BOUND
val top = (random.nextFloat() * 2 - 1) * COORDINATE_BOUND
val right = left + random.nextFloat() * COORDINATE_BOUND
val bottom = top + random.nextFloat() * COORDINATE_BOUND
return Rect(left, top, right, bottom)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.geometry.Size
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverChain
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

private const val MAX_DIMENSION = 1000f

/**
* Resolves [Size] types with randomized positive float dimensions.
*
* @param random Random source used when generating dimensions.
*/
class SizeResolver(
private val random: Random
) : Resolver {
override fun canResolve(type: KType): Boolean = type == typeOf<Size>()

override fun resolve(type: KType, chain: ResolverChain): Any {
val width = random.nextFloat() * MAX_DIMENSION
val height = random.nextFloat() * MAX_DIMENSION
return Size(width, height)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
import dev.appoutlet.some.core.Resolver
import dev.appoutlet.some.core.ResolverChain
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

private const val MAX_SP = 100f

/**
* Resolves [TextUnit] types with randomized float values in `sp`.
*
* @param random Random source used when generating values.
*/
class SpResolver(
private val random: Random
) : Resolver {
override fun canResolve(type: KType): Boolean = type == typeOf<TextUnit>()

override fun resolve(type: KType, chain: ResolverChain): Any {
return (random.nextFloat() * MAX_SP).sp
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ import dev.appoutlet.some.android.resolver.SizeResolver
import dev.appoutlet.some.android.resolver.UriResolver
import dev.appoutlet.some.android.resolver.UserHandleResolver
import dev.appoutlet.some.android.resolver.compose.AnnotatedStringResolver
import dev.appoutlet.some.android.resolver.compose.DpResolver
import dev.appoutlet.some.android.resolver.compose.IntOffsetResolver
import dev.appoutlet.some.android.resolver.compose.IntSizeResolver
import dev.appoutlet.some.android.resolver.compose.OffsetResolver
import dev.appoutlet.some.android.resolver.compose.SpResolver
import dev.appoutlet.some.config.DefaultStrategyProvider
import org.junit.Assert.assertEquals
import org.junit.Test
import kotlin.random.Random
import dev.appoutlet.some.android.resolver.compose.ColorResolver as ComposeColorResolver
import dev.appoutlet.some.android.resolver.compose.RectResolver as ComposeRectResolver
import dev.appoutlet.some.android.resolver.compose.SizeResolver as ComposeSizeResolver

class AndroidResolverProviderTest {
@Test
Expand All @@ -25,20 +32,28 @@ class AndroidResolverProviderTest {

assertEquals(
listOf(
UriResolver::class,
BundleResolver::class,
RectResolver::class,
RectFResolver::class,
PointResolver::class,
ColorResolver::class,
PairResolver::class,
PointFResolver::class,
SizeResolver::class,
PointResolver::class,
RectFResolver::class,
RectResolver::class,
SizeFResolver::class,
PairResolver::class,
SizeResolver::class,
UriResolver::class,
UserHandleResolver::class,
ColorResolver::class,
AnnotatedStringResolver::class,
ComposeColorResolver::class,
DpResolver::class,
IntOffsetResolver::class,
IntSizeResolver::class,
OffsetResolver::class,
ComposeRectResolver::class,
ComposeSizeResolver::class,
SpResolver::class,
),

resolvers.map { it::class }
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package dev.appoutlet.some.android

import android.graphics.Point
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.TextUnit
import dev.appoutlet.some.some
import org.junit.Assert.assertTrue
import org.junit.Test
Expand Down Expand Up @@ -31,4 +38,15 @@ class AndroidServiceLoaderTest {
val result: ComposeColor = some()
assertTrue(result.alpha in 0f..1f)
}

@Test
fun `top-level some resolves Compose types through AndroidResolverProvider`() {
assertTrue(some<Dp>() is Dp)
assertTrue(some<TextUnit>().isSp)
assertTrue(some<Offset>() is Offset)
assertTrue(some<Size>() is Size)
assertTrue(some<Rect>() is Rect)
assertTrue(some<IntOffset>() is IntOffset)
assertTrue(some<IntSize>() is IntSize)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package dev.appoutlet.some.android.resolver.compose

import androidx.compose.ui.unit.Dp
import dev.appoutlet.some.config.NullableStrategy
import dev.appoutlet.some.core.ResolverChain
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import kotlin.random.Random
import kotlin.reflect.typeOf

@RunWith(RobolectricTestRunner::class)
class DpResolverTest {
@Test
fun `DpResolver generates Dp values`() {
val resolver = DpResolver(Random.Default)
val result = resolver.resolve(typeOf<Dp>(), testChain)
assertTrue(result is Dp)
}

@Test
fun `DpResolver generates values within range`() {
val resolver = DpResolver(Random.Default)
repeat(100) {
val result = resolver.resolve(typeOf<Dp>(), testChain) as Dp
assertTrue(result.value in 0f..1000f)
}
}

@Test
fun `DpResolver canResolve detects Dp type`() {
val resolver = DpResolver(Random.Default)
assertTrue(resolver.canResolve(typeOf<Dp>()))
}

@Test
fun `DpResolver rejects non-Dp types`() {
val resolver = DpResolver(Random.Default)
assertFalse(resolver.canResolve(typeOf<Float>()))
assertFalse(resolver.canResolve(typeOf<Int>()))
}

companion object {
private val testChain = ResolverChain(emptyList(), NullableStrategy.NullOnCircularReference)
}
}
Loading