My Resumes history, modern M3 redesign, authenticated exports #2

Merged
armistace merged 10 commits from feature/my-resumes-modern into master 2026-08-04 23:58:13 +10:00
Showing only changes of commit 54b002b72f - Show all commits

View File

@ -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)
}
}
}