Skip to content

Commit 6842e4a

Browse files
committed
test: tests for entitlement validations and deactivation on expired validtill
1 parent 6af7c71 commit 6842e4a

File tree

2 files changed

+180
-8
lines changed

2 files changed

+180
-8
lines changed

src/services/login-service.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ define(function (require, exports, module) {
5050

5151
// save a copy of window.fetch so that extensions wont tamper with it.
5252
let fetchFn = window.fetch;
53+
let dateNowFn = Date.now;
5354

5455
const KernalModeTrust = window.KernalModeTrust;
5556
if(!KernalModeTrust){
@@ -383,14 +384,14 @@ define(function (require, exports, module) {
383384
return;
384385
}
385386

386-
const currentDate = Date.now();
387+
const currentDate = dateNowFn();
387388

388389
if(entitlements.plan && (!entitlements.plan.validTill || currentDate > entitlements.plan.validTill)) {
389390
entitlements.plan = {
390391
...entitlements.plan,
391392
paidSubscriber: false,
392393
name: Strings.USER_FREE_PLAN_NAME,
393-
validTill: Date.now() + (FREE_PLAN_VALIDITY_DAYS * MS_IN_DAY)
394+
validTill: currentDate + (FREE_PLAN_VALIDITY_DAYS * MS_IN_DAY)
394395
};
395396
}
396397

@@ -401,10 +402,11 @@ define(function (require, exports, module) {
401402

402403
for(const featureName in featureEntitlements) {
403404
const feature = featureEntitlements[featureName];
404-
if(feature && feature.validTill && currentDate > feature.validTill) {
405+
if(feature && (!feature.validTill || currentDate > feature.validTill)) {
405406
feature.activated = false;
406407
feature.upgradeToPlan = feature.upgradeToPlan || brackets.config.main_pro_plan;
407408
feature.subscribeURL = feature.subscribeURL || brackets.config.purchase_url;
409+
feature.validTill = feature.validTill || (currentDate - MS_IN_DAY);
408410
}
409411
}
410412
}
@@ -525,7 +527,7 @@ define(function (require, exports, module) {
525527
...serverEntitlements.plan,
526528
paidSubscriber: true,
527529
name: brackets.config.main_pro_plan,
528-
validTill: Date.now() + trialDaysRemaining * MS_IN_DAY
530+
validTill: dateNowFn() + trialDaysRemaining * MS_IN_DAY
529531
},
530532
isInProTrial: true,
531533
trialDaysRemaining: trialDaysRemaining,
@@ -535,7 +537,7 @@ define(function (require, exports, module) {
535537
activated: true,
536538
subscribeURL: brackets.config.purchase_url,
537539
upgradeToPlan: brackets.config.main_pro_plan,
538-
validTill: Date.now() + trialDaysRemaining * MS_IN_DAY
540+
validTill: dateNowFn() + trialDaysRemaining * MS_IN_DAY
539541
}
540542
}
541543
};
@@ -546,7 +548,7 @@ define(function (require, exports, module) {
546548
plan: {
547549
paidSubscriber: true,
548550
name: brackets.config.main_pro_plan,
549-
validTill: Date.now() + trialDaysRemaining * MS_IN_DAY
551+
validTill: dateNowFn() + trialDaysRemaining * MS_IN_DAY
550552
},
551553
isInProTrial: true,
552554
trialDaysRemaining: trialDaysRemaining,
@@ -555,7 +557,7 @@ define(function (require, exports, module) {
555557
activated: true,
556558
subscribeURL: brackets.config.purchase_url,
557559
upgradeToPlan: brackets.config.main_pro_plan,
558-
validTill: Date.now() + trialDaysRemaining * MS_IN_DAY
560+
validTill: dateNowFn() + trialDaysRemaining * MS_IN_DAY
559561
}
560562
}
561563
};
@@ -574,7 +576,11 @@ define(function (require, exports, module) {
574576
LoginService,
575577
setFetchFn: function _setFetchFn(fn) {
576578
fetchFn = fn;
577-
}
579+
},
580+
setDateNowFn: function _setDdateNowFn(fn) {
581+
dateNowFn = fn;
582+
},
583+
_validateAndFilterEntitlements: _validateAndFilterEntitlements
578584
};
579585
}
580586

test/spec/promotions-integ-test.js

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)