@@ -296,4 +296,153 @@ void testAddDonateItem_DoesNotAddWhenNameAlreadyPresent() {
296296 assertThat (donateItemsResolver .getDonateItems ().size (), is (originalSize ));
297297 assertThat (donateItemsResolver .getDonateItems (), not (hasItem (equalTo (duplicateDonateMap ))));
298298 }
299+
300+ @ Test
301+ void testAddDonateItem_DoesNotAddWhenInvalidFields () {
302+ // 1. Invalid alt containing non-alphanumeric chars
303+ Donate invalidAlt = Donate .builder ()
304+ .name ("The Jack and Jill Children’s Foundation" )
305+ .alt ("<script>" )
306+ .link ("https://valid.org" )
307+ .donate ("https://valid.org/donate" )
308+ .img ("valid" )
309+ .overview ("Valid overview" )
310+ .founded (2000 )
311+ .phone ("+3531234567" )
312+ .build ();
313+ assertThat (donateItemsResolver .addDonateItem (invalidAlt ), is (false ));
314+
315+ // 2. Invalid link
316+ Donate invalidLink = Donate .builder ()
317+ .name ("The Jack and Jill Children’s Foundation" )
318+ .alt ("Valid" )
319+ .link ("ftp://invalid.org" )
320+ .donate ("https://valid.org/donate" )
321+ .img ("valid" )
322+ .overview ("Valid overview" )
323+ .founded (2000 )
324+ .phone ("+3531234567" )
325+ .build ();
326+ assertThat (donateItemsResolver .addDonateItem (invalidLink ), is (false ));
327+
328+ // 3. Invalid founded (too low)
329+ Donate invalidFoundedLow = Donate .builder ()
330+ .name ("The Jack and Jill Children’s Foundation" )
331+ .alt ("Valid" )
332+ .link ("https://valid.org" )
333+ .donate ("https://valid.org/donate" )
334+ .img ("valid" )
335+ .overview ("Valid overview" )
336+ .founded (999 )
337+ .phone ("+3531234567" )
338+ .build ();
339+ assertThat (donateItemsResolver .addDonateItem (invalidFoundedLow ), is (false ));
340+
341+ // 4. Invalid founded (too high)
342+ Donate invalidFoundedHigh = Donate .builder ()
343+ .name ("The Jack and Jill Children’s Foundation" )
344+ .alt ("Valid" )
345+ .link ("https://valid.org" )
346+ .donate ("https://valid.org/donate" )
347+ .img ("valid" )
348+ .overview ("Valid overview" )
349+ .founded (2200 )
350+ .phone ("+3531234567" )
351+ .build ();
352+ assertThat (donateItemsResolver .addDonateItem (invalidFoundedHigh ), is (false ));
353+
354+ // 5. Invalid phone (too short)
355+ Donate invalidPhone = Donate .builder ()
356+ .name ("The Jack and Jill Children’s Foundation" )
357+ .alt ("Valid" )
358+ .link ("https://valid.org" )
359+ .donate ("https://valid.org/donate" )
360+ .img ("valid" )
361+ .overview ("Valid overview" )
362+ .founded (2000 )
363+ .phone ("123" )
364+ .build ();
365+ assertThat (donateItemsResolver .addDonateItem (invalidPhone ), is (false ));
366+ }
367+
368+ @ Test
369+ void testHelpers_NullAndCornerCases () throws Exception {
370+ // Verify null check in isAlreadyPresent
371+ java .lang .reflect .Method isAlreadyPresentMethod = DonateItemsResolver .class .getDeclaredMethod ("isAlreadyPresent" , String .class );
372+ isAlreadyPresentMethod .setAccessible (true );
373+ boolean resultNull = (boolean ) isAlreadyPresentMethod .invoke (donateItemsResolver , (String ) null );
374+ assertThat (resultNull , is (false ));
375+
376+ // Verify null name branch in memory list
377+ java .lang .reflect .Field field = DonateItemsResolver .class .getDeclaredField ("donateItems" );
378+ field .setAccessible (true );
379+ @ SuppressWarnings ("unchecked" )
380+ List <Donate > internalList = (List <Donate >) field .get (donateItemsResolver );
381+ internalList .add (Donate .builder ().name (null ).build ());
382+
383+ boolean resultWithNullInMemory = (boolean ) isAlreadyPresentMethod .invoke (donateItemsResolver , "Some Name" );
384+ assertThat (resultWithNullInMemory , is (false ));
385+ }
386+
387+ @ Test
388+ void testValidation_Directly () throws Exception {
389+ java .lang .reflect .Method isValidDonateMethod = DonateItemsResolver .class .getDeclaredMethod ("isValidDonate" , Donate .class );
390+ isValidDonateMethod .setAccessible (true );
391+
392+ // Test null phone/email
393+ Donate nullPhone = Donate .builder ()
394+ .alt ("Valid" )
395+ .name ("Valid" )
396+ .link ("https://valid.org" )
397+ .donate ("https://valid.org/donate" )
398+ .img ("valid" )
399+ .overview ("Valid overview" )
400+ .founded (2000 )
401+ .phone (null )
402+ .build ();
403+ boolean resNullPhone = (boolean ) isValidDonateMethod .invoke (donateItemsResolver , nullPhone );
404+ assertThat (resNullPhone , is (false ));
405+
406+ // Test empty phone/email
407+ Donate emptyPhone = Donate .builder ()
408+ .alt ("Valid" )
409+ .name ("Valid" )
410+ .link ("https://valid.org" )
411+ .donate ("https://valid.org/donate" )
412+ .img ("valid" )
413+ .overview ("Valid overview" )
414+ .founded (2000 )
415+ .phone (" " )
416+ .build ();
417+ boolean resEmptyPhone = (boolean ) isValidDonateMethod .invoke (donateItemsResolver , emptyPhone );
418+ assertThat (resEmptyPhone , is (false ));
419+
420+ // Test valid email
421+ Donate validEmail = Donate .builder ()
422+ .alt ("Valid" )
423+ .name ("Valid" )
424+ .link ("https://valid.org" )
425+ .donate ("https://valid.org/donate" )
426+ .img ("valid" )
427+ .overview ("Valid overview" )
428+ .founded (2000 )
429+ .phone ("test@charity.org" )
430+ .build ();
431+ boolean resValidEmail = (boolean ) isValidDonateMethod .invoke (donateItemsResolver , validEmail );
432+ assertThat (resValidEmail , is (true ));
433+
434+ // Test valid phone with space
435+ Donate validPhoneWithSpace = Donate .builder ()
436+ .alt ("Valid" )
437+ .name ("Valid" )
438+ .link ("https://valid.org" )
439+ .donate ("https://valid.org/donate" )
440+ .img ("valid" )
441+ .overview ("Valid overview" )
442+ .founded (2000 )
443+ .phone ("+353 1 234 5678" )
444+ .build ();
445+ boolean resValidPhone = (boolean ) isValidDonateMethod .invoke (donateItemsResolver , validPhoneWithSpace );
446+ assertThat (resValidPhone , is (true ));
447+ }
299448}
0 commit comments