@@ -48,6 +48,18 @@ describe("NodeCache", () => {
4848 expect ( cache . get ( "baz" ) ) . toBe ( "qux" ) ;
4949 } ) ;
5050
51+ test ( "should return false from mset when any item has a negative ttl" , ( ) => {
52+ const cache = new NodeCache ( { checkperiod : 0 } ) ;
53+ const list = [
54+ { key : "good" , value : "ok" } ,
55+ { key : "bad" , value : "nope" , ttl : - 1 } ,
56+ ] ;
57+ const result = cache . mset ( list ) ;
58+ expect ( result ) . toBe ( false ) ;
59+ expect ( cache . get ( "good" ) ) . toBe ( "ok" ) ;
60+ expect ( cache . has ( "bad" ) ) . toBe ( false ) ;
61+ } ) ;
62+
5163 test ( "should get multiple cache items" , ( ) => {
5264 const cache = new NodeCache ( { checkperiod : 0 } ) ;
5365 cache . set ( "foo" , "bar" ) ;
@@ -127,12 +139,12 @@ describe("NodeCache", () => {
127139
128140 test ( "ttl should default to 0 if no ttl is set" , ( ) => {
129141 const cache = new NodeCache ( { checkperiod : 0 } ) ;
130- cache . set ( "foo" , "bar" ) ; // Set to 10 by stdTTL
142+ cache . set ( "foo" , "bar" ) ;
131143 const ttl = cache . getTtl ( "foo" ) ;
132144 expect ( ttl ) . toBe ( 0 ) ;
133- cache . ttl ( "foo" ) ;
145+ cache . ttl ( "foo" ) ; // No args, stdTTL is 0 → stays unlimited
134146 const ttl2 = cache . getTtl ( "foo" ) ;
135- expect ( ttl2 ) . toBeGreaterThan ( ttl ! ) ;
147+ expect ( ttl2 ) . toBe ( 0 ) ;
136148 } ) ;
137149
138150 test ( "should return 0 if there is no key to delete" , ( ) => {
@@ -235,6 +247,71 @@ describe("NodeCache", () => {
235247 expect ( cache . get ( "moo" ) ) . toBe ( undefined ) ;
236248 } ) ;
237249
250+ test ( "should cache indefinitely when ttl is explicitly 0 even with stdTTL set" , async ( ) => {
251+ const cache = new NodeCache ( { checkperiod : 0 , stdTTL : 0.5 } ) ;
252+ cache . set ( "withStdTTL" , "expires" ) ; // omitted ttl → uses stdTTL
253+ cache . set ( "unlimited" , "stays" , 0 ) ; // explicit 0 → cache indefinitely
254+ await sleep ( 600 ) ;
255+ expect ( cache . get ( "withStdTTL" ) ) . toBe ( undefined ) ;
256+ expect ( cache . get ( "unlimited" ) ) . toBe ( "stays" ) ;
257+ } ) ;
258+
259+ test ( "should return false and not store key when ttl is negative" , ( ) => {
260+ const cache = new NodeCache ( { checkperiod : 0 } ) ;
261+ const result = cache . set ( "foo" , "bar" , - 1 ) ;
262+ expect ( result ) . toBe ( false ) ;
263+ expect ( cache . has ( "foo" ) ) . toBe ( false ) ;
264+ expect ( cache . get ( "foo" ) ) . toBe ( undefined ) ;
265+ } ) ;
266+
267+ test ( "should return false on ttl() method when ttl is negative" , ( ) => {
268+ const cache = new NodeCache ( { checkperiod : 0 } ) ;
269+ cache . set ( "foo" , "bar" ) ;
270+ const result = cache . ttl ( "foo" , - 1 ) ;
271+ expect ( result ) . toBe ( false ) ;
272+ expect ( cache . get ( "foo" ) ) . toBe ( "bar" ) ;
273+ } ) ;
274+
275+ test ( "should reject negative TTL passed as a numeric string in set()" , ( ) => {
276+ const cache = new NodeCache ( { checkperiod : 0 } ) ;
277+ const result = cache . set ( "foo" , "bar" , "-1" ) ;
278+ expect ( result ) . toBe ( false ) ;
279+ expect ( cache . has ( "foo" ) ) . toBe ( false ) ;
280+ } ) ;
281+
282+ test ( "should reject negative TTL passed as a numeric string in ttl()" , ( ) => {
283+ const cache = new NodeCache ( { checkperiod : 0 } ) ;
284+ cache . set ( "foo" , "bar" ) ;
285+ const result = cache . ttl ( "foo" , "-5" ) ;
286+ expect ( result ) . toBe ( false ) ;
287+ expect ( cache . get ( "foo" ) ) . toBe ( "bar" ) ;
288+ } ) ;
289+
290+ test ( "should set unlimited expiration on ttl() method when ttl is 0" , async ( ) => {
291+ const cache = new NodeCache ( { checkperiod : 0 , stdTTL : 0.5 } ) ;
292+ cache . set ( "foo" , "bar" ) ; // uses stdTTL (0.5s)
293+ cache . ttl ( "foo" , 0 ) ; // override to unlimited
294+ await sleep ( 600 ) ;
295+ expect ( cache . get ( "foo" ) ) . toBe ( "bar" ) ;
296+ expect ( cache . getTtl ( "foo" ) ) . toBe ( 0 ) ;
297+ } ) ;
298+
299+ test ( "should treat zero-duration string stdTTL as unlimited" , ( ) => {
300+ const cache = new NodeCache ( { checkperiod : 0 , stdTTL : "0ms" } ) ;
301+ cache . set ( "foo" , "bar" ) ;
302+ expect ( cache . getTtl ( "foo" ) ) . toBe ( 0 ) ;
303+ expect ( cache . get ( "foo" ) ) . toBe ( "bar" ) ;
304+ } ) ;
305+
306+ test ( "should use stdTTL when ttl() is called without ttl argument and stdTTL is set" , ( ) => {
307+ const cache = new NodeCache ( { checkperiod : 0 , stdTTL : 60 } ) ;
308+ cache . set ( "foo" , "bar" , 0 ) ; // explicit 0 = unlimited
309+ expect ( cache . getTtl ( "foo" ) ) . toBe ( 0 ) ;
310+ cache . ttl ( "foo" ) ; // no ttl arg → fall back to stdTTL (60s)
311+ const ttl = cache . getTtl ( "foo" ) ;
312+ expect ( ttl ) . toBeGreaterThan ( 0 ) ;
313+ } ) ;
314+
238315 test ( "should get the internal id and stop the interval" , ( ) => {
239316 const cache = new NodeCache ( ) ;
240317 expect ( cache . getIntervalId ( ) ) . toBeDefined ( ) ;
0 commit comments