My Resumes history, modern M3 redesign, authenticated exports #2
@ -0,0 +1,81 @@
|
||||
package com.example.resbuilder
|
||||
|
||||
import com.example.resbuilder.data.model.JobListResponse
|
||||
import com.example.resbuilder.data.model.JobSummary
|
||||
import com.google.gson.Gson
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Tests for the API response models introduced with the "My Resumes" feature.
|
||||
*
|
||||
* These verify the exact wire format expected from `GET /jobs` so that a backend
|
||||
* contract change fails loudly here rather than silently breaking the UI.
|
||||
*/
|
||||
class JobListModelsTest {
|
||||
|
||||
private val gson = Gson()
|
||||
|
||||
@Test
|
||||
fun `parses a completed resume job from the backend shape`() {
|
||||
val json = """
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"job_id": "abc-123",
|
||||
"type": "resume",
|
||||
"status": "completed",
|
||||
"title": "Senior Android Engineer",
|
||||
"created_at": "2026-08-04T12:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val parsed = gson.fromJson(json, JobListResponse::class.java)
|
||||
|
||||
assertEquals(1, parsed.jobs.size)
|
||||
val job = parsed.jobs[0]
|
||||
assertEquals("abc-123", job.job_id)
|
||||
assertEquals("resume", job.type)
|
||||
assertEquals("completed", job.status)
|
||||
assertEquals("Senior Android Engineer", job.title)
|
||||
assertEquals("2026-08-04T12:00:00Z", job.created_at)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `title is null when backend omits it`() {
|
||||
val json = """
|
||||
{"jobs": [{"job_id": "x", "type": "cover_letter", "status": "queued"}]}
|
||||
""".trimIndent()
|
||||
|
||||
val parsed = gson.fromJson(json, JobListResponse::class.java)
|
||||
val job = parsed.jobs[0]
|
||||
|
||||
assertNull(job.title)
|
||||
assertNull(job.created_at)
|
||||
assertEquals("cover_letter", job.type)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `empty jobs list parses to empty collection`() {
|
||||
val json = """{"jobs": []}"""
|
||||
|
||||
val parsed = gson.fromJson(json, JobListResponse::class.java)
|
||||
|
||||
assertTrue(parsed.jobs.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JobSummary fields are immutable`() {
|
||||
val job = JobSummary(job_id = "id", type = "resume", status = "completed")
|
||||
|
||||
// Reflectively assert all fields are val (final). This guards against
|
||||
// regressions that would make the model mutable and thread-unsafe.
|
||||
for (field in JobSummary::class.java.declaredFields) {
|
||||
assertEquals("Field ${field.name} must be final", java.lang.reflect.Modifier.FINAL, field.modifiers and java.lang.reflect.Modifier.FINAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user