Improve tests
This commit is contained in:
@@ -120,7 +120,6 @@ fun App(
|
|||||||
textAlign = TextAlign.End
|
textAlign = TextAlign.End
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
spacing = spacing,
|
|
||||||
game, resetCluesBeacon
|
game, resetCluesBeacon
|
||||||
)
|
)
|
||||||
EndOfGame(isSolved = isSolved, time = time, onRestart = onNewGame)
|
EndOfGame(isSolved = isSolved, time = time, onRestart = onNewGame)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import androidx.compose.ui.layout.Layout
|
|||||||
import androidx.compose.ui.layout.Placeable
|
import androidx.compose.ui.layout.Placeable
|
||||||
import androidx.compose.ui.unit.Constraints
|
import androidx.compose.ui.unit.Constraints
|
||||||
import androidx.compose.ui.unit.Constraints.Companion.fixed
|
import androidx.compose.ui.unit.Constraints.Companion.fixed
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ch.dissem.yaep.ui.common.focus.CluesSelectionManager
|
import ch.dissem.yaep.ui.common.focus.CluesSelectionManager
|
||||||
import ch.dissem.yaep.ui.common.focus.FocusFollowingFocusable
|
import ch.dissem.yaep.ui.common.focus.FocusFollowingFocusable
|
||||||
@@ -29,7 +28,6 @@ fun AdaptiveGameLayout(
|
|||||||
horizontalClues: @Composable (SelectionManager<*>) -> Unit,
|
horizontalClues: @Composable (SelectionManager<*>) -> Unit,
|
||||||
verticalClues: @Composable (SelectionManager<*>) -> Unit,
|
verticalClues: @Composable (SelectionManager<*>) -> Unit,
|
||||||
time: @Composable () -> Unit,
|
time: @Composable () -> Unit,
|
||||||
spacing: Dp = 8.dp,
|
|
||||||
vararg resetBeacons: Any
|
vararg resetBeacons: Any
|
||||||
) {
|
) {
|
||||||
val gridFocusable = remember(*resetBeacons) { selectionManager.add() }
|
val gridFocusable = remember(*resetBeacons) { selectionManager.add() }
|
||||||
@@ -80,7 +78,7 @@ fun AdaptiveGameLayout(
|
|||||||
val timeMeasurable = measurables[6][0]
|
val timeMeasurable = measurables[6][0]
|
||||||
val dividerMeasurables = measurables[7]
|
val dividerMeasurables = measurables[7]
|
||||||
|
|
||||||
val spacingPx = spacing.roundToPx()
|
val spacingPx = 8.dp.roundToPx()
|
||||||
|
|
||||||
when (aspectRatio) {
|
when (aspectRatio) {
|
||||||
PORTRAIT -> {
|
PORTRAIT -> {
|
||||||
|
|||||||
@@ -1,20 +1,30 @@
|
|||||||
package ch.dissem.yaep.ui.common
|
package ch.dissem.yaep.ui.common
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
|
import androidx.compose.ui.input.key.Key
|
||||||
|
import androidx.compose.ui.input.key.onKeyEvent
|
||||||
import androidx.compose.ui.test.ExperimentalTestApi
|
import androidx.compose.ui.test.ExperimentalTestApi
|
||||||
import androidx.compose.ui.test.SkikoComposeUiTest
|
import androidx.compose.ui.test.SkikoComposeUiTest
|
||||||
import androidx.compose.ui.test.onNodeWithTag
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
|
import androidx.compose.ui.test.onRoot
|
||||||
|
import androidx.compose.ui.test.performKeyInput
|
||||||
|
import androidx.compose.ui.test.pressKey
|
||||||
import androidx.compose.ui.test.runSkikoComposeUiTest
|
import androidx.compose.ui.test.runSkikoComposeUiTest
|
||||||
|
import androidx.compose.ui.test.withKeyDown
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ch.dissem.yaep.domain.Game
|
import ch.dissem.yaep.domain.Game
|
||||||
import ch.dissem.yaep.domain.UnsolvablePuzzleException
|
import ch.dissem.yaep.domain.UnsolvablePuzzleException
|
||||||
import ch.dissem.yaep.ui.common.focus.FocusFollowingSelectionManager
|
import ch.dissem.yaep.ui.common.focus.FocusFollowingSelectionManager
|
||||||
|
import ch.dissem.yaep.ui.common.focus.GridSelectionManager
|
||||||
|
import ch.tutteli.atrium.api.fluent.en_GB.notToEqualNull
|
||||||
|
import ch.tutteli.atrium.api.fluent.en_GB.toBeAnInstanceOf
|
||||||
import ch.tutteli.atrium.api.fluent.en_GB.toEqual
|
import ch.tutteli.atrium.api.fluent.en_GB.toEqual
|
||||||
|
import ch.tutteli.atrium.api.fluent.en_GB.toHaveElementsAndAll
|
||||||
|
import ch.tutteli.atrium.api.fluent.en_GB.toHaveSize
|
||||||
import ch.tutteli.atrium.api.verbs.expect
|
import ch.tutteli.atrium.api.verbs.expect
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.fail
|
import kotlin.test.fail
|
||||||
@@ -25,7 +35,7 @@ class AppTest {
|
|||||||
var resetCluesBeacon by mutableStateOf(Any())
|
var resetCluesBeacon by mutableStateOf(Any())
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensure_app_can_be_rendered_on_1920x1080_and_can_be_solved() = ensure_app_can_be_rendered_on(
|
fun ensure_app_can_be_rendered_on_1920x1080_and_can_be_solved() = showApp(
|
||||||
Size(1920f, 1080f)
|
Size(1920f, 1080f)
|
||||||
) {
|
) {
|
||||||
val clues = game.clues
|
val clues = game.clues
|
||||||
@@ -49,31 +59,89 @@ class AppTest {
|
|||||||
} while (removedOptions)
|
} while (removedOptions)
|
||||||
|
|
||||||
expect(game.isSolved).toEqual(true)
|
expect(game.isSolved).toEqual(true)
|
||||||
onNodeWithTag("EndOfGame.solved_time").assertExists("End of Game must be shown when puzzle is solved")
|
onNodeWithTag("EndOfGame.solved_time")
|
||||||
|
.assertExists("End of Game must be shown when puzzle is solved")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensure_app_can_be_rendered_on_1080x1920() = ensure_app_can_be_rendered_on(
|
fun ensure_app_can_be_rendered_on_1080x1920_and_keyboard_selection_and_deselection_works() = showApp(
|
||||||
Size(1080f, 1920f)
|
Size(1080f, 1920f)
|
||||||
)
|
) {
|
||||||
|
expect(game.grid[0][1].selection).toEqual(null)
|
||||||
|
expect(FocusFollowingSelectionManager.focused).notToEqualNull()
|
||||||
|
expect(FocusFollowingSelectionManager.focused?.child).toBeAnInstanceOf<GridSelectionManager>()
|
||||||
|
onRoot().performKeyInput {
|
||||||
|
pressKey(Key.DirectionRight)
|
||||||
|
pressKey(Key.One)
|
||||||
|
}
|
||||||
|
expect(game.grid[0][1].selection).notToEqualNull()
|
||||||
|
|
||||||
|
onRoot().performKeyInput {
|
||||||
|
pressKey(Key.Backspace)
|
||||||
|
}
|
||||||
|
expect(game.grid[0][1].selection).toEqual(null)
|
||||||
|
expect(game.grid.map { it.options }).toHaveElementsAndAll {
|
||||||
|
toHaveSize(6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensure_app_can_be_rendered_on_800x600() = ensure_app_can_be_rendered_on(
|
fun ensure_app_can_be_rendered_on_800x600_and_keyboard_option_removal_works() = showApp(
|
||||||
Size(800f, 600f)
|
Size(800f, 600f)
|
||||||
)
|
) {
|
||||||
|
val gridCell = game.grid[0][1]
|
||||||
|
|
||||||
|
expect(gridCell.selection).toEqual(null)
|
||||||
|
onRoot().performKeyInput {
|
||||||
|
pressKey(Key.DirectionRight)
|
||||||
|
withKeyDown(Key.ShiftLeft) {
|
||||||
|
expect(gridCell.options).toHaveSize(6)
|
||||||
|
pressKey(Key.One)
|
||||||
|
expect(gridCell.options).toHaveSize(5)
|
||||||
|
pressKey(Key.Two)
|
||||||
|
expect(gridCell.options).toHaveSize(4)
|
||||||
|
pressKey(Key.Three)
|
||||||
|
expect(gridCell.options).toHaveSize(3)
|
||||||
|
pressKey(Key.Four)
|
||||||
|
expect(gridCell.options).toHaveSize(2)
|
||||||
|
pressKey(Key.Five)
|
||||||
|
expect(gridCell.options).toHaveSize(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(gridCell.selection).notToEqualNull()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensure_app_can_be_rendered_on_600x800() = ensure_app_can_be_rendered_on(
|
fun ensure_app_can_be_rendered_on_600x800_and_numpad_option_selection_works() = showApp(
|
||||||
Size(600f, 800f)
|
Size(600f, 800f)
|
||||||
)
|
) {
|
||||||
|
val gridCell = game.grid[0][1]
|
||||||
|
|
||||||
fun ensure_app_can_be_rendered_on(
|
onRoot().performKeyInput {
|
||||||
|
pressKey(Key.DirectionRight)
|
||||||
|
withKeyDown(Key.ShiftLeft) {
|
||||||
|
expect(gridCell.options).toHaveSize(6)
|
||||||
|
pressKey(Key.NumPad1)
|
||||||
|
expect(gridCell.options).toHaveSize(5)
|
||||||
|
pressKey(Key.NumPad5)
|
||||||
|
expect(gridCell.options).toHaveSize(4)
|
||||||
|
pressKey(Key.NumPad5)
|
||||||
|
expect(gridCell.options).toHaveSize(5)
|
||||||
|
pressKey(Key.NumPad4)
|
||||||
|
expect(gridCell.options).toHaveSize(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showApp(
|
||||||
screenSize: Size,
|
screenSize: Size,
|
||||||
block: suspend SkikoComposeUiTest.() -> Unit = {}
|
block: suspend SkikoComposeUiTest.() -> Unit = {}
|
||||||
) = runSkikoComposeUiTest(size = screenSize) {
|
) = runSkikoComposeUiTest(size = screenSize) {
|
||||||
setContent {
|
setContent {
|
||||||
App(
|
App(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.onKeyEvent { event ->
|
||||||
|
FocusFollowingSelectionManager.onKeyEvent(event)
|
||||||
|
},
|
||||||
rootSelectionManager = FocusFollowingSelectionManager,
|
rootSelectionManager = FocusFollowingSelectionManager,
|
||||||
spacing = 8.dp,
|
spacing = 8.dp,
|
||||||
game = game,
|
game = game,
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package ch.dissem.yaep.ui.common
|
||||||
|
|
||||||
|
import androidx.compose.ui.test.ExperimentalTestApi
|
||||||
|
import androidx.compose.ui.test.runComposeUiTest
|
||||||
|
import ch.dissem.yaep.domain.Animal
|
||||||
|
import ch.dissem.yaep.domain.Drink
|
||||||
|
import ch.dissem.yaep.domain.Fruit
|
||||||
|
import ch.dissem.yaep.domain.ItemClass
|
||||||
|
import ch.dissem.yaep.domain.Nationality
|
||||||
|
import ch.dissem.yaep.domain.Profession
|
||||||
|
import ch.dissem.yaep.domain.Transportation
|
||||||
|
import ch.tutteli.atrium.api.fluent.en_GB.notToBeBlank
|
||||||
|
import ch.tutteli.atrium.api.fluent.en_GB.toHaveElementsAndAll
|
||||||
|
import ch.tutteli.atrium.api.verbs.expect
|
||||||
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
@OptIn(ExperimentalTestApi::class)
|
||||||
|
class NamesTest {
|
||||||
|
@Test
|
||||||
|
fun ensure_names_are_defined_for_animal() {
|
||||||
|
ensure_names_are_defined_for(Animal.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ensure_names_are_defined_for_nationality() {
|
||||||
|
ensure_names_are_defined_for(Nationality.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ensure_names_are_defined_for_drink() {
|
||||||
|
ensure_names_are_defined_for(Drink.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ensure_names_are_defined_for_profession() {
|
||||||
|
ensure_names_are_defined_for(Profession.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ensure_names_are_defined_for_fruit() {
|
||||||
|
ensure_names_are_defined_for(Fruit.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ensure_names_are_defined_for_dessert() {
|
||||||
|
ensure_names_are_defined_for(Fruit.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ensure_names_are_defined_for_transportation() {
|
||||||
|
ensure_names_are_defined_for(Transportation.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ensure_names_are_defined_for(items: List<ItemClass<*>>) {
|
||||||
|
runComposeUiTest {
|
||||||
|
var strings = listOf<String>()
|
||||||
|
setContent {
|
||||||
|
strings = items.map { stringResource(it.localName) }
|
||||||
|
}
|
||||||
|
expect(strings).toHaveElementsAndAll {
|
||||||
|
notToBeBlank()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package ch.dissem.yaep.ui.common.focus
|
package ch.dissem.yaep.ui.common.focus
|
||||||
|
|
||||||
import androidx.compose.ui.InternalComposeUiApi
|
|
||||||
import androidx.compose.ui.input.key.Key
|
import androidx.compose.ui.input.key.Key
|
||||||
import androidx.compose.ui.input.key.KeyEvent
|
|
||||||
import androidx.compose.ui.input.key.KeyEventType
|
import androidx.compose.ui.input.key.KeyEventType
|
||||||
import ch.tutteli.atrium.api.fluent.en_GB.toEqual
|
import ch.tutteli.atrium.api.fluent.en_GB.toEqual
|
||||||
import ch.tutteli.atrium.api.verbs.expect
|
import ch.tutteli.atrium.api.verbs.expect
|
||||||
@@ -58,10 +56,4 @@ abstract class SelectionManagerTest<F : Focusable<F>, M : SelectionManager<F>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(InternalComposeUiApi::class)
|
|
||||||
fun keyEvent(key: Key, type: KeyEventType = KeyEventType.KeyUp) = KeyEvent(
|
|
||||||
key = key,
|
|
||||||
type = type
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package ch.dissem.yaep.ui.common.focus
|
||||||
|
|
||||||
|
import androidx.compose.ui.InternalComposeUiApi
|
||||||
|
import androidx.compose.ui.input.key.Key
|
||||||
|
import androidx.compose.ui.input.key.KeyEvent
|
||||||
|
import androidx.compose.ui.input.key.KeyEventType
|
||||||
|
|
||||||
|
@OptIn(InternalComposeUiApi::class)
|
||||||
|
fun keyEvent(key: Key, type: KeyEventType = KeyEventType.KeyUp) = KeyEvent(
|
||||||
|
key = key,
|
||||||
|
type = type
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user