@@ -271,6 +271,108 @@ describe("TalentPlusSubscription", () => {
271271 } ) ;
272272 } ) ;
273273
274+ describe ( "User Subscription Management with Custom Expiration" , ( ) => {
275+ const basicSlug = "basic" ;
276+ const premiumSlug = "premium" ;
277+ const basicDuration = 30 * 24 * 60 * 60 ; // 30 days
278+ const premiumDuration = 90 * 24 * 60 * 60 ; // 90 days
279+ const basicPrice = ethers . utils . parseEther ( "50" ) ;
280+ const premiumPrice = ethers . utils . parseEther ( "100" ) ;
281+
282+ beforeEach ( async ( ) => {
283+ await talentPlusSubscription . connect ( admin ) . addSubscriptionModel ( basicSlug , basicDuration , basicPrice ) ;
284+ await talentPlusSubscription . connect ( admin ) . addSubscriptionModel ( premiumSlug , premiumDuration , premiumPrice ) ;
285+ } ) ;
286+
287+ it ( "should allow trusted signer to add user subscription with custom expiration" , async ( ) => {
288+ const customExpiration = Math . floor ( Date . now ( ) / 1000 ) + 60 * 24 * 60 * 60 ; // 60 days from now
289+
290+ const tx = await talentPlusSubscription . connect ( trustedSigner ) . addUserSubscriptionWithExpiration (
291+ user1 . address ,
292+ customExpiration
293+ ) ;
294+
295+ const event = await findEvent ( tx , "UserSubscriptionAdded" ) ;
296+ expect ( event ) . to . exist ;
297+
298+ expect ( await talentPlusSubscription . hasActiveSubscription ( user1 . address ) ) . to . eq ( true ) ;
299+ expect ( await talentPlusSubscription . hasActiveSubscriptionForModel ( user1 . address , "custom" ) ) . to . eq ( true ) ;
300+
301+ const expiration = await talentPlusSubscription . getSubscriptionExpiration ( user1 . address ) ;
302+ expect ( expiration . toNumber ( ) ) . to . be . closeTo ( customExpiration , 60 ) ; // Allow 1 minute tolerance
303+ } ) ;
304+
305+ it ( "should not allow non-trusted signer to add user subscription with custom expiration" , async ( ) => {
306+ const customExpiration = Math . floor ( Date . now ( ) / 1000 ) + 60 * 24 * 60 * 60 ; // 60 days from now
307+
308+ const action = talentPlusSubscription . connect ( nonTrustedSigner ) . addUserSubscriptionWithExpiration (
309+ user1 . address ,
310+ customExpiration
311+ ) ;
312+ await expect ( action ) . to . be . revertedWith ( "Only trusted signers can add user subscriptions" ) ;
313+ } ) ;
314+
315+ it ( "should not allow subscription for zero address with custom expiration" , async ( ) => {
316+ const customExpiration = Math . floor ( Date . now ( ) / 1000 ) + 60 * 24 * 60 * 60 ; // 60 days from now
317+
318+ const action = talentPlusSubscription . connect ( trustedSigner ) . addUserSubscriptionWithExpiration (
319+ ethers . constants . AddressZero ,
320+ customExpiration
321+ ) ;
322+ await expect ( action ) . to . be . revertedWith ( "Invalid wallet address" ) ;
323+ } ) ;
324+
325+ it ( "should not allow expiration time in the past" , async ( ) => {
326+ const pastExpiration = Math . floor ( Date . now ( ) / 1000 ) - 60 * 24 * 60 * 60 ; // 60 days ago
327+
328+ const action = talentPlusSubscription . connect ( trustedSigner ) . addUserSubscriptionWithExpiration (
329+ user1 . address ,
330+ pastExpiration
331+ ) ;
332+ await expect ( action ) . to . be . revertedWith ( "Expiration time must be in the future" ) ;
333+ } ) ;
334+
335+ it ( "should replace existing subscription when adding with custom expiration" , async ( ) => {
336+ // First add a basic subscription
337+ await talentPlusSubscription . connect ( trustedSigner ) . addUserSubscription ( user1 . address , basicSlug ) ;
338+
339+ // Then replace with premium subscription with custom expiration
340+ const customExpiration = Math . floor ( Date . now ( ) / 1000 ) + 120 * 24 * 60 * 60 ; // 120 days from now
341+
342+ const tx = await talentPlusSubscription . connect ( trustedSigner ) . addUserSubscriptionWithExpiration (
343+ user1 . address ,
344+ customExpiration
345+ ) ;
346+
347+ const event = await findEvent ( tx , "UserSubscriptionReplaced" ) ;
348+ expect ( event ) . to . exist ;
349+
350+ expect ( await talentPlusSubscription . hasActiveSubscriptionForModel ( user1 . address , "custom" ) ) . to . eq ( true ) ;
351+ expect ( await talentPlusSubscription . hasActiveSubscriptionForModel ( user1 . address , basicSlug ) ) . to . eq ( false ) ;
352+
353+ const expiration = await talentPlusSubscription . getSubscriptionExpiration ( user1 . address ) ;
354+ expect ( expiration . toNumber ( ) ) . to . be . closeTo ( customExpiration , 60 ) ; // Allow 1 minute tolerance
355+ } ) ;
356+
357+ it ( "should allow setting subscription with expiration very close to current time" , async ( ) => {
358+ const currentBlockTime = ( await ethers . provider . getBlock ( 'latest' ) ) . timestamp ;
359+ const nearFutureExpiration = currentBlockTime + 86400 ; // 1 day from current block time
360+
361+ const tx = await talentPlusSubscription . connect ( trustedSigner ) . addUserSubscriptionWithExpiration (
362+ user1 . address ,
363+ nearFutureExpiration
364+ ) ;
365+
366+ const event = await findEvent ( tx , "UserSubscriptionAdded" ) ;
367+ expect ( event ) . to . exist ;
368+
369+ expect ( await talentPlusSubscription . hasActiveSubscription ( user1 . address ) ) . to . eq ( true ) ;
370+
371+ const expiration = await talentPlusSubscription . getSubscriptionExpiration ( user1 . address ) ;
372+ expect ( expiration . toNumber ( ) ) . to . be . closeTo ( nearFutureExpiration , 60 ) ; // Allow 1 minute tolerance
373+ } ) ;
374+ } ) ;
375+
274376 describe ( "Subscription Queries" , ( ) => {
275377 const basicSlug = "basic" ;
276378 const basicDuration = 30 * 24 * 60 * 60 ; // 30 days
0 commit comments