summaryrefslogtreecommitdiff
path: root/test-runner/src
diff options
context:
space:
mode:
Diffstat (limited to 'test-runner/src')
-rw-r--r--test-runner/src/main/kotlin/org/terst/nav/vessel/CrewMember.kt15
-rw-r--r--test-runner/src/main/kotlin/org/terst/nav/vessel/Vessel.kt22
-rw-r--r--test-runner/src/main/kotlin/org/terst/nav/vessel/VesselRepository.kt55
-rw-r--r--test-runner/src/test/kotlin/org/terst/nav/vessel/VesselRepositoryTest.kt154
4 files changed, 246 insertions, 0 deletions
diff --git a/test-runner/src/main/kotlin/org/terst/nav/vessel/CrewMember.kt b/test-runner/src/main/kotlin/org/terst/nav/vessel/CrewMember.kt
new file mode 100644
index 0000000..0df8cb9
--- /dev/null
+++ b/test-runner/src/main/kotlin/org/terst/nav/vessel/CrewMember.kt
@@ -0,0 +1,15 @@
+package org.terst.nav.vessel
+
+data class CrewMember(
+ val id: String,
+ val name: String,
+ val role: CrewRole = CrewRole.CREW,
+ val emergencyContact: String = "",
+ val emergencyPhone: String = "",
+ val certifications: List<String> = emptyList(),
+ val notes: String = ""
+)
+
+enum class CrewRole {
+ SKIPPER, FIRST_MATE, WATCH_CAPTAIN, CREW, GUEST
+}
diff --git a/test-runner/src/main/kotlin/org/terst/nav/vessel/Vessel.kt b/test-runner/src/main/kotlin/org/terst/nav/vessel/Vessel.kt
new file mode 100644
index 0000000..b7c0eaf
--- /dev/null
+++ b/test-runner/src/main/kotlin/org/terst/nav/vessel/Vessel.kt
@@ -0,0 +1,22 @@
+package org.terst.nav.vessel
+
+data class Vessel(
+ val id: String,
+ val name: String,
+ val mmsi: String = "",
+ val callsign: String = "",
+ val flag: String = "",
+ val homePort: String = "",
+ val hullType: HullType = HullType.MONOHULL,
+ val loaMeters: Double = 0.0,
+ val beamMeters: Double = 0.0,
+ val draftMeters: Double = 0.0,
+ val displacementKg: Double = 0.0,
+ val engineHp: Int = 0,
+ val notes: String = "",
+ val isOwnVessel: Boolean = false
+)
+
+enum class HullType {
+ MONOHULL, CATAMARAN, TRIMARAN, POWERBOAT, OTHER
+}
diff --git a/test-runner/src/main/kotlin/org/terst/nav/vessel/VesselRepository.kt b/test-runner/src/main/kotlin/org/terst/nav/vessel/VesselRepository.kt
new file mode 100644
index 0000000..fe4c44d
--- /dev/null
+++ b/test-runner/src/main/kotlin/org/terst/nav/vessel/VesselRepository.kt
@@ -0,0 +1,55 @@
+package org.terst.nav.vessel
+
+import java.util.UUID
+
+class VesselRepository {
+
+ private val vessels = mutableListOf<Vessel>()
+ private val crew = mutableListOf<CrewMember>()
+
+ fun addVessel(vessel: Vessel): Vessel {
+ val v = if (vessel.id.isBlank()) vessel.copy(id = UUID.randomUUID().toString()) else vessel
+ vessels.removeAll { it.id == v.id }
+ vessels.add(v)
+ return v
+ }
+
+ fun updateVessel(vessel: Vessel): Boolean {
+ val idx = vessels.indexOfFirst { it.id == vessel.id }
+ if (idx < 0) return false
+ vessels[idx] = vessel
+ return true
+ }
+
+ fun removeVessel(id: String): Boolean = vessels.removeAll { it.id == id }
+
+ fun getVessel(id: String): Vessel? = vessels.find { it.id == id }
+
+ fun getVessels(): List<Vessel> = vessels.toList()
+
+ fun getOwnVessel(): Vessel? = vessels.find { it.isOwnVessel }
+
+ fun addCrewMember(member: CrewMember): CrewMember {
+ val m = if (member.id.isBlank()) member.copy(id = UUID.randomUUID().toString()) else member
+ crew.removeAll { it.id == m.id }
+ crew.add(m)
+ return m
+ }
+
+ fun updateCrewMember(member: CrewMember): Boolean {
+ val idx = crew.indexOfFirst { it.id == member.id }
+ if (idx < 0) return false
+ crew[idx] = member
+ return true
+ }
+
+ fun removeCrewMember(id: String): Boolean = crew.removeAll { it.id == id }
+
+ fun getCrewMember(id: String): CrewMember? = crew.find { it.id == id }
+
+ fun getCrew(): List<CrewMember> = crew.toList()
+
+ fun getCrewByRole(role: CrewRole): List<CrewMember> = crew.filter { it.role == role }
+
+ fun getSkipper(): CrewMember? = crew.find { it.role == CrewRole.SKIPPER }
+}
diff --git a/test-runner/src/test/kotlin/org/terst/nav/vessel/VesselRepositoryTest.kt b/test-runner/src/test/kotlin/org/terst/nav/vessel/VesselRepositoryTest.kt
new file mode 100644
index 0000000..cec2a54
--- /dev/null
+++ b/test-runner/src/test/kotlin/org/terst/nav/vessel/VesselRepositoryTest.kt
@@ -0,0 +1,154 @@
+package org.terst.nav.vessel
+
+import org.junit.Assert.*
+import org.junit.Before
+import org.junit.Test
+
+class VesselRepositoryTest {
+
+ private lateinit var repo: VesselRepository
+
+ @Before
+ fun setup() {
+ repo = VesselRepository()
+ }
+
+ // --- Vessel tests ---
+
+ @Test
+ fun `addVessel with blank id assigns a generated id`() {
+ val v = repo.addVessel(Vessel(id = "", name = "Perseverance"))
+ assertTrue(v.id.isNotBlank())
+ }
+
+ @Test
+ fun `addVessel with explicit id preserves id`() {
+ val v = repo.addVessel(Vessel(id = "abc123", name = "Perseverance"))
+ assertEquals("abc123", v.id)
+ }
+
+ @Test
+ fun `getVessels returns all added vessels`() {
+ repo.addVessel(Vessel(id = "1", name = "Alpha"))
+ repo.addVessel(Vessel(id = "2", name = "Beta"))
+ assertEquals(2, repo.getVessels().size)
+ }
+
+ @Test
+ fun `getVessel returns correct vessel by id`() {
+ repo.addVessel(Vessel(id = "1", name = "Alpha"))
+ repo.addVessel(Vessel(id = "2", name = "Beta"))
+ assertEquals("Beta", repo.getVessel("2")?.name)
+ }
+
+ @Test
+ fun `updateVessel replaces vessel data`() {
+ repo.addVessel(Vessel(id = "1", name = "Alpha"))
+ val updated = repo.updateVessel(Vessel(id = "1", name = "Alpha II", loaMeters = 12.5))
+ assertTrue(updated)
+ assertEquals("Alpha II", repo.getVessel("1")?.name)
+ assertEquals(12.5, repo.getVessel("1")?.loaMeters ?: 0.0, 0.001)
+ }
+
+ @Test
+ fun `updateVessel returns false for unknown id`() {
+ assertFalse(repo.updateVessel(Vessel(id = "nope", name = "Ghost")))
+ }
+
+ @Test
+ fun `removeVessel removes by id`() {
+ repo.addVessel(Vessel(id = "1", name = "Alpha"))
+ repo.addVessel(Vessel(id = "2", name = "Beta"))
+ repo.removeVessel("1")
+ assertNull(repo.getVessel("1"))
+ assertEquals(1, repo.getVessels().size)
+ }
+
+ @Test
+ fun `getOwnVessel returns only own vessel`() {
+ repo.addVessel(Vessel(id = "1", name = "Alpha", isOwnVessel = true))
+ repo.addVessel(Vessel(id = "2", name = "Beta", isOwnVessel = false))
+ assertEquals("Alpha", repo.getOwnVessel()?.name)
+ }
+
+ @Test
+ fun `getOwnVessel returns null when none set`() {
+ repo.addVessel(Vessel(id = "1", name = "Alpha", isOwnVessel = false))
+ assertNull(repo.getOwnVessel())
+ }
+
+ @Test
+ fun `addVessel upserts on duplicate id`() {
+ repo.addVessel(Vessel(id = "1", name = "Alpha"))
+ repo.addVessel(Vessel(id = "1", name = "Alpha Updated"))
+ assertEquals(1, repo.getVessels().size)
+ assertEquals("Alpha Updated", repo.getVessel("1")?.name)
+ }
+
+ // --- Crew tests ---
+
+ @Test
+ fun `addCrewMember with blank id assigns generated id`() {
+ val m = repo.addCrewMember(CrewMember(id = "", name = "Jane Doe"))
+ assertTrue(m.id.isNotBlank())
+ }
+
+ @Test
+ fun `getCrew returns all crew members`() {
+ repo.addCrewMember(CrewMember(id = "c1", name = "Alice"))
+ repo.addCrewMember(CrewMember(id = "c2", name = "Bob"))
+ assertEquals(2, repo.getCrew().size)
+ }
+
+ @Test
+ fun `getSkipper returns skipper crew member`() {
+ repo.addCrewMember(CrewMember(id = "c1", name = "Alice", role = CrewRole.CREW))
+ repo.addCrewMember(CrewMember(id = "c2", name = "Bob", role = CrewRole.SKIPPER))
+ assertEquals("Bob", repo.getSkipper()?.name)
+ }
+
+ @Test
+ fun `getSkipper returns null when no skipper`() {
+ repo.addCrewMember(CrewMember(id = "c1", name = "Alice", role = CrewRole.CREW))
+ assertNull(repo.getSkipper())
+ }
+
+ @Test
+ fun `updateCrewMember updates role and details`() {
+ repo.addCrewMember(CrewMember(id = "c1", name = "Alice", role = CrewRole.CREW))
+ val ok = repo.updateCrewMember(
+ CrewMember(id = "c1", name = "Alice", role = CrewRole.FIRST_MATE, emergencyContact = "Bob")
+ )
+ assertTrue(ok)
+ assertEquals(CrewRole.FIRST_MATE, repo.getCrewMember("c1")?.role)
+ assertEquals("Bob", repo.getCrewMember("c1")?.emergencyContact)
+ }
+
+ @Test
+ fun `removeCrewMember removes by id`() {
+ repo.addCrewMember(CrewMember(id = "c1", name = "Alice"))
+ repo.addCrewMember(CrewMember(id = "c2", name = "Bob"))
+ repo.removeCrewMember("c1")
+ assertNull(repo.getCrewMember("c1"))
+ assertEquals(1, repo.getCrew().size)
+ }
+
+ @Test
+ fun `getCrewByRole filters correctly`() {
+ repo.addCrewMember(CrewMember(id = "c1", name = "Alice", role = CrewRole.CREW))
+ repo.addCrewMember(CrewMember(id = "c2", name = "Bob", role = CrewRole.WATCH_CAPTAIN))
+ repo.addCrewMember(CrewMember(id = "c3", name = "Carol", role = CrewRole.CREW))
+ val result = repo.getCrewByRole(CrewRole.CREW)
+ assertEquals(2, result.size)
+ assertTrue(result.all { it.role == CrewRole.CREW })
+ }
+
+ @Test
+ fun `vessel registry and crew are independent`() {
+ repo.addVessel(Vessel(id = "v1", name = "Alpha"))
+ repo.addCrewMember(CrewMember(id = "c1", name = "Alice"))
+ repo.removeVessel("v1")
+ assertEquals(1, repo.getCrew().size)
+ assertEquals(0, repo.getVessels().size)
+ }
+}