11import datetime
22from collections import ChainMap
3+ from datetime import timedelta
34
45import ddt
56import factory
67import pytest
78from django .conf import settings
89from django .contrib .sites .models import Site
910from django .test import TestCase , override_settings
11+ from django .utils import timezone
1012from pytz import UTC
1113
1214from conftest import TEST_DOMAIN
1618from course_discovery .apps .course_metadata .choices import ExternalProductStatus , ProgramStatus
1719from course_discovery .apps .course_metadata .models import CourseRunStatus , CourseType , ProductValue , ProgramType
1820from course_discovery .apps .course_metadata .tests .factories import (
19- AdditionalMetadataFactory , CourseFactory , CourseRunFactory , CourseTypeFactory , DegreeAdditionalMetadataFactory ,
20- DegreeFactory , GeoLocationFactory , LevelTypeFactory , OrganizationFactory , ProductMetaFactory , ProgramFactory ,
21- ProgramSubscriptionFactory , ProgramSubscriptionPriceFactory , ProgramTypeFactory , RestrictedCourseRunFactory ,
22- SeatFactory , SeatTypeFactory , SourceFactory , SubjectFactory , VideoFactory
21+ AdditionalMetadataFactory , CourseFactory , CourseRunFactory , CourseRunTypeFactory , CourseTypeFactory ,
22+ DegreeAdditionalMetadataFactory , DegreeFactory , GeoLocationFactory , LevelTypeFactory , OrganizationFactory ,
23+ ProductMetaFactory , ProgramFactory , ProgramSubscriptionFactory , ProgramSubscriptionPriceFactory , ProgramTypeFactory ,
24+ RestrictedCourseRunFactory , SeatFactory , SeatTypeFactory , SourceFactory , SubjectFactory , VideoFactory
2325)
2426from course_discovery .apps .ietf_language_tags .models import LanguageTag
2527
@@ -599,6 +601,68 @@ def test_course_ai_languages__no_advertised_run(self):
599601 'transcription_languages' : []
600602 }
601603
604+ def test_product_weeks_to_complete_returns_value (self ):
605+ course = CourseFactory ()
606+ run_type = CourseRunTypeFactory (is_marketable = True )
607+ CourseRunFactory (
608+ course = course ,
609+ type = run_type ,
610+ weeks_to_complete = 8 ,
611+ start = timezone .now () - timedelta (days = 1 ),
612+ end = timezone .now () + timedelta (days = 30 ),
613+ hidden = False ,
614+ make_marketable = True ,
615+ )
616+ course .refresh_from_db ()
617+ proxy_course = AlgoliaProxyCourse .objects .get (pk = course .id )
618+ assert proxy_course .product_weeks_to_complete == 8
619+
620+ def test_product_weeks_to_complete_none_if_no_advertised_run (self ):
621+ course = CourseFactory ()
622+ proxy_course = AlgoliaProxyCourse .objects .get (pk = course .id )
623+ assert proxy_course .product_weeks_to_complete is None
624+
625+ def test_multiple_runs_only_advertised_run_is_used (self ):
626+ course = CourseFactory ()
627+ run_type = CourseRunTypeFactory (is_marketable = True )
628+ CourseRunFactory (
629+ course = course ,
630+ type = run_type ,
631+ weeks_to_complete = 4 ,
632+ start = timezone .now () - timedelta (days = 1 ),
633+ end = timezone .now () + timedelta (days = 10 ),
634+ hidden = False ,
635+ make_marketable = True ,
636+ )
637+ advertised_run = CourseRunFactory (
638+ course = course ,
639+ type = run_type ,
640+ weeks_to_complete = 12 ,
641+ start = timezone .now () - timedelta (days = 1 ),
642+ end = timezone .now () + timedelta (days = 20 ),
643+ hidden = False ,
644+ make_marketable = True ,
645+ )
646+ course .advertised_course_run_id = advertised_run .id
647+ course .save ()
648+ course .refresh_from_db ()
649+ proxy_course = AlgoliaProxyCourse .objects .get (pk = course .id )
650+ assert proxy_course .product_weeks_to_complete == 12
651+
652+ @ddt .data (6 , None )
653+ def test_weeks_to_complete_property_type (self , weeks ):
654+ course = CourseFactory ()
655+ if weeks is not None :
656+ run = CourseRunFactory (course = course , weeks_to_complete = weeks )
657+ if hasattr (course , 'set_advertised_course_run' ):
658+ course .set_advertised_course_run (run )
659+ else :
660+ course .advertised_course_run_id = run .id
661+ course .save ()
662+ proxy_course = AlgoliaProxyCourse .objects .get (pk = course .id )
663+ value = proxy_course .product_weeks_to_complete
664+ assert value is None or isinstance (value , int )
665+
602666
603667@ddt .ddt
604668@pytest .mark .django_db
@@ -610,6 +674,16 @@ class TestAlgoliaProxyProgram(TestAlgoliaProxyWithEdxPartner):
610674 IN_FIFTEEN_DAYS = datetime .datetime .now (UTC ) + datetime .timedelta (days = 15 )
611675 IN_TWO_MONTHS = datetime .datetime .now (UTC ) + datetime .timedelta (days = 60 )
612676
677+ def test_product_weeks_to_complete_always_none (self ):
678+ program = ProgramFactory ()
679+ proxy_program = AlgoliaProxyProgram .objects .get (pk = program .id )
680+ assert proxy_program .product_weeks_to_complete is None
681+
682+ def test_product_weeks_to_complete_none_even_with_related_courses (self ):
683+ program = ProgramFactory ()
684+ proxy_program = AlgoliaProxyProgram .objects .get (pk = program .id )
685+ assert proxy_program .product_weeks_to_complete is None
686+
613687 def attach_course_run (self , course , availability = "Archived" ):
614688 course_start = course_end = ''
615689 if availability == 'none' :
0 commit comments