@@ -782,5 +782,171 @@ define(function (require, exports, module) {
782782 } ;
783783 } ) ;
784784 } ) ;
785+
786+ describe ( "Entitlements Validation" , function ( ) {
787+ let LoginServiceExports ;
788+
789+ beforeEach ( function ( ) {
790+ // Access login service exports
791+ LoginServiceExports = testWindow . _test_login_service_exports ;
792+
793+ // Set up time mocking
794+ if ( LoginServiceExports . setDateNowFn ) {
795+ LoginServiceExports . setDateNowFn ( ( ) => mockNow ) ;
796+ }
797+ } ) ;
798+
799+ afterEach ( function ( ) {
800+ // Reset time function
801+ if ( LoginServiceExports . setDateNowFn ) {
802+ LoginServiceExports . setDateNowFn ( Date . now ) ;
803+ }
804+ } ) ;
805+
806+ it ( "should handle expired plans correctly" , function ( ) {
807+
808+ // Test expired plan gets reset to free plan
809+ const expiredPlanEntitlements = {
810+ plan : {
811+ paidSubscriber : true ,
812+ name : "Phoenix Pro" ,
813+ validTill : mockNow - 86400000 // 1 day ago
814+ } ,
815+ entitlements : { }
816+ } ;
817+
818+ LoginServiceExports . _validateAndFilterEntitlements ( expiredPlanEntitlements ) ;
819+
820+ expect ( expiredPlanEntitlements . plan . paidSubscriber ) . toBe ( false ) ;
821+ expect ( expiredPlanEntitlements . plan . name ) . toBe ( testWindow . Strings . USER_FREE_PLAN_NAME ) ;
822+ expect ( expiredPlanEntitlements . plan . validTill ) . toBeGreaterThan ( mockNow ) ;
823+
824+ // Test valid plan remains unchanged
825+ const validPlanEntitlements = {
826+ plan : {
827+ paidSubscriber : true ,
828+ name : "Phoenix Pro" ,
829+ validTill : mockNow + 86400000 // 1 day from now
830+ } ,
831+ entitlements : { }
832+ } ;
833+ const originalPlan = JSON . parse ( JSON . stringify ( validPlanEntitlements . plan ) ) ;
834+
835+ LoginServiceExports . _validateAndFilterEntitlements ( validPlanEntitlements ) ;
836+
837+ expect ( validPlanEntitlements . plan ) . toEqual ( originalPlan ) ;
838+
839+ // Test missing validTill gets reset
840+ const noValidTillEntitlements = {
841+ plan : {
842+ paidSubscriber : true ,
843+ name : "Phoenix Pro"
844+ } ,
845+ entitlements : { }
846+ } ;
847+
848+ LoginServiceExports . _validateAndFilterEntitlements ( noValidTillEntitlements ) ;
849+
850+ expect ( noValidTillEntitlements . plan . paidSubscriber ) . toBe ( false ) ;
851+ expect ( noValidTillEntitlements . plan . name ) . toBe ( testWindow . Strings . USER_FREE_PLAN_NAME ) ;
852+ } ) ;
853+
854+ it ( "should validate and filter expired feature entitlements" , function ( ) {
855+ // Test expired features get deactivated
856+ const entitlementsWithExpiredFeatures = {
857+ plan : {
858+ paidSubscriber : true ,
859+ name : "Phoenix Pro" ,
860+ validTill : mockNow + 86400000
861+ } ,
862+ entitlements : {
863+ liveEdit : {
864+ activated : true ,
865+ validTill : mockNow - 86400000 // expired
866+ } ,
867+ liveEditAI : {
868+ activated : true ,
869+ validTill : mockNow + 86400000 // valid
870+ }
871+ }
872+ } ;
873+
874+ LoginServiceExports . _validateAndFilterEntitlements ( entitlementsWithExpiredFeatures ) ;
875+
876+ expect ( entitlementsWithExpiredFeatures . entitlements . liveEdit . activated ) . toBe ( false ) ;
877+ expect ( entitlementsWithExpiredFeatures . entitlements . liveEditAI . activated )
878+ . toBe ( true ) ; // should remain unchanged
879+ expect ( entitlementsWithExpiredFeatures . entitlements . liveEdit . upgradeToPlan )
880+ . toBe ( testWindow . brackets . config . main_pro_plan ) ;
881+ expect ( entitlementsWithExpiredFeatures . entitlements . liveEdit . subscribeURL )
882+ . toBe ( testWindow . brackets . config . purchase_url ) ;
883+
884+ // Test features without validTill get deactivated (treated as expired)
885+ const entitlementsNoValidTill = {
886+ plan : {
887+ paidSubscriber : true ,
888+ name : "Phoenix Pro" ,
889+ validTill : mockNow + 86400000
890+ } ,
891+ entitlements : {
892+ liveEdit : {
893+ activated : true
894+ // no validTill property - should be treated as expired
895+ }
896+ }
897+ } ;
898+
899+ LoginServiceExports . _validateAndFilterEntitlements ( entitlementsNoValidTill ) ;
900+
901+ expect ( entitlementsNoValidTill . entitlements . liveEdit . activated )
902+ . toBe ( false ) ; // should be deactivated
903+ expect ( entitlementsNoValidTill . entitlements . liveEdit . upgradeToPlan )
904+ . toBe ( testWindow . brackets . config . main_pro_plan ) ;
905+ expect ( entitlementsNoValidTill . entitlements . liveEdit . subscribeURL )
906+ . toBe ( testWindow . brackets . config . purchase_url ) ;
907+ expect ( entitlementsNoValidTill . entitlements . liveEdit . validTill < mockNow )
908+ . toBeTrue ( ) ; // should be set to past date
909+ } ) ;
910+
911+ it ( "should handle null and edge cases safely" , function ( ) {
912+ const validateFn = LoginServiceExports . _validateAndFilterEntitlements ;
913+
914+ // Test null entitlements
915+ expect ( function ( ) {
916+ validateFn ( null ) ;
917+ } ) . not . toThrow ( ) ;
918+
919+ // Test undefined entitlements
920+ expect ( function ( ) {
921+ validateFn ( undefined ) ;
922+ } ) . not . toThrow ( ) ;
923+
924+ // Test entitlements without plan
925+ const noPlanEntitlements = {
926+ entitlements : { }
927+ } ;
928+ expect ( function ( ) {
929+ validateFn ( noPlanEntitlements ) ;
930+ } ) . not . toThrow ( ) ;
931+
932+ // Test entitlements without entitlements object
933+ const noEntitlementsObj = {
934+ plan : {
935+ paidSubscriber : true ,
936+ name : "Phoenix Pro" ,
937+ validTill : mockNow + 86400000
938+ }
939+ } ;
940+ expect ( function ( ) {
941+ validateFn ( noEntitlementsObj ) ;
942+ } ) . not . toThrow ( ) ;
943+
944+ // Test empty entitlements object
945+ const emptyEntitlements = { } ;
946+ expect ( function ( ) {
947+ validateFn ( emptyEntitlements ) ;
948+ } ) . not . toThrow ( ) ;
949+ } ) ;
950+ } ) ;
785951 } ) ;
786952} ) ;
0 commit comments