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