@@ -402,3 +402,93 @@ async fn test_crawl_contests_fetches_filtered_archive_categories() {
402402 . any( |contest| contest. id == "adt_all_20260612_2" )
403403 ) ;
404404}
405+
406+ #[ tokio:: test]
407+ async fn test_crawl_adt_problems ( ) {
408+ let db = setup_db ( ) . await . unwrap ( ) ;
409+
410+ // 1. ABCのコンテスト、問題がクロールされる
411+ sql_entities:: contests:: Entity :: insert ( sql_entities:: contests:: ActiveModel {
412+ id : Set ( "abc001" . to_string ( ) ) ,
413+ start_epoch_second : Set ( 0 ) ,
414+ duration_second : Set ( 0 ) ,
415+ title : Set ( "AtCoder Beginner Contest 001" . to_string ( ) ) ,
416+ rate_change : Set ( "?" . to_string ( ) ) ,
417+ } )
418+ . exec ( & db)
419+ . await
420+ . unwrap ( ) ;
421+
422+ let mut abc_fetcher = MockProblemFetcher :: new ( ) ;
423+ abc_fetcher
424+ . expect_fetch_problems ( )
425+ . withf ( |contest_id| contest_id == "abc001" )
426+ . times ( 1 )
427+ . returning ( |_| {
428+ Ok ( vec ! [ Problem {
429+ id: "abc001_a" . to_string( ) ,
430+ contest_id: "abc001" . to_string( ) ,
431+ problem_index: "A" . to_string( ) ,
432+ name: "Problem A" . to_string( ) ,
433+ } ] )
434+ } ) ;
435+
436+ atcoder_problems_backend:: crawler_utils:: crawl_problems ( & abc_fetcher, & db)
437+ . await
438+ . unwrap ( ) ;
439+
440+ // 2. 次に、ADTのコンテスト、問題がクロールされる
441+ sql_entities:: contests:: Entity :: insert ( sql_entities:: contests:: ActiveModel {
442+ id : Set ( "adt_all_20260612" . to_string ( ) ) ,
443+ start_epoch_second : Set ( 0 ) ,
444+ duration_second : Set ( 0 ) ,
445+ title : Set ( "AtCoder Daily Training 2026/06/12 All" . to_string ( ) ) ,
446+ rate_change : Set ( "-" . to_string ( ) ) ,
447+ } )
448+ . exec ( & db)
449+ . await
450+ . unwrap ( ) ;
451+
452+ let mut adt_fetcher = MockProblemFetcher :: new ( ) ;
453+ adt_fetcher
454+ . expect_fetch_problems ( )
455+ . withf ( |contest_id| contest_id == "adt_all_20260612" )
456+ . times ( 1 )
457+ . returning ( |_| {
458+ Ok ( vec ! [ Problem {
459+ id: "abc001_a" . to_string( ) ,
460+ contest_id: "adt_all_20260612" . to_string( ) ,
461+ problem_index: "C" . to_string( ) ,
462+ name: "Problem C" . to_string( ) ,
463+ } ] )
464+ } ) ;
465+
466+ atcoder_problems_backend:: crawler_utils:: crawl_problems ( & adt_fetcher, & db)
467+ . await
468+ . unwrap ( ) ;
469+
470+ // 3. abc001_aがabc001とadt_all_20260612の両方に紐づいていることを確認する
471+ let problems_after_adt = sql_entities:: problems:: Entity :: find ( )
472+ . all ( & db)
473+ . await
474+ . unwrap ( ) ;
475+ assert_eq ! ( problems_after_adt. len( ) , 1 ) ;
476+ assert_eq ! ( problems_after_adt[ 0 ] . id, "abc001_a" ) ;
477+ assert_eq ! ( problems_after_adt[ 0 ] . contest_id, "abc001" ) ;
478+
479+ let contest_problems = sql_entities:: contest_problem:: Entity :: find ( )
480+ . all ( & db)
481+ . await
482+ . unwrap ( ) ;
483+ assert_eq ! ( contest_problems. len( ) , 2 ) ;
484+ assert ! ( contest_problems. iter( ) . any( |cp| cp. contest_id == "abc001"
485+ && cp. problem_id == "abc001_a"
486+ && cp. problem_index == "A" ) ) ;
487+ assert ! (
488+ contest_problems
489+ . iter( )
490+ . any( |cp| cp. contest_id == "adt_all_20260612"
491+ && cp. problem_id == "abc001_a"
492+ && cp. problem_index == "C" )
493+ ) ;
494+ }
0 commit comments