@adobe/spacecat-shared-tier-client 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/tier-client.js +29 -0
- package/test/tier-client.test.js +132 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-tier-client-v1.3.3](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.3.2...@adobe/spacecat-shared-tier-client-v1.3.3) (2025-11-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* support for revoke paid entitlement ([#1180](https://github.com/adobe/spacecat-shared/issues/1180)) ([f584c60](https://github.com/adobe/spacecat-shared/commit/f584c600937bb117f60cc6d5cab0dba5dda30d84))
|
|
7
|
+
|
|
8
|
+
# [@adobe/spacecat-shared-tier-client-v1.3.2](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.3.1...@adobe/spacecat-shared-tier-client-v1.3.2) (2025-11-25)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* add lib for revoke entitlement ([#1169](https://github.com/adobe/spacecat-shared/issues/1169)) ([d0f2e67](https://github.com/adobe/spacecat-shared/commit/d0f2e67332e52ee23ece5310d484a43bd42146a4))
|
|
14
|
+
|
|
1
15
|
# [@adobe/spacecat-shared-tier-client-v1.3.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tier-client-v1.3.0...@adobe/spacecat-shared-tier-client-v1.3.1) (2025-11-24)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
package/src/tier-client.js
CHANGED
|
@@ -288,6 +288,35 @@ class TierClient {
|
|
|
288
288
|
throw error;
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Revokes entitlement for the current organization.
|
|
294
|
+
* @returns {Promise<object>} HTTP response object.
|
|
295
|
+
*/
|
|
296
|
+
async revokeEntitlement() {
|
|
297
|
+
const existing = await this.checkValidEntitlement();
|
|
298
|
+
if (existing.entitlement) {
|
|
299
|
+
if (existing.entitlement.getTier() === EntitlementModel.TIERS.PAID) {
|
|
300
|
+
throw new Error('Paid entitlement cannot be revoked');
|
|
301
|
+
}
|
|
302
|
+
await existing.entitlement.remove();
|
|
303
|
+
} else {
|
|
304
|
+
throw new Error('Entitlement not found');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Revokes PAID/FREE entitlement for the current organization.
|
|
310
|
+
* @returns {Promise<object>} HTTP response object.
|
|
311
|
+
*/
|
|
312
|
+
async revokePaidEntitlement() {
|
|
313
|
+
const existing = await this.checkValidEntitlement();
|
|
314
|
+
if (existing.entitlement) {
|
|
315
|
+
await existing.entitlement.remove();
|
|
316
|
+
} else {
|
|
317
|
+
throw new Error('Entitlement not found');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
291
320
|
}
|
|
292
321
|
|
|
293
322
|
export default TierClient;
|
package/test/tier-client.test.js
CHANGED
|
@@ -186,6 +186,13 @@ describe('TierClient', () => {
|
|
|
186
186
|
expect(mockDataAccess.Organization.findById).to.have.been.calledWith(orgId);
|
|
187
187
|
});
|
|
188
188
|
|
|
189
|
+
it('should throw error when organization not found for site', async () => {
|
|
190
|
+
mockDataAccess.Organization.findById.resolves(null);
|
|
191
|
+
|
|
192
|
+
await expect(TierClient.createForSite(mockContext, testSite, productCode))
|
|
193
|
+
.to.be.rejectedWith(`[TierClient] Organization not found for organizationId: ${orgId}`);
|
|
194
|
+
});
|
|
195
|
+
|
|
189
196
|
it('should throw error when site is not provided', async () => {
|
|
190
197
|
await expect(TierClient.createForSite(mockContext, null, productCode)).to.be.rejectedWith('Entity must be an instance of Site');
|
|
191
198
|
});
|
|
@@ -545,6 +552,131 @@ describe('TierClient', () => {
|
|
|
545
552
|
});
|
|
546
553
|
});
|
|
547
554
|
|
|
555
|
+
describe('revokeEntitlement', () => {
|
|
556
|
+
it('should successfully revoke entitlement when it exists', async () => {
|
|
557
|
+
const mockEntitlementWithRemove = {
|
|
558
|
+
...mockEntitlement,
|
|
559
|
+
remove: sandbox.stub().resolves(),
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
mockDataAccess.Entitlement
|
|
563
|
+
.findByOrganizationIdAndProductCode.resolves(mockEntitlementWithRemove);
|
|
564
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
|
|
565
|
+
|
|
566
|
+
await tierClient.revokeEntitlement();
|
|
567
|
+
|
|
568
|
+
expect(mockEntitlementWithRemove.remove.calledOnce).to.be.true;
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
it('should throw error when entitlement is PAID tier', async () => {
|
|
572
|
+
const mockPaidEntitlement = {
|
|
573
|
+
...mockEntitlement,
|
|
574
|
+
getTier: () => 'PAID',
|
|
575
|
+
remove: sandbox.stub().resolves(),
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
mockDataAccess.Entitlement
|
|
579
|
+
.findByOrganizationIdAndProductCode.resolves(mockPaidEntitlement);
|
|
580
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
|
|
581
|
+
|
|
582
|
+
await expect(tierClient.revokeEntitlement()).to.be.rejectedWith('Paid entitlement cannot be revoked');
|
|
583
|
+
expect(mockPaidEntitlement.remove).to.not.have.been.called;
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
it('should throw error when entitlement does not exist', async () => {
|
|
587
|
+
mockDataAccess.Entitlement.findByOrganizationIdAndProductCode.resolves(null);
|
|
588
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
|
|
589
|
+
|
|
590
|
+
await expect(tierClient.revokeEntitlement()).to.be.rejectedWith('Entitlement not found');
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
it('should handle database errors during entitlement removal', async () => {
|
|
594
|
+
const mockEntitlementWithRemoveError = {
|
|
595
|
+
...mockEntitlement,
|
|
596
|
+
remove: sandbox.stub().rejects(new Error('Database error')),
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
mockDataAccess.Entitlement
|
|
600
|
+
.findByOrganizationIdAndProductCode.resolves(mockEntitlementWithRemoveError);
|
|
601
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
|
|
602
|
+
|
|
603
|
+
await expect(tierClient.revokeEntitlement()).to.be.rejectedWith('Database error');
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
it('should handle errors when checking valid entitlement', async () => {
|
|
607
|
+
mockDataAccess.Entitlement
|
|
608
|
+
.findByOrganizationIdAndProductCode
|
|
609
|
+
.rejects(new Error('Database error'));
|
|
610
|
+
|
|
611
|
+
await expect(tierClient.revokeEntitlement()).to.be.rejectedWith('Database error');
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
it('should work with organization-only client (no site)', async () => {
|
|
615
|
+
const mockEntitlementWithRemove = {
|
|
616
|
+
...mockEntitlement,
|
|
617
|
+
remove: sandbox.stub().resolves(),
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
const orgOnlyClient = new TierClient(
|
|
621
|
+
mockContext,
|
|
622
|
+
organizationInstance,
|
|
623
|
+
null,
|
|
624
|
+
productCode,
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
mockDataAccess.Entitlement
|
|
628
|
+
.findByOrganizationIdAndProductCode.resolves(mockEntitlementWithRemove);
|
|
629
|
+
|
|
630
|
+
await orgOnlyClient.revokeEntitlement();
|
|
631
|
+
|
|
632
|
+
expect(mockEntitlementWithRemove.remove.calledOnce).to.be.true;
|
|
633
|
+
});
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
describe('revokePaidEntitlement', () => {
|
|
637
|
+
it('should successfully revoke entitlement regardless of tier', async () => {
|
|
638
|
+
const mockPaidEntitlement = {
|
|
639
|
+
...mockEntitlement,
|
|
640
|
+
getTier: () => 'PAID',
|
|
641
|
+
remove: sandbox.stub().resolves(),
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
mockDataAccess.Entitlement.findByOrganizationIdAndProductCode.resolves(mockPaidEntitlement);
|
|
645
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
|
|
646
|
+
|
|
647
|
+
await tierClient.revokePaidEntitlement();
|
|
648
|
+
|
|
649
|
+
expect(mockPaidEntitlement.remove.calledOnce).to.be.true;
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
it('should throw error when entitlement does not exist', async () => {
|
|
653
|
+
mockDataAccess.Entitlement.findByOrganizationIdAndProductCode.resolves(null);
|
|
654
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
|
|
655
|
+
|
|
656
|
+
await expect(tierClient.revokePaidEntitlement()).to.be.rejectedWith('Entitlement not found');
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
it('should handle database errors during entitlement removal', async () => {
|
|
660
|
+
const mockEntitlementWithRemoveError = {
|
|
661
|
+
...mockEntitlement,
|
|
662
|
+
remove: sandbox.stub().rejects(new Error('Database error')),
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
mockDataAccess.Entitlement
|
|
666
|
+
.findByOrganizationIdAndProductCode.resolves(mockEntitlementWithRemoveError);
|
|
667
|
+
mockDataAccess.SiteEnrollment.allBySiteId.resolves([]);
|
|
668
|
+
|
|
669
|
+
await expect(tierClient.revokePaidEntitlement()).to.be.rejectedWith('Database error');
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
it('should propagate errors when checking valid entitlement', async () => {
|
|
673
|
+
mockDataAccess.Entitlement
|
|
674
|
+
.findByOrganizationIdAndProductCode
|
|
675
|
+
.rejects(new Error('Database error'));
|
|
676
|
+
|
|
677
|
+
await expect(tierClient.revokePaidEntitlement()).to.be.rejectedWith('Database error');
|
|
678
|
+
});
|
|
679
|
+
});
|
|
548
680
|
describe('getAllEnrollment', () => {
|
|
549
681
|
beforeEach(() => {
|
|
550
682
|
mockDataAccess.SiteEnrollment.allByEntitlementId = sandbox.stub();
|