@@ -87,6 +87,11 @@ class ConnectOpportunitiesParserTest {
8787 put(" learn_modules" , JSONArray ())
8888 }
8989
90+ private fun claimedJobJson (
91+ id : Int ,
92+ claim : JSONObject ,
93+ ): JSONObject = validJobJson(id).apply { put(" claim" , claim) }
94+
9095 private fun jsonArrayOf (vararg objects : JSONObject ): ByteArrayInputStream {
9196 val array = JSONArray ().apply { objects.forEach { put(it) } }
9297 return ByteArrayInputStream (array.toString().toByteArray())
@@ -225,4 +230,111 @@ class ConnectOpportunitiesParserTest {
225230 }
226231 verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
227232 }
233+
234+ @Test
235+ fun `parse stores valid job and skips job with malformed end_date` () {
236+ val malformedJob = validJobJson(10 ).apply { put(" end_date" , " not-a-date" ) }
237+ val inputStream = jsonArrayOf(validJobJson(1 ), malformedJob)
238+ every { ConnectJobUtils .storeJobs(any(), any(), any()) } returns 1
239+ every { ConnectReleaseTogglesWorker .scheduleOneTimeFetch(any()) } just Runs
240+
241+ assertThrows(JSONException ::class .java) {
242+ parser.parse(200 , inputStream, null )
243+ }
244+ verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
245+ }
246+
247+ @Test
248+ fun `parse stores valid job and skips job with null start_date` () {
249+ val nullStartJob = validJobJson(10 ).apply { put(" start_date" , JSONObject .NULL ) }
250+ val inputStream = jsonArrayOf(validJobJson(1 ), nullStartJob)
251+ every { ConnectJobUtils .storeJobs(any(), any(), any()) } returns 1
252+ every { ConnectReleaseTogglesWorker .scheduleOneTimeFetch(any()) } just Runs
253+
254+ assertThrows(JSONException ::class .java) {
255+ parser.parse(200 , inputStream, null )
256+ }
257+ verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
258+ }
259+
260+ @Test
261+ fun `parse stores valid job and skips job with malformed start_date` () {
262+ val malformedJob = validJobJson(10 ).apply { put(" start_date" , " not-a-date" ) }
263+ val inputStream = jsonArrayOf(validJobJson(1 ), malformedJob)
264+ every { ConnectJobUtils .storeJobs(any(), any(), any()) } returns 1
265+ every { ConnectReleaseTogglesWorker .scheduleOneTimeFetch(any()) } just Runs
266+
267+ assertThrows(JSONException ::class .java) {
268+ parser.parse(200 , inputStream, null )
269+ }
270+ verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
271+ }
272+
273+ @Test
274+ fun `parse stores valid job and skips claimed job with null claim end_date` () {
275+ val claim =
276+ JSONObject ().apply {
277+ put(" end_date" , JSONObject .NULL )
278+ put(" date_claimed" , " 2025-01-15" )
279+ }
280+ val inputStream = jsonArrayOf(validJobJson(1 ), claimedJobJson(10 , claim))
281+ every { ConnectJobUtils .storeJobs(any(), any(), any()) } returns 1
282+ every { ConnectReleaseTogglesWorker .scheduleOneTimeFetch(any()) } just Runs
283+
284+ assertThrows(JSONException ::class .java) {
285+ parser.parse(200 , inputStream, null )
286+ }
287+ verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
288+ }
289+
290+ @Test
291+ fun `parse stores valid job and skips claimed job with malformed claim end_date` () {
292+ val claim =
293+ JSONObject ().apply {
294+ put(" end_date" , " not-a-date" )
295+ put(" date_claimed" , " 2025-01-15" )
296+ }
297+ val inputStream = jsonArrayOf(validJobJson(1 ), claimedJobJson(10 , claim))
298+ every { ConnectJobUtils .storeJobs(any(), any(), any()) } returns 1
299+ every { ConnectReleaseTogglesWorker .scheduleOneTimeFetch(any()) } just Runs
300+
301+ assertThrows(JSONException ::class .java) {
302+ parser.parse(200 , inputStream, null )
303+ }
304+ verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
305+ }
306+
307+ @Test
308+ fun `parse stores valid job and skips claimed job with null date_claimed` () {
309+ val claim =
310+ JSONObject ().apply {
311+ put(" end_date" , " 2025-12-31" )
312+ put(" date_claimed" , JSONObject .NULL )
313+ }
314+ val inputStream = jsonArrayOf(validJobJson(1 ), claimedJobJson(10 , claim))
315+ every { ConnectJobUtils .storeJobs(any(), any(), any()) } returns 1
316+ every { ConnectReleaseTogglesWorker .scheduleOneTimeFetch(any()) } just Runs
317+
318+ assertThrows(JSONException ::class .java) {
319+ parser.parse(200 , inputStream, null )
320+ }
321+ verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
322+ }
323+
324+ @Test
325+ fun `parse stores valid job and skips claimed job with malformed date_claimed` () {
326+ val claim =
327+ JSONObject ().apply {
328+ put(" end_date" , " 2025-12-31" )
329+ put(" date_claimed" , " not-a-date" )
330+ }
331+ val inputStream = jsonArrayOf(validJobJson(1 ), claimedJobJson(10 , claim))
332+ every { ConnectJobUtils .storeJobs(any(), any(), any()) } returns 1
333+ every { ConnectReleaseTogglesWorker .scheduleOneTimeFetch(any()) } just Runs
334+
335+ assertThrows(JSONException ::class .java) {
336+ parser.parse(200 , inputStream, null )
337+ }
338+ verify(exactly = 1 ) { ConnectJobUtils .storeJobs(any(), match { it.size == 1 && it[0 ].jobId == 1 }, true ) }
339+ }
228340}
0 commit comments