Skip to content
Open
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
4 changes: 4 additions & 0 deletions chessevolved_model/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dependencies {
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion"
api "org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion"


// BEGIN SUPABASE DEPENDENCIES
implementation platform("io.github.jan-tennert.supabase:bom:$supabaseVersion")
implementation 'io.github.jan-tennert.supabase:postgrest-kt' //DB Operations
Expand All @@ -61,6 +62,9 @@ dependencies {
// Testing with kotlin.test and JUnit
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.1"

testImplementation "org.mockito:mockito-core:5.+"
testImplementation "org.mockito.kotlin:mockito-kotlin:5.+"
}

test {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package io.github.chessevolved.entities

import com.badlogic.ashley.core.Engine
import com.badlogic.gdx.assets.AssetManager
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.TextureRegion
import io.github.chessevolved.components.AbilityComponent
import io.github.chessevolved.enums.AbilityType
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import kotlin.test.assertEquals

class AbilityItemFactoryTest {
private lateinit var engine: Engine
private lateinit var assetManager: AssetManager
private lateinit var factory: AbilityItemFactory
private lateinit var mockTexture: TextureRegion

/**
* Mock the AssetManager to return a mock Texture for each ability type.
* This allows us to test the AbilityItemFactory without loading actual textures.
*/
@BeforeEach
fun setUp() {
engine = Engine()
assetManager = mock(AssetManager::class.java)
mockTexture = mock(TextureRegion::class.java)
AbilityType.values().forEach { type ->
val path = "abilities/cards/${type.toString().lowercase()}Card.png"
`when`(assetManager.get(path, Texture::class.java)).thenReturn(mock(Texture::class.java))
}

factory = AbilityItemFactory(engine, assetManager)
}

/**
* Test that that each ability type created by the factory has the correct cooldown time
*/
@Test
fun `test cooldown values`() {
val expectedCooldowns =
mapOf(
AbilityType.SHIELD to 3,
AbilityType.EXPLOSION to 2,
AbilityType.SWAP to 2,
AbilityType.MIRROR to 3,
AbilityType.NEW_MOVEMENT to 0,
)

expectedCooldowns.forEach { (abilityType, expectedCooldown) ->
val entity = factory.createAbilityItem(abilityType)
val abilityComponent = entity.getComponent(AbilityComponent::class.java)

assertEquals(expectedCooldown, abilityComponent.abilityCooldownTime)
}
}

/**
* Test that the AbilityItemFactory adds one entity to the engine for each ability type.
*/
@Test
fun `test entity added to engine`() {
val initialEntityCount = engine.entities.size()
AbilityType.values().forEach { abilityType ->
factory.createAbilityItem(abilityType)
}

assertEquals(
initialEntityCount + AbilityType.values().size,
engine.entities.size(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PieceFactoryTest {
fun createPawn() {
assertFails({
pieceFactory.createPawn(
false,
// false,
Position(1000, 1000),
PlayerColor.BLACK,
Stage(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package io.github.chessevolved.systems

import com.badlogic.ashley.core.Entity
import com.badlogic.gdx.assets.AssetManager
import io.github.chessevolved.components.AbilityComponent
import io.github.chessevolved.components.AbilityTriggerComponent
import io.github.chessevolved.components.BlockedComponent
import io.github.chessevolved.components.PlayerColorComponent
import io.github.chessevolved.components.VisualEffectComponent
import io.github.chessevolved.data.Position
import io.github.chessevolved.enums.AbilityType
import io.github.chessevolved.enums.PlayerColor
import io.github.chessevolved.singletons.EcsEngine
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.Mockito.mock
import kotlin.test.assertEquals
import kotlin.test.assertNull

class AbilitySystemTest {
private lateinit var abilitySystem: AbilitySystem
private lateinit var assetManager: AssetManager

/**
* Setup a clean ECS engine state before each test.
*/
@BeforeEach
fun setUp() {
assetManager = mock(AssetManager::class.java)
EcsEngine.removeAllEntities()
val systems = EcsEngine.systems.toList()
systems.forEach { EcsEngine.removeSystem(it) }
abilitySystem = AbilitySystem()
EcsEngine.addSystem(abilitySystem)
}

/**
* Verifies that ability cooldown time decrements after
* the system processes an entity with an ability.
*/
@Test
fun `test that cooldown decrements time`() {
val entity = Entity()
val abilityComponent = AbilityComponent(AbilityType.EXPLOSION, 5, 3)

entity.add(abilityComponent)
entity.add(AbilityTriggerComponent(Position(0, 0), Position(0, 0)))
entity.add(PlayerColorComponent(PlayerColor.WHITE))
EcsEngine.addEntity(entity)
EcsEngine.update(0f)

assertEquals(2, abilityComponent.currentAbilityCDTime)
}

/**
* Verifies that triggering an EXPLOSION ability
* creates a new entity with a VisualEffectComponent.
*/
@Test
fun `test that explosion effect creates a visual effect`() {
val entity =
Entity().apply {
add(AbilityComponent(AbilityType.EXPLOSION, 5, 0))
add(AbilityTriggerComponent(Position(0, 0), Position(0, 0)))
add(PlayerColorComponent(PlayerColor.WHITE))
}

EcsEngine.addEntity(entity)
EcsEngine.update(0f)
val effectEntities =
EcsEngine.entities.filter {
it.getComponent(VisualEffectComponent::class.java) != null
}

assertEquals(1, effectEntities.size)
}

/**
* Verifies that triggering a SHIELD ability
* adds a BlockedComponent to the same entity.
*/
@Test
fun `test that shield effect adds a blocked component`() {
val entity =
Entity().apply {
add(AbilityComponent(AbilityType.SHIELD, 5, 0))
add(AbilityTriggerComponent(Position(1, 1), Position(0, 0)))
}

EcsEngine.addEntity(entity)
EcsEngine.update(0f)
val blockedComponent = entity.getComponent(BlockedComponent::class.java)

assert(blockedComponent != null)
}

/**
* Ensures that after an ability is triggered and processed,
* the AbilityTriggerComponent is removed from the entity.
*/
@Test
fun `test that ability trigger component is removed after processing`() {
val entity =
Entity().apply {
add(AbilityComponent(AbilityType.EXPLOSION, 5, 0))
add(AbilityTriggerComponent(Position(0, 0), Position(0, 0)))
add(PlayerColorComponent(PlayerColor.WHITE))
}

EcsEngine.addEntity(entity)
EcsEngine.update(0f)

assertNull(entity.getComponent(AbilityTriggerComponent::class.java))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package io.github.chessevolved.systems

import com.badlogic.ashley.core.Entity
import io.github.chessevolved.components.ActorComponent
import io.github.chessevolved.components.CanBeCapturedComponent
import io.github.chessevolved.components.CapturedComponent
import io.github.chessevolved.components.MovementIntentComponent
import io.github.chessevolved.components.PieceTypeComponent
import io.github.chessevolved.components.PositionComponent
import io.github.chessevolved.components.SelectionComponent
import io.github.chessevolved.data.Position
import io.github.chessevolved.enums.PieceType
import io.github.chessevolved.singletons.EcsEngine
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.kotlin.mock
import kotlin.test.assertNotNull
import kotlin.test.assertNull

class CaptureSystemTest {
private lateinit var system: CaptureSystem

/**
* Resets ECS state and adds a fresh instance of the CaptureSystem
* before each test.
*/
@BeforeEach
fun setUp() {
EcsEngine.removeAllEntities()
EcsEngine.systems.toList().forEach { EcsEngine.removeSystem(it) }
system = CaptureSystem()
EcsEngine.addSystem(system)
}

/**
* Test that the system correctly removes the captured entity
* and updates the capturing entity's components.
*/
@Test
fun `test that entity captured not by ability triggers the movement intent`() {
val captured =
Entity().apply {
add(PositionComponent(Position(2, 3)))
add(CapturedComponent(capturedByAbility = false))
add(ActorComponent(mock()))
}

val capturing =
Entity().apply {
add(PieceTypeComponent(PieceType.KNIGHT))
add(SelectionComponent())
}

EcsEngine.addEntity(captured)
EcsEngine.addEntity(capturing)
EcsEngine.update(0f)

assertNull(EcsEngine.entities.find { it == captured })
assertNotNull(capturing.getComponent(MovementIntentComponent::class.java))
}

/**
* Verifies that all entities with CanBeCapturedComponent have it removed
* once the CaptureSystem processes a captured piece.
*/
@Test
fun `test that CanBeCapturedComponent is removed`() {
val piece1 = Entity().apply { add(CanBeCapturedComponent()) }
val piece2 = Entity().apply { add(CanBeCapturedComponent()) }
val captured =
Entity().apply {
add(PositionComponent(Position(0, 0)))
add(CapturedComponent())
add(ActorComponent(mock()))
}

EcsEngine.addEntity(piece1)
EcsEngine.addEntity(piece2)
EcsEngine.addEntity(captured)
EcsEngine.update(0f)

assertNull(piece1.getComponent(CanBeCapturedComponent::class.java))
assertNull(piece2.getComponent(CanBeCapturedComponent::class.java))
}
}
Loading